GPRS or Edge Howto?

Posted on
Page
of 4
Prev
/ 4
Last Next
  • Hmm - well that was a waste of a morning. Looks like my module is dead. It couldn't see any cell towers and it couldn't read the SIM card, even after a firmware update.

    I've just ordered a different SIM900 module, so hopefully I'll have more luck with that.

  • Oh... this is annoying. Which module do you exactly have? I have this one:

    http://imall.iteadstudio.com/im140318007­.html

    This is pretty good.

  • That one looks good - mine was a very cheap Chinese one off eBay. The simple way to check is to put a SIM card in, plug it into power, and then see if after a while the light goes from blinking every 0.8s to blinking every 3 sec. Mine never did :)

  • Hello all, I started writing a driver for the SIM900A today based on the ESP8266 driver.

    1. init is working
    2. connect is working
    3. getIP is working
    4. reset is just calling init currently because I didn't find a way to reset the SIM900 by using an AT-command (for ESP8266 there is AT+RST)

    I got stuck at sending a HTTP-Request through NetworkJS. What happens is, that the send-method is called over and over and after a few retries it stops. I can not see any response from the server currently. I assume that there are subtle differences in the use of the AT+CIPSEND command for ESP8266 and SIM900A. Any ideas?

    Here you find the code:

    Serial1.setup(115200, { rx: B7, tx : B6 });
    
    
    var at;
    var socks = [];
    var sockData = ["","","","",""];
    var MAXSOCKETS = 5;
    
    var netCallbacks = {
      create : function(host, port) {
        /* Create a socket and return its index, host is a string, port is an integer.
        If host isn't defined, create a server socket */  
        if (host===undefined) {
          sckt = MAXSOCKETS;
          socks[sckt] = "Wait";
          sockData[sckt] = "";
          at.cmd("AT+CIPSERVER=1,"+port+"\r\n", 10000, function(d) {
            if (d=="OK") {
              socks[sckt] = true;
            } else {
              socks[sckt] = undefined;
              throw new Error("CIPSERVER failed");
            }
          });
          return MAXSOCKETS;
        } else {
          var sckt = 0;
          while (socks[sckt]!==undefined) sckt++; // find free socket
          if (sckt>=MAXSOCKETS) throw new Error("No free sockets");
          socks[sckt] = "Wait";
          sockData[sckt] = "";
          at.cmd('AT+CIPSTART='+sckt+',"TCP",'+JSO­N.stringify(host)+','+port+'\r\n',10000,­ function(d) {
            if (d=="OK") {
              at.registerLine(sckt + ', CONNECT OK', function() {
                at.unregisterLine(sckt + ', CONNECT OK');
                socks[sckt] = true;
              });
              at.registerLine(sckt + ', CLOSED', function() {
                at.unregisterLine(sckt + ', CLOSED');
                socks[sckt] = undefined;
              });
            } else {
              socks[sckt] = undefined;
              throw new Error("CIPSTART failed");
            }
          });
        }
        return sckt;
      },
      /* Close the socket. returns nothing */
      close : function(sckt) {    
        at.cmd('AT+CIPCLOSE='+sckt+"\r\n",1000, function(/*d*/) {
          socks[sckt] = undefined;
          //console.log("?"+JSON.stringify(d));
        });
      },
      /* Accept the connection on the server socket. Returns socket number or -1 if no connection */
      accept : function(sckt) {
        // console.log("Accept",sckt);
        for (var i=0;i<MAXSOCKETS;i++)
          if (sockData[i] && socks[i]===undefined) {
            //console.log("Socket accept "+i,JSON.stringify(sockData[i]),socks[i]­);
            socks[i] = true;
            return i;
          }
        return -1;
      },
      /* Receive data. Returns a string (even if empty).
      If non-string returned, socket is then closed */
      recv : function(sckt, maxLen) {    
        if (at.isBusy() || socks[sckt]=="Wait") return "";
        if (sockData[sckt]) {
          var r;
          if (sockData[sckt].length > maxLen) {
            r = sockData[sckt].substr(0,maxLen);
            sockData[sckt] = sockData[sckt].substr(maxLen);
          } else {
            r = sockData[sckt];
            sockData[sckt] = "";
          }
          return r;
        }
        if (!socks[sckt]) return -1; // close it
        return "";
      },
      /* Send data. Returns the number of bytes sent - 0 is ok.
      Less than 0  */
      send : function(sckt, data) {
        console.log(data);
        if (at.isBusy() || socks[sckt]=="Wait") return 0;
        if (!socks[sckt]) return -1; // error - close it
        console.log("Send: " + data);
        var f = function(d) {
          // TODO: register for '>'
          //console.log("?"+JSON.stringify(d));
          if (d=="> ") {
            return f;
          }
        };
        at.cmd('AT+CIPSEND='+sckt+','+data.lengt­h+'\r\n' + data , 10000, f);
        return data.length;
      }
    };
    
    
    //Handle +IPD input data from SIM900A
    function ipdHandler(line) {
      var colon = line.indexOf(":");
      if (colon<0) return line; // not enough data here at the moment
      var parms = line.substring(5,colon).split(",");
      parms[1] = 0|parms[1];
      var len = line.length-(colon+1);
      if (len>=parms[1]) {
       // we have everything
       sockData[parms[0]] += line.substr(colon+1,parms[1]);
       return line.substr(colon+parms[1]+1); // return anything else
      } else { 
       // still some to get
       sockData[parms[0]] += line.substr(colon+1,len);
       return "+IPD,"+parms[0]+","+(parms[1]-len)+":";­ // return IPD so we get called next time    
      }
    }
    
    var gprsFuncs = {
      ipdHandler:ipdHandler,
      "debug" : function() {
        return {
          socks:socks,
          sockData:sockData
        };
      },
      // initialise the SIM900A
      "init" : function(callback) { 
        var s = 0;
        var cb = function(r) {
          console.log(r);
          switch(s) {
            case 0:
              if(r === 'ATE0' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 1;
                at.cmd('AT+CPIN?\r\n', 100, cb);
              }
              break;
            case 1:
              if(r === '+CPIN: READY' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 2;
                at.cmd('AT+CGATT?\r\n', 100, cb);
              }
              break;
            case 2:
              if(r === '+CGATT: 1' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 3;
                at.cmd('AT+CIPSHUT\r\n', 100, cb);
              }
              break;
            case 3:
              if(r === 'SHUT OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 4;
                at.cmd('AT+CIPSTATUS\r\n', 100, cb);
              }
              break;
            case 4:
              if(r === 'STATE: IP INITIAL' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 5;
                at.cmd('AT+CIPMUX=1\r\n', 100, cb);
              }
              break;
            case 5:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                callback(null);
              }
              break;
          }
          return cb;
        };
        at.cmd("ATE0\r\n",1000,cb);
      },
      "reset" : function(callback) {
        gprsFuncs.init(callback);
      },
      "getVersion" : function(callback) {
        at.cmd("AT+GMR\r\n", 1000, function(d) {
          callback(null,d);
        });
      },
      "connect" : function(apn, username, password, callback) {
        var s = 0;
        var cb = function(r) {
          switch(s) {
            case 0:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 1;
                at.cmd('AT+CIICR\r\n', 2000, cb);
              }
              break;
            case 1:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                callback(null);
              }
              break;
          }
        };
        at.cmd('AT+CSTT="' + apn + '", "' + username + '", "' + password + '"\r\n', 1000, cb);
      },
      "getIP" : function(callback) {
        var ip;
        var cb = function(r) {
          if(r && r != 'ERROR') {
            ip = r;
            return cb;
          } else if(r === 'ERROR') {
            callback('CIFSR Error');
          } else if(!r) {
            callback(null, ip);
          }
        };
        at.cmd('AT+CIFSR\r\n', 2000, cb);
      }
    };
    var connect = function(usart, connectedCallback) {
      gprsFuncs.at = at = require("AT").connect(usart);
      require("NetworkJS").create(netCallbacks­);
      at.register("+IPD", ipdHandler);
      gprsFuncs.reset(connectedCallback);
      return gprsFuncs;
    };
    
    connect(Serial1, function() {
      gprsFuncs.connect('pinternet.interkom.de­', '', '', function(err) {
        console.log(err);
        gprsFuncs.getIP(function(err, ip) {
          console.log('IP:' + ip);
          require("http").get("http://www.pur3.co.­uk/hello.txt", function(res) {
            console.log("Response: ",res);
            res.on('data', function(d) {
              console.log("--->"+d);
            });
          });
        });
      });
    });
    
  • What get shown when you call gprsFuncs.at.debug()? From what I can see, it looks like CIPSEND behaves the same way when CIPMUX=1 was used - which is was in your case. It's possible it doesn't like the newline after \r though... It should return SEND OK if all has gone well.

    It looks like it might just send back the result data without +IPD, which would make it harder for Espruino to get the data.

    I think you need to send the AT+CIPHEAD=1 command when initialising to make sure that +IPD gets prepended to any data.

  • I think the problem is within the AT lib. It just handles lines which end with \r\n. On the SIM900 you have to wait for "> " before sending the data after sending AT+CIPSEND=...

    The "> " is not ending with \r\n therefore it is not sent back to the callback provided to at.cmd()

    My send method currently looks like this:

      send : function(sckt, data) {
        if (at.isBusy() || socks[sckt]=="Wait" || sockBusy[sckt]) return 0;
        if (!socks[sckt]) return -1; // error - close it
        sockBusy[sckt] = true;
    
        var cb = function(r) {
          at.debug();
          console.log('-->' + JSON.stringify(r));
          return cb;
        };
        sockSent[sckt] += data.length;
        console.log('Send '+ data.length + ': ' + JSON.stringify(data));
        console.log('Total: ' + sockSent[sckt]);
        at.cmd('AT+CIPSEND='+sckt+','+data.lengt­h+'\r\n', 3000, cb);
        return sockSent[sckt];
      }
    
  • I added the CIPHEAD=1 setting to init and I took the send method of the ESP8266 driver now and I call at.debug() in the callback.

    It now looks like this:

      send : function(sckt, data) {
        if (at.isBusy() || socks[sckt]=="Wait") return 0;
        if (!socks[sckt]) return -1; // error - close it
        var f = function(d) {
          console.log(d);
          at.debug();
          if (d=="> ") return f;
        };
        at.cmd('AT+CIPSEND='+sckt+','+data.lengt­h+'\r\n'+data, 10000, f);
        return data.length;
      }
    

    The output is the following:

     _____                 _
    |   __|___ ___ ___ _ _|_|___ ___
    |   __|_ -| . |  _| | | |   | . |
    |_____|___|  _|_| |___|_|_|_|___|
              |_| http://espruino.com
     1v80 Copyright 2015 G.Williams
    >echo(0);
    =undefined
    null
    IP:10.54.158.176
    undefined
    ["AT+CIPSEND=0,31\r\nclose\r\nHost: http://www.pur3.co.uk\r\n\r\n"
    ] "> \r\n0" <--- "\r\n0"
    >
    ] "0, CLOSED\r\n\r\nERROR\r\n" <--- ", CLOSED\r\n\r\nERROR\r\n"
    ERROR
    ["AT+CIPCLOSE=0\r\n"
    ] "\r" <--- "\r"
    ] "\nERROR\r\n" <--- "\nERROR\r\n"
    > 
    
  • You probably want to call at.debug(); before CIPSTART, just so you can see what's being sent back a bit sooner.

    It looks to me like the CIPSEND command itself is working, but the connection has already been closed by the server - hence the CLOSED message?

    While the AT command module doesn't have an easy way to respond to just >, I don't think you have to worry. It basically always sends > so you can pretty much ignore having to wait for it and just keep sending data.

  • Hello again,

    the entire at.debug() trace is the following:

     _____                 _
    |   __|___ ___ ___ _ _|_|___ ___
    |   __|_ -| . |  _| | | |   | . |
    |_____|___|  _|_| |___|_|_|_|___|
              |_| http://espruino.com
     1v80 Copyright 2015 G.Williams
    >echo(0);
    =undefined
    ["AT+CPIN?\r\n"
    ] "\r" <--- "\r"
    ] "\n+CPIN: READY\r\n\r\nOK\r\n" <--- "\n+CPIN: READY\r\n\r\nOK\r\n"
    ["AT+CGATT?\r\n"
    ] "\r" <--- "\r"
    ] "\n+CGATT: 1\r\n\r\nOK\r\n" <--- "\n+CGATT: 1\r\n\r\nOK\r\n"
    ["AT+CIPSHUT\r\n"
    ] "\r" <--- "\r"
    ] "\nSHUT OK\r\n" <--- "\nSHUT OK\r\n"
    ["AT+CIPSTATUS\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n\r\nSTATE: IP INITIAL\r\n" <--- "\nOK\r\n\r\nSTATE: IP INITIAL\r\n"
    ["AT+CIPMUX=1\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CIPHEAD=1\r\n"
    ] "\r\n" <--- "\r\n"
    ] "OK\r\n" <--- "OK\r\n"
    ["AT+CSTT=\"pinternet.interkom.de\", \"\", \"\"\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CIICR\r\n"
    ] "\r\n" <--- "\r\n"
    ] "OK\r\n" <--- "OK\r\n"
    null
    ["AT+CIFSR\r\n"
    ] "\r" <--- "\r"
    ] "\n10.50.96.30\r\n" <--- "\n10.50.96.30\r\n"
    IP:10.50.96.30
    ["AT+CIPSTART=0,\"TCP\",\"http://www.pur­3.co.uk\",80\r\n"
    ] "\r\nOK\r\n" <--- "\r\nOK\r\n"
    ] "\r\n0" <--- "\r\n0"
    ] "0, CONNECT OK\r\n" <--- ", CONNECT OK\r\n"
    ["AT+CIPSEND=0,64\r\nGET /hello.txt HTTP/1.0\r\nUser-Agent: Espruino 1v80\r\nConnection: "
    ] "\r\n> " <--- "\r\n> "
    ["AAT+CIPSEND=0,31\r\nclose\r\nHost: http://www.pur3.co.uk\r\n\r\n"
    ] "> \r\n0, CLOSE" <--- "\r\n0, CLOSE"
    ] "0, CLOSED\r\n\r\nERROR\r\n" <--- "D\r\n\r\nERROR\r\n"
    ["AT+CIPCLOSE=0\r\n"
    ] "\r\n" <--- "\r\n"
    ] "ERROR\r\n" <--- "ERROR\r\n"
    >
    
  • I cannot see any "0, SEND OK" responses and I currently have no idea why.

  • Thanks - as you say, no response even to the first CIPSEND.

    Have you tried just sending the CIPSEND command manually and seeing if you can get it to go sending something simple? It might be it wants a newline after the text that's sent?

    The other option is to go for Ctrl+Z terminated mode:

      send : function(sckt, data) {
        if (at.isBusy() || socks[sckt]=="Wait") return 0;
        if (!socks[sckt]) return -1; // error - close it
        var f = function(d) {
          if (d=="> ") return f;
        };
        at.cmd('AT+CIPSEND='+sckt+'\r\n'+data+"\­x1A"/*ctrl+z*/, 10000, f);
        return data.length;
      }
    

    That'd be easier but will cause you problems if you want to send binary data.

  • Hello again,

    I tried it manually. When I wait for the "> " to appear, it works:

    ["AT+CIPSTART=0,\"TCP\",\"http://www.pur­3.co.uk\",80\r\n"
    =0
    ] "\r\n" <--- "\r\n"
    ] "OK\r\n" <--- "OK\r\n"
    ] "\r" <--- "\r"
    ] "\n0, CONNECT OK\r\n" <--- "\n0, CONNECT OK\r\n"
    >at.cmd('AT+CIPSEND=0,5\r\n');
    ["AT+CIPSEND=0,5\r\n"
    =undefined
    ] "\r" <--- "\r"
    ] "\n> " <--- "\n> "
    >at.cmd('HELLO');
    ["HELLO"
    =undefined
    ] "> \r" <--- "\r"
    ] "\n0, SEND OK\r\n" <--- "\n0, SEND OK\r\n"
    ] "\r" <--- "\r"
    ] "\n0, CLOSED\r\n" <--- "\n0, CLOSED\r\n"
    

    Do you have an idea how I can wait for "> " using the AT-lib?

    Best,

    Tobias

  • Ok, great! Yes, It's possible using register - I'll just try and come up with some code for you.

  • Ok, turns out there's a very annoying bug in the interpreter! > is used as a character that prefixes internal variables that users don't want to see, and it means it gets ignored when it's in an array. I've just pushed out a new AT module with a workaround in.

    Try:

    send : function(sckt, data) {
        if (at.isBusy() || socks[sckt]=="Wait") return 0;
        if (!socks[sckt]) return -1; // error - close it
        var f = function(d) {
          at.unregister(">");
          if (d!="SEND OK") console.log("Send got: "+d);
        };
        at.register(">", function() {
          at.write(data);
          return "";
        });
        at.cmd('AT+CIPSEND='+sckt+','+data.lengt­h+'\r\n', 10000, f);
        return data.length;
      }
    
  • Thank you Gordon. I tried it, but it doesn't work for me :(

    ["AT+CPIN?\r\n"
    ] "\r" <--- "\r"
    ] "\n+CPIN: READY\r\n\r\nOK\r\n" <--- "\n+CPIN: READY\r\n\r\nOK\r\n"
    ["AT+CGATT?\r\n"
    ] "\r" <--- "\r"
    ] "\n+CGATT: 1\r\n\r\nOK\r\n" <--- "\n+CGATT: 1\r\n\r\nOK\r\n"
    ["AT+CIPSHUT\r\n"
    ] "\r" <--- "\r"
    ] "\nSHUT OK\r\n" <--- "\nSHUT OK\r\n"
    ["AT+CIPSTATUS\r\n"
    ] "\r\n" <--- "\r\n"
    ] "OK\r\n\r\nSTATE: IP INITIAL\r\n" <--- "OK\r\n\r\nSTATE: IP INITIAL\r\n"
    ["AT+CIPMUX=1\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CIPHEAD=1\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CSTT=\"pinternet.interkom.de\", \"\", \"\"\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CIICR\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    null
    ["AT+CIFSR\r\n"
    ] "\r" <--- "\r"
    ] "\n10.37.76.134\r\n" <--- "\n10.37.76.134\r\n"
    IP:10.37.76.134
    ["AT+CIPSTART=0,\"TCP\",\"http://www.pur­3.co.uk\",80\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ] "\r\n0, CONNECT O" <--- "\r\n0, CONNECT O"
    ] "0, CONNECT OK\r\n" <--- "K\r\n"
    ["AT+CIPSEND=0,64\r\n"
    ] "\r\n> " <--- "\r\n> "
    Send got: undefined
    ["AT+CIPSEND=0,31\r\n"
    ] "> \r\n" <--- "\r\n"
    ] "0, CLOSED\r\n\r\nERROR\r\n" <--- "0, CLOSED\r\n\r\nERROR\r\n"
    Send got: ERROR
    ["AT+CIPCLOSE=0\r\n"
    ] "\r\n" <--- "\r\n"
    ] "ERROR\r\n" <--- "ERROR\r\n"
    > 
    
  • Can you add some debug code to make sure the register(">" handler is getting called?

    It looks possible it's getting confused by the leading newlines. You could hack it in for now by changing the line to:

    at.register("\r\n>", function() {
    

    I'll see about modifying the AT command thing a bit more

  • Ok, maybe try now - without the \r\n>?

  • Great to see good progress :)

    I should react somewhere to "0, CLOSE". What I do not see currently is that the responses which are coming in are sent back to the HTTP-Lib.

     _____                 _
    |   __|___ ___ ___ _ _|_|___ ___
    |   __|_ -| . |  _| | | |   | . |
    |_____|___|  _|_| |___|_|_|_|___|
              |_| http://espruino.com
     1v80 Copyright 2015 G.Williams
    >echo(0);
    =undefined
    ["AT+CPIN?\r\n"
    ] "\r" <--- "\r"
    ] "\n+CPIN: READY\r\n\r\nOK\r\n" <--- "\n+CPIN: READY\r\n\r\nOK\r\n"
    ["AT+CGATT?\r\n"
    ] "\r" <--- "\r"
    ] "\n+CGATT: 1\r\n\r\nOK\r\n" <--- "\n+CGATT: 1\r\n\r\nOK\r\n"
    ["AT+CIPSHUT\r\n"
    ] "\r" <--- "\r"
    ] "\nSHUT OK\r\n" <--- "\nSHUT OK\r\n"
    ["AT+CIPSTATUS\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n\r\nSTATE: IP INITIAL\r\n" <--- "\nOK\r\n\r\nSTATE: IP INITIAL\r\n"
    ["AT+CIPMUX=1\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CIPHEAD=1\r\n"
    ] "\r\n" <--- "\r\n"
    ] "OK\r\n" <--- "OK\r\n"
    ["AT+CSTT=\"pinternet.interkom.@\ üÍ ñÿÿ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    ["AT+CIICR\r\n"
    ] "\r" <--- "\r"
    ] "\nOK\r\n" <--- "\nOK\r\n"
    null
    ["AT+CIFSR\r\n"
    ] "\r\n" <--- "\r\n"
    ] "10.49.128.77\r\n" <--- "10.49.128.77\r\n"
    IP::10.49.128.77
    ["AT+CIPSTART=0,\"TCP\",\"http://www.pur­3.co.uk\",80\r\n"
    ] "\r\nOK\r\n" <--- "\r\nOK\r\n"
    ] "\r\n0, CONN" <--- "\r\n0, CONN"
    ] "0, CONNECT OK\r\n" <--- "ECT OK\r\n"
    ["AT+CIPSEND=0,64\r\n"
    ] "\r\n> " <--- "\r\n> "
    ] "\r\n0, SEND OK\r\n" <--- "\r\n0, SEND OK\r\n"
    Send got: 0, SEND OK
    ["AT+CIPSEND=0,31\r\n"
    ] "\r\n" <--- "\r\n"
    ] "> " <--- "> "
    ] "\r\n0," <--- "\r\n0,"
    ] "0, SEND OK\r\n" <--- " SEND OK\r\n"
    Send got: 0, SEND OK
    ] "\r\n+RECEIVE," <--- "\r\n+RECEIVE,"
    ] "+RECEIVE,0,289:\r\nHTTP/1.1 200 OK\r\nDate: Tue, 02 Jun" <--- "0,289:\r\nHTTP/1.1 200 OK\r\nDate: Tue, 02 Jun"
    ] "Date: Tue, 02 Jun 2015 14:39:12 GMT\r\nServer: Apache/2.2.14 (Ubuntu)\r\nLast-Modified: Fri, 15 Nov 2013 " <--- " 2015 14:39:12 GMT\r\nServer: Apache/2.2.14 (Ubuntu)\r\nLast-Modified: Fri, 15 Nov 2013 "
    ] "Last-Modified: Fri, 15 Nov 2013 15:42:26 GMT\r\nETag: \"c01036-d-4eb390b8a8d18\"\r\nAccept-Ran­ges: bytes\r\nContent-Length: 13\r\nVary: Accept-Encoding\r\nC" <--- "15:42:26 GMT\r\nETag: \"c01036-d-4eb390b8a8d18\"\r\nAccept-Ran­ges: bytes\r\nContent-Length: 13\r\nVary: Accept-Encoding\r\nC"
    ] "Connection: close\r\nContent-Type: text/plain\r\n\r\nHello World!\n" <--- "onnection: close\r\nContent-Type: text/plain\r\n\r\nHello World!\n"
    ] "Hello World!\n\r\n0" <--- "\r\n0"
    ] "0, CLOSED\r\n" <--- ", CLOSED\r\n"
    ["AT+CIPCLOSE=0\r\n"
    ] "\r\n" <--- "\r\n"
    ] "ERROR\r\n" <--- "ERROR\r\n"
    > 
    
  • Closing is as well now working well. Do you have an idea why the response doesn't show up in the HTTP lib?

    Here is the entire code:

    Serial1.setup(115200, { rx: B7, tx : B6 });
    
    
    var at;
    var socks = [];
    var sockData = ["","","","",""];
    
    var MAXSOCKETS = 5;
    
    var netCallbacks = {
      create : function(host, port) {
        /* Create a socket and return its index, host is a string, port is an integer.
        If host isn't defined, create a server socket */  
        if (host===undefined) {
          sckt = MAXSOCKETS;
          socks[sckt] = "Wait";
          sockData[sckt] = "";
          at.cmd("AT+CIPSERVER=1,"+port+"\r\n", 10000, function(d) {
            if (d=="OK") {
              socks[sckt] = true;
            } else {
              socks[sckt] = undefined;
              throw new Error("CIPSERVER failed");
            }
          });
          return MAXSOCKETS;
        } else {
          var sckt = 0;
          while (socks[sckt]!==undefined) sckt++; // find free socket
          if (sckt>=MAXSOCKETS) throw new Error("No free sockets");
          socks[sckt] = "Wait";
          sockData[sckt] = "";
          at.cmd('AT+CIPSTART='+sckt+',"TCP",'+JSO­N.stringify(host)+','+port+'\r\n',10000,­ function(d) {
            at.debug();
            if (d=="OK") {
              at.registerLine(sckt + ', CONNECT OK', function() {
                at.unregisterLine(sckt + ', CONNECT OK');
                socks[sckt] = true;
              });
              at.registerLine(sckt + ', CLOSED', function() {
                at.unregisterLine(sckt + ', CLOSED');
                socks[sckt] = undefined;
              });
            } else {
              socks[sckt] = undefined;
              throw new Error("CIPSTART failed");
            }
          });
        }
        return sckt;
      },
      /* Close the socket. returns nothing */
      close : function(sckt) {
        if(socks[sckt]) {
          at.cmd('AT+CIPCLOSE='+sckt+"\r\n",1000, function(/*d*/) {
          socks[sckt] = undefined;
          });
        }
      },
      /* Accept the connection on the server socket. Returns socket number or -1 if no connection */
      accept : function(sckt) {
        // console.log("Accept",sckt);
        for (var i=0;i<MAXSOCKETS;i++)
          if (sockData[i] && socks[i]===undefined) {
            //console.log("Socket accept "+i,JSON.stringify(sockData[i]),socks[i]­);
            socks[i] = true;
            return i;
          }
        return -1;
      },
      /* Receive data. Returns a string (even if empty).
      If non-string returned, socket is then closed */
      recv : function(sckt, maxLen) {
        if (at.isBusy() || socks[sckt]=="Wait") return "";
        if (sockData[sckt]) {
          var r;
          if (sockData[sckt].length > maxLen) {
            r = sockData[sckt].substr(0,maxLen);
            sockData[sckt] = sockData[sckt].substr(maxLen);
          } else {
            r = sockData[sckt];
            sockData[sckt] = "";
          }
          return r;
        }
        if (!socks[sckt]) return -1; // close it
        return "";
      },
      /* Send data. Returns the number of bytes sent - 0 is ok.
      Less than 0  */
      send : function(sckt, data) {
        if (at.isBusy() || socks[sckt]=="Wait") return 0;
        if (!socks[sckt]) return -1; // error - close it
        var f = function(d) {
          at.unregister(">");
          if (d!="SEND OK") console.log("Send got: "+d);
        };
        at.register(">", function() {
          at.write(data);
          return "";
        });
        at.cmd('AT+CIPSEND='+sckt+','+data.lengt­h+'\r\n', 10000, f);
        return data.length;
      }
    };
    
    
    //Handle +IPD input data from SIM900A
    function ipdHandler(line) {
      var colon = line.indexOf(":");
      if (colon<0) return line; // not enough data here at the moment
      var parms = line.substring(5,colon).split(",");
      parms[1] = 0|parms[1];
      var len = line.length-(colon+1);
      if (len>=parms[1]) {
       // we have everything
       sockData[parms[0]] += line.substr(colon+1,parms[1]);
       return line.substr(colon+parms[1]+1); // return anything else
      } else { 
       // still some to get
       sockData[parms[0]] += line.substr(colon+1,len);
       return "+IPD,"+parms[0]+","+(parms[1]-len)+":";­ // return IPD so we get called next time    
      }
    }
    
    var gprsFuncs = {
      ipdHandler:ipdHandler,
      "debug" : function() {
        return {
          socks:socks,
          sockData:sockData
        };
      },
      // initialise the SIM900A
      "init" : function(callback) {
        var s = 0;
        var cb = function(r) {
          at.debug();
          switch(s) {
            case 0:
              if(r === 'ATE0' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 1;
                at.cmd('AT+CPIN?\r\n', 100, cb);
              }
              break;
            case 1:
              if(r === '+CPIN: READY' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 2;
                at.cmd('AT+CGATT?\r\n', 100, cb);
              }
              break;
            case 2:
              if(r === '+CGATT: 1' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 3;
                at.cmd('AT+CIPSHUT\r\n', 100, cb);
              }
              break;
            case 3:
              if(r === 'SHUT OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 4;
                at.cmd('AT+CIPSTATUS\r\n', 100, cb);
              }
              break;
            case 4:
              if(r === 'STATE: IP INITIAL' || r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 5;
                at.cmd('AT+CIPMUX=1\r\n', 100, cb);
              }
              break;
            case 5:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 6;
                at.cmd('AT+CIPHEAD=1\r\n', 100, cb);
              }
              break;
            case 6:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                callback(null);
              }
              break;
          }
        };
        at.cmd("ATE0\r\n",1000,cb);
      },
      "reset" : function(callback) {
        gprsFuncs.init(callback);
      },
      "getVersion" : function(callback) {
        at.cmd("AT+GMR\r\n", 1000, function(d) {
          callback(null,d);
        });
      },
      "connect" : function(apn, username, password, callback) {
        var s = 0;
        var cb = function(r) {
          switch(s) {
            case 0:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                s = 1;
                at.cmd('AT+CIICR\r\n', 2000, cb);
              }
              break;
            case 1:
              if(r === 'OK') return cb;
              else if(r) {
                callback('Error in ' + s + ': ' + r);
              } else {
                callback(null);
              }
              break;
          }
        };
        at.cmd('AT+CSTT="' + apn + '", "' + username + '", "' + password + '"\r\n', 1000, cb);
      },
      "getIP" : function(callback) {
        var ip;
        var cb = function(r) {
          if(r && r != 'ERROR') {
            ip = r;
            return cb;
          } else if(r === 'ERROR') {
            callback('CIFSR Error');
          } else if(!r) {
            callback(null, ip);
          }
        };
        at.cmd('AT+CIFSR\r\n', 2000, cb);
      }
    };
    var connect = function(usart, connectedCallback) {
      gprsFuncs.at = at = require("AT").connect(usart);
      require("NetworkJS").create(netCallbacks­);
      at.register("+IPD", ipdHandler);
      gprsFuncs.reset(connectedCallback);
      return gprsFuncs;
    };
    
    connect(Serial1, function() {
      gprsFuncs.connect('pinternet.interkom.de­', '', '', function(err) {
        console.log(err);
        gprsFuncs.getIP(function(err, ip) {
          console.log('IP:' + ip);
          require("http").get("http://www.pur3.co.­uk/hello.txt", function(res) {
            console.log("Response: ",res);
            res.on('data', function(d) {
              console.log("--->"+d);
            });
          });
        });
      });
    });
    
  • I replaced +IPD by +RECEIVE and the Handler-Function is getting called. But no response is being shown in the HTTP lib

  • Great! The response is coming back prefixed with +RECEIVE, not +IPD. Seems odd (I'd expected IPD after the call to CIPHEAD), but it can be changed easily...

    // Instead of ipdHandler:
    
    //Handle +RECEIVE input data from SIM900A
    function receiveHandler(line) {
      var colon = line.indexOf(":");
      if (colon<0) return line; // not enough data here at the moment
      var parms = line.substring(9,colon).split(",");
      parms[1] = 0|parms[1];
      var len = line.length-(colon+1);
      if (len>=parms[1]) {
       // we have everything
       sockData[parms[0]] += line.substr(colon+1,parms[1]);
       return line.substr(colon+parms[1]+1); // return anything else
      } else { 
       // still some to get
       sockData[parms[0]] += line.substr(colon+1,len);
       return "+RECEIVE,"+parms[0]+","+(parms[1]-len)+­":"; // return RECEIVE so we get called next time    
      }
    }
    
    // ...
    
    
    var connect = function(usart, connectedCallback) {
      gprsFuncs.at = at = require("AT").connect(usart);
      require("NetworkJS").create(netCallbacks­);
      at.register("+RECEIVE", receiveHandler); // <----------------------------
      gprsFuncs.reset(connectedCallback);
      return gprsFuncs;
    };
    
    

    Sorry for not getting this sorted for you last time - I've been a bit busy. I did buy the second GPRS module, from a UK seller, but I still wasn't getting a mobile connection so couldn't get anything working :(

  • Maybe take a look in the socks array and check that the socket's state isn't wait or something. Also check sockData array to see if the data is getting sent in there.

    If the ipdHandler/receiveHandler is working ok the the data should all go into sockData, and the recv function is then responsible for giving that to Espruino.

    If you changed the text in ipdHandler, dod you change line.substring(5,colon) to line.substring(9,colon) as well? That could be important...

  • Did you get this working in the end?

  • Hi Gordon,

    I am currently testing the driver in my project. When everything is working fine, I'll send you the code of it, so you can publish it as module here, if you like.

    Best,

    Tobias

  • Hello Gordon,

    I tested the driver again. I currently have the issue that the http status code is not correctly read by the HTTP lib on close. What I get on a HTTP-Request in res.statusCode is the String "\nHTTP/1.1". Is this a problem with with receiveHandler-Function?

    Best,

    Tobias

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

GPRS or Edge Howto?

Posted by Avatar for fobus @fobus

Actions