From b196746fc07e13db9e57eab6ff7e64cc552edfad Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Thu, 6 Apr 2017 13:12:09 -0400 Subject: [PATCH] Restructured to bring similar functions together --- TinyGsmClientA6.h | 233 ++++++++++++++------------- TinyGsmClientESP8266.h | 91 +++++------ TinyGsmClientM590.h | 257 +++++++++++++++-------------- TinyGsmClientSIM800.h | 356 ++++++++++++++++++++--------------------- library.json | 2 +- library.properties | 2 +- 6 files changed, 488 insertions(+), 453 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 4972a54..3d2bef8 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -238,9 +238,8 @@ public: if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { return ""; } - String res = stream.readStringUntil('\n'); + String res = streamReadUntil('\n'); waitResponse(); - res.trim(); return res; } @@ -249,9 +248,8 @@ public: if (waitResponse(GF(GSM_NL)) != 1) { return ""; } - String res = stream.readStringUntil('\n'); + String res = streamReadUntil('\n'); waitResponse(); - res.trim(); return res; } @@ -260,38 +258,11 @@ public: if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { return 99; } - int res = stream.readStringUntil(',').toInt(); + int res = streamReadUntil(',').toInt(); waitResponse(); return res; } - bool callAnswer() { - sendAT(GF("A")); - return waitResponse() == 1; - } - - bool callNumber(const String& number) { - sendAT(GF("D"), number); - return waitResponse() == 1; - } - - bool callHangup(const String& number) { - sendAT(GF("H"), number); - return waitResponse() == 1; - } - - bool sendSMS(const String& number, const String& text) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - stream.print(text); - stream.write((char)0x1A); - return waitResponse(60000L) == 1; - } - SimStatus getSimStatus(unsigned long timeout = 10000L) { for (unsigned long start = millis(); millis() - start < timeout; ) { sendAT(GF("+CPIN?")); @@ -317,7 +288,7 @@ public: return REG_UNKNOWN; } streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); + int status = streamReadUntil('\n').toInt(); waitResponse(); return (RegStatus)status; } @@ -328,7 +299,7 @@ public: return ""; } streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); + String res = streamReadUntil('"'); waitResponse(); return res; } @@ -338,8 +309,6 @@ public: RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) { return true; - } else if (s == REG_UNREGISTERED) { - return false; } delay(1000); } @@ -393,6 +362,21 @@ public: * Phone Call functions */ + bool callAnswer() { + sendAT(GF("A")); + return waitResponse() == 1; + } + + bool callNumber(const String& number) { + sendAT(GF("D"), number); + return waitResponse() == 1; + } + + bool callHangup(const String& number) { + sendAT(GF("H"), number); + return waitResponse() == 1; + } + /* * Messaging functions */ @@ -403,6 +387,18 @@ public: void sendSMS() { } + bool sendSMS(const String& number, const String& text) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CMGS=\""), number, GF("\"")); + if (waitResponse(GF(">")) != 1) { + return false; + } + stream.print(text); + stream.write((char)0x1A); + return waitResponse(60000L) == 1; + } + /* * Location functions */ @@ -413,76 +409,13 @@ public: * Battery functions */ -private: - int modemConnect(const char* host, uint16_t port, uint8_t* mux) { - sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port); - - if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { - return -1; - } - int newMux = stream.readStringUntil('\n').toInt(); - - int rsp = waitResponse(75000L, - GF("CONNECT OK" GSM_NL), - GF("CONNECT FAIL" GSM_NL), - GF("ALREADY CONNECT" GSM_NL)); - if (waitResponse() != 1) { - return -1; - } - *mux = newMux; - - return (1 == rsp); - } - - int modemSend(const void* buff, size_t len, uint8_t mux) { - sendAT(GF("+CIPSEND="), mux, ',', len); - if (waitResponse(10000L, GF(GSM_NL ">")) != 1) { - return -1; - } - stream.write((uint8_t*)buff, len); - stream.flush(); - if (waitResponse(10000L, GFP(GSM_OK), GF(GSM_NL "FAIL")) != 1) { - return -1; - } - return len; - } - - bool modemGetConnected(uint8_t mux) { //TODO mux? - sendAT(GF("+CIPSTATUS")); - int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); - waitResponse(); - return 1 == res; - } - - /* Utilities */ - template - void streamWrite(T last) { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) { - stream.print(head); - streamWrite(tail...); - } - - int streamRead() { return stream.read(); } - - bool streamSkipUntil(char c) { //TODO: timeout - while (true) { - while (!stream.available()) {} - if (stream.read() == c) - return true; - } - return false; - } - + /* Public Utilities */ template void sendAT(Args... cmd) { streamWrite("AT", cmd..., GSM_NL); stream.flush(); TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); + DBG(GSM_NL, ">>> AT:", cmd...); } // TODO: Optimize this! @@ -521,8 +454,8 @@ private: index = 5; goto finish; } else if (data.endsWith(GF("+CIPRCV:"))) { - int mux = stream.readStringUntil(',').toInt(); - int len = stream.readStringUntil(',').toInt(); + int mux = streamReadUntil(',').toInt(); + int len = streamReadUntil(',').toInt(); if (len > sockets[mux]->rx.free()) { DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); } else { @@ -535,14 +468,14 @@ private: data = ""; return index; } else if (data.endsWith(GF("+TCPCLOSED:"))) { - int mux = stream.readStringUntil(',').toInt(); - stream.readStringUntil('\n'); - sockets[mux]->sock_connected = false; - data = ""; + int mux = streamReadUntil(',').toInt(); + streamReadUntil('\n'); + sockets[mux]->sock_connected = false; + data = ""; } } } while (millis() - startMillis < timeout); -finish: + finish: if (!index) { data.trim(); if (data.length()) { @@ -550,6 +483,15 @@ finish: } data = ""; } + else { + data.trim(); + data.replace(GSM_NL GSM_NL, GSM_NL); + data.replace(GSM_NL, GSM_NL " "); + if (data.length()) { + DBG(GSM_NL, "<<< ", data); + } + data = ""; + } return index; } @@ -567,6 +509,81 @@ finish: return waitResponse(1000, r1, r2, r3, r4, r5); } +private: + int modemConnect(const char* host, uint16_t port, uint8_t* mux) { + sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port); + + if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { + return -1; + } + int newMux = streamReadUntil('\n').toInt(); + + int rsp = waitResponse(75000L, + GF("CONNECT OK" GSM_NL), + GF("CONNECT FAIL" GSM_NL), + GF("ALREADY CONNECT" GSM_NL)); + if (waitResponse() != 1) { + return -1; + } + *mux = newMux; + + return (1 == rsp); + } + + int modemSend(const void* buff, size_t len, uint8_t mux) { + sendAT(GF("+CIPSEND="), mux, ',', len); + if (waitResponse(10000L, GF(GSM_NL ">")) != 1) { + return -1; + } + stream.write((uint8_t*)buff, len); + stream.flush(); + if (waitResponse(10000L, GFP(GSM_OK), GF(GSM_NL "FAIL")) != 1) { + return -1; + } + return len; + } + + bool modemGetConnected(uint8_t mux) { //TODO mux? + sendAT(GF("+CIPSTATUS")); + int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); + waitResponse(); + return 1 == res; + } + + /* Private Utilities */ + template + void streamWrite(T last) { + stream.print(last); + } + + template + void streamWrite(T head, Args... tail) { + stream.print(head); + streamWrite(tail...); + } + + int streamRead() { return stream.read(); } + + String streamReadUntil(char c) { + String return_string = stream.readStringUntil(c); + return_string.trim(); + if (String(c) == GSM_NL || String(c) == "\n"){ + DBG(return_string, c, " "); + } else DBG(return_string, c); + return return_string; + } + + bool streamSkipUntil(char c) { //TODO: timeout + String skipped = stream.readStringUntil(c); + skipped.trim(); + if (skipped.length()) { + if (String(c) == GSM_NL || String(c) == "\n"){ + DBG(skipped, c, " "); + } else DBG(skipped, c); + return true; + } else return false; + } + private: Stream& stream; GsmClient* sockets[8]; diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index a3c3b4e..7d51d5a 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -233,55 +233,13 @@ public: return waitResponse(10000L) == 1; } -private: - int modemConnect(const char* host, uint16_t port, uint8_t mux) { - sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",120")); - int rsp = waitResponse(75000L, - GFP(GSM_OK), - GFP(GSM_ERROR), - GF(GSM_NL "ALREADY CONNECT" GSM_NL)); - return (1 == rsp); - } - - int modemSend(const void* buff, size_t len, uint8_t mux) { - sendAT(GF("+CIPSEND="), mux, ',', len); - if (waitResponse(GF(">")) != 1) { - return -1; - } - stream.write((uint8_t*)buff, len); - if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) { - return -1; - } - return len; - } - - bool modemGetConnected(uint8_t mux) { - sendAT(GF("+CIPSTATUS="), mux); - int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); - waitResponse(); - return 1 == res; - } - - /* Utilities */ - template - void streamWrite(T last) { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) { - stream.print(head); - streamWrite(tail...); - } - - int streamRead() { return stream.read(); } - + /* Public Utilities */ template void sendAT(Args... cmd) { streamWrite("AT", cmd..., GSM_NL); stream.flush(); TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); + DBG(GSM_NL, ">>> AT:", cmd...); } // TODO: Optimize this! @@ -339,7 +297,7 @@ private: } } } while (millis() - startMillis < timeout); -finish: + finish: if (!index) { data.trim(); if (data.length()) { @@ -364,6 +322,49 @@ finish: return waitResponse(1000, r1, r2, r3, r4, r5); } +private: + int modemConnect(const char* host, uint16_t port, uint8_t mux) { + sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",120")); + int rsp = waitResponse(75000L, + GFP(GSM_OK), + GFP(GSM_ERROR), + GF(GSM_NL "ALREADY CONNECT" GSM_NL)); + return (1 == rsp); + } + + int modemSend(const void* buff, size_t len, uint8_t mux) { + sendAT(GF("+CIPSEND="), mux, ',', len); + if (waitResponse(GF(">")) != 1) { + return -1; + } + stream.write((uint8_t*)buff, len); + if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) { + return -1; + } + return len; + } + + bool modemGetConnected(uint8_t mux) { + sendAT(GF("+CIPSTATUS="), mux); + int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); + waitResponse(); + return 1 == res; + } + + /* Private Utilities */ + template + void streamWrite(T last) { + stream.print(last); + } + + template + void streamWrite(T head, Args... tail) { + stream.print(head); + streamWrite(tail...); + } + + int streamRead() { return stream.read(); } + private: Stream& stream; GsmClient* sockets[5]; diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 6c4513a..81a72a9 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -247,9 +247,8 @@ public: if (waitResponse(GF(GSM_NL "+CCID:")) != 1) { return ""; } - String res = stream.readStringUntil('\n'); + String res = streamReadUntil('\n'); waitResponse(); - res.trim(); return res; } @@ -258,9 +257,8 @@ public: if (waitResponse(GF(GSM_NL)) != 1) { return ""; } - String res = stream.readStringUntil('\n'); + String res = streamReadUntil('\n'); waitResponse(); - res.trim(); return res; } @@ -269,38 +267,11 @@ public: if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { return 99; } - int res = stream.readStringUntil(',').toInt(); + int res = streamReadUntil(',').toInt(); waitResponse(); return res; } - bool callAnswer() { - sendAT(GF("A")); - return waitResponse() == 1; - } - - bool callNumber(const String& number) { - sendAT(GF("D"), number); - return waitResponse() == 1; - } - - bool callHangup(const String& number) { - sendAT(GF("H"), number); - return waitResponse() == 1; - } - - bool sendSMS(const String& number, const String& text) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - stream.print(text); - stream.write((char)0x1A); - return waitResponse(60000L) == 1; - } - SimStatus getSimStatus(unsigned long timeout = 10000L) { for (unsigned long start = millis(); millis() - start < timeout; ) { sendAT(GF("+CPIN?")); @@ -326,7 +297,7 @@ public: return REG_UNKNOWN; } streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); + int status = streamReadUntil('\n').toInt(); waitResponse(); return (RegStatus)status; } @@ -337,7 +308,7 @@ public: return ""; } streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); + String res = streamReadUntil('"'); waitResponse(); return res; } @@ -347,8 +318,6 @@ public: RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) { return true; - } else if (s == REG_UNREGISTERED) { - return false; } delay(1000); } @@ -400,110 +369,60 @@ public: * Phone Call functions */ - /* - * Messaging functions - */ - - void sendUSSD() { + bool callAnswer() { + sendAT(GF("A")); + return waitResponse() == 1; } - void sendSMS() { + bool callNumber(const String& number) { + sendAT(GF("D"), number); + return waitResponse() == 1; } - /* - * Location functions - */ - void getLocation() { + bool callHangup(const String& number) { + sendAT(GF("H"), number); + return waitResponse() == 1; } /* - * Battery functions + * Messaging functions */ -private: - String dnsIpQuery(const char* host) { - sendAT(GF("+DNS=\""), host, GF("\"")); - if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(GF("+DNS:OK" GSM_NL)); - res.trim(); - return res; + void sendUSSD() { } - int modemConnect(const char* host, uint16_t port, uint8_t mux) { - int rsp = 0; - for (int i=0; i<3; i++) { - String ip = dnsIpQuery(host); - - sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); - int rsp = waitResponse(75000L, - GF(",OK" GSM_NL), - GF(",FAIL" GSM_NL), - GF("+TCPSETUP:Error" GSM_NL)); - if (1 == rsp) { - return true; - } else if (3 == rsp) { - sendAT(GF("+TCPCLOSE="), mux); - waitResponse(); - } - delay(1000); - } - return false; + void sendSMS() { } - int modemSend(const void* buff, size_t len, uint8_t mux) { - sendAT(GF("+TCPSEND="), mux, ',', len); + bool sendSMS(const String& number, const String& text) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CMGS=\""), number, GF("\"")); if (waitResponse(GF(">")) != 1) { - return 0; - } - stream.write((uint8_t*)buff, len); - stream.write((char)0x0D); - - if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { - return 0; + return false; } - stream.readStringUntil('\n'); - return len; - } - - bool modemGetConnected(uint8_t mux) { - sendAT(GF("+CIPSTATUS="), mux); - int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); - waitResponse(); - return 1 == res; - } - - /* Utilities */ - template - void streamWrite(T last) { - stream.print(last); + stream.print(text); + stream.write((char)0x1A); + return waitResponse(60000L) == 1; } - template - void streamWrite(T head, Args... tail) { - stream.print(head); - streamWrite(tail...); + /* + * Location functions + */ + void getLocation() { } - int streamRead() { return stream.read(); } - - bool streamSkipUntil(char c) { //TODO: timeout - while (true) { - while (!stream.available()) {} - if (stream.read() == c) - return true; - } - return false; - } + /* + * Battery functions + */ + /* Public Utilities */ template void sendAT(Args... cmd) { streamWrite("AT", cmd..., GSM_NL); stream.flush(); TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); + DBG(GSM_NL, ">>> AT:", cmd...); } // TODO: Optimize this! @@ -542,8 +461,8 @@ private: index = 5; goto finish; } else if (data.endsWith(GF("+TCPRECV:"))) { - int mux = stream.readStringUntil(',').toInt(); - int len = stream.readStringUntil(',').toInt(); + int mux = streamReadUntil(',').toInt(); + int len = streamReadUntil(',').toInt(); if (len > sockets[mux]->rx.free()) { DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); } else { @@ -556,14 +475,14 @@ private: data = ""; return index; } else if (data.endsWith(GF("+TCPCLOSE:"))) { - int mux = stream.readStringUntil(',').toInt(); - stream.readStringUntil('\n'); + int mux = streamReadUntil(',').toInt(); + streamReadUntil('\n'); sockets[mux]->sock_connected = false; data = ""; } } } while (millis() - startMillis < timeout); -finish: + finish: if (!index) { data.trim(); if (data.length()) { @@ -571,6 +490,15 @@ finish: } data = ""; } + else { + data.trim(); + data.replace(GSM_NL GSM_NL, GSM_NL); + data.replace(GSM_NL, GSM_NL " "); + if (data.length()) { + DBG(GSM_NL, "<<< ", data); + } + data = ""; + } return index; } @@ -588,6 +516,95 @@ finish: return waitResponse(1000, r1, r2, r3, r4, r5); } +private: + String dnsIpQuery(const char* host) { + sendAT(GF("+DNS=\""), host, GF("\"")); + if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) { + return ""; + } + String res = streamReadUntil('\n'); + waitResponse(GF("+DNS:OK" GSM_NL)); + res.trim(); + return res; + } + + int modemConnect(const char* host, uint16_t port, uint8_t mux) { + int rsp = 0; + for (int i=0; i<3; i++) { + String ip = dnsIpQuery(host); + + sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); + int rsp = waitResponse(75000L, + GF(",OK" GSM_NL), + GF(",FAIL" GSM_NL), + GF("+TCPSETUP:Error" GSM_NL)); + if (1 == rsp) { + return true; + } else if (3 == rsp) { + sendAT(GF("+TCPCLOSE="), mux); + waitResponse(); + } + delay(1000); + } + return false; + } + + int modemSend(const void* buff, size_t len, uint8_t mux) { + sendAT(GF("+TCPSEND="), mux, ',', len); + if (waitResponse(GF(">")) != 1) { + return 0; + } + stream.write((uint8_t*)buff, len); + stream.write((char)0x0D); + + if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { + return 0; + } + streamReadUntil('\n'); + return len; + } + + bool modemGetConnected(uint8_t mux) { + sendAT(GF("+CIPSTATUS="), mux); + int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); + waitResponse(); + return 1 == res; + } + + /* Private Utilities */ + template + void streamWrite(T last) { + stream.print(last); + } + + template + void streamWrite(T head, Args... tail) { + stream.print(head); + streamWrite(tail...); + } + + int streamRead() { return stream.read(); } + + String streamReadUntil(char c) { + String return_string = stream.readStringUntil(c); + return_string.trim(); + if (String(c) == GSM_NL || String(c) == "\n"){ + DBG(return_string, c, " "); + } else DBG(return_string, c); + return return_string; + } + + bool streamSkipUntil(char c) { //TODO: timeout + String skipped = stream.readStringUntil(c); + skipped.trim(); + if (skipped.length()) { + if (String(c) == GSM_NL || String(c) == "\n"){ + DBG(skipped, c, " "); + } else DBG(skipped, c); + return true; + } else return false; + } + private: Stream& stream; GsmClient* sockets[2]; diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 0c03c4d..958540e 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -187,7 +187,7 @@ public: } bool autoBaud(unsigned long timeout = 10000L) { - streamWrite(GF("AAAAAAAAAAAA")); // some extra A's to help detect the baud rate + streamWrite(GF("AAAAAAAAAAAAA")); // extra A's to help detect the baud rate for (unsigned long start = millis(); millis() - start < timeout; ) { sendAT(GF("")); if (waitResponse(200) == 1) { @@ -279,79 +279,11 @@ public: return res; } - String getGsmLocation() { - sendAT(GF("+CIPGSMLOC=1,1")); - if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) { - return ""; - } - String res = streamReadUntil('\n'); - waitResponse(); - return res; - } - - bool setGsmBusy(bool busy = true) { - sendAT(GF("+GSMBUSY="), busy ? 1 : 0); - return waitResponse() == 1; - } - - bool callAnswer() { - sendAT(GF("A")); - return waitResponse() == 1; - } - - bool callNumber(const String& number) { - sendAT(GF("D"), number); - return waitResponse() == 1; - } - - bool callHangup(const String& number) { - sendAT(GF("H"), number); - return waitResponse() == 1; - } - - bool sendSMS(const String& number, const String& text) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - stream.print(text); - stream.write((char)0x1A); - return waitResponse(60000L) == 1; - } - - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - return waitResponse(60000L) == 1; - } - SimStatus getSimStatus(unsigned long timeout = 10000L) { for (unsigned long start = millis(); millis() - start < timeout; ) { sendAT(GF("+CPIN?")); if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) { - delay(250); + delay(1000); continue; } int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED")); @@ -389,16 +321,14 @@ public: } bool waitForNetwork(unsigned long timeout = 60000L) { - unsigned long start = millis(); - bool is_registered = false; - while (millis() - start < timeout && is_registered == false){ + for (unsigned long start = millis(); millis() - start < timeout; ) { RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) { - is_registered = true; + return true; } delay(1000); } - return is_registered; + return false; } /* @@ -491,6 +421,26 @@ public: * Phone Call functions */ + bool setGsmBusy(bool busy = true) { + sendAT(GF("+GSMBUSY="), busy ? 1 : 0); + return waitResponse() == 1; + } + + bool callAnswer() { + sendAT(GF("A")); + return waitResponse() == 1; + } + + bool callNumber(const String& number) { + sendAT(GF("D"), number); + return waitResponse() == 1; + } + + bool callHangup(const String& number) { + sendAT(GF("H"), number); + return waitResponse() == 1; + } + /* * Messaging functions */ @@ -501,12 +451,61 @@ public: void sendSMS() { } + bool sendSMS(const String& number, const String& text) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CMGS=\""), number, GF("\"")); + if (waitResponse(GF(">")) != 1) { + return false; + } + stream.print(text); + stream.write((char)0x1A); + return waitResponse(60000L) == 1; + } + + bool sendSMS_UTF16(const String& number, const void* text, size_t len) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CSCS=\"HEX\"")); + waitResponse(); + sendAT(GF("+CSMP=17,167,0,8")); + waitResponse(); + + sendAT(GF("+CMGS=\""), number, GF("\"")); + if (waitResponse(GF(">")) != 1) { + return false; + } + + uint16_t* t = (uint16_t*)text; + for (size_t i=0; i> 8; + if (c < 0x10) { stream.print('0'); } + stream.print(c, HEX); + c = t[i] & 0xFF; + if (c < 0x10) { stream.print('0'); } + stream.print(c, HEX); + } + stream.write((char)0x1A); + return waitResponse(60000L) == 1; + } + + /* * Location functions */ void getLocation() { } + String getGsmLocation() { + sendAT(GF("+CIPGSMLOC=1,1")); + if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) { + return ""; + } + String res = streamReadUntil('\n'); + waitResponse(); + return res; + } + /* * Battery functions */ @@ -524,6 +523,109 @@ public: return res; } + /* Public Utilities */ + template + void sendAT(Args... cmd) { + streamWrite("AT", cmd..., GSM_NL); + stream.flush(); + TINY_GSM_YIELD(); + DBG(GSM_NL, ">>> AT:", cmd...); + } + + // TODO: Optimize this! + uint8_t waitResponse(uint32_t timeout, String& data, + GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), + GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) + { + /*String r1s(r1); r1s.trim(); + String r2s(r2); r2s.trim(); + String r3s(r3); r3s.trim(); + String r4s(r4); r4s.trim(); + String r5s(r5); r5s.trim(); + DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ + data.reserve(64); + bool gotData = false; + int mux = -1; + int index = 0; + unsigned long startMillis = millis(); + do { + TINY_GSM_YIELD(); + while (stream.available() > 0) { + int a = streamRead(); + if (a <= 0) continue; // Skip 0x00 bytes, just in case + data += (char)a; + if (r1 && data.endsWith(r1)) { + index = 1; + goto finish; + } else if (r2 && data.endsWith(r2)) { + index = 2; + goto finish; + } else if (r3 && data.endsWith(r3)) { + index = 3; + goto finish; + } else if (r4 && data.endsWith(r4)) { + index = 4; + goto finish; + } else if (r5 && data.endsWith(r5)) { + index = 5; + goto finish; + } else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) { + String mode = streamReadUntil(','); + if (mode.toInt() == 1) { + mux = streamReadUntil('\n').toInt(); + gotData = true; + data = ""; + } else { + data += mode; + } + } else if (data.endsWith(GF("CLOSED" GSM_NL))) { + int nl = data.lastIndexOf(GSM_NL, data.length()-8); + int coma = data.indexOf(',', nl+2); + mux = data.substring(nl+2, coma).toInt(); + if (mux) { + sockets[mux]->sock_connected = false; + data = ""; + } + } + } + } while (millis() - startMillis < timeout); + finish: + if (!index) { + data.trim(); + if (data.length()) { + DBG("### Unhandled:", data); + } + data = ""; + } + else { + data.trim(); + data.replace(GSM_NL GSM_NL, GSM_NL); + data.replace(GSM_NL, GSM_NL " "); + if (data.length()) { + DBG(GSM_NL, "<<< ", data); + } + data = ""; + } + if (gotData) { + sockets[mux]->sock_available = modemGetAvailable(mux); + } + return index; + } + + uint8_t waitResponse(uint32_t timeout, + GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), + GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) + { + String data; + return waitResponse(timeout, data, r1, r2, r3, r4, r5); + } + + uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), + GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) + { + return waitResponse(1000, r1, r2, r3, r4, r5); + } + private: int modemConnect(const char* host, uint16_t port, uint8_t mux) { sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); @@ -604,7 +706,7 @@ private: return 1 == res; } - /* Utilities */ + /* Private Utilities */ template void streamWrite(T last) { stream.print(last); @@ -638,108 +740,6 @@ private: } else return false; } - template - void sendAT(Args... cmd) { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - DBG(GSM_NL, ">>> AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - bool gotData = false; - int mux = -1; - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = streamRead(); - if (a <= 0) continue; // Skip 0x00 bytes, just in case - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) { - String mode = streamReadUntil(','); - if (mode.toInt() == 1) { - mux = streamReadUntil('\n').toInt(); - gotData = true; - data = ""; - } else { - data += mode; - } - } else if (data.endsWith(GF("CLOSED" GSM_NL))) { - int nl = data.lastIndexOf(GSM_NL, data.length()-8); - int coma = data.indexOf(',', nl+2); - mux = data.substring(nl+2, coma).toInt(); - if (mux) { - sockets[mux]->sock_connected = false; - data = ""; - } - } - } - } while (millis() - startMillis < timeout); - finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - else { - data.trim(); - data.replace(GSM_NL GSM_NL, GSM_NL); - data.replace(GSM_NL, GSM_NL " "); - if (data.length()) { - DBG(GSM_NL, "<<< ", data); - } - data = ""; - } - if (gotData) { - sockets[mux]->sock_available = modemGetAvailable(mux); - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - private: Stream& stream; GsmClient* sockets[5]; diff --git a/library.json b/library.json index ed747fa..6d87889 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TinyGSM", - "version": "0.1.7", + "version": "0.1.8", "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968", "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968", "authors": diff --git a/library.properties b/library.properties index 73e5460..526c925 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TinyGSM -version=0.1.7 +version=0.1.8 author=Volodymyr Shymanskyy maintainer=Volodymyr Shymanskyy sentence=A small Arduino library for GPRS modules, that just works.