Friday, April 18, 2008

Nokia E series codes'n'tricks

Here's some codes and tricks I've found useful while deploying a Cisco WLC - Nokia Dual Mode architecture.

These apply to th e series phones.

To see the phone's WLAN mac-address :
Check behind the battery, or
*#62209526# (mnemonic trick : it is like writing "*#mac wlan#" with T9) will display it.

To reset to factory defaults, get to Tools->Settings->Phone->General->Orig. phone settings
The default unlock code is 12345.

There is also a code to reset the ROM and the factory defaults, without deleting data files : *#7780#

Then there's the Deep Reset code : *#7370#
This one resets factory settings, deletes every data file and uninstall everything. This reset asks for the unlock code too.

To read the phone's IMEI : *#06#

To check the phone's firmware version the code is *#0000#

Then determine if firmware version is up to date : http://europe.nokia.com/A4577224

Tuesday, April 8, 2008

Push XML to my Cisco IP Phone in .NET

Or "the Expect-100 story", or the "CiscoIPPhoneError 6 quest"...

I was trying to do a simple thing, i.e., push XML to my Cisco IP Phone, in order to make it display a message and/or display a sound.
Theory is simple : POST an XML message to the IP Phone's /CGI/Execute by means of a simple HTTP connection.
I decided to use the C# HttpWebRequest object, thinking it's exactly what I needed.

Note : this is a story of a good workaround, not of the solution, I'm still workin' on it, stay tuned.

What I wanted was to post this to my IP Phone :
"XML=<ciscoipphoneexecute><executeitem priority="0" url="Play:chime.raw"><executeitem priority="0" url="http://10.10.10.10:8080/textmessage.xml"></executeitem>"

that means : play chime.raw and display the xml returned by a GET from the phone on http://10.10.10.10:8080/textmessage.xml

Here's my simple HttpWebRequest code (NOT working...)

string sXML = "XML=<ciscoipphoneexecute><executeitem priority="0" url="Play:chime.raw"><executeitem priority="0" url="http://10.10.10.10:8080/textmessage.xml"></executeitem>"
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create("http://10.1.1.1/CGI/Execute");
webRequest.Method = "POST";
webRequest.Credentials =
new NetworkCredential("test", "test");
byte[] bArr = Encoding.UTF8.GetBytes(sXML);
webRequest.ContentType = "
application/x-www-form-urlencoded";
webRequest.ContentLength = bArr.Length;
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();

All I obtained was always a very annoying
<CiscoIPPhoneError Number="6" />

I found nothing on this error, as Cisco docs say :

CiscoIPPhoneError

The following list gives possible CiscoIPPhoneError codes:

  • Error 1 = Error parsing CiscoIPPhoneExecute object

  • Error 2 = Error framing CiscoIPPhoneResponse object

  • Error 3 = Internal file error

  • Error 4 = Authentication error


    So I started sniffing the POST from my dev box to the phone observing some strange traffic before sending the POST message.
    The reason is .NET implementation of the HTTP request, that add an Expect 100-Continue header on the very first packet, and then send the real POST after receiving the 100-Continue from the server (the IP Phone in this case).

    You can find a more exhaustive explanation on this here.
    Note that implementing the solution indicated (set the System.Net.ServicePointManager.Expect100Continue to false) worked not on my code, I'm still workin' on it.

    My solution, or workaround if you wish, was to use a simpler object, the MSXML2.XMLHTTPClass class.

    Here's the working code :

    string sXML = "XML=<ciscoipphoneexecute><executeitem priority="0" url="Play:chime.raw"><executeitem priority="0" url="http://10.10.10.10:8080/textmessage.xml"></executeitem>"
    byte[] bb = System.Text.ASCIIEncoding.UTF8.GetBytes("test" + ":" + "test");
    MSXML2.
    XMLHTTPClass xmlhttp = new MSXML2.XMLHTTPClass();

    xmlhttp.open("
    POST", "http://10.1.1.1/CGI/Execute", true, "", "");
    xmlhttp.setRequestHeader("
    Authorization", "Basic " + Convert.ToBase64String(bb));
    xmlhttp.setRequestHeader("
    Connection", "close");
    xmlhttp.setRequestHeader("
    Content-type", "application/x-www-form-urlencoded");
    xmlhttp.send(sXML);