-
• #27
Oh... this is annoying. Which module do you exactly have? I have this one:
http://imall.iteadstudio.com/im140318007.html
This is pretty good.
-
• #28
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 :)
-
• #29
Hello all, I started writing a driver for the SIM900A today based on the ESP8266 driver.
- init is working
- connect is working
- getIP is working
- 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",'+JSON.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.length+'\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); }); }); }); }); });
- init is working
-
• #30
What get shown when you call
gprsFuncs.at.debug()
? From what I can see, it looks likeCIPSEND
behaves the same way whenCIPMUX=1
was used - which is was in your case. It's possible it doesn't like the newline after\r
though... It should returnSEND 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. -
• #31
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.length+'\r\n', 3000, cb); return sockSent[sckt]; }
-
• #32
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.length+'\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" >
-
• #33
You probably want to call
at.debug();
beforeCIPSTART
, 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 theCLOSED
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. -
• #34
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.pur3.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" >
-
• #35
I cannot see any "0, SEND OK" responses and I currently have no idea why.
-
• #36
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.
-
• #37
Hello again,
I tried it manually. When I wait for the "> " to appear, it works:
["AT+CIPSTART=0,\"TCP\",\"http://www.pur3.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
-
• #38
Ok, great! Yes, It's possible using
register
- I'll just try and come up with some code for you. -
• #39
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 newAT
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.length+'\r\n', 10000, f); return data.length; }
-
• #40
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.pur3.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" >
-
• #41
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
-
• #42
Ok, maybe try now - without the
\r\n>
? -
• #43
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.pur3.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-Ranges: bytes\r\nContent-Length: 13\r\nVary: Accept-Encoding\r\nC" <--- "15:42:26 GMT\r\nETag: \"c01036-d-4eb390b8a8d18\"\r\nAccept-Ranges: 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" >
-
• #44
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",'+JSON.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.length+'\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); }); }); }); }); });
-
• #45
I replaced +IPD by +RECEIVE and the Handler-Function is getting called. But no response is being shown in the HTTP lib
-
• #46
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 :(
-
• #47
Maybe take a look in the
socks
array and check that the socket's state isn'twait
or something. Also checksockData
array to see if the data is getting sent in there.If the
ipdHandler
/receiveHandler
is working ok the the data should all go intosockData
, and therecv
function is then responsible for giving that to Espruino.If you changed the text in
ipdHandler
, dod you changeline.substring(5,colon)
toline.substring(9,colon)
as well? That could be important... -
• #48
Did you get this working in the end?
-
• #49
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
-
• #50
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
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.