Cellular Radio Module Driver for TCP is incorrect

I have found a bug in the Cellular Radio Module driver for TCP
this code will never send the data portion

 public ReturnedState SendTcpData(string data)
        {
            SendATCommand("AT+CIPSEND");
            Thread.Sleep(1000);
            return SendATCommand(data + (char)26);

        }

because

 public ReturnedState SendATCommand(string atCommand)
        {
            // Check if module is busy
            if (isModuleBusy) return ReturnedState.ModuleBusy;

            // Append carriage return
            if (atCommand.IndexOf("\r") < 0) atCommand += "\r";

            // Check if string is an AT command
            if (atCommand.IndexOf("AT") < 0) return ReturnedState.InvalidCommand;

            // Check if module is on
            if (!isPowerOn) return ReturnedState.ModuleIsOff;

            // Check if serial line is open
            if (serialLine.IsOpen) serialLine.Write(atCommand);
            else return ReturnedState.Error;
            Thread.Sleep(100);
            DebugPrint("SENT: " + atCommand);
            return ReturnedState.OK;
        }

will generate an error because it is not an AT command and will not send the data.
To fix this i changed the SendTcpData to

 public ReturnedState SendTcpData(string data)
        {
            SendATCommand("AT+CIPSEND");
            Thread.Sleep(1000);
            if (serialLine.IsOpen) serialLine.Write(data + (char)26);
            else return ReturnedState.Error;
            Thread.Sleep(3000);
            DebugPrint("SENT: " + data);
            return ReturnedState.OK;
        }

It works with this.

it would be better to split the AT command and the data so the data chunks could be written directly to the module and not the whole data set as this can result im memory errors.

Thanks a lot :wink:

Hi Mike,

You are correct - the SendTcpData implementation is wrong and will always return InvalidCommand.

If you want to send proper blocks of data, or even receive (the holy grail!) you actually need to put the SIM900 in transparent data mode instead of AT command mode. You need to modify the driver, because as it is written the serial receive thread can only parse AT responses. We set ours up to have a DataMode flag that switches between AT command mode and Modem mode. Note that in Modem mode it is not required to send the (char)26 as data is automatically sent when the serial line is idle for a (configurable) time. If you do send (char)26, it will go in the data stream.

To get out of data mode, you send “+++”. Look at the delays in the sample code. If you don’t use these delays, then the SIM900 will just send the “+++” as data.

Added to Codeshare at http://www.tinyclr.com/codeshare/entry/590 and Codeplex at https://tcpcellularradio.codeplex.com/

I did a whole new TCP implementation and it works great for me. I will share it a soon as possible. unfortunately i haven’t time to finish it.

ok, thanks. Ignore then my modified version.

has anyone managed to use the cellular radio module to make a web service call?

Here is my code, i hope somebody has fun with it http://www.tinyclr.com/codeshare/entry/622
please send me any problem, question or additional implementations

That’s exactly how we use our implementation. We POST JSON objects to an Azure hosted web service.

@ Byron - thats pretty much what I’m aiming to do, but I’m struggling slightly pulling the code together.

I’ve grabbed your drivers from CodePlex, and the CellularRadioManager extension you posted on the forum. So first off thanks for that.

So I have a test project, which refers to the drivers, and seems pretty happy, can send and recieve txt msgs that kind of thing.

Next I’ve dropped the CellularRadioManager class into the test project, but I can’t figure out where to call it (I’m using the usage code from the forum). I’ve added the ‘usage’ example code to a button pressed event handler, and it successfully retrieves the IMEI, starts up GSM and GPRS, but that’s it.

I’m sorry to be so stupid, but would you be kind enough to provide a bit more context, or a few pointers on how to use the CellularRadioManager?

Initially I’m just trying to hit www.google.com and retrieve data to prove the functionality, then I’ll write a simple webservice.

Would it be a case of making the events in the CellularRadioManager public, and adding handlers in the test project perhaps?

back from holidays in 3 days, will post full example to codeplex then

Hi Byron,

I’ve pretty much tried every combination to make a simple HTTP GET to www.google.com, but i’m consistently getting the following response

Error 400 (Bad Request)!!1....I don't suppose you came across this did you?

