From 454eae4876aa6409268d68a10e56f5fb32c66c78 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 17:50:52 +0300 Subject: [PATCH 01/82] Improve operation on ESP32 and ESP8266 (add TINY_GSM_YIELD where needed) --- TinyGsmClientA6.h | 4 ++-- TinyGsmClientESP8266.h | 2 +- TinyGsmClientM590.h | 4 ++-- TinyGsmClientSIM800.h | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 4972a54..c5cd912 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -470,7 +470,7 @@ private: bool streamSkipUntil(char c) { //TODO: timeout while (true) { - while (!stream.available()) {} + while (!stream.available()) { TINY_GSM_YIELD(); } if (stream.read() == c) return true; } @@ -529,7 +529,7 @@ private: DBG("### Got: ", len, "->", sockets[mux]->rx.free()); } while (len--) { - while (!stream.available()) {} + while (!stream.available()) { TINY_GSM_YIELD(); } sockets[mux]->rx.put(stream.read()); } data = ""; diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index a3c3b4e..0b8967e 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -328,7 +328,7 @@ private: DBG("### Got: ", len, "->", sockets[mux]->rx.free()); } while (len--) { - while (!stream.available()) {} + while (!stream.available()) { TINY_GSM_YIELD(); } sockets[mux]->rx.put(stream.read()); } data = ""; diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 6c4513a..42f928e 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -491,7 +491,7 @@ private: bool streamSkipUntil(char c) { //TODO: timeout while (true) { - while (!stream.available()) {} + while (!stream.available()) { TINY_GSM_YIELD(); } if (stream.read() == c) return true; } @@ -550,7 +550,7 @@ private: DBG("### Got: ", len, "->", sockets[mux]->rx.free()); } while (len--) { - while (!stream.available()) {} + while (!stream.available()) { TINY_GSM_YIELD(); } sockets[mux]->rx.put(stream.read()); } data = ""; diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index b33c2b9..97788aa 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -568,13 +568,13 @@ private: for (size_t i=0; irx.put(c); @@ -621,7 +621,7 @@ private: bool streamSkipUntil(char c) { //TODO: timeout while (true) { - while (!stream.available()) {} + while (!stream.available()) { TINY_GSM_YIELD(); } if (stream.read() == c) return true; } From 124b210927442710cc10c3272c711973444b741a Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 17:58:46 +0300 Subject: [PATCH 02/82] SMS Encoding set to GSM --- TinyGsmClientM590.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 42f928e..0e050fa 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -290,6 +290,8 @@ public: } bool sendSMS(const String& number, const String& text) { + sendAT(GF("+CSCS=\"gsm\"")); + waitResponse(); sendAT(GF("+CMGF=1")); waitResponse(); sendAT(GF("+CMGS=\""), number, GF("\"")); From 294767d6ba086ba58b44b9f8127257b6d4bbdcea Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 18:14:13 +0300 Subject: [PATCH 03/82] Fix recursive waitResponse --- TinyGsmClientSIM800.h | 44 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 97788aa..722b458 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -16,6 +16,8 @@ #define TINY_GSM_RX_BUFFER 64 #endif +#define TINY_GSM_MUX_COUNT 5 + #include #define GSM_NL "\r\n" @@ -65,6 +67,7 @@ public: this->mux = mux; sock_available = 0; sock_connected = false; + got_data = false; at->sockets[mux] = this; @@ -162,6 +165,7 @@ private: uint8_t mux; uint16_t sock_available; bool sock_connected; + bool got_data; RxFifo rx; }; @@ -199,6 +203,12 @@ public: } void maintain() { + for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { + if (sockets[mux] && sockets[mux]->got_data) { + sockets[mux]->got_data = false; + sockets[mux]->sock_available = modemGetAvailable(mux); + } + } while (stream.available()) { waitResponse(10, NULL, NULL); } @@ -239,6 +249,18 @@ public: return init(); } + bool radioOff() { + if (!autoBaud()) { + return false; + } + sendAT(GF("+CFUN=0")); + if (waitResponse(10000L) != 1) { + return false; + } + delay(3000); + return true; + } + /* * SIM card & Networ Operator functions */ @@ -526,6 +548,20 @@ public: return res; } + int getBattPercent() { + if (!autoBaud()) { + return false; + } + sendAT(GF("+CBC")); + if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + return false; + } + stream.readStringUntil(','); + int res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + private: int modemConnect(const char* host, uint16_t port, uint8_t mux) { sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); @@ -648,7 +684,6 @@ private: 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(); @@ -677,8 +712,8 @@ private: String mode = stream.readStringUntil(','); if (mode.toInt() == 1) { mux = stream.readStringUntil('\n').toInt(); - gotData = true; data = ""; + sockets[mux]->got_data = true; } else { data += mode; } @@ -701,9 +736,6 @@ finish: } data = ""; } - if (gotData) { - sockets[mux]->sock_available = modemGetAvailable(mux); - } return index; } @@ -723,7 +755,7 @@ finish: private: Stream& stream; - GsmClient* sockets[5]; + GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; typedef TinyGsm::GsmClient TinyGsmClient; From 1c6141f25c1937c4f17ccd5847b84ff0f9205ce4 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 18:54:40 +0300 Subject: [PATCH 04/82] Rearrange stuff so it makes more sense --- TinyGsmClientSIM800.h | 169 +++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 722b458..b341b51 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -191,6 +191,7 @@ public: } bool autoBaud(unsigned long timeout = 10000L) { + streamWrite(GF("AAAAAAA")); // extra A's to help detect the baud rate for (unsigned long start = millis(); millis() - start < timeout; ) { sendAT(GF("")); if (waitResponse(200) == 1) { @@ -262,7 +263,7 @@ public: } /* - * SIM card & Networ Operator functions + * SIM card functions */ bool simUnlock(const char *pin) { @@ -292,85 +293,6 @@ public: return res; } - int getSignalQuality() { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - String getGsmLocation() { - sendAT(GF("+CIPGSMLOC=1,1")); - if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - 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?")); @@ -412,13 +334,25 @@ public: return res; } + /* + * Generic network functions + */ + + int getSignalQuality() { + sendAT(GF("+CSQ")); + if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { + return 99; + } + int res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + bool waitForNetwork(unsigned long timeout = 60000L) { for (unsigned long start = millis(); millis() - start < timeout; ) { RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) { return true; - } else if (s == REG_UNREGISTERED) { - return false; } delay(1000); } @@ -515,20 +449,86 @@ 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 */ + // TODO void sendUSSD() { } - 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 = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; } /* @@ -578,6 +578,7 @@ private: return -1; } stream.write((uint8_t*)buff, len); + stream.flush(); if (waitResponse(GF(GSM_NL "DATA ACCEPT:")) != 1) { return -1; } From 8cf9571a2f12f131648d1ca75da9f00044e2939e Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:04:58 +0300 Subject: [PATCH 05/82] Rearrange stuff so it makes more sense --- TinyGsmClientM590.h | 94 +++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 0e050fa..3e79fbc 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -15,6 +15,8 @@ #define TINY_GSM_RX_BUFFER 256 #endif +#define TINY_GSM_MUX_COUNT 2 + #include #define GSM_NL "\r\n" @@ -234,7 +236,7 @@ public: } /* - * SIM card & Networ Operator functions + * SIM card functions */ bool simUnlock(const char *pin) { @@ -264,45 +266,6 @@ public: return res; } - int getSignalQuality() { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').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("+CSCS=\"gsm\"")); - waitResponse(); - 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?")); @@ -344,13 +307,25 @@ public: return res; } + /* + * Generic network functions + */ + + int getSignalQuality() { + sendAT(GF("+CSQ")); + if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { + return 99; + } + int res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + bool waitForNetwork(unsigned long timeout = 60000L) { for (unsigned long start = millis(); millis() - start < timeout; ) { RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) { return true; - } else if (s == REG_UNREGISTERED) { - return false; } delay(1000); } @@ -402,20 +377,49 @@ 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 */ + // TODO void sendUSSD() { } - void sendSMS() { + bool sendSMS(const String& number, const String& text) { + sendAT(GF("+CSCS=\"gsm\"")); + waitResponse(); + 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 */ - void getLocation() { + + void getGsmLocation() { } /* @@ -592,7 +596,7 @@ finish: private: Stream& stream; - GsmClient* sockets[2]; + GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; typedef TinyGsm::GsmClient TinyGsmClient; From bcc346fcf5b95953fdd7e44c3f3c95c43a76471e Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:09:22 +0300 Subject: [PATCH 06/82] Rearrange stuff so it makes more sense --- TinyGsmClientESP8266.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index 0b8967e..28bfc9f 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -1,13 +1,13 @@ /** - * @file TinyWiFiClientESP8266.h + * @file TinyGsmClientESP8266.h * @author Volodymyr Shymanskyy * @license LGPL-3.0 * @copyright Copyright (c) 2016 Volodymyr Shymanskyy * @date Nov 2016 */ -#ifndef TinyWiFiClientESP8266_h -#define TinyWiFiClientESP8266_h +#ifndef TinyGsmClientESP8266_h +#define TinyGsmClientESP8266_h //#define TINY_GSM_DEBUG Serial @@ -15,6 +15,8 @@ #define TINY_GSM_RX_BUFFER 256 #endif +#define TINY_GSM_MUX_COUNT 5 + #include #define GSM_NL "\r\n" @@ -366,7 +368,7 @@ finish: private: Stream& stream; - GsmClient* sockets[5]; + GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; typedef TinyGsm::GsmClient TinyGsmClient; From 9015b5b7bc5272a4bd1ca3e98027a0fbcdf70a9d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:21:47 +0300 Subject: [PATCH 07/82] Rearrange stuff so it makes more sense --- TinyGsmClientA6.h | 92 +++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index c5cd912..fc09b33 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -15,6 +15,8 @@ #define TINY_GSM_RX_BUFFER 256 #endif +#define TINY_GSM_MUX_COUNT 8 + #include #define GSM_NL "\r\n" @@ -225,7 +227,7 @@ public: } /* - * SIM card & Networ Operator functions + * SIM card functions */ bool simUnlock(const char *pin) { @@ -255,43 +257,6 @@ public: return res; } - int getSignalQuality() { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').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?")); @@ -333,13 +298,25 @@ public: return res; } + /* + * Generic network functions + */ + + int getSignalQuality() { + sendAT(GF("+CSQ")); + if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { + return 99; + } + int res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + bool waitForNetwork(unsigned long timeout = 60000L) { for (unsigned long start = millis(); millis() - start < timeout; ) { RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) { return true; - } else if (s == REG_UNREGISTERED) { - return false; } delay(1000); } @@ -393,20 +370,48 @@ 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 */ + // TODO void sendUSSD() { } - 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); + stream.flush(); + return waitResponse(60000L) == 1; } + /* * Location functions */ - void getLocation() { + + void getGsmLocation() { } /* @@ -414,6 +419,7 @@ public: */ private: + int modemConnect(const char* host, uint16_t port, uint8_t* mux) { sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port); @@ -569,7 +575,7 @@ finish: private: Stream& stream; - GsmClient* sockets[8]; + GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; typedef TinyGsm::GsmClient TinyGsmClient; From 6ce92551f9192d2a0170389f28698f1d14a166c9 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:22:55 +0300 Subject: [PATCH 08/82] Add more module options --- examples/BlynkClient/BlynkClient.ino | 8 +++++--- examples/FileDownload/FileDownload.ino | 10 ++++++---- examples/MqttClient/MqttClient.ino | 8 +++++--- examples/WebClient/WebClient.ino | 8 +++++--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/examples/BlynkClient/BlynkClient.ino b/examples/BlynkClient/BlynkClient.ino index 9de5419..434c474 100644 --- a/examples/BlynkClient/BlynkClient.ino +++ b/examples/BlynkClient/BlynkClient.ino @@ -30,9 +30,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_A6 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 #include #include diff --git a/examples/FileDownload/FileDownload.ino b/examples/FileDownload/FileDownload.ino index 781047a..cce8ca6 100644 --- a/examples/FileDownload/FileDownload.ino +++ b/examples/FileDownload/FileDownload.ino @@ -14,9 +14,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_A6 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 // Increase RX buffer #define TINY_GSM_RX_BUFFER 1030 @@ -126,7 +128,7 @@ void loop() { //Serial.println(line); // Uncomment this to show response header line.toLowerCase(); if (line.startsWith("content-length:")) { - contentLength = line.substring(line.lastIndexOf(':') + 1).toInt(); + contentLength = line.substring(line.lastIndexOf(':') + 1).toInt(); } else if (line.length() == 0) { break; } diff --git a/examples/MqttClient/MqttClient.ino b/examples/MqttClient/MqttClient.ino index 6fe5676..d85d5ec 100644 --- a/examples/MqttClient/MqttClient.ino +++ b/examples/MqttClient/MqttClient.ino @@ -27,9 +27,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_A6 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 #include #include diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index 0e58bfa..f75d15a 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -10,9 +10,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_A6 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 #include From 9f7559f9f1e5d296043b6bb73a00f18bfbfc7062 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:23:37 +0300 Subject: [PATCH 09/82] Add more module options --- tools/AT_Debug/AT_Debug.ino | 7 +++++-- tools/Diagnostics/Diagnostics.ino | 8 +++++--- tools/FactoryReset/FactoryReset.ino | 7 +++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/AT_Debug/AT_Debug.ino b/tools/AT_Debug/AT_Debug.ino index 26db144..ef53630 100644 --- a/tools/AT_Debug/AT_Debug.ino +++ b/tools/AT_Debug/AT_Debug.ino @@ -10,8 +10,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 #include diff --git a/tools/Diagnostics/Diagnostics.ino b/tools/Diagnostics/Diagnostics.ino index 41d804d..2f0089b 100644 --- a/tools/Diagnostics/Diagnostics.ino +++ b/tools/Diagnostics/Diagnostics.ino @@ -11,9 +11,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_A6 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 // Increase buffer fo see less commands #define TINY_GSM_RX_BUFFER 256 diff --git a/tools/FactoryReset/FactoryReset.ino b/tools/FactoryReset/FactoryReset.ino index 72d258f..a66a0f8 100644 --- a/tools/FactoryReset/FactoryReset.ino +++ b/tools/FactoryReset/FactoryReset.ino @@ -11,8 +11,11 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 -//#define TINY_GSM_MODEM_SIM900 -//#define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 #include #include From e37b2a62e4be3f530db59bb055bebe0409f74f5b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:26:54 +0300 Subject: [PATCH 10/82] Add stream.flush(); here and there --- TinyGsmClientESP8266.h | 1 + TinyGsmClientM590.h | 3 ++- TinyGsmClientSIM800.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index 28bfc9f..75155b2 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -251,6 +251,7 @@ private: return -1; } stream.write((uint8_t*)buff, len); + stream.flush(); if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) { return -1; } diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 3e79fbc..47eb014 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -411,6 +411,7 @@ public: } stream.print(text); stream.write((char)0x1A); + stream.flush(); return waitResponse(60000L) == 1; } @@ -466,7 +467,7 @@ private: } stream.write((uint8_t*)buff, len); stream.write((char)0x0D); - + stream.flush(); if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { return 0; } diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index b341b51..20af6db 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -486,6 +486,7 @@ public: } stream.print(text); stream.write((char)0x1A); + stream.flush(); return waitResponse(60000L) == 1; } @@ -512,6 +513,7 @@ public: stream.print(c, HEX); } stream.write((char)0x1A); + stream.flush(); return waitResponse(60000L) == 1; } From 9129d8fe8f44eba3de338f507e60feac20a1323e Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 19:50:19 +0300 Subject: [PATCH 11/82] Fix #67 --- TinyGsmClientSIM800.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 20af6db..abc3509 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -524,7 +524,7 @@ public: String getGsmLocation() { sendAT(GF("+CIPGSMLOC=1,1")); - if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) { + if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); From 4da3780d2816b2fee78152998d322d24c2d9f682 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 22:02:58 +0300 Subject: [PATCH 12/82] Add "How does it work?" --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 382b3a8..f52fc76 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,11 @@ Watch this repo for new updates! And of course, contributions are welcome ;) Send an ```AT``` command using [this sketch](tools/AT_Debug/AT_Debug.ino) 5. Check if GSM antenna is attached +## How does it work? + +Many GSM modems, WiFi and radio modules can be controlled by sending AT commands over Serial. +TinyGSM knows which commands to send, and how to handle AT responses, and wraps that into standard Arduino Client interface. + ## Troubleshooting ### SoftwareSerial problems From d37c4fd0ef97b7e22616d7141b69483e97e77ba0 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 22:03:37 +0300 Subject: [PATCH 13/82] Improve A6 operation --- TinyGsmClientA6.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index fc09b33..53c4244 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -113,7 +113,7 @@ public: virtual int available() { TINY_GSM_YIELD(); - if (!rx.size()) { + if (!rx.size() && sock_connected) { at->maintain(); } return rx.size(); @@ -541,8 +541,7 @@ private: data = ""; return index; } else if (data.endsWith(GF("+TCPCLOSED:"))) { - int mux = stream.readStringUntil(',').toInt(); - stream.readStringUntil('\n'); + int mux = stream.readStringUntil('\n').toInt(); // TODO: No comma? sockets[mux]->sock_connected = false; data = ""; } @@ -552,7 +551,12 @@ finish: if (!index) { data.trim(); if (data.length()) { - DBG("### Unhandled:", data); + if (data.endsWith(GF("+TCPCLOSED:"))) { + int mux = stream.readStringUntil('\n').toInt(); + sockets[mux]->sock_connected = false; + } else { + DBG("### Unhandled:", data); + } } data = ""; } From f41236234130f8f613fa5c97f333908d2d96ad38 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 22:09:19 +0300 Subject: [PATCH 14/82] MEGA fix for SIM800. Stable now? ;) --- TinyGsmClientSIM800.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index abc3509..6f43754 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -66,6 +66,7 @@ public: this->at = modem; this->mux = mux; sock_available = 0; + prev_check = 0; sock_connected = false; got_data = false; @@ -113,7 +114,14 @@ public: virtual int available() { TINY_GSM_YIELD(); - if (!rx.size()) { + if (sock_connected && !rx.size()) { + // Workaround: sometimes SIM800 forgets to notify about data arrival. + // TODO: Currently we ping the module periodically, + // but maybe there's a better indicator that we need to poll + if (millis() - prev_check > 500) { + got_data = true; + prev_check = millis(); + } at->maintain(); } return rx.size() + sock_available; @@ -164,6 +172,7 @@ private: TinyGsm* at; uint8_t mux; uint16_t sock_available; + uint32_t prev_check; bool sock_connected; bool got_data; RxFifo rx; @@ -191,7 +200,7 @@ public: } bool autoBaud(unsigned long timeout = 10000L) { - streamWrite(GF("AAAAAAA")); // extra A's to help detect the baud rate + //streamWrite(GF("AAAAA" GSM_NL)); // TODO: extra A's to help detect the baud rate for (unsigned long start = millis(); millis() - start < timeout; ) { sendAT(GF("")); if (waitResponse(200) == 1) { @@ -205,9 +214,10 @@ public: void maintain() { for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { - if (sockets[mux] && sockets[mux]->got_data) { - sockets[mux]->got_data = false; - sockets[mux]->sock_available = modemGetAvailable(mux); + GsmClient* sock = sockets[mux]; + if (sock && sock->got_data) { + sock->got_data = false; + sock->sock_available = modemGetAvailable(mux); } } while (stream.available()) { From 1dba3dbafc7a50de9044a72ccc81e0d1595ba32f Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sat, 2 Sep 2017 22:09:39 +0300 Subject: [PATCH 15/82] Boost ver --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index ed747fa..1b046d0 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TinyGSM", - "version": "0.1.7", + "version": "0.2.0", "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..efbaab3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TinyGSM -version=0.1.7 +version=0.2.0 author=Volodymyr Shymanskyy maintainer=Volodymyr Shymanskyy sentence=A small Arduino library for GPRS modules, that just works. From 6507905c151a3d294ae5ec7374b76c1b0151396f Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 3 Sep 2017 08:37:38 +0300 Subject: [PATCH 16/82] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f52fc76..c117f5b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ If you like **TinyGSM** - give it a star, or fork it and contribute! [![GitHub stars](https://img.shields.io/github/stars/vshymanskyy/TinyGSM.svg?style=social&label=Star)](https://github.com/vshymanskyy/TinyGSM/stargazers) [![GitHub forks](https://img.shields.io/github/forks/vshymanskyy/TinyGSM.svg?style=social&label=Fork)](https://github.com/vshymanskyy/TinyGSM/network) +You can also join our chat: +[![Gitter](https://img.shields.io/gitter/room/vshymanskyy/TinyGSM.svg)](https://gitter.im/tinygsm) + ### Arduino Client interface support This library is easy to integrate with lots of sketches, which use Ethernet or WiFi. Examples for **PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **Web Client** and **File Download** are provided. From 137ac7befe72fa82557fa7a33e7045e6c94a67b7 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 3 Sep 2017 21:57:19 +0300 Subject: [PATCH 17/82] Add TINY_GSM_TCP_KEEP_ALIVE --- TinyGsmClientESP8266.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index 75155b2..283b8ff 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -22,6 +22,7 @@ #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; +static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; class TinyGsm { @@ -237,7 +238,7 @@ public: private: int modemConnect(const char* host, uint16_t port, uint8_t mux) { - sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",120")); + sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE); int rsp = waitResponse(75000L, GFP(GSM_OK), GFP(GSM_ERROR), From 2106037f60a14bc78d171d80aedca46807a34443 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 3 Sep 2017 21:57:45 +0300 Subject: [PATCH 18/82] Remove extra variable --- TinyGsmClientM590.h | 1 - 1 file changed, 1 deletion(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 47eb014..4d5b327 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -440,7 +440,6 @@ private: } 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); From 7213e25d35ac490d168bf9e42cd546b5755d25cd Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 5 Sep 2017 16:45:28 +0300 Subject: [PATCH 19/82] Fix A6 <> Blynk operation --- TinyGsmClientA6.h | 61 ++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 53c4244..c15f2fd 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -42,11 +42,6 @@ enum RegStatus { class TinyGsm { -public: - TinyGsm(Stream& stream) - : stream(stream) - {} - public: class GsmClient : public Client @@ -166,6 +161,12 @@ private: public: + TinyGsm(Stream& stream) + : stream(stream) + { + memset(sockets, 0, sizeof(sockets)); + } + /* * Basic functions */ @@ -226,6 +227,11 @@ public: return init(); } + bool poweroff() { + sendAT(GF("+CPOF")); + return waitResponse() == 1; + } + /* * SIM card functions */ @@ -298,9 +304,9 @@ public: return res; } - /* - * Generic network functions - */ + /* + * Generic network functions + */ int getSignalQuality() { sendAT(GF("+CSQ")); @@ -351,12 +357,14 @@ public: return false; } - /*sendAT(GF("+CIFSR")); + /* + sendAT(GF("+CIFSR")); String data; if (waitResponse(10000L, data) != 1) { data.replace(GSM_NL, ""); return false; - }*/ + } + */ return true; } @@ -370,6 +378,8 @@ public: * Phone Call functions */ + bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; + bool callAnswer() { sendAT(GF("A")); return waitResponse() == 1; @@ -380,6 +390,11 @@ public: return waitResponse() == 1; } + void callRedial() { + sendAT(GF("DLST")); + return waitResponse() == 1; + } + bool callHangup(const String& number) { sendAT(GF("H"), number); return waitResponse() == 1; @@ -389,9 +404,7 @@ public: * Messaging functions */ - // TODO - void sendUSSD() { - } + void sendUSSD() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool sendSMS(const String& number, const String& text) { sendAT(GF("+CMGF=1")); @@ -411,8 +424,7 @@ public: * Location functions */ - void getGsmLocation() { - } + String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; /* * Battery functions @@ -442,7 +454,7 @@ private: int modemSend(const void* buff, size_t len, uint8_t mux) { sendAT(GF("+CIPSEND="), mux, ',', len); - if (waitResponse(10000L, GF(GSM_NL ">")) != 1) { + if (waitResponse(2000L, GF(GSM_NL ">")) != 1) { return -1; } stream.write((uint8_t*)buff, len); @@ -460,7 +472,10 @@ private: return 1 == res; } +public: + /* Utilities */ + template void streamWrite(T last) { stream.print(last); @@ -472,8 +487,6 @@ private: streamWrite(tail...); } - int streamRead() { return stream.read(); } - bool streamSkipUntil(char c) { //TODO: timeout while (true) { while (!stream.available()) { TINY_GSM_YIELD(); } @@ -508,7 +521,7 @@ private: do { TINY_GSM_YIELD(); while (stream.available() > 0) { - int a = streamRead(); + int a = stream.read(); if (a <= 0) continue; // Skip 0x00 bytes, just in case data += (char)a; if (r1 && data.endsWith(r1)) { @@ -539,9 +552,8 @@ private: sockets[mux]->rx.put(stream.read()); } data = ""; - return index; } else if (data.endsWith(GF("+TCPCLOSED:"))) { - int mux = stream.readStringUntil('\n').toInt(); // TODO: No comma? + int mux = stream.readStringUntil('\n').toInt(); sockets[mux]->sock_connected = false; data = ""; } @@ -551,12 +563,7 @@ finish: if (!index) { data.trim(); if (data.length()) { - if (data.endsWith(GF("+TCPCLOSED:"))) { - int mux = stream.readStringUntil('\n').toInt(); - sockets[mux]->sock_connected = false; - } else { - DBG("### Unhandled:", data); - } + DBG("### Unhandled:", data); } data = ""; } From 130e755f2deca51cb29ba137faff5f9f7ac3eae3 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 5 Sep 2017 16:45:46 +0300 Subject: [PATCH 20/82] Add TINY_GSM_ATTR_* --- TinyGsmCommon.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TinyGsmCommon.h b/TinyGsmCommon.h index 8946ee0..60a5e48 100644 --- a/TinyGsmCommon.h +++ b/TinyGsmCommon.h @@ -26,6 +26,9 @@ #define TINY_GSM_YIELD() { delay(0); } #endif +#define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type"))) +#define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) + #if defined(__AVR__) #define TINY_GSM_PROGMEM PROGMEM typedef const __FlashStringHelper* GsmConstStr; From e178fa1d28fb112a248abfa8f79f3a48f586b8a1 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 5 Sep 2017 16:50:01 +0300 Subject: [PATCH 21/82] Make sendAT(...) and waitResponce() public --- TinyGsmClientM590.h | 68 +++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 4d5b327..eda599c 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -42,11 +42,6 @@ enum RegStatus { class TinyGsm { -public: - TinyGsm(Stream& stream) - : stream(stream) - {} - public: class GsmClient : public Client @@ -110,7 +105,7 @@ public: virtual int available() { TINY_GSM_YIELD(); - if (!rx.size()) { + if (!rx.size() && sock_connected) { at->maintain(); } return rx.size(); @@ -163,6 +158,12 @@ private: public: + TinyGsm(Stream& stream) + : stream(stream) + { + memset(sockets, 0, sizeof(sockets)); + } + /* * Basic functions */ @@ -235,6 +236,8 @@ public: return init(); } + bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; + /* * SIM card functions */ @@ -307,9 +310,9 @@ public: return res; } - /* - * Generic network functions - */ + /* + * Generic network functions + */ int getSignalQuality() { sendAT(GF("+CSQ")); @@ -357,13 +360,15 @@ public: sendAT(GF("+XIIC?")); waitResponse(); - /*sendAT(GF("+DNSSERVER=1,8.8.8.8")); + /* + sendAT(GF("+DNSSERVER=1,8.8.8.8")); waitResponse(); sendAT(GF("+DNSSERVER=2,8.8.4.4")); if (waitResponse() != 1) { return false; - }*/ + } + */ return true; } @@ -377,6 +382,8 @@ public: * Phone Call functions */ + bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; + bool callAnswer() { sendAT(GF("A")); return waitResponse() == 1; @@ -387,6 +394,8 @@ public: return waitResponse() == 1; } + void callRedial() TINY_GSM_ATTR_NOT_AVAILABLE; + bool callHangup(const String& number) { sendAT(GF("H"), number); return waitResponse() == 1; @@ -396,9 +405,7 @@ public: * Messaging functions */ - // TODO - void sendUSSD() { - } + void sendUSSD() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool sendSMS(const String& number, const String& text) { sendAT(GF("+CSCS=\"gsm\"")); @@ -420,27 +427,16 @@ public: * Location functions */ - void getGsmLocation() { - } + String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; /* * 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) { - for (int i=0; i<3; i++) { + for (int i=0; i<3; i++) { // TODO: no need for loop? String ip = dnsIpQuery(host); sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); @@ -481,7 +477,21 @@ private: return 1 == res; } + 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; + } + +public: + /* Utilities */ + template void streamWrite(T last) { stream.print(last); @@ -493,8 +503,6 @@ private: streamWrite(tail...); } - int streamRead() { return stream.read(); } - bool streamSkipUntil(char c) { //TODO: timeout while (true) { while (!stream.available()) { TINY_GSM_YIELD(); } @@ -529,7 +537,7 @@ private: do { TINY_GSM_YIELD(); while (stream.available() > 0) { - int a = streamRead(); + int a = stream.read(); if (a <= 0) continue; // Skip 0x00 bytes, just in case data += (char)a; if (r1 && data.endsWith(r1)) { From ebb163371816b677337c895d3aef94466a22713f Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 5 Sep 2017 16:53:58 +0300 Subject: [PATCH 22/82] Make sendAT(...) and waitResponce() public --- TinyGsmClientSIM800.h | 50 +++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 6f43754..b7328e0 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -43,11 +43,6 @@ enum RegStatus { class TinyGsm { -public: - TinyGsm(Stream& stream) - : stream(stream) - {} - public: class GsmClient : public Client @@ -180,6 +175,12 @@ private: public: + TinyGsm(Stream& stream) + : stream(stream) + { + memset(sockets, 0, sizeof(sockets)); + } + /* * Basic functions */ @@ -191,7 +192,9 @@ public: if (!autoBaud()) { return false; } - sendAT(GF("&FZE0")); // Factory + Reset + Echo Off + sendAT(GF("&FZ")); // Factory + Reset + waitResponse(); + sendAT(GF("E0")); // Echo Off if (waitResponse() != 1) { return false; } @@ -344,9 +347,9 @@ public: return res; } - /* - * Generic network functions - */ + /* + * Generic network functions + */ int getSignalQuality() { sendAT(GF("+CSQ")); @@ -474,6 +477,11 @@ public: return waitResponse() == 1; } + void callRedial() { + sendAT(GF("DL")); + return waitResponse() == 1; + } + bool callHangup(const String& number) { sendAT(GF("H"), number); return waitResponse() == 1; @@ -483,9 +491,7 @@ public: * Messaging functions */ - // TODO - void sendUSSD() { - } + void sendUSSD() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool sendSMS(const String& number, const String& text) { sendAT(GF("+CMGF=1")); @@ -654,7 +660,10 @@ private: return 1 == res; } +public: + /* Utilities */ + template void streamWrite(T last) { stream.print(last); @@ -666,8 +675,6 @@ private: streamWrite(tail...); } - int streamRead() { return stream.read(); } - bool streamSkipUntil(char c) { //TODO: timeout while (true) { while (!stream.available()) { TINY_GSM_YIELD(); } @@ -697,13 +704,12 @@ private: String r5s(r5); r5s.trim(); DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ data.reserve(64); - int mux = -1; int index = 0; unsigned long startMillis = millis(); do { TINY_GSM_YIELD(); while (stream.available() > 0) { - int a = streamRead(); + int a = stream.read(); if (a <= 0) continue; // Skip 0x00 bytes, just in case data += (char)a; if (r1 && data.endsWith(r1)) { @@ -724,20 +730,22 @@ private: } else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) { String mode = stream.readStringUntil(','); if (mode.toInt() == 1) { - mux = stream.readStringUntil('\n').toInt(); + int mux = stream.readStringUntil('\n').toInt(); + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { + sockets[mux]->got_data = true; + } data = ""; - sockets[mux]->got_data = true; } 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) { + int mux = data.substring(nl+2, coma).toInt(); + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { sockets[mux]->sock_connected = false; - data = ""; } + data = ""; } } } while (millis() - startMillis < timeout); From 7df8d17e2507583c4bcb061f7e006eff58a756bb Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 5 Sep 2017 16:54:15 +0300 Subject: [PATCH 23/82] Make sendAT(...) and waitResponce() public --- TinyGsmClientESP8266.h | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index 283b8ff..ac6e697 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -27,11 +27,6 @@ static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; class TinyGsm { -public: - TinyGsm(Stream& stream) - : stream(stream) - {} - public: class GsmClient : public Client @@ -95,7 +90,7 @@ public: virtual int available() { TINY_GSM_YIELD(); - if (!rx.size()) { + if (!rx.size() && sock_connected) { at->maintain(); } return rx.size(); @@ -148,6 +143,12 @@ private: public: + TinyGsm(Stream& stream) + : stream(stream) + { + memset(sockets, 0, sizeof(sockets)); + } + /* * Basic functions */ @@ -237,6 +238,7 @@ public: } private: + int modemConnect(const char* host, uint16_t port, uint8_t mux) { sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE); int rsp = waitResponse(75000L, @@ -266,7 +268,10 @@ private: return 1 == res; } +public: + /* Utilities */ + template void streamWrite(T last) { stream.print(last); @@ -278,7 +283,14 @@ private: streamWrite(tail...); } - int streamRead() { return stream.read(); } + bool streamSkipUntil(char c) { //TODO: timeout + while (true) { + while (!stream.available()) { TINY_GSM_YIELD(); } + if (stream.read() == c) + return true; + } + return false; + } template void sendAT(Args... cmd) { @@ -305,7 +317,7 @@ private: do { TINY_GSM_YIELD(); while (stream.available() > 0) { - int a = streamRead(); + int a = stream.read(); if (a <= 0) continue; // Skip 0x00 bytes, just in case data += (char)a; if (r1 && data.endsWith(r1)) { From 7052185f88f749d4406850ce9a48724b65e61903 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 10 Sep 2017 22:19:34 +0300 Subject: [PATCH 24/82] Fix connect() returning false positive result. --- TinyGsmClientA6.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index c15f2fd..b02f321 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -107,6 +107,7 @@ public: } virtual int available() { + //DBG("available?"); TINY_GSM_YIELD(); if (!rx.size() && sock_connected) { at->maintain(); @@ -115,6 +116,7 @@ public: } virtual int read(uint8_t *buf, size_t size) { + //DBG("read:", size); TINY_GSM_YIELD(); size_t cnt = 0; while (cnt < size) { @@ -432,11 +434,11 @@ public: private: - int modemConnect(const char* host, uint16_t port, uint8_t* mux) { + bool 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; + return false; } int newMux = stream.readStringUntil('\n').toInt(); @@ -445,7 +447,7 @@ private: GF("CONNECT FAIL" GSM_NL), GF("ALREADY CONNECT" GSM_NL)); if (waitResponse() != 1) { - return -1; + return false; } *mux = newMux; @@ -556,6 +558,7 @@ public: int mux = stream.readStringUntil('\n').toInt(); sockets[mux]->sock_connected = false; data = ""; + DBG("### Closed: ", mux); } } } while (millis() - startMillis < timeout); From 60424c41f29a6c28c3d0c17bb73157b2d1ea421a Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 10 Sep 2017 22:22:14 +0300 Subject: [PATCH 25/82] Fix diagnostics for some modem types --- tools/Diagnostics/Diagnostics.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/Diagnostics/Diagnostics.ino b/tools/Diagnostics/Diagnostics.ino index 2f0089b..732a166 100644 --- a/tools/Diagnostics/Diagnostics.ino +++ b/tools/Diagnostics/Diagnostics.ino @@ -17,8 +17,8 @@ // #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_ESP8266 -// Increase buffer fo see less commands -#define TINY_GSM_RX_BUFFER 256 +// Increase the buffer +#define TINY_GSM_RX_BUFFER 512 #include #include @@ -46,7 +46,7 @@ TinyGsm modem(debugger); TinyGsmClient client(modem); const char server[] = "cdn.rawgit.com"; -const char resource[] = "/vshymanskyy/tinygsm/master/extras/test_simple.txt"; +const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; void setup() { // Set console baud rate @@ -143,9 +143,9 @@ void loop() { SerialMon.println("************************"); SerialMon.print (" Received: "); SerialMon.print(bytesReceived); - SerialMon.println("bytes"); + SerialMon.println(" bytes"); SerialMon.print (" Test: "); - SerialMon.println((bytesReceived == 1000) ? "PASSED" : "FAIL"); + SerialMon.println((bytesReceived == 121) ? "PASSED" : "FAILED"); SerialMon.println("************************"); // Do nothing forevermore From b4ac86e89e172f0e457185cc5b703d760b43dc53 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 10 Sep 2017 23:32:03 +0300 Subject: [PATCH 26/82] Fix link --- examples/FileDownload/FileDownload.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/FileDownload/FileDownload.ino b/examples/FileDownload/FileDownload.ino index cce8ca6..164695a 100644 --- a/examples/FileDownload/FileDownload.ino +++ b/examples/FileDownload/FileDownload.ino @@ -1,7 +1,7 @@ /************************************************************** * * For this example, you need to install CRC32 library: - * https://github.com/vshymanskyy/CRC32.git + * https://github.com/bakercp/CRC32 * or from http://librarymanager/all#CRC32+checksum * * TinyGSM Getting Started guide: From 77e2d193de8463234846ee91cc0da1869892f66b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 10 Sep 2017 23:32:21 +0300 Subject: [PATCH 27/82] Const port --- examples/WebClient/WebClient.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index f75d15a..44b7d66 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -37,7 +37,7 @@ TinyGsmClient client(modem); const char server[] = "cdn.rawgit.com"; const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; -int port = 80; +const int port = 80; void setup() { // Set console baud rate From 899e90963cb1ea2b5357eceed95fa6acd695c757 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 10 Sep 2017 23:35:24 +0300 Subject: [PATCH 28/82] Move StreamDebugger --- tools/Diagnostics/Diagnostics.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/Diagnostics/Diagnostics.ino b/tools/Diagnostics/Diagnostics.ino index 732a166..abef844 100644 --- a/tools/Diagnostics/Diagnostics.ino +++ b/tools/Diagnostics/Diagnostics.ino @@ -21,7 +21,6 @@ #define TINY_GSM_RX_BUFFER 512 #include -#include // Your GPRS credentials // Leave empty, if missing user or pass @@ -41,6 +40,7 @@ const char pass[] = ""; //SoftwareSerial SerialAT(2, 3); // RX, TX +#include StreamDebugger debugger(SerialAT, SerialMon); TinyGsm modem(debugger); TinyGsmClient client(modem); From 247f2a5cc3ce0cfb7f44ab383f7ee29618256d64 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Sun, 10 Sep 2017 23:37:33 +0300 Subject: [PATCH 29/82] Move StreamDebugger --- tools/FactoryReset/FactoryReset.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/FactoryReset/FactoryReset.ino b/tools/FactoryReset/FactoryReset.ino index a66a0f8..4940c7d 100644 --- a/tools/FactoryReset/FactoryReset.ino +++ b/tools/FactoryReset/FactoryReset.ino @@ -18,7 +18,6 @@ // #define TINY_GSM_MODEM_ESP8266 #include -#include // Set serial for debug console (to the Serial Monitor, speed 115200) #define SerialMon Serial @@ -31,6 +30,7 @@ //#include //SoftwareSerial SerialAT(2, 3); // RX, TX +#include StreamDebugger debugger(SerialAT, SerialMon); TinyGsm modem(debugger); From 4a86db07452fa85461227dc9f5dbb54cec14625f Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 00:32:57 +0300 Subject: [PATCH 30/82] Fix gprsConnect, add getLocalIP(). Fix #9 --- TinyGsmClientA6.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index b02f321..b37e303 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -337,9 +337,17 @@ public: bool gprsConnect(const char* apn, const char* user, const char* pwd) { gprsDisconnect(); + sendAT(GF("+CGATT=1")); + if (waitResponse(60000L) != 1) + return false; + + // TODO: wait AT+CGATT? + sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); waitResponse(); + if (!user) user = ""; + if (!pwd) pwd = ""; sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); if (waitResponse(60000L) != 1) { return false; @@ -348,12 +356,6 @@ public: sendAT(GF("+CGACT=1,1")); waitResponse(60000L); - sendAT(GF("+CGATT=1")); - if (waitResponse(60000L) != 1) - return false; - - // TODO: wait AT+CGATT? - sendAT(GF("+CIPMUX=1")); if (waitResponse() != 1) { return false; @@ -376,6 +378,16 @@ public: return waitResponse(60000L) == 1; } + String getLocalIP() { + sendAT(GF("+CIFSR")); + String res; + if (waitResponse(10000L, res) != 1) { + return ""; + } + res.trim(); + return res; + } + /* * Phone Call functions */ From 4d3d0176004bcfe17f28f31aa900a02fb7377d43 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 00:35:05 +0300 Subject: [PATCH 31/82] Add getLocalIP() --- TinyGsmClientM590.h | 2 ++ TinyGsmClientSIM800.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index eda599c..8d090bf 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -378,6 +378,8 @@ public: return waitResponse(60000L) == 1; } + String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + /* * Phone Call functions */ diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index b7328e0..9bd762d 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -163,6 +163,13 @@ public: return sock_connected; } virtual operator bool() { return connected(); } + + /* + * Extended API + */ + + String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + private: TinyGsm* at; uint8_t mux; @@ -458,6 +465,16 @@ public: return waitResponse(60000L) == 1; } + String getLocalIP() { + sendAT(GF("+CIFSR;E0")); + String res; + if (waitResponse(10000L, res) != 1) { + return ""; + } + res.trim(); + return res; + } + /* * Phone Call functions */ From 4dc0d71687e00c9fc40ff57688e64c07da652c5d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 09:02:26 +0300 Subject: [PATCH 32/82] Add function stubs --- TinyGsmClientM590.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 8d090bf..7e2ec26 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -149,6 +149,13 @@ public: return sock_connected; } virtual operator bool() { return connected(); } + + /* + * Extended API + */ + + String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + private: TinyGsm* at; uint8_t mux; @@ -435,6 +442,10 @@ public: * Battery functions */ + uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; + + int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; + private: int modemConnect(const char* host, uint16_t port, uint8_t mux) { @@ -570,12 +581,12 @@ public: sockets[mux]->rx.put(stream.read()); } data = ""; - return index; } else if (data.endsWith(GF("+TCPCLOSE:"))) { int mux = stream.readStringUntil(',').toInt(); stream.readStringUntil('\n'); sockets[mux]->sock_connected = false; data = ""; + DBG("### Closed: ", mux); } } } while (millis() - startMillis < timeout); From bbe6d1074890bc1f062eaaf3397b11338cb3e25d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 09:02:49 +0300 Subject: [PATCH 33/82] Add function stubs --- TinyGsmClientA6.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index b37e303..28391d3 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -107,7 +107,6 @@ public: } virtual int available() { - //DBG("available?"); TINY_GSM_YIELD(); if (!rx.size() && sock_connected) { at->maintain(); @@ -116,7 +115,6 @@ public: } virtual int read(uint8_t *buf, size_t size) { - //DBG("read:", size); TINY_GSM_YIELD(); size_t cnt = 0; while (cnt < size) { @@ -154,6 +152,13 @@ public: return sock_connected; } virtual operator bool() { return connected(); } + + /* + * Extended API + */ + + String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + private: TinyGsm* at; uint8_t mux; @@ -361,15 +366,6 @@ public: return false; } - /* - sendAT(GF("+CIFSR")); - String data; - if (waitResponse(10000L, data) != 1) { - data.replace(GSM_NL, ""); - return false; - } - */ - return true; } @@ -444,6 +440,10 @@ public: * Battery functions */ + uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; + + int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; + private: bool modemConnect(const char* host, uint16_t port, uint8_t* mux) { From 22e7464a083d817dcc5cfdb2d10202cd3f2c7051 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 09:18:35 +0300 Subject: [PATCH 34/82] Add localIP() --- TinyGsmClientA6.h | 2 ++ TinyGsmClientESP8266.h | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 28391d3..f6d8731 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -384,6 +384,8 @@ public: return res; } + IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + /* * Phone Call functions */ diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index ac6e697..41e1dc8 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -134,6 +134,13 @@ public: return sock_connected; } virtual operator bool() { return connected(); } + + /* + * Extended API + */ + + String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + private: TinyGsm* at; uint8_t mux; @@ -237,6 +244,10 @@ public: return waitResponse(10000L) == 1; } + String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + + IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + private: int modemConnect(const char* host, uint16_t port, uint8_t mux) { From 5b0e72f6bce2462c8b748b95136a12d5484300b9 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 09:19:03 +0300 Subject: [PATCH 35/82] Add localIP() --- TinyGsmClientM590.h | 4 +++- TinyGsmClientSIM800.h | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 7e2ec26..9646da1 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -387,6 +387,8 @@ public: String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + /* * Phone Call functions */ @@ -448,7 +450,7 @@ public: private: - int modemConnect(const char* host, uint16_t port, uint8_t mux) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux) { for (int i=0; i<3; i++) { // TODO: no need for loop? String ip = dnsIpQuery(host); diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 9bd762d..ef17935 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -109,7 +109,7 @@ public: virtual int available() { TINY_GSM_YIELD(); - if (sock_connected && !rx.size()) { + if (!rx.size() && sock_connected) { // Workaround: sometimes SIM800 forgets to notify about data arrival. // TODO: Currently we ping the module periodically, // but maybe there's a better indicator that we need to poll @@ -446,9 +446,7 @@ public: } sendAT(GF("+CIFSR;E0")); - String data; - if (waitResponse(10000L, data) != 1) { - data.replace(GSM_NL, ""); + if (waitResponse(10000L) != 1) { return false; } @@ -475,6 +473,8 @@ public: return res; } + IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + /* * Phone Call functions */ @@ -598,7 +598,8 @@ public: } private: - int modemConnect(const char* host, uint16_t port, uint8_t mux) { + + bool 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), From 8511ec054c0414b38c0282991aa9fb9271d078be Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 09:29:53 +0300 Subject: [PATCH 36/82] implement IPAddress localIP() --- TinyGsmClientA6.h | 6 +++++- TinyGsmClientSIM800.h | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index f6d8731..20ae5de 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -384,7 +384,11 @@ public: return res; } - IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + IPAddress localIP() { + IPAddress res; + res.fromString(getLocalIP()); + return res; + } /* * Phone Call functions diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index ef17935..cddd99f 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -473,7 +473,11 @@ public: return res; } - IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + IPAddress localIP() { + IPAddress res; + res.fromString(getLocalIP()); + return res; + } /* * Phone Call functions From c205fe0a3fdd9cc551874a332a216b1d5b368941 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 09:37:59 +0300 Subject: [PATCH 37/82] Fix build test --- TinyGsmClientA6.h | 2 +- TinyGsmClientM590.h | 2 +- TinyGsmClientSIM800.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 20ae5de..8303e91 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -406,7 +406,7 @@ public: return waitResponse() == 1; } - void callRedial() { + bool callRedial() { sendAT(GF("DLST")); return waitResponse() == 1; } diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 9646da1..23c0c5d 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -405,7 +405,7 @@ public: return waitResponse() == 1; } - void callRedial() TINY_GSM_ATTR_NOT_AVAILABLE; + bool callRedial() TINY_GSM_ATTR_NOT_AVAILABLE; bool callHangup(const String& number) { sendAT(GF("H"), number); diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index cddd99f..ac50aec 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -498,7 +498,7 @@ public: return waitResponse() == 1; } - void callRedial() { + bool callRedial() { sendAT(GF("DL")); return waitResponse() == 1; } From d50a3b3f537ad63931c9dc4beff333074d000104 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 18:51:23 +0300 Subject: [PATCH 38/82] Disable Phone Call functions --- TinyGsmClientM590.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 23c0c5d..ff57054 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -387,7 +387,11 @@ public: String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + IPAddress localIP() { + IPAddress res; + res.fromString(getLocalIP()); + return res; + } /* * Phone Call functions @@ -395,22 +399,13 @@ public: bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; - bool callAnswer() { - sendAT(GF("A")); - return waitResponse() == 1; - } + bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE; - bool callNumber(const String& number) { - sendAT(GF("D"), number); - return waitResponse() == 1; - } + bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; bool callRedial() TINY_GSM_ATTR_NOT_AVAILABLE; - bool callHangup(const String& number) { - sendAT(GF("H"), number); - return waitResponse() == 1; - } + bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE; /* * Messaging functions From cf797049c0ffa0e6e815ff2da6a508eb2e1e057d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 18:53:15 +0300 Subject: [PATCH 39/82] Add function test sketch. Fix #32 --- examples/AllFunctions/AllFunctions.ino | 155 +++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 examples/AllFunctions/AllFunctions.ino diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino new file mode 100644 index 0000000..d0e14df --- /dev/null +++ b/examples/AllFunctions/AllFunctions.ino @@ -0,0 +1,155 @@ +/************************************************************** + * + * TinyGSM Getting Started guide: + * http://tiny.cc/tiny-gsm-readme + * + * NOTE: + * Some of the functions may be unavailable for your modem. + * Just comment them out. + * + **************************************************************/ + +// Select your modem: +#define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 + +// Set serial for debug console (to the Serial Monitor, speed 115200) +#define SerialMon Serial + +// Set serial for AT commands (to the module) +// Use Hardware Serial on Mega, Leonardo, Micro +#define SerialAT Serial1 + +// or Software Serial on Uno, Nano +//#include +//SoftwareSerial SerialAT(2, 3); // RX, TX + + +//#define DUMP_AT_COMMANDS + +// Set phone numbers, if you want to test SMS and Calls +//#define SMS_TARGET "+380xxxxxxxxx" +//#define CALL_TARGET "+380xxxxxxxxx" + +// Your GPRS credentials +// Leave empty, if missing user or pass +const char apn[] = "YourAPN"; +const char user[] = ""; +const char pass[] = ""; + +#include + +#ifdef DUMP_AT_COMMANDS + #include + StreamDebugger debugger(SerialAT, SerialMon); + TinyGsm modem(debugger); +#else + TinyGsm modem(SerialAT); +#endif + +void setup() { + // Set console baud rate + SerialMon.begin(115200); + delay(10); + + // Set GSM module baud rate + SerialAT.begin(115200); + delay(3000); +} + +void loop() { + // Restart takes quite some time + // To skip it, call init() instead of restart() + DBG("Initializing modem..."); + if (!modem.restart()) { + delay(10000); + return; + } + + // Unlock your SIM card with a PIN + //modem.simUnlock("1234"); + + DBG("Waiting for network..."); + if (!modem.waitForNetwork()) { + delay(10000); + return; + } + + DBG("Connecting to", apn); + if (!modem.gprsConnect(apn, user, pass)) { + delay(10000); + return; + } + + bool res; + + String modemInfo = modem.getModemInfo(); + DBG("Modem:", modemInfo); + + String ccid = modem.getSimCCID(); + DBG("CCID:", ccid); + + String imei = modem.getIMEI(); + DBG("IMEI:", imei); + + String cop = modem.getOperator(); + DBG("Operator:", cop); + + IPAddress local = modem.localIP(); + DBG("Local IP:", local); + + int csq = modem.getSignalQuality(); + DBG("Signal quality:", csq); + + int battLevel = modem.getBattPercent(); + DBG("Battery lavel:", battLevel); + + // This is only supported on SIMxxx series + float battVoltage = modem.getBattVoltage() / 1000.0F; + DBG("Battery voltage:", battVoltage); + + // This is only supported on SIMxxx series + String gsmLoc = modem.getGsmLocation(); + DBG("GSM location:", gsmLoc); + + String ussd_balance = modem.sendUSSD("*111#"); + DBG("Balance (USSD):", ussd_balance); + + String ussd_phone_num = modem.sendUSSD("*161#"); + DBG("Phone number (USSD):", ussd_phone_num); + +#ifdef SMS_TARGET + res = modem.sendSMS(SMS_TARGET, String("Hello from ") + imei); + DBG("SMS:", res ? "OK" : "fail"); + + // This is only supported on SIMxxx series + res = modem.sendSMS_UTF16(SMS_TARGET, u"Привіііт!", 9); + DBG("UTF16 SMS:", res ? "OK" : "fail"); +#endif + +#ifdef CALL_TARGET + // This is NOT supported on M590 + res = modem.callNumber(CALL_TARGET); + DBG("Call:", res ? "OK" : "fail"); + + if (res) { + delay(5000L); + + res = modem.callHangup(); + DBG("Hang up:", res ? "OK" : "fail"); + } +#endif + + modem.gprsDisconnect(); + DBG("GPRS disconnected"); + + // Do nothing forevermore + while (true) { + delay(1000); + } +} + From 96175a0b931cfd6892e312034e5d1b5a85e8ec7c Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 18:55:19 +0300 Subject: [PATCH 40/82] Add callNumber, sendUSSD, getBattPercent --- TinyGsmClientA6.h | 87 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 8303e91..15e8367 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -401,18 +401,31 @@ public: return waitResponse() == 1; } + // Returns true on pick-up, false on error/busy bool callNumber(const String& number) { - sendAT(GF("D"), number); - return waitResponse() == 1; - } + sendAT(GF("D\""), number, "\";"); + if (waitResponse() != 1) { + return false; + } - bool callRedial() { - sendAT(GF("DLST")); - return waitResponse() == 1; + if (waitResponse(60000L, GF(GSM_NL "+CIEV: \"CALL\",1")) != 1) { + return false; + } + + int rsp = waitResponse(60000L, GF(GSM_NL "+CIEV: \"SOUNDER\",0")); + + int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL)); + + return rsp == 1 && rsp2 == 0; } - bool callHangup(const String& number) { - sendAT(GF("H"), number); + //bool callRedial() { + // sendAT(GF("DLST")); + // return waitResponse() == 1; + //} + + bool callHangup() { + sendAT(GF("H")); return waitResponse() == 1; } @@ -420,7 +433,27 @@ public: * Messaging functions */ - void sendUSSD() TINY_GSM_ATTR_NOT_IMPLEMENTED; + String sendUSSD(const String& code) { + sendAT(GF("+CSCS=HEX")); + waitResponse(); + sendAT(GF("+CUSD=1,\""), code, GF("\",15")); + if (waitResponse(10000L) != 1) { + return ""; + } + if (waitResponse(GF(GSM_NL "+CUSD:")) != 1) { + return ""; + } + stream.readStringUntil('"'); + String hex = stream.readStringUntil('"'); + stream.readStringUntil(','); + int dcs = stream.readStringUntil('\n').toInt(); + + if (dcs == 15) { + return decodeHex7bit(hex); + } else { + return hex; + } + } bool sendSMS(const String& number, const String& text) { sendAT(GF("+CMGF=1")); @@ -448,7 +481,16 @@ public: uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; - int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; + int getBattPercent() { + sendAT(GF("+CBC?")); + if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + return false; + } + stream.readStringUntil(','); + int res = stream.readStringUntil('\n').toInt(); + waitResponse(); + return res; + } private: @@ -492,6 +534,31 @@ private: return 1 == res; } + static String decodeHex7bit(String &instr) { + String result; + byte reminder = 0; + int bitstate = 7; + for (unsigned i=0; i> bitstate; + bitstate--; + if (bitstate == 0) { + char c = reminder; + result += c; + reminder = 0; + bitstate = 7; + } + } + return result; + } + public: /* Utilities */ From 1b5884dcb717268fb5c1de42cc99a2121ff2dbff Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 18:56:19 +0300 Subject: [PATCH 41/82] Add getModemInfo, callNumber, sendUSSD --- TinyGsmClientSIM800.h | 51 +++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index ac50aec..f887fb8 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -250,6 +250,16 @@ public: return waitResponse() == 1; } + String getModemInfo() { + sendAT(GF("I")); + String res; + if (waitResponse(1000L, res) != 1) { + return ""; + } + res.trim(); + return res; + } + /* * Power functions */ @@ -494,17 +504,23 @@ public: } bool callNumber(const String& number) { - sendAT(GF("D"), number); - return waitResponse() == 1; + sendAT(GF("D"), number, ";"); + int status = waitResponse(60000L, GF("OK"), GF("BUSY"), GF("NO ANSWER"), GF("NO CARRIER")); + switch (status) { + case 1: return true; + case 2: + case 3: return false; + default: return false; + } } - bool callRedial() { - sendAT(GF("DL")); - return waitResponse() == 1; - } + //bool callRedial() { + // sendAT(GF("DL")); + // return waitResponse() == 1; + //} - bool callHangup(const String& number) { - sendAT(GF("H"), number); + bool callHangup() { + sendAT(GF("H")); return waitResponse() == 1; } @@ -512,7 +528,21 @@ public: * Messaging functions */ - void sendUSSD() TINY_GSM_ATTR_NOT_IMPLEMENTED; + String sendUSSD(const String& code) { + sendAT(GF("+CSCS=\"8859-1\"")); + waitResponse(); + sendAT(GF("+CUSD=1,\""), code, GF("\"")); + if (waitResponse() != 1) { + return ""; + } + if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { + return ""; + } + stream.readStringUntil('"'); + String res = stream.readStringUntil('"'); + stream.readStringUntil('\n'); + return res; + } bool sendSMS(const String& number, const String& text) { sendAT(GF("+CMGF=1")); @@ -588,9 +618,6 @@ public: } int getBattPercent() { - if (!autoBaud()) { - return false; - } sendAT(GF("+CBC")); if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { return false; From 36568bb595d9878675154f9d85f940a1c9b72c1f Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:21:56 +0300 Subject: [PATCH 42/82] Fix getSimCCID, getModemInfo --- TinyGsmClientA6.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 15e8367..cc0eaac 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -221,6 +221,16 @@ public: return waitResponse() == 1; } + String getModemInfo() { + sendAT(GF("I")); + String res; + if (waitResponse(1000L, res) != 1) { + return ""; + } + res.trim(); + return res; + } + /* * Power functions */ @@ -250,7 +260,7 @@ public: String getSimCCID() { sendAT(GF("+CCID")); - if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { + if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); @@ -641,7 +651,9 @@ public: data = ""; } else if (data.endsWith(GF("+TCPCLOSED:"))) { int mux = stream.readStringUntil('\n').toInt(); - sockets[mux]->sock_connected = false; + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { + sockets[mux]->sock_connected = false; + } data = ""; DBG("### Closed: ", mux); } From 355d967a3583653f362697b1aa83070f0e0636c8 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:22:15 +0300 Subject: [PATCH 43/82] Add getModemInfo --- TinyGsmClientM590.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index ff57054..34e5d1d 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -226,6 +226,16 @@ public: return waitResponse() == 1; } + String getModemInfo() { + sendAT(GF("I")); + String res; + if (waitResponse(1000L, res) != 1) { + return ""; + } + res.trim(); + return res; + } + /* * Power functions */ @@ -581,7 +591,9 @@ public: } else if (data.endsWith(GF("+TCPCLOSE:"))) { int mux = stream.readStringUntil(',').toInt(); stream.readStringUntil('\n'); - sockets[mux]->sock_connected = false; + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { + sockets[mux]->sock_connected = false; + } data = ""; DBG("### Closed: ", mux); } From 226bcd5a466a957d538a8d5fb723fdaeb24c8251 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:22:32 +0300 Subject: [PATCH 44/82] Add warnings --- TinyGsmClientSIM800.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index f887fb8..4f981a1 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -503,6 +503,7 @@ public: return waitResponse() == 1; } + // Returns true on pick-up, false on error/busy bool callNumber(const String& number) { sendAT(GF("D"), number, ";"); int status = waitResponse(60000L, GF("OK"), GF("BUSY"), GF("NO ANSWER"), GF("NO CARRIER")); @@ -795,6 +796,7 @@ public: sockets[mux]->sock_connected = false; } data = ""; + DBG("### Closed: ", mux); } } } while (millis() - startMillis < timeout); From 4908d78f62a4e45da80f5b00d96120e873ac939b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:39:37 +0300 Subject: [PATCH 45/82] Add poweroff --- examples/AllFunctions/AllFunctions.ino | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index d0e14df..ca7f477 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -30,6 +30,7 @@ //#define DUMP_AT_COMMANDS +#define TINY_GSM_DEBUG SerialMon // Set phone numbers, if you want to test SMS and Calls //#define SMS_TARGET "+380xxxxxxxxx" @@ -70,6 +71,9 @@ void loop() { return; } + String modemInfo = modem.getModemInfo(); + DBG("Modem:", modemInfo); + // Unlock your SIM card with a PIN //modem.simUnlock("1234"); @@ -87,9 +91,6 @@ void loop() { bool res; - String modemInfo = modem.getModemInfo(); - DBG("Modem:", modemInfo); - String ccid = modem.getSimCCID(); DBG("CCID:", ccid); @@ -147,9 +148,14 @@ void loop() { modem.gprsDisconnect(); DBG("GPRS disconnected"); + // Try to power-off (modem may decide to restart automatically) + // To turn off modem completely, please use Reset/Enable pins + modem.poweroff(); + DBG("Poweroff."); + // Do nothing forevermore while (true) { - delay(1000); + modem.maintain(); } } From a58079bf86a3ebe82b4098e16301d29e7b0a0a48 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:39:51 +0300 Subject: [PATCH 46/82] Add poweroff() --- TinyGsmClientSIM800.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 4f981a1..978fc37 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -256,6 +256,8 @@ public: if (waitResponse(1000L, res) != 1) { return ""; } + res.replace(GSM_NL "OK" GSM_NL, ""); + res.replace(GSM_NL, ""); res.trim(); return res; } @@ -280,6 +282,11 @@ public: return init(); } + bool poweroff() { + sendAT(GF("+CPOWD=1")); + return waitResponse(GF("NORMAL POWER DOWN")) == 1; + } + bool radioOff() { if (!autoBaud()) { return false; From b5c25a6cef781f6acf2e6490433125ff2aaa9b72 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:40:09 +0300 Subject: [PATCH 47/82] Fix getModemInfo() --- TinyGsmClientA6.h | 2 ++ TinyGsmClientM590.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index cc0eaac..756bca9 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -227,6 +227,8 @@ public: if (waitResponse(1000L, res) != 1) { return ""; } + res.replace(GSM_NL "OK" GSM_NL, ""); + res.replace(GSM_NL, ""); res.trim(); return res; } diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 34e5d1d..c8c94ba 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -232,6 +232,8 @@ public: if (waitResponse(1000L, res) != 1) { return ""; } + res.replace(GSM_NL "OK" GSM_NL, ""); + res.replace(GSM_NL, ""); res.trim(); return res; } From 601892d106bb7646c67a47ae1b10cacdead9c394 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:56:56 +0300 Subject: [PATCH 48/82] Add debug --- examples/AllFunctions/AllFunctions.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index ca7f477..0d027c8 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -63,6 +63,7 @@ void setup() { } void loop() { + // Restart takes quite some time // To skip it, call init() instead of restart() DBG("Initializing modem..."); @@ -133,6 +134,8 @@ void loop() { #endif #ifdef CALL_TARGET + DBG("Calling:", CALL_TARGET); + // This is NOT supported on M590 res = modem.callNumber(CALL_TARGET); DBG("Call:", res ? "OK" : "fail"); From 2b099c6e7340769902388ca5eb7dbf7a81f1e458 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 19:57:23 +0300 Subject: [PATCH 49/82] Support NO ANSWER in callNumber --- TinyGsmClientA6.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 756bca9..69f04f9 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -228,7 +228,7 @@ public: return ""; } res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, ""); + res.replace(GSM_NL, " "); res.trim(); return res; } @@ -420,13 +420,13 @@ public: return false; } - if (waitResponse(60000L, GF(GSM_NL "+CIEV: \"CALL\",1")) != 1) { + if (waitResponse(60000L, GF(GSM_NL "+CIEV: \"CALL\",1"), GF(GSM_NL "+CIEV: \"CALL\",0")) != 1) { return false; } - int rsp = waitResponse(60000L, GF(GSM_NL "+CIEV: \"SOUNDER\",0")); + int rsp = waitResponse(60000L, GF(GSM_NL "+CIEV: \"SOUNDER\",0"), GF(GSM_NL "+CIEV: \"CALL\",0")); - int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL)); + int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL), GF(GSM_NL "NO ANSWER" GSM_NL)); return rsp == 1 && rsp2 == 0; } From f738bfd6d8764d05ac5118ac50ee5040015c17df Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 20:07:46 +0300 Subject: [PATCH 50/82] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c117f5b..486bb15 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,11 @@ Watch this repo for new updates! And of course, contributions are welcome ;) Many GSM modems, WiFi and radio modules can be controlled by sending AT commands over Serial. TinyGSM knows which commands to send, and how to handle AT responses, and wraps that into standard Arduino Client interface. +## API Reference + +For GPRS data streams, this library provides the standard [Arduino Client](https://www.arduino.cc/en/Reference/ClientConstructor) interface. +For additional functions, please refer to [this example sketch](examples/AllFunctions/AllFunctions.ino) + ## Troubleshooting ### SoftwareSerial problems From ba98d718094df56da19d4ac4ba0333b5fd7b7cf4 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 22:45:08 +0300 Subject: [PATCH 51/82] Add Modem Info to all examples --- examples/BlynkClient/BlynkClient.ino | 4 ++++ examples/FileDownload/FileDownload.ino | 4 ++++ examples/MqttClient/MqttClient.ino | 4 ++++ examples/WebClient/WebClient.ino | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/examples/BlynkClient/BlynkClient.ino b/examples/BlynkClient/BlynkClient.ino index 434c474..5264c79 100644 --- a/examples/BlynkClient/BlynkClient.ino +++ b/examples/BlynkClient/BlynkClient.ino @@ -73,6 +73,10 @@ void setup() Serial.println("Initializing modem..."); modem.restart(); + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + // Unlock your SIM card with a PIN //modem.simUnlock("1234"); diff --git a/examples/FileDownload/FileDownload.ino b/examples/FileDownload/FileDownload.ino index 164695a..e3c56ce 100644 --- a/examples/FileDownload/FileDownload.ino +++ b/examples/FileDownload/FileDownload.ino @@ -61,6 +61,10 @@ void setup() { Serial.println("Initializing modem..."); modem.restart(); + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + // Unlock your SIM card with a PIN //modem.simUnlock("1234"); } diff --git a/examples/MqttClient/MqttClient.ino b/examples/MqttClient/MqttClient.ino index d85d5ec..9327462 100644 --- a/examples/MqttClient/MqttClient.ino +++ b/examples/MqttClient/MqttClient.ino @@ -80,6 +80,10 @@ void setup() { Serial.println("Initializing modem..."); modem.restart(); + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + // Unlock your SIM card with a PIN //modem.simUnlock("1234"); diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index 44b7d66..504e47c 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -53,6 +53,10 @@ void setup() { Serial.println(F("Initializing modem...")); modem.restart(); + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + // Unlock your SIM card with a PIN //modem.simUnlock("1234"); } From a33cfd1505310a5deeb851816b01a64e5a163c7d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 11 Sep 2017 22:58:44 +0300 Subject: [PATCH 52/82] Fix #74 --- examples/HttpClient/HttpClient.ino | 151 +++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 examples/HttpClient/HttpClient.ino diff --git a/examples/HttpClient/HttpClient.ino b/examples/HttpClient/HttpClient.ino new file mode 100644 index 0000000..1b8029b --- /dev/null +++ b/examples/HttpClient/HttpClient.ino @@ -0,0 +1,151 @@ +/************************************************************** + * + * This sketch connects to a website and downloads a page. + * It can be used to perform HTTP/RESTful API calls. + * + * For this example, you need to install ArduinoHttpClient library: + * https://github.com/arduino-libraries/ArduinoHttpClient + * or from http://librarymanager/all#ArduinoHttpClient + * + * TinyGSM Getting Started guide: + * http://tiny.cc/tiny-gsm-readme + * + **************************************************************/ + +// Select your modem: +#define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM900 +// #define TINY_GSM_MODEM_A6 +// #define TINY_GSM_MODEM_A7 +// #define TINY_GSM_MODEM_M590 +// #define TINY_GSM_MODEM_ESP8266 + +// Increase RX buffer +#define TINY_GSM_RX_BUFFER 512 + +// Use Hardware Serial on Mega, Leonardo, Micro +#define SerialAT Serial1 + +// or Software Serial on Uno, Nano +//#include +//SoftwareSerial SerialAT(2, 3); // RX, TX + +//#define DUMP_AT_COMMANDS +//#define TINY_GSM_DEBUG Serial + + +// Your GPRS credentials +// Leave empty, if missing user or pass +const char apn[] = "YourAPN"; +const char user[] = ""; +const char pass[] = ""; + +// Name of the server we want to connect to +const char server[] = "cdn.rawgit.com"; +const int port = 80; +// Path to download (this is the bit after the hostname in the URL) +const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; + +#include +#include + +#ifdef DUMP_AT_COMMANDS + #include + StreamDebugger debugger(SerialAT, Serial); + TinyGsm modem(debugger); +#else + TinyGsm modem(SerialAT); +#endif + +TinyGsmClient client(modem); +HttpClient http(client, server, port); + +void setup() { + // Set console baud rate + Serial.begin(115200); + delay(10); + + // Set GSM module baud rate + SerialAT.begin(115200); + delay(3000); + + // Restart takes quite some time + // To skip it, call init() instead of restart() + Serial.println("Initializing modem..."); + modem.restart(); + + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + + // Unlock your SIM card with a PIN + //modem.simUnlock("1234"); +} + +void loop() { + Serial.print(F("Waiting for network...")); + if (!modem.waitForNetwork()) { + Serial.println(" fail"); + delay(10000); + return; + } + Serial.println(" OK"); + + Serial.print(F("Connecting to ")); + Serial.print(apn); + if (!modem.gprsConnect(apn, user, pass)) { + Serial.println(" fail"); + delay(10000); + return; + } + Serial.println(" OK"); + + + Serial.print(F("Performing HTTP GET request... ")); + int err = http.get(resource); + if (err != 0) { + Serial.println("failed to connect"); + delay(10000); + return; + } + + int status = http.responseStatusCode(); + Serial.println(status); + if (!status) { + delay(10000); + return; + } + + while (http.headerAvailable()) { + String headerName = http.readHeaderName(); + String headerValue = http.readHeaderValue(); + //Serial.println(headerName + " : " + headerValue); + } + + int length = http.contentLength(); + if (length >= 0) { + Serial.println(String("Content length is: ") + length); + } + if (http.isResponseChunked()) { + Serial.println("This response is chunked"); + } + + String body = http.responseBody(); + Serial.println("Response:"); + Serial.println(body); + + Serial.println(String("Body length is: ") + body.length()); + + // Shutdown + + http.stop(); + + modem.gprsDisconnect(); + Serial.println("GPRS disconnected"); + + // Do nothing forevermore + while (true) { + delay(1000); + } +} + From 16b6c853fe337b882dec2c867afef149605c520b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 01:30:40 +0300 Subject: [PATCH 53/82] decodeHex16bit support for sendUSSD --- TinyGsmClientA6.h | 29 +++++++++++++++++++++--- TinyGsmClientSIM800.h | 51 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 69f04f9..9af5bb6 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -446,7 +446,9 @@ public: */ String sendUSSD(const String& code) { - sendAT(GF("+CSCS=HEX")); + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CSCS=\"HEX\"")); waitResponse(); sendAT(GF("+CUSD=1,\""), code, GF("\",15")); if (waitResponse(10000L) != 1) { @@ -462,6 +464,8 @@ public: if (dcs == 15) { return decodeHex7bit(hex); + } else if (dcs == 72) { + return decodeHex16bit(hex); } else { return hex; } @@ -539,8 +543,8 @@ private: return len; } - bool modemGetConnected(uint8_t mux) { //TODO mux? - sendAT(GF("+CIPSTATUS")); + bool modemGetConnected(uint8_t mux) { + sendAT(GF("+CIPSTATUS")); //TODO mux? int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); waitResponse(); return 1 == res; @@ -571,6 +575,25 @@ private: return result; } + static String decodeHex16bit(String &instr) { + String result; + for (unsigned i=0; i Date: Tue, 12 Sep 2017 01:31:11 +0300 Subject: [PATCH 54/82] poweroff, localIP, sendUSSD support --- TinyGsmClientM590.h | 81 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index c8c94ba..35ee3c4 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -233,7 +233,7 @@ public: return ""; } res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, ""); + res.replace(GSM_NL, " "); res.trim(); return res; } @@ -255,7 +255,10 @@ public: return init(); } - bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool poweroff() { + sendAT(GF("+CPWROFF")); + return waitResponse(3000L) == 1; + } /* * SIM card functions @@ -397,7 +400,17 @@ public: return waitResponse(60000L) == 1; } - String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + String getLocalIP() { + sendAT(GF("+XIIC?")); + if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { + return ""; + } + stream.readStringUntil(','); + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } IPAddress localIP() { IPAddress res; @@ -423,10 +436,35 @@ public: * Messaging functions */ - void sendUSSD() TINY_GSM_ATTR_NOT_IMPLEMENTED; + String sendUSSD(const String& code) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CSCS=\"HEX\"")); + waitResponse(); + sendAT(GF("D"), code); + if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { + return ""; + } + stream.readStringUntil('"'); + String hex = stream.readStringUntil('"'); + stream.readStringUntil(','); + int dcs = stream.readStringUntil('\n').toInt(); + + if (waitResponse() != 1) { + return ""; + } + + if (dcs == 15) { + return decodeHex8bit(hex); + } else if (dcs == 72) { + return decodeHex16bit(hex); + } else { + return hex; + } + } bool sendSMS(const String& number, const String& text) { - sendAT(GF("+CSCS=\"gsm\"")); + sendAT(GF("+CSCS=\"GSM\"")); waitResponse(); sendAT(GF("+CMGF=1")); waitResponse(); @@ -440,6 +478,8 @@ public: return waitResponse(60000L) == 1; } + bool sendSMS_UTF16(const String& number, const void* text, size_t len) + TINY_GSM_ATTR_NOT_AVAILABLE; /* * Location functions @@ -510,6 +550,37 @@ private: return res; } + static String decodeHex8bit(String &instr) { + String result; + for (unsigned i=0; i Date: Tue, 12 Sep 2017 01:31:31 +0300 Subject: [PATCH 55/82] Use TinyGsmAutoBaud --- examples/AllFunctions/AllFunctions.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index 0d027c8..b3a8c62 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -58,7 +58,7 @@ void setup() { delay(10); // Set GSM module baud rate - SerialAT.begin(115200); + TinyGsmAutoBaud(SerialAT); delay(3000); } @@ -107,6 +107,7 @@ void loop() { int csq = modem.getSignalQuality(); DBG("Signal quality:", csq); + // This is NOT supported on M590 int battLevel = modem.getBattPercent(); DBG("Battery lavel:", battLevel); From b534d6a5f6a2c61f5e90c9320643f28653cfc4ad Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 01:31:43 +0300 Subject: [PATCH 56/82] Add TinyGsmAutoBaud --- TinyGsmCommon.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/TinyGsmCommon.h b/TinyGsmCommon.h index 60a5e48..e0a37aa 100644 --- a/TinyGsmCommon.h +++ b/TinyGsmCommon.h @@ -71,4 +71,26 @@ const T& TinyGsmMax(const T& a, const T& b) return (b < a) ? a : b; } +template +uint32_t TinyGsmAutoBaud(T& SerialAT) +{ + static uint32_t rates[] = { 115200, 57600, 38400, 19200, 9600, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 }; + + for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) { + uint32_t rate = rates[i]; + DBG("Trying baud rate", rate, "..."); + SerialAT.begin(rate); + delay(10); + for (int i=0; i<3; i++) { + SerialAT.print("AT\r\n"); + String input = SerialAT.readString(); + if (input.indexOf("OK") >= 0) { + DBG("Modem responded at rate", rate); + return rate; + } + } + } + return 0; +} + #endif From 4a74e86be0bec091e5c2a35c257dd86ed8cf915c Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 01:39:39 +0300 Subject: [PATCH 57/82] Use TinyGsmAutoBaud --- tools/AT_Debug/AT_Debug.ino | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/tools/AT_Debug/AT_Debug.ino b/tools/AT_Debug/AT_Debug.ino index ef53630..f850f3b 100644 --- a/tools/AT_Debug/AT_Debug.ino +++ b/tools/AT_Debug/AT_Debug.ino @@ -16,8 +16,6 @@ // #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_ESP8266 -#include - // Set serial for debug console (to the Serial Monitor, speed 115200) #define SerialMon Serial @@ -29,7 +27,9 @@ //#include //SoftwareSerial SerialAT(2, 3); // RX, TX -TinyGsm modem(SerialAT); +#define TINY_GSM_DEBUG SerialMon + +#include // Module baud rate uint32_t rate = 0; // Set to 0 for Auto-Detect @@ -43,21 +43,7 @@ void setup() { void loop() { if (!rate) { - static uint32_t rates[] = { 115200, 9600, 57600, 19200, 38400, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 }; - - SerialMon.println("Autodetecting baud rate"); - for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) { - SerialMon.print(String("Trying baud rate ") + rates[i] + "... "); - SerialAT.begin(rates[i]); - delay(10); - if (modem.autoBaud(1000)) { - rate = rates[i]; - SerialMon.println(F("OK")); - break; - } else { - SerialMon.println(F("fail")); - } - } + rate = TinyGsmAutoBaud(SerialAT); } if (!rate) { From 34cabe2159013f946290ab769b3b5c4ddc0e4e3e Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 09:27:30 +0300 Subject: [PATCH 58/82] Add feature table --- README.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 486bb15..e6b54e9 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ You can also join our chat: ### Arduino Client interface support This library is easy to integrate with lots of sketches, which use Ethernet or WiFi. -Examples for **PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **Web Client** and **File Download** are provided. +**PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **HTTP Client** and **File Download** examples are provided. ![examples](/extras/examples.png) @@ -33,7 +33,32 @@ Arduino GSM library uses 15868 bytes (49%) of Flash and 1113 bytes (54%) of RAM TinyGSM also pulls data gently from the modem (whenever possible), so it can operate on very little RAM. **Now, you have more space for your experiments.** -### Supported modem models +## Features + +Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 +--- | --- | --- | --- | --- | --- +**Data connections** +TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ +UDP | | | | | +SSL/TLS (HTTPS) | 🅧 | 🅧 | 🅧 | 🅧 | ◌ +**USSD** +Sending USSD requests | ✔ | ✔ | ✔ | ✔ | 🅧 +Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | 🅧 +**SMS** +Sending | ✔ | ✔ | ✔ | ✔ | 🅧 +Sending Unicode | ✔ | ✔ | ◌ | 🅧 | 🅧 +Receiving/Reading | | | | | 🅧 +**Calls** +Dial, hangup | ✔ | ✔ | ✔ | 🅧 | 🅧 +Receiving calls | ◌ | ◌ | ◌ | 🅧 | 🅧 +**Location** +GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 +GPS/GNSS | 🅧 | | | 🅧 | 🅧 + +✔ - implemented  ◌ - planned  🅧 - not available for this modem + +## Supported modems + - [x] SIMCom SIM800 series (SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868) - [x] SIMCom SIM900 series (SIM900A, SIM900D, SIM908, SIM968) - [x] AI-Thinker A6, A6C, A7 From 7f2466e67a814e794cc457d88c74ef5d35f5024b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 10:04:51 +0300 Subject: [PATCH 59/82] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6b54e9..686a22b 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 **Data connections** TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ UDP | | | | | -SSL/TLS (HTTPS) | 🅧 | 🅧 | 🅧 | 🅧 | ◌ +SSL/TLS (HTTPS) | ◌ | ◌ | 🅧 | 🅧 | ◌ **USSD** Sending USSD requests | ✔ | ✔ | ✔ | ✔ | 🅧 Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | 🅧 From d9cc4d4e32a3653853f8e982c6881e4c9f5cd881 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 10:07:15 +0300 Subject: [PATCH 60/82] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 686a22b..9d0cc74 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Receiving/Reading | | | | | 🅧 **Calls** Dial, hangup | ✔ | ✔ | ✔ | 🅧 | 🅧 Receiving calls | ◌ | ◌ | ◌ | 🅧 | 🅧 +DTMF decoding | | | 🅧 | 🅧 | 🅧 **Location** GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 GPS/GNSS | 🅧 | | | 🅧 | 🅧 From 4f4d0b1b90c6063df674b9d95b3a0e8faa0c4a5b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 11:28:38 +0300 Subject: [PATCH 61/82] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9d0cc74..1eb4a18 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 **Data connections** TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ UDP | | | | | -SSL/TLS (HTTPS) | ◌ | ◌ | 🅧 | 🅧 | ◌ +SSL/TLS (HTTPS) | ◌¹ | ◌¹ | 🅧 | 🅧 | ◌ **USSD** Sending USSD requests | ✔ | ✔ | ✔ | ✔ | 🅧 Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | 🅧 @@ -54,9 +54,10 @@ Receiving calls | ◌ | ◌ | ◌ | 🅧 | 🅧 DTMF decoding | | | 🅧 | 🅧 | 🅧 **Location** GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 -GPS/GNSS | 🅧 | | | 🅧 | 🅧 +GPS/GNSS | 🅧 | ◌ | ◌¹ | 🅧 | 🅧 -✔ - implemented  ◌ - planned  🅧 - not available for this modem +✔ - implemented  ◌ - planned  🅧 - not available for this modem +¹ - supported only on some models or firmware revisions ## Supported modems From 38437f5c03251fbde05e2d231451a1617a631a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brun=20von=20der=20G=C3=B6nne?= Date: Tue, 12 Sep 2017 10:46:59 +0200 Subject: [PATCH 62/82] copied sim800 to sim808 --- TinyGsmClientSIM808.h | 883 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 883 insertions(+) create mode 100644 TinyGsmClientSIM808.h diff --git a/TinyGsmClientSIM808.h b/TinyGsmClientSIM808.h new file mode 100644 index 0000000..6b50293 --- /dev/null +++ b/TinyGsmClientSIM808.h @@ -0,0 +1,883 @@ +/** + * @file TinyGsmClientSIM800.h + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef TinyGsmClientSIM800_h +#define TinyGsmClientSIM800_h + +//#define TINY_GSM_DEBUG Serial +//#define TINY_GSM_USE_HEX + +#if !defined(TINY_GSM_RX_BUFFER) + #define TINY_GSM_RX_BUFFER 64 +#endif + +#define TINY_GSM_MUX_COUNT 5 + +#include + +#define GSM_NL "\r\n" +static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; +static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; + +enum SimStatus { + SIM_ERROR = 0, + SIM_READY = 1, + SIM_LOCKED = 2, +}; + +enum RegStatus { + REG_UNREGISTERED = 0, + REG_SEARCHING = 2, + REG_DENIED = 3, + REG_OK_HOME = 1, + REG_OK_ROAMING = 5, + REG_UNKNOWN = 4, +}; + + +class TinyGsm +{ + +public: + +class GsmClient : public Client +{ + friend class TinyGsm; + typedef TinyGsmFifo RxFifo; + +public: + GsmClient() {} + + GsmClient(TinyGsm& modem, uint8_t mux = 1) { + init(&modem, mux); + } + + bool init(TinyGsm* modem, uint8_t mux = 1) { + this->at = modem; + this->mux = mux; + sock_available = 0; + prev_check = 0; + sock_connected = false; + got_data = false; + + at->sockets[mux] = this; + + return true; + } + +public: + virtual int connect(const char *host, uint16_t port) { + TINY_GSM_YIELD(); + rx.clear(); + sock_connected = at->modemConnect(host, port, mux); + return sock_connected; + } + + virtual int connect(IPAddress ip, uint16_t port) { + String host; host.reserve(16); + host += ip[0]; + host += "."; + host += ip[1]; + host += "."; + host += ip[2]; + host += "."; + host += ip[3]; + return connect(host.c_str(), port); + } + + virtual void stop() { + TINY_GSM_YIELD(); + at->sendAT(GF("+CIPCLOSE="), mux); + sock_connected = false; + at->waitResponse(); + } + + virtual size_t write(const uint8_t *buf, size_t size) { + TINY_GSM_YIELD(); + at->maintain(); + return at->modemSend(buf, size, mux); + } + + virtual size_t write(uint8_t c) { + return write(&c, 1); + } + + virtual int available() { + TINY_GSM_YIELD(); + if (!rx.size() && sock_connected) { + // Workaround: sometimes SIM800 forgets to notify about data arrival. + // TODO: Currently we ping the module periodically, + // but maybe there's a better indicator that we need to poll + if (millis() - prev_check > 500) { + got_data = true; + prev_check = millis(); + } + at->maintain(); + } + return rx.size() + sock_available; + } + + virtual int read(uint8_t *buf, size_t size) { + TINY_GSM_YIELD(); + at->maintain(); + size_t cnt = 0; + while (cnt < size) { + size_t chunk = TinyGsmMin(size-cnt, rx.size()); + if (chunk > 0) { + rx.get(buf, chunk); + buf += chunk; + cnt += chunk; + continue; + } + // TODO: Read directly into user buffer? + at->maintain(); + if (sock_available > 0) { + at->modemRead(rx.free(), mux); + } else { + break; + } + } + return cnt; + } + + virtual int read() { + uint8_t c; + if (read(&c, 1) == 1) { + return c; + } + return -1; + } + + virtual int peek() { return -1; } //TODO + virtual void flush() { at->stream.flush(); } + + virtual uint8_t connected() { + if (available()) { + return true; + } + return sock_connected; + } + virtual operator bool() { return connected(); } + + /* + * Extended API + */ + + String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + +private: + TinyGsm* at; + uint8_t mux; + uint16_t sock_available; + uint32_t prev_check; + bool sock_connected; + bool got_data; + RxFifo rx; +}; + +public: + + TinyGsm(Stream& stream) + : stream(stream) + { + memset(sockets, 0, sizeof(sockets)); + } + + /* + * Basic functions + */ + bool begin() { + return init(); + } + + bool init() { + if (!autoBaud()) { + return false; + } + sendAT(GF("&FZ")); // Factory + Reset + waitResponse(); + sendAT(GF("E0")); // Echo Off + if (waitResponse() != 1) { + return false; + } + getSimStatus(); + return true; + } + + bool autoBaud(unsigned long timeout = 10000L) { + //streamWrite(GF("AAAAA" GSM_NL)); // TODO: extra A's to help detect the baud rate + for (unsigned long start = millis(); millis() - start < timeout; ) { + sendAT(GF("")); + if (waitResponse(200) == 1) { + delay(100); + return true; + } + delay(100); + } + return false; + } + + void maintain() { + for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { + GsmClient* sock = sockets[mux]; + if (sock && sock->got_data) { + sock->got_data = false; + sock->sock_available = modemGetAvailable(mux); + } + } + while (stream.available()) { + waitResponse(10, NULL, NULL); + } + } + + bool factoryDefault() { + sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write + waitResponse(); + sendAT(GF("+IPR=0")); // Auto-baud + waitResponse(); + sendAT(GF("+IFC=0,0")); // No Flow Control + waitResponse(); + sendAT(GF("+ICF=3,3")); // 8 data 0 parity 1 stop + waitResponse(); + sendAT(GF("+CSCLK=0")); // Disable Slow Clock + waitResponse(); + sendAT(GF("&W")); // Write configuration + return waitResponse() == 1; + } + + String getModemInfo() { + sendAT(GF("I")); + String res; + if (waitResponse(1000L, res) != 1) { + return ""; + } + res.replace(GSM_NL "OK" GSM_NL, ""); + res.replace(GSM_NL, " "); + res.trim(); + return res; + } + + /* + * Power functions + */ + + bool restart() { + if (!autoBaud()) { + return false; + } + sendAT(GF("+CFUN=0")); + if (waitResponse(10000L) != 1) { + return false; + } + sendAT(GF("+CFUN=1,1")); + if (waitResponse(10000L) != 1) { + return false; + } + delay(3000); + return init(); + } + + bool poweroff() { + sendAT(GF("+CPOWD=1")); + return waitResponse(GF("NORMAL POWER DOWN")) == 1; + } + + bool radioOff() { + if (!autoBaud()) { + return false; + } + sendAT(GF("+CFUN=0")); + if (waitResponse(10000L) != 1) { + return false; + } + delay(3000); + return true; + } + + /* + * SIM card functions + */ + + bool simUnlock(const char *pin) { + sendAT(GF("+CPIN=\""), pin, GF("\"")); + return waitResponse() == 1; + } + + String getSimCCID() { + sendAT(GF("+ICCID")); + if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } + + String getIMEI() { + sendAT(GF("+GSN")); + if (waitResponse(GF(GSM_NL)) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } + + 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(1000); + continue; + } + int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED")); + waitResponse(); + switch (status) { + case 2: + case 3: return SIM_LOCKED; + case 1: return SIM_READY; + default: return SIM_ERROR; + } + } + return SIM_ERROR; + } + + RegStatus getRegistrationStatus() { + sendAT(GF("+CREG?")); + if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { + return REG_UNKNOWN; + } + streamSkipUntil(','); // Skip format (0) + int status = stream.readStringUntil('\n').toInt(); + waitResponse(); + return (RegStatus)status; + } + + String getOperator() { + sendAT(GF("+COPS?")); + if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { + return ""; + } + streamSkipUntil('"'); // Skip mode and format + String res = stream.readStringUntil('"'); + waitResponse(); + return res; + } + + /* + * Generic network functions + */ + + int getSignalQuality() { + sendAT(GF("+CSQ")); + if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { + return 99; + } + int res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + + bool waitForNetwork(unsigned long timeout = 60000L) { + for (unsigned long start = millis(); millis() - start < timeout; ) { + RegStatus s = getRegistrationStatus(); + if (s == REG_OK_HOME || s == REG_OK_ROAMING) { + return true; + } + delay(1000); + } + return false; + } + + /* + * GPRS functions + */ + bool gprsConnect(const char* apn, const char* user, const char* pwd) { + gprsDisconnect(); + + sendAT(GF("+SAPBR=3,1,\"Contype\",\"GPRS\"")); + waitResponse(); + + sendAT(GF("+SAPBR=3,1,\"APN\",\""), apn, '"'); + waitResponse(); + + if (user) { + sendAT(GF("+SAPBR=3,1,\"USER\",\""), user, '"'); + waitResponse(); + } + if (pwd) { + sendAT(GF("+SAPBR=3,1,\"PWD\",\""), pwd, '"'); + waitResponse(); + } + + sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); + waitResponse(); + + sendAT(GF("+CGACT=1,1")); + waitResponse(60000L); + + // Open a GPRS context + sendAT(GF("+SAPBR=1,1")); + waitResponse(85000L); + // Query the GPRS context + sendAT(GF("+SAPBR=2,1")); + if (waitResponse(30000L) != 1) + return false; + + sendAT(GF("+CGATT=1")); + if (waitResponse(60000L) != 1) + return false; + + // TODO: wait AT+CGATT? + + sendAT(GF("+CIPMUX=1")); + if (waitResponse() != 1) { + return false; + } + + sendAT(GF("+CIPQSEND=1")); + if (waitResponse() != 1) { + return false; + } + + sendAT(GF("+CIPRXGET=1")); + if (waitResponse() != 1) { + return false; + } + + sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); + if (waitResponse(60000L) != 1) { + return false; + } + + sendAT(GF("+CIICR")); + if (waitResponse(60000L) != 1) { + return false; + } + + sendAT(GF("+CIFSR;E0")); + if (waitResponse(10000L) != 1) { + return false; + } + + sendAT(GF("+CDNSCFG=\"8.8.8.8\",\"8.8.4.4\"")); + if (waitResponse() != 1) { + return false; + } + + return true; + } + + bool gprsDisconnect() { + sendAT(GF("+CIPSHUT")); + return waitResponse(60000L) == 1; + } + + String getLocalIP() { + sendAT(GF("+CIFSR;E0")); + String res; + if (waitResponse(10000L, res) != 1) { + return ""; + } + res.trim(); + return res; + } + + IPAddress localIP() { + IPAddress res; + res.fromString(getLocalIP()); + return res; + } + + /* + * 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; + } + + // Returns true on pick-up, false on error/busy + bool callNumber(const String& number) { + sendAT(GF("D"), number, ";"); + int status = waitResponse(60000L, GF("OK"), GF("BUSY"), GF("NO ANSWER"), GF("NO CARRIER")); + switch (status) { + case 1: return true; + case 2: + case 3: return false; + default: return false; + } + } + + //bool callRedial() { + // sendAT(GF("DL")); + // return waitResponse() == 1; + //} + + bool callHangup() { + sendAT(GF("H")); + return waitResponse() == 1; + } + + /* + * Messaging functions + */ + + String sendUSSD(const String& code) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CSCS=\"HEX\"")); + waitResponse(); + sendAT(GF("+CUSD=1,\""), code, GF("\"")); + if (waitResponse() != 1) { + return ""; + } + if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { + return ""; + } + stream.readStringUntil('"'); + String hex = stream.readStringUntil('"'); + stream.readStringUntil(','); + int dcs = stream.readStringUntil('\n').toInt(); + + if (dcs == 15) { + return decodeHex8bit(hex); + } else if (dcs == 72) { + return decodeHex16bit(hex); + } else { + return hex; + } + } + + 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); + stream.flush(); + 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); + stream.flush(); + return waitResponse(60000L) == 1; + } + + + /* + * Location functions + */ + + String getGsmLocation() { + sendAT(GF("+CIPGSMLOC=1,1")); + if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } + + /* + * Battery functions + */ + // Use: float vBatt = modem.getBattVoltage() / 1000.0; + uint16_t getBattVoltage() { + sendAT(GF("+CBC")); + if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + return 0; + } + streamSkipUntil(','); // Skip + streamSkipUntil(','); // Skip + + uint16_t res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + + int getBattPercent() { + sendAT(GF("+CBC")); + if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + return false; + } + stream.readStringUntil(','); + int res = stream.readStringUntil(',').toInt(); + waitResponse(); + return res; + } + +private: + + bool 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 stream.readStringUntil('\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 = stream.readStringUntil(',').toInt(); + sockets[mux]->sock_available = stream.readStringUntil('\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 = stream.readStringUntil('\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; + } + + static String decodeHex8bit(String &instr) { + String result; + for (unsigned i=0; i + void streamWrite(T last) { + stream.print(last); + } + + template + void streamWrite(T head, Args... tail) { + stream.print(head); + streamWrite(tail...); + } + + bool streamSkipUntil(char c) { //TODO: timeout + while (true) { + while (!stream.available()) { TINY_GSM_YIELD(); } + if (stream.read() == c) + return true; + } + return false; + } + + template + void sendAT(Args... cmd) { + streamWrite("AT", cmd..., GSM_NL); + stream.flush(); + TINY_GSM_YIELD(); + //DBG("### 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); + int index = 0; + unsigned long startMillis = millis(); + do { + TINY_GSM_YIELD(); + while (stream.available() > 0) { + int a = stream.read(); + 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 = stream.readStringUntil(','); + if (mode.toInt() == 1) { + int mux = stream.readStringUntil('\n').toInt(); + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { + sockets[mux]->got_data = 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); + int mux = data.substring(nl+2, coma).toInt(); + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { + sockets[mux]->sock_connected = false; + } + data = ""; + DBG("### Closed: ", mux); + } + } + } while (millis() - startMillis < timeout); +finish: + if (!index) { + data.trim(); + if (data.length()) { + DBG("### Unhandled:", data); + } + data = ""; + } + 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[TINY_GSM_MUX_COUNT]; +}; + +typedef TinyGsm::GsmClient TinyGsmClient; + +#endif From e56ca051be039fefaedf3c76cd2c7d3c1365af86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brun=20von=20der=20G=C3=B6nne?= Date: Tue, 12 Sep 2017 10:49:32 +0200 Subject: [PATCH 63/82] add functions to read and delete SMS --- TinyGsmClientSIM808.h | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/TinyGsmClientSIM808.h b/TinyGsmClientSIM808.h index 6b50293..505a56c 100644 --- a/TinyGsmClientSIM808.h +++ b/TinyGsmClientSIM808.h @@ -601,6 +601,77 @@ public: stream.flush(); return waitResponse(60000L) == 1; } + + int getNumSMS() { + + sendAT(GF("+CMGF=1")); + if (waitResponse() != 1) { + return 0; + } + + sendAT(GF("+CPMS?")); + if (waitResponse(GF(GSM_NL "+CPMS:")) != 1) { + return 0; + } + String res = stream.readStringUntil('\n'); + int index1 = res.indexOf(","); + int index2 = res.indexOf(",", index1+1); + String tmp = res.substring(index1+1,index2); + waitResponse(); + //res.trim(); + tmp.trim(); + //return res; + //int num = tmp.toInt(); + return tmp.toInt(); + } + + String readSMS(int num, char *sender) { + String buffer; + + sendAT(GF("+CMGF=1")); + if (waitResponse() != 1) { + return ""; + } + sendAT(GF("+CSDH=1")); + if (waitResponse() != 1) { + return ""; + } + + + sendAT(GF("+CMGR="), num, GF("")); + if (waitResponse(GF(GSM_NL "+CMGR:")) != 1) { + return ""; + } + + stream.readStringUntil(','); + buffer = stream.readStringUntil(','); + buffer.replace('"', ' '); + buffer.trim(); + buffer.toCharArray(sender, 18); + + stream.readStringUntil('\r'); + + buffer = ""; + + delay(20); // Wait a moment to get data into the buffer + while (stream.available()) { + char c = stream.read(); + buffer = buffer + c; + } + + String res = buffer; + waitResponse(); + res.trim(); + return res; + } + + boolean deleteSMS(int num) { + sendAT(GF("+CMGD="), num, GF("")); + if (waitResponse(GF(GSM_NL "+CMGD:")) != 1) { + return false; + } + return true; + } /* @@ -645,6 +716,16 @@ public: waitResponse(); return res; } + + + + + +/* + * Starting GPS functions + */ + + private: From d75d3f9265015fed92db91b05d3cda06f3105c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brun=20von=20der=20G=C3=B6nne?= Date: Tue, 12 Sep 2017 10:52:18 +0200 Subject: [PATCH 64/82] add GPS functions --- TinyGsmClientSIM808.h | 123 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/TinyGsmClientSIM808.h b/TinyGsmClientSIM808.h index 505a56c..500f9e0 100644 --- a/TinyGsmClientSIM808.h +++ b/TinyGsmClientSIM808.h @@ -722,10 +722,131 @@ public: /* - * Starting GPS functions + * GPS location functions */ + // enable GPS + boolean enableGPS() { + uint16_t state; + + sendAT(GF("+CGNSPWR=1")); + if (waitResponse() != 1) { + return false; + } + + return true; + } + + boolean disableGPS() { + uint16_t state; + + sendAT(GF("+CGNSPWR=0")); + if (waitResponse() != 1) { + return false; + } + + return true; + } + + // get the RAW GPS output + // works only with ans SIM808 V2 + String getGPSraw() { + sendAT(GF("+CGNSINF")); + if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } + + // get GPS informations + // works only with ans SIM808 V2 + boolean getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { + //String buffer = ""; + char chr_buffer[12]; + boolean fix = false; + + sendAT(GF("+CGNSINF")); + if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { + return false; + } + + stream.readStringUntil(','); // mode + if ( stream.readStringUntil(',').toInt() == 1 ) fix = true; + stream.readStringUntil(','); //utctime + *lat = stream.readStringUntil(',').toFloat(); //lat + *lon = stream.readStringUntil(',').toFloat(); //lon + if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //lon + if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites + if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites + stream.readStringUntil('\n'); + + + waitResponse(); + + return fix; + } + + // get GPS time + // works only with SIM808 V2 + boolean getGPSTime(int *year, int *month, int *day, int *hour, int *minute, int *second) { + boolean fix = false; + char chr_buffer[12]; + sendAT(GF("+CGNSINF")); + if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { + return false; + } + + + for (int i = 0; i < 3; i++) { + String buffer = stream.readStringUntil(','); + buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); + switch (i) { + case 0: + //mode + break; + case 1: + //fixstatus + if ( buffer.toInt() == 1 ) { + fix = buffer.toInt(); + } + break; + case 2: + *year = buffer.substring(0,4).toInt(); + *month = buffer.substring(4,6).toInt(); + *day = buffer.substring(6,8).toInt(); + *hour = buffer.substring(8,10).toInt(); + *minute = buffer.substring(10,12).toInt(); + *second = buffer.substring(12,14).toInt(); + break; + + default: + // if nothing else matches, do the default + // default is optional + break; + } + } + String res = stream.readStringUntil('\n'); + waitResponse(); + + if (fix) { + return true; + } else { + return false; + } + } + private: From 43332c9845c47d173860ecb85eef74243bfe6983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brun=20von=20der=20G=C3=B6nne?= Date: Tue, 12 Sep 2017 11:16:43 +0200 Subject: [PATCH 65/82] add SIM808 to TinyGsmClient.h --- TinyGsmClient.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TinyGsmClient.h b/TinyGsmClient.h index b9de490..040e9b2 100644 --- a/TinyGsmClient.h +++ b/TinyGsmClient.h @@ -11,6 +11,8 @@ #if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900) #include +#elif defined(TINY_GSM_MODEM_SIM808) +#include #elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) #include #elif defined(TINY_GSM_MODEM_M590) From 62b326df5771082517a24c9c6d0cd29b8f76dd34 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 12:42:19 +0300 Subject: [PATCH 66/82] Allow to DUMP_AT_COMMANDS --- examples/FileDownload/FileDownload.ino | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/examples/FileDownload/FileDownload.ino b/examples/FileDownload/FileDownload.ino index e3c56ce..c3aab53 100644 --- a/examples/FileDownload/FileDownload.ino +++ b/examples/FileDownload/FileDownload.ino @@ -23,8 +23,7 @@ // Increase RX buffer #define TINY_GSM_RX_BUFFER 1030 -#include -#include +//#define DUMP_AT_COMMANDS // Your GPRS credentials // Leave empty, if missing user or pass @@ -39,12 +38,23 @@ const char pass[] = ""; //#include //SoftwareSerial SerialAT(2, 3); // RX, TX -TinyGsm modem(SerialAT); +#include +#include + +#ifdef DUMP_AT_COMMANDS + #include + StreamDebugger debugger(SerialAT, Serial); + TinyGsm modem(debugger); +#else + TinyGsm modem(SerialAT); +#endif TinyGsmClient client(modem); const char server[] = "cdn.rawgit.com"; -const char resource[] = "/vshymanskyy/tinygsm/master/extras/test_1k.bin"; -uint32_t knownCRC32 = 0x6f50d767; +const int port = 80; + +const char resource[] = "/vshymanskyy/tinygsm/master/extras/test_1k.bin"; +uint32_t knownCRC32 = 0x6f50d767; uint32_t knownFileSize = 1024; // In case server does not send it void setup() { @@ -102,7 +112,7 @@ void loop() { Serial.print(server); // if you get a connection, report back via serial: - if (!client.connect(server, 80)) { + if (!client.connect(server, port)) { Serial.println(" fail"); delay(10000); return; From 2d564870f75b9122823f3e372c54334517ffeeb8 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 12:44:33 +0300 Subject: [PATCH 67/82] Add TINY_GSM_DEBUG -> Serial --- examples/FileDownload/FileDownload.ino | 1 + examples/HttpClient/HttpClient.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/FileDownload/FileDownload.ino b/examples/FileDownload/FileDownload.ino index c3aab53..0853d3b 100644 --- a/examples/FileDownload/FileDownload.ino +++ b/examples/FileDownload/FileDownload.ino @@ -24,6 +24,7 @@ #define TINY_GSM_RX_BUFFER 1030 //#define DUMP_AT_COMMANDS +//#define TINY_GSM_DEBUG Serial // Your GPRS credentials // Leave empty, if missing user or pass diff --git a/examples/HttpClient/HttpClient.ino b/examples/HttpClient/HttpClient.ino index 1b8029b..0ab7726 100644 --- a/examples/HttpClient/HttpClient.ino +++ b/examples/HttpClient/HttpClient.ino @@ -42,7 +42,7 @@ const char pass[] = ""; // Name of the server we want to connect to const char server[] = "cdn.rawgit.com"; -const int port = 80; +const int port = 443; // Path to download (this is the bit after the hostname in the URL) const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; From 87af409c4debbc868c829feae3ea82a81e22b90d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 12:46:05 +0300 Subject: [PATCH 68/82] SSL/TLS support. Added GsmClientSecure. Fix #29 --- TinyGsmClientSIM800.h | 42 +++++++- examples/HttpsClient/HttpsClient.ino | 154 +++++++++++++++++++++++++++ keywords.txt | 1 + 3 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 examples/HttpsClient/HttpsClient.ino diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 6b50293..72a5b78 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -180,6 +180,24 @@ private: RxFifo rx; }; +class GsmClientSecure : public GsmClient +{ +public: + GsmClientSecure() {} + + GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) + : GsmClient(modem, mux) + {} + +public: + virtual int connect(const char *host, uint16_t port) { + TINY_GSM_YIELD(); + rx.clear(); + sock_connected = at->modemConnect(host, port, mux, true); + return sock_connected; + } +}; + public: TinyGsm(Stream& stream) @@ -262,6 +280,14 @@ public: return res; } + bool hasSSL() { + sendAT(GF("+CIPSSL=?")); + if (waitResponse(GF(GSM_NL "+CIPSSL:")) != 1) { + return false; + } + return waitResponse() == 1; + } + /* * Power functions */ @@ -648,12 +674,17 @@ public: private: - bool modemConnect(const char* host, uint16_t port, uint8_t mux) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + sendAT(GF("+CIPSSL="), ssl); + int rsp = waitResponse(); + if (ssl && rsp != 1) { + return false; + } 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)); + rsp = waitResponse(75000L, + GF("CONNECT OK" GSM_NL), + GF("CONNECT FAIL" GSM_NL), + GF("ALREADY CONNECT" GSM_NL)); return (1 == rsp); } @@ -879,5 +910,6 @@ private: }; typedef TinyGsm::GsmClient TinyGsmClient; +typedef TinyGsm::GsmClientSecure TinyGsmClientSecure; #endif diff --git a/examples/HttpsClient/HttpsClient.ino b/examples/HttpsClient/HttpsClient.ino new file mode 100644 index 0000000..f91928d --- /dev/null +++ b/examples/HttpsClient/HttpsClient.ino @@ -0,0 +1,154 @@ +/************************************************************** + * + * This sketch connects to a website and downloads a page. + * It can be used to perform HTTP/RESTful API calls. + * + * For this example, you need to install ArduinoHttpClient library: + * https://github.com/arduino-libraries/ArduinoHttpClient + * or from http://librarymanager/all#ArduinoHttpClient + * + * TinyGSM Getting Started guide: + * http://tiny.cc/tiny-gsm-readme + * + **************************************************************/ + +// Select your modem +// SSL/TLS is currently supported only with SIM800 series +#define TINY_GSM_MODEM_SIM800 + +// Increase RX buffer +#define TINY_GSM_RX_BUFFER 64 + +// Use Hardware Serial on Mega, Leonardo, Micro +#define SerialAT Serial1 + +// or Software Serial on Uno, Nano +//#include +//SoftwareSerial SerialAT(2, 3); // RX, TX + +//#define DUMP_AT_COMMANDS +//#define TINY_GSM_DEBUG Serial + + +// Your GPRS credentials +// Leave empty, if missing user or pass +const char apn[] = "YourAPN"; +const char user[] = ""; +const char pass[] = ""; + +// Name of the server we want to connect to +const char server[] = "cdn.rawgit.com"; +const int port = 443; +// Path to download (this is the bit after the hostname in the URL) +const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; + +#include +#include + +#ifdef DUMP_AT_COMMANDS + #include + StreamDebugger debugger(SerialAT, Serial); + TinyGsm modem(debugger); +#else + TinyGsm modem(SerialAT); +#endif + +TinyGsmClientSecure client(modem); +HttpClient http(client, server, port); + +void setup() { + // Set console baud rate + Serial.begin(115200); + delay(10); + + // Set GSM module baud rate + SerialAT.begin(115200); + delay(3000); + + // Restart takes quite some time + // To skip it, call init() instead of restart() + Serial.println("Initializing modem..."); + modem.restart(); + + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + + // Unlock your SIM card with a PIN + //modem.simUnlock("1234"); +} + +void loop() { + if (!modem.hasSSL()) { + Serial.print("SSL is not supported by this modem"); + delay(10000); + return; + } + + Serial.print(F("Waiting for network...")); + if (!modem.waitForNetwork()) { + Serial.println(" fail"); + delay(10000); + return; + } + Serial.println(" OK"); + + Serial.print(F("Connecting to ")); + Serial.print(apn); + if (!modem.gprsConnect(apn, user, pass)) { + Serial.println(" fail"); + delay(10000); + return; + } + Serial.println(" OK"); + + + Serial.print(F("Performing HTTP GET request... ")); + http.connectionKeepAlive(); // Currently, this is needed for HTTPS + int err = http.get(resource); + if (err != 0) { + Serial.println("failed to connect"); + delay(10000); + return; + } + + int status = http.responseStatusCode(); + Serial.println(status); + if (!status) { + delay(10000); + return; + } + + while (http.headerAvailable()) { + String headerName = http.readHeaderName(); + String headerValue = http.readHeaderValue(); + //Serial.println(headerName + " : " + headerValue); + } + + int length = http.contentLength(); + if (length >= 0) { + Serial.println(String("Content length is: ") + length); + } + if (http.isResponseChunked()) { + Serial.println("This response is chunked"); + } + + String body = http.responseBody(); + Serial.println("Response:"); + Serial.println(body); + + Serial.println(String("Body length is: ") + body.length()); + + // Shutdown + + http.stop(); + + modem.gprsDisconnect(); + Serial.println("GPRS disconnected"); + + // Do nothing forevermore + while (true) { + delay(1000); + } +} + diff --git a/keywords.txt b/keywords.txt index 5c6cd82..fa2df44 100644 --- a/keywords.txt +++ b/keywords.txt @@ -3,6 +3,7 @@ ####################################### TinyGsm KEYWORD1 TinyGsmClient KEYWORD1 +TinyGsmClientSecure KEYWORD1 SerialAT KEYWORD1 SerialMon KEYWORD1 From 60962d03e8917c2ce3159ee4c4b729af6ec244dd Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 12:55:02 +0300 Subject: [PATCH 69/82] Boost ver --- README.md | 2 +- examples/HttpsClient/HttpsClient.ino | 2 +- library.json | 2 +- library.properties | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1eb4a18..b01c1df 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 **Data connections** TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ UDP | | | | | -SSL/TLS (HTTPS) | ◌¹ | ◌¹ | 🅧 | 🅧 | ◌ +SSL/TLS (HTTPS) | ✔¹ | ✔¹ | 🅧 | 🅧 | ◌ **USSD** Sending USSD requests | ✔ | ✔ | ✔ | ✔ | 🅧 Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | 🅧 diff --git a/examples/HttpsClient/HttpsClient.ino b/examples/HttpsClient/HttpsClient.ino index f91928d..49a85fe 100644 --- a/examples/HttpsClient/HttpsClient.ino +++ b/examples/HttpsClient/HttpsClient.ino @@ -80,7 +80,7 @@ void setup() { void loop() { if (!modem.hasSSL()) { - Serial.print("SSL is not supported by this modem"); + Serial.println("SSL is not supported by this modem"); delay(10000); return; } diff --git a/library.json b/library.json index 1b046d0..9600e16 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TinyGSM", - "version": "0.2.0", + "version": "0.3.0", "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 efbaab3..e1b1ec6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TinyGSM -version=0.2.0 +version=0.3.0 author=Volodymyr Shymanskyy maintainer=Volodymyr Shymanskyy sentence=A small Arduino library for GPRS modules, that just works. From 5846604f22c47ea3e5dde96744ca858d1f62fa9b Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 13:09:24 +0300 Subject: [PATCH 70/82] Prepare SIM808 for integration --- TinyGsmClientSIM808.h | 1115 ++++------------------------------------- 1 file changed, 89 insertions(+), 1026 deletions(-) diff --git a/TinyGsmClientSIM808.h b/TinyGsmClientSIM808.h index 500f9e0..aea2324 100644 --- a/TinyGsmClientSIM808.h +++ b/TinyGsmClientSIM808.h @@ -1,327 +1,57 @@ /** - * @file TinyGsmClientSIM800.h - * @author Volodymyr Shymanskyy - * @license LGPL-3.0 + * @file TinyGsmClientSIM808.h + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 * @copyright Copyright (c) 2016 Volodymyr Shymanskyy - * @date Nov 2016 + * @date Nov 2016 */ -#ifndef TinyGsmClientSIM800_h -#define TinyGsmClientSIM800_h +#ifndef TinyGsmClientSIM808_h +#define TinyGsmClientSIM808_h -//#define TINY_GSM_DEBUG Serial -//#define TINY_GSM_USE_HEX +#include -#if !defined(TINY_GSM_RX_BUFFER) - #define TINY_GSM_RX_BUFFER 64 -#endif - -#define TINY_GSM_MUX_COUNT 5 - -#include - -#define GSM_NL "\r\n" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, -}; - -enum RegStatus { - REG_UNREGISTERED = 0, - REG_SEARCHING = 2, - REG_DENIED = 3, - REG_OK_HOME = 1, - REG_OK_ROAMING = 5, - REG_UNKNOWN = 4, -}; - - -class TinyGsm +class TinyGsmSim808: public TinyGsm { public: -class GsmClient : public Client -{ - friend class TinyGsm; - typedef TinyGsmFifo RxFifo; - -public: - GsmClient() {} - - GsmClient(TinyGsm& modem, uint8_t mux = 1) { - init(&modem, mux); - } - - bool init(TinyGsm* modem, uint8_t mux = 1) { - this->at = modem; - this->mux = mux; - sock_available = 0; - prev_check = 0; - sock_connected = false; - got_data = false; - - at->sockets[mux] = this; - - return true; - } - -public: - virtual int connect(const char *host, uint16_t port) { - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, mux); - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) { - String host; host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return connect(host.c_str(), port); - } - - virtual void stop() { - TINY_GSM_YIELD(); - at->sendAT(GF("+CIPCLOSE="), mux); - sock_connected = false; - at->waitResponse(); - } - - virtual size_t write(const uint8_t *buf, size_t size) { - TINY_GSM_YIELD(); - at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) { - return write(&c, 1); - } - - virtual int available() { - TINY_GSM_YIELD(); - if (!rx.size() && sock_connected) { - // Workaround: sometimes SIM800 forgets to notify about data arrival. - // TODO: Currently we ping the module periodically, - // but maybe there's a better indicator that we need to poll - if (millis() - prev_check > 500) { - got_data = true; - prev_check = millis(); - } - at->maintain(); - } - return rx.size() + sock_available; - } - - virtual int read(uint8_t *buf, size_t size) { - TINY_GSM_YIELD(); - at->maintain(); - size_t cnt = 0; - while (cnt < size) { - size_t chunk = TinyGsmMin(size-cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // TODO: Read directly into user buffer? - at->maintain(); - if (sock_available > 0) { - at->modemRead(rx.free(), mux); - } else { - break; - } - } - return cnt; - } - - virtual int read() { - uint8_t c; - if (read(&c, 1) == 1) { - return c; - } - return -1; - } - - virtual int peek() { return -1; } //TODO - virtual void flush() { at->stream.flush(); } - - virtual uint8_t connected() { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() { return connected(); } + TinyGsmSim808(Stream& stream) + : TinyGsm(stream) + {} /* - * Extended API + * GPS location functions */ - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - -private: - TinyGsm* at; - uint8_t mux; - uint16_t sock_available; - uint32_t prev_check; - bool sock_connected; - bool got_data; - RxFifo rx; -}; - -public: - - TinyGsm(Stream& stream) - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin() { - return init(); - } + // enable GPS + bool enableGPS() { + uint16_t state; - bool init() { - if (!autoBaud()) { - return false; - } - sendAT(GF("&FZ")); // Factory + Reset - waitResponse(); - sendAT(GF("E0")); // Echo Off + sendAT(GF("+CGNSPWR=1")); if (waitResponse() != 1) { return false; } - getSimStatus(); - return true; - } - - bool autoBaud(unsigned long timeout = 10000L) { - //streamWrite(GF("AAAAA" GSM_NL)); // TODO: extra A's to help detect the baud rate - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("")); - if (waitResponse(200) == 1) { - delay(100); - return true; - } - delay(100); - } - return false; - } - - void maintain() { - for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { - GsmClient* sock = sockets[mux]; - if (sock && sock->got_data) { - sock->got_data = false; - sock->sock_available = modemGetAvailable(mux); - } - } - while (stream.available()) { - waitResponse(10, NULL, NULL); - } - } - - bool factoryDefault() { - sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write - waitResponse(); - sendAT(GF("+IPR=0")); // Auto-baud - waitResponse(); - sendAT(GF("+IFC=0,0")); // No Flow Control - waitResponse(); - sendAT(GF("+ICF=3,3")); // 8 data 0 parity 1 stop - waitResponse(); - sendAT(GF("+CSCLK=0")); // Disable Slow Clock - waitResponse(); - sendAT(GF("&W")); // Write configuration - return waitResponse() == 1; - } - String getModemInfo() { - sendAT(GF("I")); - String res; - if (waitResponse(1000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, " "); - res.trim(); - return res; + return true; } - /* - * Power functions - */ + bool disableGPS() { + uint16_t state; - bool restart() { - if (!autoBaud()) { - return false; - } - sendAT(GF("+CFUN=0")); - if (waitResponse(10000L) != 1) { - return false; - } - sendAT(GF("+CFUN=1,1")); - if (waitResponse(10000L) != 1) { + sendAT(GF("+CGNSPWR=0")); + if (waitResponse() != 1) { return false; } - delay(3000); - return init(); - } - - bool poweroff() { - sendAT(GF("+CPOWD=1")); - return waitResponse(GF("NORMAL POWER DOWN")) == 1; - } - bool radioOff() { - if (!autoBaud()) { - return false; - } - sendAT(GF("+CFUN=0")); - if (waitResponse(10000L) != 1) { - return false; - } - delay(3000); return true; } - /* - * SIM card functions - */ - - bool simUnlock(const char *pin) { - sendAT(GF("+CPIN=\""), pin, GF("\"")); - return waitResponse() == 1; - } - - String getSimCCID() { - sendAT(GF("+ICCID")); - if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - String getIMEI() { - sendAT(GF("+GSN")); - if (waitResponse(GF(GSM_NL)) != 1) { + // get the RAW GPS output + // works only with ans SIM808 V2 + String getGPSraw() { + sendAT(GF("+CGNSINF")); + if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); @@ -330,756 +60,89 @@ public: return res; } - 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(1000); - continue; - } - int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED")); - waitResponse(); - switch (status) { - case 2: - case 3: return SIM_LOCKED; - case 1: return SIM_READY; - default: return SIM_ERROR; - } - } - return SIM_ERROR; - } - - RegStatus getRegistrationStatus() { - sendAT(GF("+CREG?")); - if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { - return REG_UNKNOWN; - } - streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); - waitResponse(); - return (RegStatus)status; - } - - String getOperator() { - sendAT(GF("+COPS?")); - if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { - return ""; - } - streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); - waitResponse(); - return res; - } - - /* - * Generic network functions - */ - - int getSignalQuality() { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - bool waitForNetwork(unsigned long timeout = 60000L) { - for (unsigned long start = millis(); millis() - start < timeout; ) { - RegStatus s = getRegistrationStatus(); - if (s == REG_OK_HOME || s == REG_OK_ROAMING) { - return true; - } - delay(1000); - } - return false; - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user, const char* pwd) { - gprsDisconnect(); - - sendAT(GF("+SAPBR=3,1,\"Contype\",\"GPRS\"")); - waitResponse(); - - sendAT(GF("+SAPBR=3,1,\"APN\",\""), apn, '"'); - waitResponse(); - - if (user) { - sendAT(GF("+SAPBR=3,1,\"USER\",\""), user, '"'); - waitResponse(); - } - if (pwd) { - sendAT(GF("+SAPBR=3,1,\"PWD\",\""), pwd, '"'); - waitResponse(); - } - - sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); - waitResponse(); - - sendAT(GF("+CGACT=1,1")); - waitResponse(60000L); - - // Open a GPRS context - sendAT(GF("+SAPBR=1,1")); - waitResponse(85000L); - // Query the GPRS context - sendAT(GF("+SAPBR=2,1")); - if (waitResponse(30000L) != 1) - return false; - - sendAT(GF("+CGATT=1")); - if (waitResponse(60000L) != 1) - return false; - - // TODO: wait AT+CGATT? - - sendAT(GF("+CIPMUX=1")); - if (waitResponse() != 1) { - return false; - } + // get GPS informations + // works only with ans SIM808 V2 + bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { + //String buffer = ""; + char chr_buffer[12]; + bool fix = false; - sendAT(GF("+CIPQSEND=1")); - if (waitResponse() != 1) { + sendAT(GF("+CGNSINF")); + if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return false; } - sendAT(GF("+CIPRXGET=1")); - if (waitResponse() != 1) { - return false; - } - - sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); - if (waitResponse(60000L) != 1) { - return false; - } - - sendAT(GF("+CIICR")); - if (waitResponse(60000L) != 1) { - return false; - } - - sendAT(GF("+CIFSR;E0")); - if (waitResponse(10000L) != 1) { - return false; - } - - sendAT(GF("+CDNSCFG=\"8.8.8.8\",\"8.8.4.4\"")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - bool gprsDisconnect() { - sendAT(GF("+CIPSHUT")); - return waitResponse(60000L) == 1; - } - - String getLocalIP() { - sendAT(GF("+CIFSR;E0")); - String res; - if (waitResponse(10000L, res) != 1) { - return ""; - } - res.trim(); - return res; - } - - IPAddress localIP() { - IPAddress res; - res.fromString(getLocalIP()); - return res; - } - - /* - * 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; - } - - // Returns true on pick-up, false on error/busy - bool callNumber(const String& number) { - sendAT(GF("D"), number, ";"); - int status = waitResponse(60000L, GF("OK"), GF("BUSY"), GF("NO ANSWER"), GF("NO CARRIER")); - switch (status) { - case 1: return true; - case 2: - case 3: return false; - default: return false; - } - } - - //bool callRedial() { - // sendAT(GF("DL")); - // return waitResponse() == 1; - //} - - bool callHangup() { - sendAT(GF("H")); - return waitResponse() == 1; - } - - /* - * Messaging functions - */ - - String sendUSSD(const String& code) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CUSD=1,\""), code, GF("\"")); - if (waitResponse() != 1) { - return ""; - } - if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { - return ""; - } - stream.readStringUntil('"'); - String hex = stream.readStringUntil('"'); + stream.readStringUntil(','); // mode + if ( stream.readStringUntil(',').toInt() == 1 ) fix = true; + stream.readStringUntil(','); //utctime + *lat = stream.readStringUntil(',').toFloat(); //lat + *lon = stream.readStringUntil(',').toFloat(); //lon + if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //lon + if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed stream.readStringUntil(','); - int dcs = stream.readStringUntil('\n').toInt(); - - if (dcs == 15) { - return decodeHex8bit(hex); - } else if (dcs == 72) { - return decodeHex16bit(hex); - } else { - return hex; - } - } + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + stream.readStringUntil(','); + if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites + if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites + stream.readStringUntil('\n'); - 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); - stream.flush(); - 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(); + return fix; + } - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { + // get GPS time + // works only with SIM808 V2 + bool getGPSTime(int *year, int *month, int *day, int *hour, int *minute, int *second) { + bool fix = false; + char chr_buffer[12]; + sendAT(GF("+CGNSINF")); + if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 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); - stream.flush(); - return waitResponse(60000L) == 1; - } - - int getNumSMS() { - - sendAT(GF("+CMGF=1")); - if (waitResponse() != 1) { - return 0; - } - - sendAT(GF("+CPMS?")); - if (waitResponse(GF(GSM_NL "+CPMS:")) != 1) { - return 0; - } - String res = stream.readStringUntil('\n'); - int index1 = res.indexOf(","); - int index2 = res.indexOf(",", index1+1); - String tmp = res.substring(index1+1,index2); - waitResponse(); - //res.trim(); - tmp.trim(); - //return res; - //int num = tmp.toInt(); - return tmp.toInt(); - } - - String readSMS(int num, char *sender) { - String buffer; - - sendAT(GF("+CMGF=1")); - if (waitResponse() != 1) { - return ""; - } - sendAT(GF("+CSDH=1")); - if (waitResponse() != 1) { - return ""; - } - - - sendAT(GF("+CMGR="), num, GF("")); - if (waitResponse(GF(GSM_NL "+CMGR:")) != 1) { - return ""; - } - - stream.readStringUntil(','); - buffer = stream.readStringUntil(','); - buffer.replace('"', ' '); - buffer.trim(); - buffer.toCharArray(sender, 18); - - stream.readStringUntil('\r'); - - buffer = ""; - - delay(20); // Wait a moment to get data into the buffer - while (stream.available()) { - char c = stream.read(); - buffer = buffer + c; - } - - String res = buffer; - waitResponse(); - res.trim(); - return res; - } - - boolean deleteSMS(int num) { - sendAT(GF("+CMGD="), num, GF("")); - if (waitResponse(GF(GSM_NL "+CMGD:")) != 1) { - return false; - } - return true; - } - - - /* - * Location functions - */ - - String getGsmLocation() { - sendAT(GF("+CIPGSMLOC=1,1")); - if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { - return ""; + for (int i = 0; i < 3; i++) { + String buffer = stream.readStringUntil(','); + buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); + switch (i) { + case 0: + //mode + break; + case 1: + //fixstatus + if ( buffer.toInt() == 1 ) { + fix = buffer.toInt(); + } + break; + case 2: + *year = buffer.substring(0,4).toInt(); + *month = buffer.substring(4,6).toInt(); + *day = buffer.substring(6,8).toInt(); + *hour = buffer.substring(8,10).toInt(); + *minute = buffer.substring(10,12).toInt(); + *second = buffer.substring(12,14).toInt(); + break; + + default: + // if nothing else matches, do the default + // default is optional + break; + } } String res = stream.readStringUntil('\n'); waitResponse(); - res.trim(); - return res; - } - - /* - * Battery functions - */ - // Use: float vBatt = modem.getBattVoltage() / 1000.0; - uint16_t getBattVoltage() { - sendAT(GF("+CBC")); - if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { - return 0; - } - streamSkipUntil(','); // Skip - streamSkipUntil(','); // Skip - - uint16_t res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - int getBattPercent() { - sendAT(GF("+CBC")); - if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + if (fix) { + return true; + } else { return false; } - stream.readStringUntil(','); - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - - - - -/* - * GPS location functions - */ - - - // enable GPS - boolean enableGPS() { - uint16_t state; - - sendAT(GF("+CGNSPWR=1")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - boolean disableGPS() { - uint16_t state; - - sendAT(GF("+CGNSPWR=0")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - // get the RAW GPS output - // works only with ans SIM808 V2 - String getGPSraw() { - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - // get GPS informations - // works only with ans SIM808 V2 - boolean getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { - //String buffer = ""; - char chr_buffer[12]; - boolean fix = false; - - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { - return false; - } - - stream.readStringUntil(','); // mode - if ( stream.readStringUntil(',').toInt() == 1 ) fix = true; - stream.readStringUntil(','); //utctime - *lat = stream.readStringUntil(',').toFloat(); //lat - *lon = stream.readStringUntil(',').toFloat(); //lon - if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //lon - if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites - if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites - stream.readStringUntil('\n'); - - - waitResponse(); - - return fix; - } - - // get GPS time - // works only with SIM808 V2 - boolean getGPSTime(int *year, int *month, int *day, int *hour, int *minute, int *second) { - boolean fix = false; - char chr_buffer[12]; - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { - return false; - } - - - for (int i = 0; i < 3; i++) { - String buffer = stream.readStringUntil(','); - buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); - switch (i) { - case 0: - //mode - break; - case 1: - //fixstatus - if ( buffer.toInt() == 1 ) { - fix = buffer.toInt(); - } - break; - case 2: - *year = buffer.substring(0,4).toInt(); - *month = buffer.substring(4,6).toInt(); - *day = buffer.substring(6,8).toInt(); - *hour = buffer.substring(8,10).toInt(); - *minute = buffer.substring(10,12).toInt(); - *second = buffer.substring(12,14).toInt(); - break; - - default: - // if nothing else matches, do the default - // default is optional - break; - } - } - String res = stream.readStringUntil('\n'); - waitResponse(); - - if (fix) { - return true; - } else { - return false; - } - } - - -private: - - bool 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 stream.readStringUntil('\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 = stream.readStringUntil(',').toInt(); - sockets[mux]->sock_available = stream.readStringUntil('\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 = stream.readStringUntil('\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; - } - - static String decodeHex8bit(String &instr) { - String result; - for (unsigned i=0; i - void streamWrite(T last) { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) { - stream.print(head); - streamWrite(tail...); - } - - bool streamSkipUntil(char c) { //TODO: timeout - while (true) { - while (!stream.available()) { TINY_GSM_YIELD(); } - if (stream.read() == c) - return true; - } - return false; - } - - template - void sendAT(Args... cmd) { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### 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); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = stream.read(); - 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 = stream.readStringUntil(','); - if (mode.toInt() == 1) { - int mux = stream.readStringUntil('\n').toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { - sockets[mux]->got_data = 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); - int mux = data.substring(nl+2, coma).toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { - sockets[mux]->sock_connected = false; - } - data = ""; - DBG("### Closed: ", mux); - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - 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[TINY_GSM_MUX_COUNT]; }; -typedef TinyGsm::GsmClient TinyGsmClient; - #endif From 144a9c371e15e2c4b449c2facb9a3c5cfe1f0a0c Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 13:32:34 +0300 Subject: [PATCH 71/82] Integrate SIM808 nicely --- TinyGsmClient.h | 18 ++++++++++++++++-- TinyGsmClientA6.h | 2 -- TinyGsmClientESP8266.h | 2 -- TinyGsmClientM590.h | 2 -- TinyGsmClientSIM800.h | 21 +++++++++------------ TinyGsmClientSIM808.h | 4 ++-- examples/AllFunctions/AllFunctions.ino | 12 ++++++++++-- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/TinyGsmClient.h b/TinyGsmClient.h index 040e9b2..36cc919 100644 --- a/TinyGsmClient.h +++ b/TinyGsmClient.h @@ -11,14 +11,28 @@ #if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900) #include -#elif defined(TINY_GSM_MODEM_SIM808) -#include + typedef TinyGsmSim800 TinyGsm; + typedef TinyGsmSim800::GsmClient TinyGsmClient; + typedef TinyGsmSim800::GsmClientSecure TinyGsmClientSecure; + +#elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) + #include + typedef TinyGsmSim808 TinyGsm; + typedef TinyGsmSim808::GsmClient TinyGsmClient; + typedef TinyGsmSim808::GsmClientSecure TinyGsmClientSecure; + #elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) #include + typedef TinyGsm::GsmClient TinyGsmClient; + #elif defined(TINY_GSM_MODEM_M590) #include + typedef TinyGsm::GsmClient TinyGsmClient; + #elif defined(TINY_GSM_MODEM_ESP8266) #include + typedef TinyGsm::GsmClient TinyGsmClient; + #else #error "Please define GSM modem model" #endif diff --git a/TinyGsmClientA6.h b/TinyGsmClientA6.h index 9af5bb6..c8c0db0 100644 --- a/TinyGsmClientA6.h +++ b/TinyGsmClientA6.h @@ -714,6 +714,4 @@ private: GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; -typedef TinyGsm::GsmClient TinyGsmClient; - #endif diff --git a/TinyGsmClientESP8266.h b/TinyGsmClientESP8266.h index 41e1dc8..b15a70e 100644 --- a/TinyGsmClientESP8266.h +++ b/TinyGsmClientESP8266.h @@ -396,6 +396,4 @@ private: GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; -typedef TinyGsm::GsmClient TinyGsmClient; - #endif diff --git a/TinyGsmClientM590.h b/TinyGsmClientM590.h index 35ee3c4..d6a4e4c 100644 --- a/TinyGsmClientM590.h +++ b/TinyGsmClientM590.h @@ -702,6 +702,4 @@ private: GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; -typedef TinyGsm::GsmClient TinyGsmClient; - #endif diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 72a5b78..b437719 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -40,24 +40,24 @@ enum RegStatus { }; -class TinyGsm +class TinyGsmSim800 { public: class GsmClient : public Client { - friend class TinyGsm; + friend class TinyGsmSim800; typedef TinyGsmFifo RxFifo; public: GsmClient() {} - GsmClient(TinyGsm& modem, uint8_t mux = 1) { + GsmClient(TinyGsmSim800& modem, uint8_t mux = 1) { init(&modem, mux); } - bool init(TinyGsm* modem, uint8_t mux = 1) { + bool init(TinyGsmSim800* modem, uint8_t mux = 1) { this->at = modem; this->mux = mux; sock_available = 0; @@ -171,7 +171,7 @@ public: String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; private: - TinyGsm* at; + TinyGsmSim800* at; uint8_t mux; uint16_t sock_available; uint32_t prev_check; @@ -185,7 +185,7 @@ class GsmClientSecure : public GsmClient public: GsmClientSecure() {} - GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) + GsmClientSecure(TinyGsmSim800& modem, uint8_t mux = 1) : GsmClient(modem, mux) {} @@ -200,7 +200,7 @@ public: public: - TinyGsm(Stream& stream) + TinyGsmSim800(Stream& stream) : stream(stream) { memset(sockets, 0, sizeof(sockets)); @@ -672,7 +672,7 @@ public: return res; } -private: +protected: bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { sendAT(GF("+CIPSSL="), ssl); @@ -904,12 +904,9 @@ finish: return waitResponse(1000, r1, r2, r3, r4, r5); } -private: +protected: Stream& stream; GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; -typedef TinyGsm::GsmClient TinyGsmClient; -typedef TinyGsm::GsmClientSecure TinyGsmClientSecure; - #endif diff --git a/TinyGsmClientSIM808.h b/TinyGsmClientSIM808.h index aea2324..2b9c49a 100644 --- a/TinyGsmClientSIM808.h +++ b/TinyGsmClientSIM808.h @@ -11,13 +11,13 @@ #include -class TinyGsmSim808: public TinyGsm +class TinyGsmSim808: public TinyGsmSim800 { public: TinyGsmSim808(Stream& stream) - : TinyGsm(stream) + : TinyGsmSim800(stream) {} /* diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index b3a8c62..0dd80bd 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -11,6 +11,7 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 @@ -125,7 +126,14 @@ void loop() { String ussd_phone_num = modem.sendUSSD("*161#"); DBG("Phone number (USSD):", ussd_phone_num); -#ifdef SMS_TARGET +#if defined(TINY_GSM_MODEM_SIM808) + modem.enableGPS(); + String gps_raw = modem.getGPSraw(); + modem.disableGPS(); + DBG("GPS raw data:", gps_raw); +#endif + +#if defined(SMS_TARGET) res = modem.sendSMS(SMS_TARGET, String("Hello from ") + imei); DBG("SMS:", res ? "OK" : "fail"); @@ -134,7 +142,7 @@ void loop() { DBG("UTF16 SMS:", res ? "OK" : "fail"); #endif -#ifdef CALL_TARGET +#if defined(CALL_TARGET) DBG("Calling:", CALL_TARGET); // This is NOT supported on M590 From 512c69f3dfeda7f0a50dcb575cfe60cdc2041983 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 13:50:34 +0300 Subject: [PATCH 72/82] Adjust modem selection options --- examples/AllFunctions/AllFunctions.ino | 1 - examples/BlynkClient/BlynkClient.ino | 1 + examples/FileDownload/FileDownload.ino | 1 + examples/HttpClient/HttpClient.ino | 1 + examples/HttpsClient/HttpsClient.ino | 3 ++- examples/MqttClient/MqttClient.ino | 1 + examples/WebClient/WebClient.ino | 1 + 7 files changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index 0dd80bd..1e28bcb 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -16,7 +16,6 @@ // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_M590 -// #define TINY_GSM_MODEM_ESP8266 // Set serial for debug console (to the Serial Monitor, speed 115200) #define SerialMon Serial diff --git a/examples/BlynkClient/BlynkClient.ino b/examples/BlynkClient/BlynkClient.ino index 5264c79..2716612 100644 --- a/examples/BlynkClient/BlynkClient.ino +++ b/examples/BlynkClient/BlynkClient.ino @@ -30,6 +30,7 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 diff --git a/examples/FileDownload/FileDownload.ino b/examples/FileDownload/FileDownload.ino index 0853d3b..2ee647b 100644 --- a/examples/FileDownload/FileDownload.ino +++ b/examples/FileDownload/FileDownload.ino @@ -14,6 +14,7 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 diff --git a/examples/HttpClient/HttpClient.ino b/examples/HttpClient/HttpClient.ino index 0ab7726..a2c1b73 100644 --- a/examples/HttpClient/HttpClient.ino +++ b/examples/HttpClient/HttpClient.ino @@ -14,6 +14,7 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 diff --git a/examples/HttpsClient/HttpsClient.ino b/examples/HttpsClient/HttpsClient.ino index 49a85fe..b0308ff 100644 --- a/examples/HttpsClient/HttpsClient.ino +++ b/examples/HttpsClient/HttpsClient.ino @@ -13,8 +13,9 @@ **************************************************************/ // Select your modem -// SSL/TLS is currently supported only with SIM800 series +// SSL/TLS is currently supported only with SIM8xx series #define TINY_GSM_MODEM_SIM800 +#define TINY_GSM_MODEM_SIM808 // Increase RX buffer #define TINY_GSM_RX_BUFFER 64 diff --git a/examples/MqttClient/MqttClient.ino b/examples/MqttClient/MqttClient.ino index 9327462..856eb05 100644 --- a/examples/MqttClient/MqttClient.ino +++ b/examples/MqttClient/MqttClient.ino @@ -27,6 +27,7 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index 504e47c..6f65c93 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -10,6 +10,7 @@ // Select your modem: #define TINY_GSM_MODEM_SIM800 +// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 From 6133a17ef995a76cb1ff1c4194a353af04cd4467 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 14:04:41 +0300 Subject: [PATCH 73/82] Boost ver --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 9600e16..2572e66 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TinyGSM", - "version": "0.3.0", + "version": "0.3.1", "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 e1b1ec6..e5bac8a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TinyGSM -version=0.3.0 +version=0.3.1 author=Volodymyr Shymanskyy maintainer=Volodymyr Shymanskyy sentence=A small Arduino library for GPRS modules, that just works. From da1558c6f5fcb33dab4ea37b69b808934018c009 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 14:10:26 +0300 Subject: [PATCH 74/82] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b01c1df..776049d 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Receiving calls | ◌ | ◌ | ◌ | 🅧 | 🅧 DTMF decoding | | | 🅧 | 🅧 | 🅧 **Location** GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 -GPS/GNSS | 🅧 | ◌ | ◌¹ | 🅧 | 🅧 +GPS/GNSS | 🅧 | ✔ | ◌¹ | 🅧 | 🅧 ✔ - implemented  ◌ - planned  🅧 - not available for this modem ¹ - supported only on some models or firmware revisions From 270d52992bd16ccdeb8acf054ea385605aed359d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 15:10:11 +0300 Subject: [PATCH 75/82] Update README.md [ci skip] --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 776049d..1de4a08 100644 --- a/README.md +++ b/README.md @@ -42,19 +42,19 @@ TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ UDP | | | | | SSL/TLS (HTTPS) | ✔¹ | ✔¹ | 🅧 | 🅧 | ◌ **USSD** -Sending USSD requests | ✔ | ✔ | ✔ | ✔ | 🅧 -Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | 🅧 +Sending USSD requests | ✔ | ✔ | ✔ | ✔ | +Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | **SMS** -Sending | ✔ | ✔ | ✔ | ✔ | 🅧 -Sending Unicode | ✔ | ✔ | ◌ | 🅧 | 🅧 -Receiving/Reading | | | | | 🅧 +Sending | ✔ | ✔ | ✔ | ✔ | +Sending Unicode | ✔ | ✔ | ◌ | 🅧 | +Receiving/Reading | | | | | **Calls** -Dial, hangup | ✔ | ✔ | ✔ | 🅧 | 🅧 -Receiving calls | ◌ | ◌ | ◌ | 🅧 | 🅧 -DTMF decoding | | | 🅧 | 🅧 | 🅧 +Dial, hangup | ✔ | ✔ | ✔ | 🅧 | +Receiving calls | ◌ | ◌ | ◌ | 🅧 | +DTMF decoding | | | 🅧 | 🅧 | **Location** -GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 -GPS/GNSS | 🅧 | ✔ | ◌¹ | 🅧 | 🅧 +GSM location service | ✔ | ✔ | 🅧 | 🅧 | +GPS/GNSS | 🅧 | ✔ | ◌¹ | 🅧 | ✔ - implemented  ◌ - planned  🅧 - not available for this modem ¹ - supported only on some models or firmware revisions From bb7161abd7eab71a19430ac563db83d31f431406 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 15:58:55 +0300 Subject: [PATCH 76/82] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1de4a08..74e0437 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,11 @@ Receiving calls | ◌ | ◌ | ◌ | 🅧 | DTMF decoding | | | 🅧 | 🅧 | **Location** GSM location service | ✔ | ✔ | 🅧 | 🅧 | -GPS/GNSS | 🅧 | ✔ | ◌¹ | 🅧 | +GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 | ✔ - implemented  ◌ - planned  🅧 - not available for this modem -¹ - supported only on some models or firmware revisions +¹ - only some device models or firmware revisions have this feature +² - current implementation only supports SIM808 V2 GPS ## Supported modems From 597b101e49b60c57dae9bddec9d92b68077a6ec7 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 16:00:11 +0300 Subject: [PATCH 77/82] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74e0437..3d5bb62 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ GSM location service | ✔ | ✔ | 🅧 | 🅧 | GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 | ✔ - implemented  ◌ - planned  🅧 - not available for this modem -¹ - only some device models or firmware revisions have this feature +¹ - only some device models or firmware revisions have this feature ² - current implementation only supports SIM808 V2 GPS ## Supported modems From 8dd2e0e335513e6db5fc6c9a3a26a5dd6be61e94 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 16:01:23 +0300 Subject: [PATCH 78/82] Update .travis.yml --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f49d1d7..ee065dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,8 @@ env: - PLATFORMIO_CI_SRC=tools/FactoryReset # Arduino test - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=esp01 --board=nodemcuv2 --board=esp32dev" + #TODO: add --board=uno_pic32 # Energia test - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='framework=energia' --board=lplm4f120h5qr" From 12f0f0fa59065fc119cfd910c3a2ef6774b33c42 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 18 Sep 2017 00:06:45 +0300 Subject: [PATCH 79/82] Update README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 3d5bb62..e612c4f 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,16 @@ More modems may be supported later: Watch this repo for new updates! And of course, contributions are welcome ;) +## Donation + +[![Donate BountySource](https://img.shields.io/badge/Donate-BountySource-149E5E.svg)](https://salt.bountysource.com/checkout/amount?team=tinygsm-dev) +[![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-orange.svg)](http://tny.im/aen) + +Your donations will be spent for: +- Covering cellular network expences +- Buying new hardware and modems for integration +- Bounty Budget (to reward other developers for contributing into TinyGSM) + ## Getting Started 1. Using your phone: From 5b0d6ca6c0c5e97d4d7bf110ddfbf9438659ed63 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 18 Sep 2017 00:09:02 +0300 Subject: [PATCH 80/82] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e612c4f..5b0ff7c 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ Watch this repo for new updates! And of course, contributions are welcome ;) Your donations will be spent for: - Covering cellular network expences - Buying new hardware and modems for integration -- Bounty Budget (to reward other developers for contributing into TinyGSM) +- Bounty Budget (to reward other developers for their contributions) ## Getting Started From 5cc30261f6e3de7e9da6915b5efd5d6c2a16428c Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 18 Sep 2017 00:14:49 +0300 Subject: [PATCH 81/82] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b0ff7c..1a5afd2 100644 --- a/README.md +++ b/README.md @@ -89,10 +89,13 @@ Watch this repo for new updates! And of course, contributions are welcome ;) [![Donate BountySource](https://img.shields.io/badge/Donate-BountySource-149E5E.svg)](https://salt.bountysource.com/checkout/amount?team=tinygsm-dev) [![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-orange.svg)](http://tny.im/aen) -Your donations will be spent for: +If you have found TinyGSM to be useful in your work, research or company, please consider making a donation to the project commensurate with your resources. Any amount helps! +**All donations will be used strictly to fund the development of TinyGSM:** - Covering cellular network expences - Buying new hardware and modems for integration - Bounty Budget (to reward other developers for their contributions) +- Implementing new features +- Quality Assurance ## Getting Started From b37c55f41349fbf969d7b6604267b70831af54ab Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 18 Sep 2017 15:23:22 +0300 Subject: [PATCH 82/82] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1a5afd2..5722642 100644 --- a/README.md +++ b/README.md @@ -40,21 +40,24 @@ Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 **Data connections** TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ UDP | | | | | -SSL/TLS (HTTPS) | ✔¹ | ✔¹ | 🅧 | 🅧 | ◌ +SSL/TLS (HTTPS) | ✔¹ | ✔¹ | 🅧 | 🅧 | ◌ **USSD** Sending USSD requests | ✔ | ✔ | ✔ | ✔ | Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | **SMS** Sending | ✔ | ✔ | ✔ | ✔ | Sending Unicode | ✔ | ✔ | ◌ | 🅧 | -Receiving/Reading | | | | | +Reading | | | | | +Incoming message event | | | | ? | **Calls** Dial, hangup | ✔ | ✔ | ✔ | 🅧 | -Receiving calls | ◌ | ◌ | ◌ | 🅧 | -DTMF decoding | | | 🅧 | 🅧 | +Receiving calls | ✔ | ✔ | ✔ | 🅧 | +Incoming event (RING) | ◌ | ◌ | ◌ | 🅧 | +DTMF sending | ◌ | ◌ | ◌ | 🅧 | +DTMF decoding | ◌ | ◌ | 🅧 | 🅧 | **Location** GSM location service | ✔ | ✔ | 🅧 | 🅧 | -GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 | +GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 | ✔ - implemented  ◌ - planned  🅧 - not available for this modem ¹ - only some device models or firmware revisions have this feature