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 | 378 ++++++++++++++++++++--------------------- library.json | 2 +- library.properties | 2 +- 6 files changed, 499 insertions(+), 464 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,6 +369,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 */ @@ -410,6 +394,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 */ @@ -420,90 +416,13 @@ public: * Battery 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; - } - - 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; - } - 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); - } - - 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! @@ -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,120 +523,7 @@ public: return res; } -private: - int modemConnect(const char* host, uint16_t port, uint8_t mux) { - sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - int rsp = waitResponse(75000L, - GF("CONNECT OK" GSM_NL), - GF("CONNECT FAIL" GSM_NL), - GF("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); - stream.flush(); - if (waitResponse(GF(GSM_NL "DATA ACCEPT:")) != 1) { - return -1; - } - streamSkipUntil(','); // Skip mux - return streamReadUntil('\n').toInt(); - } - - size_t modemRead(size_t size, uint8_t mux) { -#ifdef TINY_GSM_USE_HEX - sendAT(GF("+CIPRXGET=3,"), mux, ',', size); - if (waitResponse(GF("+CIPRXGET:")) != 1) { - return 0; - } -#else - sendAT(GF("+CIPRXGET=2,"), mux, ',', size); - if (waitResponse(GF("+CIPRXGET:")) != 1) { - return 0; - } -#endif - streamSkipUntil(','); // Skip mode 2/3 - streamSkipUntil(','); // Skip mux - size_t len = streamReadUntil(',').toInt(); - sockets[mux]->sock_available = streamReadUntil('\n').toInt(); - - for (size_t i=0; irx.put(c); - } - waitResponse(); - return len; - } - - size_t modemGetAvailable(uint8_t mux) { - sendAT(GF("+CIPRXGET=4,"), mux); - size_t result = 0; - if (waitResponse(GF("+CIPRXGET:")) == 1) { - streamSkipUntil(','); // Skip mode 4 - streamSkipUntil(','); // Skip mux - result = streamReadUntil('\n').toInt(); - waitResponse(); - } - if (!result) { - sockets[mux]->sock_connected = modemGetConnected(mux); - } - return result; - } - - 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(); } - - 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; - } - + /* Public Utilities */ template void sendAT(Args... cmd) { streamWrite("AT", cmd..., GSM_NL); @@ -740,6 +626,120 @@ private: 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); + int rsp = waitResponse(75000L, + GF("CONNECT OK" GSM_NL), + GF("CONNECT FAIL" GSM_NL), + GF("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); + stream.flush(); + if (waitResponse(GF(GSM_NL "DATA ACCEPT:")) != 1) { + return -1; + } + streamSkipUntil(','); // Skip mux + return streamReadUntil('\n').toInt(); + } + + size_t modemRead(size_t size, uint8_t mux) { +#ifdef TINY_GSM_USE_HEX + sendAT(GF("+CIPRXGET=3,"), mux, ',', size); + if (waitResponse(GF("+CIPRXGET:")) != 1) { + return 0; + } +#else + sendAT(GF("+CIPRXGET=2,"), mux, ',', size); + if (waitResponse(GF("+CIPRXGET:")) != 1) { + return 0; + } +#endif + streamSkipUntil(','); // Skip mode 2/3 + streamSkipUntil(','); // Skip mux + size_t len = streamReadUntil(',').toInt(); + sockets[mux]->sock_available = streamReadUntil('\n').toInt(); + + for (size_t i=0; irx.put(c); + } + waitResponse(); + return len; + } + + size_t modemGetAvailable(uint8_t mux) { + sendAT(GF("+CIPRXGET=4,"), mux); + size_t result = 0; + if (waitResponse(GF("+CIPRXGET:")) == 1) { + streamSkipUntil(','); // Skip mode 4 + streamSkipUntil(','); // Skip mux + result = streamReadUntil('\n').toInt(); + waitResponse(); + } + if (!result) { + sockets[mux]->sock_connected = modemGetConnected(mux); + } + return result; + } + + 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[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.