my code looks like this

            if (radioManager.Connect(@ "www.google.com")) // add your server address
            {
                // send data
                String RequestString = "GET // Http1.1\r\n";
                RequestString+="Host: www.google.com:80\r\n";
                RequestString+="Connection: close\r\n\r\n";
                //RequestString+="Accept: text//html, application//xhtml+xml, *//*\r\n";
                //RequestString+="Accept-Language: en-GB\r\n";
                //RequestString+="Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\r\n";
                //RequestString+="Cache-Control: no-cache\r\n";
                //RequestString+="Referer: http:////web-sniffer.net//\r\n\r\n";

                if (radioManager.SendData(RequestString))
                     {
                        if (data.IndexOf(@ "HTTP/1.1 201 Created") > -1)  // the response you're expecting, this example calls a webservice
                        {
                            Debug.Print("Tcp Send: Server OK - \"201 Created\"");
                        }
                        else
                        {
                            Debug.Print("Tcp Send: Server FAILED");
                        }
                    }                   

the logs look like this

CellularRadio : SENT DATA: GET // Http1.1
Host: www.google.com:80
Connection: close


CellularRadio : HTTP/1.0 400 Bad Request
Content-Type: text/html; charset=UTF-8
Content-Length: 925
Date: Mon, 14 Jan 2013 00:01:49 GMT
Server: GFE/2.0

Error 400 (Bad Request)!!1 *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@ media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}} Google

400. That’s an error.

Your client has issued a malformed or illegal request. That’s all we know.

CellularRadio :
CLOSED

[quote]Your client has issued a malformed or illegal request. That’s all we know.
[/quote]

That’s what they tell you. You need to correct that.

To test that, simply use a TELNET app on a PC and telnet to the same address and port 80, and issue the same commands; you should get the same response. When you get the correct response there, put that code into your Fez App.

@ MW1, Google is helpfully telling you that you request is malformed. For starters your request has a // where it should have a /

I suggest you start here: HTTP Made Really Easy

Your request should look like (Note caps):
GET / HTTP/1.1
Host: www.google.com
[BLANK_LINE]

I use a const for my newlines;


string _crlf = "" + (char)13 + (char)10;

Done… http://tcpcellularradio.codeplex.com/

thanks for the quick response

I’ve amended my code as suggested to


 if (radioManager.IsReady)       
 {

                if (radioManager.Connect(@ "www.google.com")) // add your server address
                {
                    // send data
                    string crlf = "" + (char)13 + (char)10;
                    String RequestString = "GET // Http1.1"+crlf;
                    RequestString += "Host: www.google.com" +crlf + crlf;


                    if (radioManager.SendData(RequestString))....

but still no joy, still getting the following response from google


CellularRadio : HTTP/1.0 400 Bad Request
Content-Type: text/html; charset=UTF-8
Content-Length: 925
Date: Mon, 14 Jan 2013 11:26:14 GMT
Server: GFE/2.0

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 400 (Bad Request)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@ media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}
  </style>
  <a href=//www.google.com/><img src=//www.google.com/images/errors/logo_sm.gif alt=Google></a>
  <p><b>400.</b> <ins>That’s an error.</ins>
  <p>Your client has issued a malformed or illegal request.  <ins>That’s all we know.</ins>

I wonder if i’m missing something, maybe, or perhaps it might be better to use the http commands built into the cellular radio sim900 rather than using raw tcp connections?

My bad on the missing slash. Bashing out answers without thinking :slight_smile:

@ MW1, you are using “//” when you should be using “/” (the forward slash does not need to be escaped, and the escape character is “”).

Also, as a matter of style, HTTP/1.1 should be uppercase (not "Http).

ahhh ok, I thought c sharp escape character is ‘/’

so I’ve amended the code as follows


                if (radioManager.Connect(@ "www.google.com")) // add your server address
                {
                    // send data
                    string crlf = "" + (char)13 + (char)10;
                    String RequestString = "GET / HTTP/1.1"+crlf;
                    RequestString += "Host: www.google.com" +crlf + crlf;

still the same reponse though! mmmmmmmstumped

…many thanks for the tips, great suggestion

Have you tried using telnet to do it manually?
I can test for you tomorrow, when I’ve got the kit available.

I tried that, but bizzarely the new command window opened with black text on a black background, so I wasn’t able to see what the responses are doing (I’m running on win2k8 r2). Once I can sort that out i’ll certainly try telnet!