2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -2,3 +2,5 @@ | ||||
| /.gitattributes export-ignore | ||||
| /.gitignore export-ignore | ||||
| /.travis.yml export-ignore | ||||
|  | ||||
| *.ino filter=updateUsersAndPasses | ||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -23,7 +23,7 @@ with your board before submitting any issues. | ||||
|  | ||||
| Main processor board: <!-- Uno, Zero, ESP32, Particle, etc --> | ||||
| Modem: <!-- Brand, model, variant, firmware version --> | ||||
| TinyGSM version: <!-- always try to use the latest (0.9.7) --> | ||||
| TinyGSM version: <!-- always try to use the latest (0.9.17) --> | ||||
| Code: <!-- Example name or paste in your code --> | ||||
|  | ||||
| ### Scenario, steps to reproduce | ||||
|   | ||||
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -22,6 +22,9 @@ | ||||
| platformio.ini | ||||
| lib/readme.txt | ||||
| include/readme.txt | ||||
| .atomrc.cson | ||||
|  | ||||
| # VSCode | ||||
| .vscode/* | ||||
| .vscode/.browse.c_cpp.db* | ||||
| .vscode/c_cpp_properties.json | ||||
| @@ -36,3 +39,7 @@ extras/Module Datasheets/* | ||||
| extras/Older Command Manuals/* | ||||
| extras/Older Command Manuals/* | ||||
| extras/At Command Manuals - Unsupported/* | ||||
|  | ||||
| # Filters | ||||
| .gitconfig | ||||
| filters/* | ||||
|   | ||||
| @@ -79,9 +79,9 @@ Watch this repo for new updates! And of course, contributions are welcome ;) | ||||
| - UDP | ||||
|     - Not yet supported on any module, though it may be some day | ||||
| - SSL/TLS (HTTPS) | ||||
|     - Supported on¹: | ||||
|     - Supported on: | ||||
|         - SIM800, u-Blox, XBee _cellular_, ESP8266, and Sequans Monarch | ||||
|         ¹ - only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.) | ||||
|         - Note:  only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.) | ||||
|     - Not yet supported on: | ||||
|         - Quectel modems, SIM7000, SIM5360/5320/7100/7500/7600 | ||||
|     - Not possible on: | ||||
|   | ||||
| @@ -60,6 +60,7 @@ | ||||
| #define TINY_GSM_TEST_SMS true | ||||
| #define TINY_GSM_TEST_USSD true | ||||
| #define TINY_GSM_TEST_BATTERY true | ||||
| #define TINY_GSM_TEST_GPS false | ||||
| // powerdown modem after tests | ||||
| #define TINY_GSM_POWERDOWN false | ||||
|  | ||||
| @@ -70,16 +71,40 @@ | ||||
| //#define SMS_TARGET  "+380xxxxxxxxx" | ||||
| //#define CALL_TARGET "+380xxxxxxxxx" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[]  = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
|  | ||||
| #if TINY_GSM_TEST_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_TEST_GPRS | ||||
| #undef TINY_GSM_TEST_CALL | ||||
| #undef TINY_GSM_TEST_SMS | ||||
| #undef TINY_GSM_TEST_USSD | ||||
| #undef TINY_GSM_TEST_WIFI | ||||
| #define TINY_GSM_TEST_GPRS false | ||||
| #define TINY_GSM_TEST_CALL false | ||||
| #define TINY_GSM_TEST_SMS false | ||||
| #define TINY_GSM_TEST_USSD false | ||||
| #define TINY_GSM_TEST_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_TEST_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
| #if TINY_GSM_TEST_GPS && not defined TINY_GSM_MODEM_HAS_GPS | ||||
| #undef TINY_GSM_TEST_GPS | ||||
| #define TINY_GSM_TEST_GPS false | ||||
| #endif | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, SerialMon); | ||||
| @@ -202,7 +227,7 @@ void loop() { | ||||
|   DBG("Phone number (USSD):", ussd_phone_num); | ||||
| #endif | ||||
|  | ||||
| #if defined(TINY_GSM_MODEM_HAS_GPS) | ||||
| #if TINY_GSM_TEST_GPS | ||||
|   modem.enableGPS(); | ||||
|   String gps_raw = modem.getGPSraw(); | ||||
|   modem.disableGPS(); | ||||
|   | ||||
| @@ -63,8 +63,7 @@ | ||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||
|  | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char user[] = ""; | ||||
| const char pass[] = ""; | ||||
| @@ -91,7 +90,7 @@ void setup() | ||||
|   modem.restart(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   SerialMon.print("Modem: "); | ||||
|   SerialMon.print("Modem Info: "); | ||||
|   SerialMon.println(modemInfo); | ||||
|  | ||||
|   // Unlock your SIM card with a PIN | ||||
|   | ||||
| @@ -61,17 +61,19 @@ | ||||
| // Add a reception delay - may be needed for a fast processor at a slow baud rate | ||||
| //#define TINY_GSM_YIELD() { delay(2); } | ||||
|  | ||||
| // Define how you're planning to connect to the internet | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
|  | ||||
| // set GSM PIN, if any | ||||
| #define GSM_PIN "" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[]  = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| @@ -82,6 +84,20 @@ const int  port = 80; | ||||
| #include <TinyGsmClient.h> | ||||
| #include <CRC32.h> | ||||
|  | ||||
| // Just in case someone defined the wrong thing.. | ||||
| #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS false | ||||
| #define TINY_GSM_USE_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
|  | ||||
| const char resource[]  = "/TinyGSM/test_1k.bin"; | ||||
| uint32_t knownCRC32    = 0x6f50d767; | ||||
| uint32_t knownFileSize = 1024;   // In case server does not send it | ||||
| @@ -101,6 +117,12 @@ void setup() { | ||||
|   SerialMon.begin(115200); | ||||
|   delay(10); | ||||
|  | ||||
|   // !!!!!!!!!!! | ||||
|   // Set your reset, enable, power pins here | ||||
|   // !!!!!!!!!!! | ||||
|  | ||||
|   SerialMon.println("Wait..."); | ||||
|  | ||||
|   // Set GSM module baud rate | ||||
|   SerialAT.begin(115200); | ||||
|   delay(3000); | ||||
| @@ -109,9 +131,10 @@ void setup() { | ||||
|   // To skip it, call init() instead of restart() | ||||
|   SerialMon.println("Initializing modem..."); | ||||
|   modem.restart(); | ||||
|   // modem.init(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   SerialMon.print("Modem: "); | ||||
|   SerialMon.print("Modem Info: "); | ||||
|   SerialMon.println(modemInfo); | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS | ||||
| @@ -135,7 +158,8 @@ void printPercent(uint32_t readLength, uint32_t contentLength) { | ||||
|  | ||||
| void loop() { | ||||
|  | ||||
| #if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   // Wifi connection parameters must be set before waiting for the network | ||||
|   SerialMon.print(F("Setting SSID/password...")); | ||||
|   if (!modem.networkConnect(wifiSSID, wifiPass)) { | ||||
|     SerialMon.println(" fail"); | ||||
| @@ -162,7 +186,8 @@ void loop() { | ||||
|     SerialMon.println("Network connected"); | ||||
|   } | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   // GPRS connection parameters are usually set after network registration | ||||
|   SerialMon.print(F("Connecting to ")); | ||||
|   SerialMon.print(apn); | ||||
|   if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { | ||||
| @@ -171,6 +196,10 @@ void loop() { | ||||
|     return; | ||||
|   } | ||||
|   SerialMon.println(" success"); | ||||
|  | ||||
|   if (modem.isGprsConnected()) { | ||||
|     SerialMon.println("GPRS connected"); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   SerialMon.print(F("Connecting to ")); | ||||
| @@ -292,8 +321,14 @@ void loop() { | ||||
|   client.stop(); | ||||
|   SerialMon.println(F("Server disconnected")); | ||||
|  | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   modem.networkDisconnect(); | ||||
|   SerialMon.println(F("WiFi disconnected")); | ||||
| #endif | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   modem.gprsDisconnect(); | ||||
|   SerialMon.println(F("GPRS disconnected")); | ||||
| #endif | ||||
|  | ||||
|   float duration = float(timeElapsed) / 1000; | ||||
|  | ||||
|   | ||||
| @@ -63,20 +63,26 @@ | ||||
| #define TINY_GSM_DEBUG SerialMon | ||||
| //#define LOGGING  // <- Logging is for the HTTP library | ||||
|  | ||||
| // Range to attempt to autobaud | ||||
| #define GSM_AUTOBAUD_MIN 9600 | ||||
| #define GSM_AUTOBAUD_MAX 115200 | ||||
|  | ||||
| // Add a reception delay - may be needed for a fast processor at a slow baud rate | ||||
| //#define TINY_GSM_YIELD() { delay(2); } | ||||
|  | ||||
| // Define how you're planning to connect to the internet | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
|  | ||||
| // set GSM PIN, if any | ||||
| #define GSM_PIN "" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[]  = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| @@ -88,6 +94,20 @@ const int  port = 80; | ||||
| #include <TinyGsmClient.h> | ||||
| #include <ArduinoHttpClient.h> | ||||
|  | ||||
| // Just in case someone defined the wrong thing.. | ||||
| #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS false | ||||
| #define TINY_GSM_USE_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, SerialMon); | ||||
| @@ -111,7 +131,8 @@ void setup() { | ||||
|   SerialMon.println("Wait..."); | ||||
|  | ||||
|   // Set GSM module baud rate | ||||
|   SerialAT.begin(115200); | ||||
|   // TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX); | ||||
|   SerialAT.begin(9600); | ||||
|   delay(3000); | ||||
|  | ||||
|   // Restart takes quite some time | ||||
| @@ -121,7 +142,7 @@ void setup() { | ||||
|   // modem.init(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   SerialMon.print("Modem: "); | ||||
|   SerialMon.print("Modem Info: "); | ||||
|   SerialMon.println(modemInfo); | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS | ||||
| @@ -134,7 +155,8 @@ void setup() { | ||||
|  | ||||
| void loop() { | ||||
|  | ||||
| #if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   // Wifi connection parameters must be set before waiting for the network | ||||
|   SerialMon.print(F("Setting SSID/password...")); | ||||
|   if (!modem.networkConnect(wifiSSID, wifiPass)) { | ||||
|     SerialMon.println(" fail"); | ||||
| @@ -161,7 +183,8 @@ void loop() { | ||||
|     SerialMon.println("Network connected"); | ||||
|   } | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   // GPRS connection parameters are usually set after network registration | ||||
|     SerialMon.print(F("Connecting to ")); | ||||
|     SerialMon.print(apn); | ||||
|     if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { | ||||
| @@ -170,6 +193,10 @@ void loop() { | ||||
|       return; | ||||
|     } | ||||
|     SerialMon.println(" success"); | ||||
|  | ||||
|     if (modem.isGprsConnected()) { | ||||
|       SerialMon.println("GPRS connected"); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   SerialMon.print(F("Performing HTTP GET request... ")); | ||||
|   | ||||
| @@ -55,20 +55,26 @@ | ||||
| #define TINY_GSM_DEBUG SerialMon | ||||
| //#define LOGGING  // <- Logging is for the HTTP library | ||||
|  | ||||
| // Range to attempt to autobaud | ||||
| #define GSM_AUTOBAUD_MIN 9600 | ||||
| #define GSM_AUTOBAUD_MAX 115200 | ||||
|  | ||||
| // Add a reception delay - may be needed for a fast processor at a slow baud rate | ||||
| //#define TINY_GSM_YIELD() { delay(2); } | ||||
|  | ||||
| // Define how you're planning to connect to the internet | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
|  | ||||
| // set GSM PIN, if any | ||||
| #define GSM_PIN "" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[]  = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| @@ -80,6 +86,20 @@ const int  port = 443; | ||||
| #include <TinyGsmClient.h> | ||||
| #include <ArduinoHttpClient.h> | ||||
|  | ||||
| // Just in case someone defined the wrong thing.. | ||||
| #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS false | ||||
| #define TINY_GSM_USE_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, SerialMon); | ||||
| @@ -103,7 +123,8 @@ void setup() { | ||||
|   SerialMon.println("Wait..."); | ||||
|  | ||||
|   // Set GSM module baud rate | ||||
|   SerialAT.begin(115200); | ||||
|   // TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX); | ||||
|   SerialAT.begin(9600); | ||||
|   delay(3000); | ||||
|  | ||||
|   // Restart takes quite some time | ||||
| @@ -113,7 +134,7 @@ void setup() { | ||||
|   // modem.init(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   SerialMon.print("Modem: "); | ||||
|   SerialMon.print("Modem Info: "); | ||||
|   SerialMon.println(modemInfo); | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS | ||||
| @@ -131,7 +152,8 @@ void setup() { | ||||
|  | ||||
| void loop() { | ||||
|  | ||||
| #if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   // Wifi connection parameters must be set before waiting for the network | ||||
|   SerialMon.print(F("Setting SSID/password...")); | ||||
|   if (!modem.networkConnect(wifiSSID, wifiPass)) { | ||||
|     SerialMon.println(" fail"); | ||||
| @@ -158,7 +180,8 @@ void loop() { | ||||
|     SerialMon.println("Network connected"); | ||||
|   } | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   // GPRS connection parameters are usually set after network registration | ||||
|     SerialMon.print(F("Connecting to ")); | ||||
|     SerialMon.print(apn); | ||||
|     if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { | ||||
| @@ -167,6 +190,10 @@ void loop() { | ||||
|       return; | ||||
|     } | ||||
|     SerialMon.println(" success"); | ||||
|  | ||||
|     if (modem.isGprsConnected()) { | ||||
|       SerialMon.println("GPRS connected"); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   SerialMon.print(F("Performing HTTPS GET request... ")); | ||||
|   | ||||
| @@ -67,27 +67,29 @@ | ||||
|  | ||||
| // Range to attempt to autobaud | ||||
| #define GSM_AUTOBAUD_MIN 9600 | ||||
| #define GSM_AUTOBAUD_MAX 38400 | ||||
| #define GSM_AUTOBAUD_MAX 115200 | ||||
|  | ||||
| // Add a reception delay - may be needed for a fast processor at a slow baud rate | ||||
| //#define TINY_GSM_YIELD() { delay(2); } | ||||
|  | ||||
| // Define how you're planning to connect to the internet | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
|  | ||||
| // set GSM PIN, if any | ||||
| #define GSM_PIN "" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[] = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[] = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| // MQTT details | ||||
| const char* broker = "test.mosquitto.org"; | ||||
| const char* broker = "broker.hivemq.com"; | ||||
|  | ||||
| const char* topicLed = "GsmClientTest/led"; | ||||
| const char* topicInit = "GsmClientTest/init"; | ||||
| @@ -96,6 +98,20 @@ const char* topicLedStatus = "GsmClientTest/ledStatus"; | ||||
| #include <TinyGsmClient.h> | ||||
| #include <PubSubClient.h> | ||||
|  | ||||
| // Just in case someone defined the wrong thing.. | ||||
| #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS false | ||||
| #define TINY_GSM_USE_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, SerialMon); | ||||
| @@ -111,6 +127,42 @@ int ledStatus = LOW; | ||||
|  | ||||
| long lastReconnectAttempt = 0; | ||||
|  | ||||
| void mqttCallback(char* topic, byte* payload, unsigned int len) { | ||||
|   SerialMon.print("Message arrived ["); | ||||
|   SerialMon.print(topic); | ||||
|   SerialMon.print("]: "); | ||||
|   SerialMon.write(payload, len); | ||||
|   SerialMon.println(); | ||||
|  | ||||
|   // Only proceed if incoming message's topic matches | ||||
|   if (String(topic) == topicLed) { | ||||
|     ledStatus = !ledStatus; | ||||
|     digitalWrite(LED_PIN, ledStatus); | ||||
|     mqtt.publish(topicLedStatus, ledStatus ? "1" : "0"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| boolean mqttConnect() { | ||||
|   SerialMon.print("Connecting to "); | ||||
|   SerialMon.print(broker); | ||||
|  | ||||
|   // Connect to MQTT Broker | ||||
|   boolean status = mqtt.connect("GsmClientTest"); | ||||
|  | ||||
|   // Or, if you want to authenticate MQTT: | ||||
|   //boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass"); | ||||
|  | ||||
|   if (status == false) { | ||||
|     SerialMon.println(" fail"); | ||||
|     return false; | ||||
|   } | ||||
|   SerialMon.println(" success"); | ||||
|   mqtt.publish(topicInit, "GsmClientTest started"); | ||||
|   mqtt.subscribe(topicLed); | ||||
|   return mqtt.connected(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void setup() { | ||||
|   // Set console baud rate | ||||
|   SerialMon.begin(115200); | ||||
| @@ -125,7 +177,8 @@ void setup() { | ||||
|   SerialMon.println("Wait..."); | ||||
|  | ||||
|   // Set GSM module baud rate | ||||
|   SerialAT.begin(115200); | ||||
|   // TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX); | ||||
|   SerialAT.begin(9600); | ||||
|   delay(3000); | ||||
|  | ||||
|   // Restart takes quite some time | ||||
| @@ -135,7 +188,7 @@ void setup() { | ||||
|   // modem.init(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   SerialMon.print("Modem: "); | ||||
|   SerialMon.print("Modem Info: "); | ||||
|   SerialMon.println(modemInfo); | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS | ||||
| @@ -145,7 +198,8 @@ void setup() { | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #if TINY_GSM_USE_WIFI | ||||
|     // Wifi connection parameters must be set before waiting for the network | ||||
|   SerialMon.print(F("Setting SSID/password...")); | ||||
|   if (!modem.networkConnect(wifiSSID, wifiPass)) { | ||||
|     SerialMon.println(" fail"); | ||||
| @@ -172,7 +226,8 @@ void setup() { | ||||
|     SerialMon.println("Network connected"); | ||||
|   } | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   // GPRS connection parameters are usually set after network registration | ||||
|     SerialMon.print(F("Connecting to ")); | ||||
|     SerialMon.print(apn); | ||||
|     if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { | ||||
| @@ -181,6 +236,10 @@ void setup() { | ||||
|       return; | ||||
|     } | ||||
|     SerialMon.println(" success"); | ||||
|  | ||||
|   if (modem.isGprsConnected()) { | ||||
|     SerialMon.println("GPRS connected"); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   // MQTT Broker setup | ||||
| @@ -188,26 +247,6 @@ void setup() { | ||||
|   mqtt.setCallback(mqttCallback); | ||||
| } | ||||
|  | ||||
| boolean mqttConnect() { | ||||
|   SerialMon.print("Connecting to "); | ||||
|   SerialMon.print(broker); | ||||
|  | ||||
|   // Connect to MQTT Broker | ||||
|   boolean status = mqtt.connect("GsmClientTest"); | ||||
|  | ||||
|   // Or, if you want to authenticate MQTT: | ||||
|   //boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass"); | ||||
|  | ||||
|   if (status == false) { | ||||
|     SerialMon.println(" fail"); | ||||
|     return false; | ||||
|   } | ||||
|   SerialMon.println(" success"); | ||||
|   mqtt.publish(topicInit, "GsmClientTest started"); | ||||
|   mqtt.subscribe(topicLed); | ||||
|   return mqtt.connected(); | ||||
| } | ||||
|  | ||||
| void loop() { | ||||
|  | ||||
|   if (!mqtt.connected()) { | ||||
| @@ -226,18 +265,3 @@ void loop() { | ||||
|  | ||||
|   mqtt.loop(); | ||||
| } | ||||
|  | ||||
| void mqttCallback(char* topic, byte* payload, unsigned int len) { | ||||
|   SerialMon.print("Message arrived ["); | ||||
|   SerialMon.print(topic); | ||||
|   SerialMon.print("]: "); | ||||
|   SerialMon.write(payload, len); | ||||
|   SerialMon.println(); | ||||
|  | ||||
|   // Only proceed if incoming message's topic matches | ||||
|   if (String(topic) == topicLed) { | ||||
|     ledStatus = !ledStatus; | ||||
|     digitalWrite(LED_PIN, ledStatus); | ||||
|     mqtt.publish(topicLedStatus, ledStatus ? "1" : "0"); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -62,17 +62,20 @@ | ||||
| // Uncomment this if you want to use SSL | ||||
| //#define USE_SSL | ||||
|  | ||||
| // Define how you're planning to connect to the internet | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
|  | ||||
| // set GSM PIN, if any | ||||
| #define GSM_PIN "" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[]  = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| // Server details | ||||
| @@ -81,6 +84,20 @@ const char resource[] = "/TinyGSM/logo.txt"; | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
|  | ||||
| // Just in case someone defined the wrong thing.. | ||||
| #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS false | ||||
| #define TINY_GSM_USE_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, SerialMon); | ||||
| @@ -120,7 +137,7 @@ void setup() { | ||||
|   // modem.init(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   SerialMon.print("Modem: "); | ||||
|   SerialMon.print("Modem Info: "); | ||||
|   SerialMon.println(modemInfo); | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS | ||||
| @@ -133,7 +150,8 @@ void setup() { | ||||
|  | ||||
| void loop() { | ||||
|  | ||||
| #if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   // Wifi connection parameters must be set before waiting for the network | ||||
|   SerialMon.print(F("Setting SSID/password...")); | ||||
|   if (!modem.networkConnect(wifiSSID, wifiPass)) { | ||||
|     SerialMon.println(" fail"); | ||||
| @@ -160,7 +178,8 @@ void loop() { | ||||
|     SerialMon.println("Network connected"); | ||||
|   } | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   // GPRS connection parameters are usually set after network registration | ||||
|     SerialMon.print(F("Connecting to ")); | ||||
|     SerialMon.print(apn); | ||||
|     if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { | ||||
| @@ -169,6 +188,10 @@ void loop() { | ||||
|       return; | ||||
|     } | ||||
|     SerialMon.println(" success"); | ||||
|  | ||||
|   if (modem.isGprsConnected()) { | ||||
|     SerialMon.println("GPRS connected"); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   SerialMon.print("Connecting to "); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "TinyGSM", | ||||
|   "version": "0.9.7", | ||||
|   "version": "0.9.17", | ||||
|   "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports many GSM, LTE, and WiFi modules with AT command interfaces.", | ||||
|   "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM7000, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968, M95, MC60, MC60E, BG96, ublox, Quectel, SIMCOM, AI Thinker, LTE, LTE-M", | ||||
|   "authors": | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| name=TinyGSM | ||||
| version=0.9.7 | ||||
| version=0.9.17 | ||||
| author=Volodymyr Shymanskyy | ||||
| maintainer=Volodymyr Shymanskyy | ||||
| sentence=A small Arduino library for GPRS modules, that just works. | ||||
|   | ||||
| @@ -135,20 +135,38 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("&FZE0"));  // Factory + Reset + Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     sendAT(GF("+CMEE=0"));  // Turn off verbose errors | ||||
|  | ||||
| #ifdef TINY_GSM_DEBUG | ||||
|     sendAT(GF("+CMEE=2"));  // turn on verbose error codes | ||||
| #else | ||||
|     sendAT(GF("+CMEE=0"));  // turn off error codes | ||||
| #endif | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CMER=3,0,0,2"));  // Set unsolicited result code output destination | ||||
|     waitResponse(); | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -525,6 +543,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|     } | ||||
|     chargeState = stream.readStringUntil(',').toInt(); | ||||
|     percent = stream.readStringUntil('\n').toInt(); | ||||
|     milliVolts = 0; | ||||
|     // Wait for final OK | ||||
|     waitResponse(); | ||||
|     return true; | ||||
| @@ -562,7 +581,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(2000L, GF(GSM_NL ">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|   | ||||
| @@ -158,16 +158,29 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("&FZE0"));  // Factory + Reset + Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -497,10 +510,12 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
| protected: | ||||
|  | ||||
|  bool modemConnect(const char* host, uint16_t port, uint8_t mux, | ||||
|                     bool ssl = false, int timeout_s = 20) | ||||
|  { | ||||
|                    bool ssl = false, int timeout_s = 20) { | ||||
|    if (ssl) { | ||||
|      DBG("SSL not yet supported on this module!"); | ||||
|    } | ||||
|    int rsp; | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|    uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000; | ||||
|  | ||||
|     // <PDPcontextID>(1-16), <connectID>(0-11),"TCP/UDP/TCP LISTENER/UDP SERVICE", | ||||
|     // "<IP_address>/<domain_name>",<remote_port>,<local_port>,<access_mode>(0-2 0=buffer) | ||||
| @@ -521,7 +536,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+QISEND="), mux, ',', len); | ||||
|     sendAT(GF("+QISEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -535,13 +550,13 @@ protected: | ||||
|   } | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
|     sendAT(GF("+QIRD="), mux, ',', size); | ||||
|     sendAT(GF("+QIRD="), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+QIRD:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|     size_t len = stream.readStringUntil('\n').toInt(); | ||||
|     int len = stream.readStringUntil('\n').toInt(); | ||||
|  | ||||
|     for (size_t i=0; i<len; i++) { | ||||
|     for (int i=0; i<len; i++) { | ||||
|       TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT | ||||
|     } | ||||
|     waitResponse(); | ||||
| @@ -557,7 +572,9 @@ protected: | ||||
|       streamSkipUntil(','); // Skip total received | ||||
|       streamSkipUntil(','); // Skip have read | ||||
|       result = stream.readStringUntil('\n').toInt(); | ||||
|       if (result) DBG("### DATA AVAILABLE:", result, "on", mux); | ||||
|       if (result) { | ||||
|         DBG("### DATA AVAILABLE:", result, "on", mux); | ||||
|       } | ||||
|       waitResponse(); | ||||
|     } | ||||
|     if (!result) { | ||||
|   | ||||
| @@ -33,13 +33,12 @@ static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; | ||||
| enum RegStatus { | ||||
|   REG_OK_IP     = 2, | ||||
|   REG_OK_TCP    = 3, | ||||
|   REG_UNREGISTERED = 4, | ||||
|   REG_OK_NO_TCP = 4, | ||||
|   REG_DENIED    = 5, | ||||
|   REG_UNKNOWN   = 6, | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| class TinyGsmESP8266 | ||||
| { | ||||
|  | ||||
| @@ -157,6 +156,9 @@ public: | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|     if (pin && strlen(pin) > 0) { | ||||
|       DBG("ESP8266 modules do not use an unlock pin!"); | ||||
|     } | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
| @@ -249,7 +251,8 @@ TINY_GSM_MODEM_MAINTAIN_LISTEN() | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     sendAT(GF("+CIPSTATUS")); | ||||
|     if (waitResponse(3000, GF("STATUS:")) != 1) return REG_UNKNOWN; | ||||
|     int status = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); | ||||
|     int status = | ||||
|         waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); | ||||
|     waitResponse();  // Returns an OK after the status | ||||
|     return (RegStatus)status; | ||||
|   } | ||||
| @@ -275,24 +278,25 @@ TINY_GSM_MODEM_MAINTAIN_LISTEN() | ||||
|  | ||||
|   bool isNetworkConnected()  { | ||||
|     RegStatus s = getRegistrationStatus(); | ||||
|     return (s == REG_OK_IP || s == REG_OK_TCP); | ||||
|     if (s == REG_OK_IP || s == REG_OK_TCP) { | ||||
|       // with these, we're definitely connected | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|   bool waitForNetwork(unsigned long timeout_ms = 60000L) { | ||||
|     for (unsigned long start = millis(); millis() - start < timeout_ms; ) { | ||||
|       sendAT(GF("+CIPSTATUS")); | ||||
|       int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:")); | ||||
|       if (res1 == 2) { | ||||
|         int res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); | ||||
|         if (res2 == 2 || res2 == 3) { | ||||
|             waitResponse(); | ||||
|     else if (s == REG_OK_NO_TCP) { | ||||
|       // with this, we may or may not be connected | ||||
|       if (getLocalIP() == "") { | ||||
|         return false; | ||||
|       } | ||||
|       else { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
|       delay(250); | ||||
|     } | ||||
|     else { | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
| @@ -370,7 +374,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -383,8 +387,37 @@ protected: | ||||
|   } | ||||
|  | ||||
|   bool modemGetConnected(uint8_t mux) { | ||||
|     RegStatus s = getRegistrationStatus(); | ||||
|     return (s == REG_OK_IP || s == REG_OK_TCP); | ||||
|     sendAT(GF("+CIPSTATUS")); | ||||
|     if (waitResponse(3000, GF("STATUS:")) != 1) return REG_UNKNOWN; | ||||
|     int status = | ||||
|         waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); | ||||
|     if (status != 3) { | ||||
|       // if the status is anything but 3, there are no connections open | ||||
|       waitResponse();  // Returns an OK after the status | ||||
|       for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) { | ||||
|         sockets[muxNo]->sock_connected = false; | ||||
|       } | ||||
|       return false; | ||||
|     } | ||||
|     bool verified_connections[TINY_GSM_MUX_COUNT] = {0, 0, 0, 0, 0}; | ||||
|     for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) { | ||||
|       uint8_t has_status = waitResponse(GF("+CIPSTATUS:"), GFP(GSM_OK), GFP(GSM_ERROR)); | ||||
|       if (has_status == 1) { | ||||
|         int returned_mux = stream.readStringUntil(',').toInt(); | ||||
|         streamSkipUntil(',');  // Skip mux | ||||
|         streamSkipUntil(',');  // Skip type | ||||
|         streamSkipUntil(',');  // Skip remote IP | ||||
|         streamSkipUntil(',');  // Skip remote port | ||||
|         streamSkipUntil(',');  // Skip local port | ||||
|         streamSkipUntil('\n');  // Skip client/server type | ||||
|         verified_connections[returned_mux] = 1; | ||||
|       } | ||||
|       if (has_status == 2) break;  // once we get to the ok, stop | ||||
|     } | ||||
|     for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) { | ||||
|       sockets[muxNo]->sock_connected = verified_connections[muxNo]; | ||||
|     } | ||||
|     return verified_connections[mux]; | ||||
|   } | ||||
|  | ||||
| public: | ||||
|   | ||||
| @@ -133,20 +133,36 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("&FZE0"));  // Factory + Reset + Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| #ifdef TINY_GSM_DEBUG | ||||
|     sendAT(GF("+CMEE=2")); | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CMEE=2"));  // turn on verbose error codes | ||||
| #else | ||||
|     sendAT(GF("+CMEE=0"));  // turn off error codes | ||||
| #endif | ||||
|     waitResponse(); | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -443,7 +459,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+TCPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+TCPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|   | ||||
| @@ -64,7 +64,6 @@ public: | ||||
|     this->mux = mux; | ||||
|     sock_available = 0; | ||||
|     sock_connected = false; | ||||
|     got_data = false; | ||||
|  | ||||
|     at->sockets[mux] = this; | ||||
|  | ||||
| @@ -110,7 +109,6 @@ private: | ||||
|   uint8_t         mux; | ||||
|   uint16_t        sock_available; | ||||
|   bool            sock_connected; | ||||
|   bool            got_data; | ||||
|   RxFifo          rx; | ||||
| }; | ||||
|  | ||||
| @@ -157,20 +155,36 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("&FZE0"));  // Factory + Reset + Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| #ifdef TINY_GSM_DEBUG | ||||
|     sendAT(GF("+CMEE=2")); | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CMEE=2"));  // turn on verbose error codes | ||||
| #else | ||||
|     sendAT(GF("+CMEE=0"));  // turn off error codes | ||||
| #endif | ||||
|     waitResponse(); | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -324,6 +338,18 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // Select TCP/IP transfer mode - NOT transparent mode | ||||
|     sendAT(GF("+QIMODE=0")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // Enable multiple TCP/IP connections | ||||
|     sendAT(GF("+QIMUX=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Start TCPIP Task and Set APN, User Name and Password | ||||
|     sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd,  "\"" ); | ||||
|     if (waitResponse() != 1) { | ||||
| @@ -332,28 +358,51 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|  | ||||
|     //Activate GPRS/CSD Context | ||||
|     sendAT(GF("+QIACT")); | ||||
|     if (waitResponse(10000) != 1) { | ||||
|     if (waitResponse(60000L) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Enable multiple TCP/IP connections | ||||
|     sendAT(GF("+QIMUX=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|     // Check that we have a local IP address | ||||
|     if (localIP() == IPAddress(0,0,0,0)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Request an IP header for received data ("IPD(data length):") | ||||
|     sendAT(GF("+QIHEAD=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Set Method to Handle Received TCP/IP Data - Retrieve Data by Command | ||||
|     // Set Method to Handle Received TCP/IP Data | ||||
|     // Mode = 1 - Output a notification when data is received | ||||
|     // “+QIRDI: <id>,<sc>,<sid>” | ||||
|     sendAT(GF("+QINDI=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // // Request an IP header for received data | ||||
|     // // "IPD(data length):" | ||||
|     // sendAT(GF("+QIHEAD=1")); | ||||
|     // if (waitResponse() != 1) { | ||||
|     //   return false; | ||||
|     // } | ||||
|     // | ||||
|     // // Do NOT show the IP address of the sender when receiving data | ||||
|     // // The format to show the address is: RECV FROM: <IP ADDRESS>:<PORT> | ||||
|     // sendAT(GF("+QISHOWRA=0")); | ||||
|     // if (waitResponse() != 1) { | ||||
|     //   return false; | ||||
|     // } | ||||
|     // | ||||
|     // // Do NOT show the protocol type at the end of the header for received data | ||||
|     // // IPD(data length)(TCP/UDP): | ||||
|     // sendAT(GF("+QISHOWPT=0")); | ||||
|     // if (waitResponse() != 1) { | ||||
|     //   return false; | ||||
|     // } | ||||
|     // | ||||
|     // // Do NOT show the destination address before receiving data | ||||
|     // // The format to show the address is: TO:<IP ADDRESS> | ||||
|     // sendAT(GF("+QISHOWLA=0")); | ||||
|     // if (waitResponse() != 1) { | ||||
|     //   return false; | ||||
|     // } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -557,10 +606,12 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
| protected: | ||||
|  | ||||
|  bool modemConnect(const char* host, uint16_t port, uint8_t mux, | ||||
|                     bool ssl = false, int timeout_s = 75) | ||||
|  { | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|     sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||
|                    bool ssl = false, int timeout_s = 75) { | ||||
|    if (ssl) { | ||||
|      DBG("SSL not yet supported on this module!"); | ||||
|    } | ||||
|    uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000; | ||||
|    sendAT(GF("+QIOPEN="), mux, GF(",\""), GF("TCP"), GF("\",\""), host, GF("\","), port); | ||||
|     int rsp = waitResponse(timeout_ms, | ||||
|                            GF("CONNECT OK" GSM_NL), | ||||
|                            GF("CONNECT FAIL" GSM_NL), | ||||
| @@ -569,7 +620,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+QISEND="), mux, ',', len); | ||||
|     sendAT(GF("+QISEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -579,44 +630,51 @@ protected: | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|     bool allAcknowledged = false; | ||||
|     // bool failed = false; | ||||
|     while ( !allAcknowledged ) { | ||||
|       sendAT( GF("+QISACK")); | ||||
|       if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) { | ||||
|         return -1; | ||||
|       } else { | ||||
|         streamSkipUntil(','); /** Skip total */ | ||||
|         streamSkipUntil(','); /** Skip acknowledged data size */ | ||||
|         if ( stream.readStringUntil('\n').toInt() == 0 ) { | ||||
|           allAcknowledged = true; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     waitResponse(5000L); | ||||
|     // bool allAcknowledged = false; | ||||
|     // // bool failed = false; | ||||
|     // while ( !allAcknowledged ) { | ||||
|     //   sendAT( GF("+QISACK")); | ||||
|     //   if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) { | ||||
|     //     return -1; | ||||
|     //   } else { | ||||
|     //     streamSkipUntil(',');  // Skip total length sent on connection | ||||
|     //     streamSkipUntil(',');  // Skip length already acknowledged by remote | ||||
|     //     // Make sure the total length un-acknowledged is 0 | ||||
|     //     if ( stream.readStringUntil('\n').toInt() == 0 ) { | ||||
|     //       allAcknowledged = true; | ||||
|     //     } | ||||
|     //   } | ||||
|     // } | ||||
|     // waitResponse(5000L); | ||||
|  | ||||
|     // streamSkipUntil(','); // Skip mux | ||||
|     // return stream.readStringUntil('\n').toInt(); | ||||
|     return len;  // TODO | ||||
|   } | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
|     // TODO:  Does this work???? | ||||
|     // AT+QIRD=<id>,<sc>,<sid>,<len> | ||||
|     // id = GPRS context number - 0, set in GPRS connect | ||||
|     // sc = roll in connection - 1, client of connection | ||||
|     // sid = index of connection - mux | ||||
|     // len = maximum length of data to send | ||||
|     sendAT(GF("+QIRD=0,1,"), mux, ',', size); | ||||
|     // sendAT(GF("+QIRD="), mux, ',', size); | ||||
|     if (waitResponse(GF("+QIRD:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|     // id = GPRS context number = 0, set in GPRS connect | ||||
|     // sc = role in connection = 1, client of connection | ||||
|     // sid = index of connection = mux | ||||
|     // len = maximum length of data to retrieve | ||||
|     sendAT(GF("+QIRD=0,1,"), mux, ',', (uint16_t)size); | ||||
|     // If it replies only OK for the write command, it means there is no | ||||
|     // received data in the buffer of the connection. | ||||
|     int res = waitResponse(GF("+QIRD:"), GFP(GSM_OK), GFP(GSM_ERROR)); | ||||
|     if (res == 1) { | ||||
|       streamSkipUntil(':');  // skip IP address | ||||
|       streamSkipUntil(',');  // skip port | ||||
|       streamSkipUntil(',');  // skip connection type (TCP/UDP) | ||||
|     size_t len = stream.readStringUntil('\n').toInt();  // read length | ||||
|     for (size_t i=0; i<len; i++) { | ||||
|       // read the real length of the retrieved data | ||||
|       uint16_t len = stream.readStringUntil('\n').toInt(); | ||||
|       // We have no way of knowing in advance how much data will be in the buffer | ||||
|       // so when data is received we always assume the buffer is completely full. | ||||
|       // Chances are, this is not true and there's really not that much there. | ||||
|       // In that case, make sure we make sure we re-set the amount of data available. | ||||
|       if (len < size) { | ||||
|           sockets[mux]->sock_available = len; | ||||
|       } | ||||
|       for (uint16_t i=0; i<len; i++) { | ||||
|         TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT | ||||
|         sockets[mux]->sock_available--; | ||||
|         // ^^ One less character available after moving from modem's FIFO to our FIFO | ||||
| @@ -624,6 +682,10 @@ protected: | ||||
|       waitResponse();  // ends with an OK | ||||
|       DBG("### READ:", len, "from", mux); | ||||
|       return len; | ||||
|     } else { | ||||
|         sockets[mux]->sock_available = 0; | ||||
|         return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   bool modemGetConnected(uint8_t mux) { | ||||
| @@ -690,14 +752,17 @@ TINY_GSM_MODEM_STREAM_UTILITIES() | ||||
|         } else if (r5 && data.endsWith(r5)) { | ||||
|           index = 5; | ||||
|           goto finish; | ||||
|         } else if (data.endsWith(GF(GSM_NL "+QIRD:"))) {  // TODO:  QIRD? or QIRDI? | ||||
|         } else if (data.endsWith(GF(GSM_NL "+QIRDI:"))) { | ||||
|           streamSkipUntil(',');  // Skip the context | ||||
|           streamSkipUntil(',');  // Skip the role | ||||
|           int mux = stream.readStringUntil('\n').toInt(); | ||||
|           DBG("### Got Data:", mux); | ||||
|           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { | ||||
|             sockets[mux]->got_data = true; | ||||
|             // We have no way of knowing how much data actually came in, so | ||||
|             // we set the value to 1500, the maximum possible size. | ||||
|             sockets[mux]->sock_available = 1500; | ||||
|           } | ||||
|           data = ""; | ||||
|         } else if (data.endsWith(GF("CLOSED" GSM_NL))) { | ||||
|           int nl = data.lastIndexOf(GSM_NL, data.length()-8); | ||||
|           int coma = data.indexOf(',', nl+2); | ||||
|   | ||||
| @@ -68,7 +68,6 @@ public: | ||||
|     this->mux = mux; | ||||
|     sock_available = 0; | ||||
|     sock_connected = false; | ||||
|     got_data = false; | ||||
|  | ||||
|     at->sockets[mux] = this; | ||||
|  | ||||
| @@ -114,7 +113,6 @@ private: | ||||
|   uint8_t         mux; | ||||
|   uint16_t        sock_available; | ||||
|   bool            sock_connected; | ||||
|   bool            got_data; | ||||
|   RxFifo          rx; | ||||
| }; | ||||
|  | ||||
| @@ -161,18 +159,32 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("&FZ"));  // Factory + Reset | ||||
|     waitResponse(); | ||||
|  | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -338,6 +350,18 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|     sendAT(GF("+CGACT=1,1")); | ||||
|     waitResponse(60000L); | ||||
|  | ||||
|     // Select TCP/IP transfer mode - NOT transparent mode | ||||
|     sendAT(GF("+QIMODE=0")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // Enable multiple TCP/IP connections | ||||
|     sendAT(GF("+QIMUX=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Start TCPIP Task and Set APN, User Name and Password | ||||
|     sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd,  "\"" ); | ||||
|     if (waitResponse() != 1) { | ||||
| @@ -350,32 +374,22 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Enable multiple TCP/IP connections | ||||
|     sendAT(GF("+QIMUX=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Request an IP header for received data ("IPD(data length):") | ||||
|     sendAT(GF("+QIHEAD=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Set Method to Handle Received TCP/IP Data - Retrieve Data by Command | ||||
|     sendAT(GF("+QINDI=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // Check that we have a local IP address | ||||
|     if (localIP() != IPAddress(0,0,0,0)) { | ||||
|       return true; | ||||
|     if (localIP() == IPAddress(0,0,0,0)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     //Set Method to Handle Received TCP/IP Data | ||||
|     // Mode=2 - Output a notification statement: | ||||
|     // “+QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>” | ||||
|     sendAT(GF("+QINDI=2")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool gprsDisconnect() { | ||||
|     sendAT(GF("+QIDEACT")); | ||||
|     return waitResponse(60000L, GF("DEACT OK"), GF("ERROR")) == 1; | ||||
| @@ -563,10 +577,12 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
| protected: | ||||
|  | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t mux, | ||||
|                     bool ssl = false, int timeout_s = 75) | ||||
|  { | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|     sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||
|                    bool ssl = false, int timeout_s = 75) { | ||||
|    if (ssl) { | ||||
|      DBG("SSL not yet supported on this module!"); | ||||
|    } | ||||
|    uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000; | ||||
|    sendAT(GF("+QIOPEN="), mux, GF(",\""), GF("TCP"), GF("\",\""), host, GF("\","), port); | ||||
|     int rsp = waitResponse(timeout_ms, | ||||
|                            GF("CONNECT OK" GSM_NL), | ||||
|                            GF("CONNECT FAIL" GSM_NL), | ||||
| @@ -575,7 +591,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+QISEND="), mux, ',', len); | ||||
|     sendAT(GF("+QISEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -614,16 +630,24 @@ protected: | ||||
|     // sc = roll in connection - 1, client of connection | ||||
|     // sid = index of connection - mux | ||||
|     // len = maximum length of data to send | ||||
|     sendAT(GF("+QIRD=0,1,"), mux, ',', size); | ||||
|     // sendAT(GF("+QIRD="), mux, ',', size); | ||||
|     if (waitResponse(GF("+QIRD:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|     sendAT(GF("+QIRD=0,1,"), mux, ',', (uint16_t)size); | ||||
|     // If it replies only OK for the write command, it means there is no | ||||
|     // received data in the buffer of the connection. | ||||
|     int res = waitResponse(GF("+QIRD:"), GFP(GSM_OK), GFP(GSM_ERROR)); | ||||
|     if (res == 1) { | ||||
|       streamSkipUntil(':');  // skip IP address | ||||
|       streamSkipUntil(',');  // skip port | ||||
|       streamSkipUntil(',');  // skip connection type (TCP/UDP) | ||||
|     size_t len = stream.readStringUntil('\n').toInt();  // read length | ||||
|     for (size_t i=0; i<len; i++) { | ||||
|       // read the real length of the retrieved data | ||||
|       uint16_t len = stream.readStringUntil('\n').toInt(); | ||||
|       // It's possible that the real length available is less than expected | ||||
|       // This is quite likely if the buffer is broken into packets - which may | ||||
|       // be different sizes. | ||||
|       // If so, make sure we make sure we re-set the amount of data available. | ||||
|       if (len < size) { | ||||
|           sockets[mux]->sock_available = len; | ||||
|       } | ||||
|       for (uint16_t i=0; i<len; i++) { | ||||
|         TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT | ||||
|         sockets[mux]->sock_available--; | ||||
|         // ^^ One less character available after moving from modem's FIFO to our FIFO | ||||
| @@ -631,6 +655,10 @@ protected: | ||||
|       waitResponse(); | ||||
|       DBG("### READ:", len, "from", mux); | ||||
|       return len; | ||||
|     } else { | ||||
|         sockets[mux]->sock_available = 0; | ||||
|         return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   bool modemGetConnected(uint8_t mux) { | ||||
| @@ -702,13 +730,20 @@ TINY_GSM_MODEM_STREAM_UTILITIES() | ||||
|           index = 6; | ||||
|           goto finish; | ||||
|         } else if (data.endsWith(GF(GSM_NL "+QIRD:"))) {  // TODO:  QIRD? or QIRDI? | ||||
|           // +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen> | ||||
|           streamSkipUntil(',');  // Skip the context | ||||
|           streamSkipUntil(',');  // Skip the role | ||||
|           int mux = stream.readStringUntil('\n').toInt(); | ||||
|           DBG("### Got Data:", mux); | ||||
|           // read the connection id | ||||
|           int mux = stream.readStringUntil(',').toInt(); | ||||
|           // read the number of packets in the buffer | ||||
|           int num_packets = stream.readStringUntil(',').toInt(); | ||||
|           // read the length of the current packet | ||||
|           int len_packet = stream.readStringUntil('\n').toInt(); | ||||
|           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { | ||||
|             sockets[mux]->got_data = true; | ||||
|             sockets[mux]->sock_available = len_packet*num_packets; | ||||
|           } | ||||
|           data = ""; | ||||
|           DBG("### Got Data:", len, "on", mux); | ||||
|         } else if (data.endsWith(GF("CLOSED" GSM_NL))) { | ||||
|           int nl = data.lastIndexOf(GSM_NL, data.length()-8); | ||||
|           int coma = data.indexOf(',', nl+2); | ||||
|   | ||||
| @@ -142,16 +142,29 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -640,24 +653,29 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
| protected: | ||||
|  | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t mux, | ||||
|                     bool ssl = false, int timeout_s = 75) { | ||||
|                     bool ssl = false, int timeout_s = 15) { | ||||
|     // Make sure we'll be getting data manually on this connection | ||||
|     sendAT(GF("+CIPRXGET=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (ssl) { | ||||
|         DBG("SSL not yet supported on this module!"); | ||||
|     } | ||||
|  | ||||
|     // Establish a connection in multi-socket mode | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000; | ||||
|     sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||
|     // The reply is +CIPOPEN: ## of socket created | ||||
|     if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) { | ||||
|     if (waitResponse(timeout_ms, GF(GSM_NL "+CIPOPEN:")) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -674,23 +692,23 @@ protected: | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #else | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #endif | ||||
|     streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX | ||||
|     streamSkipUntil(','); // Skip mux/cid (connecion id) | ||||
|     size_t len_requested = stream.readStringUntil(',').toInt(); | ||||
|     int len_requested = stream.readStringUntil(',').toInt(); | ||||
|     //  ^^ Requested number of data bytes (1-1460 bytes)to be read | ||||
|     size_t len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     int len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     // ^^ The data length which not read in the buffer | ||||
|     for (size_t i=0; i<len_requested; i++) { | ||||
|     for (int i=0; i<len_requested; i++) { | ||||
|       uint32_t startMillis = millis(); | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|       while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); } | ||||
|   | ||||
| @@ -166,16 +166,29 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -801,23 +814,25 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
| protected: | ||||
|  | ||||
|  bool modemConnect(const char* host, uint16_t port, uint8_t mux, | ||||
|                     bool ssl = false, int timeout_s = 75) | ||||
|  { | ||||
|                    bool ssl = false, int timeout_s = 75) { | ||||
|    if (ssl) { | ||||
|      DBG("SSL not yet supported on this module!"); | ||||
|    } | ||||
|  | ||||
|    int rsp; | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|     sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||
|     rsp = waitResponse(timeout_ms, | ||||
|                        GF("CONNECT OK" GSM_NL), | ||||
|                        GF("CONNECT FAIL" GSM_NL), | ||||
|                        GF("ALREADY CONNECT" GSM_NL), | ||||
|                        GF("ERROR" GSM_NL), | ||||
|    uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000; | ||||
|    sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), | ||||
|           port); | ||||
|    rsp = waitResponse( | ||||
|        timeout_ms, GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL), | ||||
|        GF("ALREADY CONNECT" GSM_NL), GF("ERROR" GSM_NL), | ||||
|        GF("CLOSE OK" GSM_NL)  // Happens when HTTPS handshake fails | ||||
|    ); | ||||
|    return (1 == rsp); | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -832,25 +847,25 @@ protected: | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #else | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #endif | ||||
|     streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX | ||||
|     streamSkipUntil(','); // Skip mux | ||||
|     size_t len_requested = stream.readStringUntil(',').toInt(); | ||||
|     int len_requested = stream.readStringUntil(',').toInt(); | ||||
|     //  ^^ Requested number of data bytes (1-1460 bytes)to be read | ||||
|     size_t len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     int len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     // ^^ Confirmed number of data bytes to be read, which may be less than requested. | ||||
|     // 0 indicates that no data can be read. | ||||
|     // This is actually be the number of bytes that will be remaining after the read | ||||
|     for (size_t i=0; i<len_requested; i++) { | ||||
|     for (int i=0; i<len_requested; i++) { | ||||
|       uint32_t startMillis = millis(); | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|       while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); } | ||||
|   | ||||
| @@ -142,16 +142,29 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -555,7 +568,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|   } | ||||
|  | ||||
|   // get GPS informations | ||||
|   bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { | ||||
|   bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0) { | ||||
|     //String buffer = ""; | ||||
|     bool fix = false; | ||||
|  | ||||
| @@ -582,8 +595,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|     stream.readStringUntil(',');//PDOP | ||||
|     stream.readStringUntil(',');//HDOP | ||||
|     stream.readStringUntil(',');//VDOP | ||||
|     //if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites | ||||
|     //if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites | ||||
|     stream.readStringUntil('\n'); | ||||
|  | ||||
|     waitResponse(); | ||||
| @@ -618,16 +629,11 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|  | ||||
|   uint8_t getBattChargeState()  TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) { | ||||
|     sendAT(GF("+CBC?")); | ||||
|     if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     // get voltage in VOLTS | ||||
|     float voltage = stream.readStringUntil('\n').toFloat(); | ||||
|     milliVolts = voltage*1000; | ||||
|     // Wait for final OK | ||||
|     waitResponse(); | ||||
|   bool getBattStats(uint8_t& chargeState, int8_t& percent, | ||||
|                     uint16_t& milliVolts) { | ||||
|     chargeState = 0; | ||||
|     percent = 0; | ||||
|     milliVolts = getBattVoltage(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -651,7 +657,10 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
| protected: | ||||
|  | ||||
|  bool modemConnect(const char* host, uint16_t port, uint8_t mux, | ||||
|                     bool ssl = false, int timeout_s = 75) { | ||||
|                    bool ssl = false, int timeout_s = 15) { | ||||
|    if (ssl) { | ||||
|      DBG("SSL not yet supported on this module!"); | ||||
|    } | ||||
|    // Make sure we'll be getting data manually on this connection | ||||
|    sendAT(GF("+CIPRXGET=1")); | ||||
|    if (waitResponse() != 1) { | ||||
| @@ -659,16 +668,18 @@ protected: | ||||
|    } | ||||
|  | ||||
|    // Establish a connection in multi-socket mode | ||||
|     sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||
|    uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000; | ||||
|    sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), | ||||
|           port); | ||||
|    // The reply is +CIPOPEN: ## of socket created | ||||
|     if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) { | ||||
|    if (waitResponse(timeout_ms, GF(GSM_NL "+CIPOPEN:")) != 1) { | ||||
|      return false; | ||||
|    } | ||||
|    return true; | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -685,23 +696,23 @@ protected: | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #else | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #endif | ||||
|     streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX | ||||
|     streamSkipUntil(','); // Skip mux/cid (connecion id) | ||||
|     size_t len_requested = stream.readStringUntil(',').toInt(); | ||||
|     int len_requested = stream.readStringUntil(',').toInt(); | ||||
|     //  ^^ Requested number of data bytes (1-1460 bytes)to be read | ||||
|     size_t len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     int len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     // ^^ The data length which not read in the buffer | ||||
|     for (size_t i=0; i<len_requested; i++) { | ||||
|     for (int i=0; i<len_requested; i++) { | ||||
|       uint32_t startMillis = millis(); | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|       while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); } | ||||
|   | ||||
| @@ -165,6 +165,7 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
| @@ -174,9 +175,19 @@ public: | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -801,7 +812,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF(">")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -816,25 +827,25 @@ protected: | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #else | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', size); | ||||
|     sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+CIPRXGET:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| #endif | ||||
|     streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX | ||||
|     streamSkipUntil(','); // Skip mux | ||||
|     size_t len_requested = stream.readStringUntil(',').toInt(); | ||||
|     int len_requested = stream.readStringUntil(',').toInt(); | ||||
|     //  ^^ Requested number of data bytes (1-1460 bytes)to be read | ||||
|     size_t len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     int len_confirmed = stream.readStringUntil('\n').toInt(); | ||||
|     // ^^ Confirmed number of data bytes to be read, which may be less than requested. | ||||
|     // 0 indicates that no data can be read. | ||||
|     // This is actually be the number of bytes that will be remaining after the read | ||||
|     for (size_t i=0; i<len_requested; i++) { | ||||
|     for (int i=0; i<len_requested; i++) { | ||||
|       uint32_t startMillis = millis(); | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|       while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); } | ||||
|   | ||||
| @@ -54,9 +54,7 @@ class GsmClient : public Client | ||||
| public: | ||||
|   GsmClient() {} | ||||
|  | ||||
|   GsmClient(TinyGsmSaraR4& modem, uint8_t mux = 0) { | ||||
|     init(&modem, mux); | ||||
|   } | ||||
|     GsmClient(TinyGsmSaraR4& modem, uint8_t mux = 0) { init(&modem, mux); } | ||||
|  | ||||
|   virtual ~GsmClient(){} | ||||
|  | ||||
| @@ -95,8 +93,18 @@ TINY_GSM_CLIENT_CONNECT_OVERLOADS() | ||||
|  | ||||
|   virtual void stop(uint32_t maxWaitMs) { | ||||
|     TINY_GSM_CLIENT_DUMP_MODEM_BUFFER() | ||||
|     at->sendAT(GF("+USOCL="), mux); | ||||
|     at->waitResponse((maxWaitMs - (millis() - startMillis)));  // NOTE:  can take up to 120s to get a response | ||||
|  | ||||
|     // // synchronous close | ||||
|     // at->sendAT(GF("+USOCL="), mux); | ||||
|     // // NOTE:  can take up to 120s to get a response | ||||
|     // at->waitResponse((maxWaitMs - (millis() - startMillis))); | ||||
|     // sock_connected = false; | ||||
|  | ||||
|     // faster asynchronous close | ||||
|     // NOT supported on SARA-R404M / SARA-R410M-01B | ||||
|     at->sendAT(GF("+USOCL="), mux, GF(",1")); | ||||
|     // NOTE:  can take up to 120s to get a response | ||||
|     at->waitResponse((maxWaitMs - (millis() - startMillis))); | ||||
|     sock_connected = false; | ||||
|   } | ||||
|  | ||||
| @@ -170,15 +178,15 @@ public: | ||||
|    * Basic functions | ||||
|    */ | ||||
|  | ||||
|   bool begin(const char* pin = NULL) { | ||||
|     return init(pin); | ||||
|   } | ||||
|   bool begin(const char* pin = NULL) { return init(pin); } | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("E0"));  // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
| @@ -191,7 +199,7 @@ public: | ||||
| #endif | ||||
|     waitResponse(); | ||||
|  | ||||
|     getModemName(); | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
| @@ -199,7 +207,8 @@ public: | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return true | ||||
|     // if the sim is ready, or it's locked but no pin has been provided,return | ||||
|     // return true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
| @@ -224,7 +233,8 @@ public: | ||||
|  | ||||
|     String name = res1 + String(' ') + res2; | ||||
|     DBG("### Modem:", name); | ||||
|     if (!name.startsWith("u-blox SARA-R4") && !name.startsWith("u-blox SARA-N4")) { | ||||
|     if (!name.startsWith("u-blox SARA-R4") && | ||||
|         !name.startsWith("u-blox SARA-N4")) { | ||||
|       DBG("### WARNING:  You are using the wrong TinyGSM modem!"); | ||||
|     } | ||||
|  | ||||
| @@ -308,13 +318,14 @@ TINY_GSM_MODEM_GET_SIMCCID_CCID() | ||||
|   } | ||||
|  | ||||
|   SimStatus getSimStatus(unsigned long timeout_ms = 10000L) { | ||||
|     for (unsigned long start = millis(); millis() - start < timeout_ms; ) { | ||||
|     for (unsigned long start = millis(); millis() - start < timeout_ms;) { | ||||
|       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")); | ||||
|       int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), | ||||
|                                 GF("NOT INSERTED")); | ||||
|       waitResponse(); | ||||
|       switch (status) { | ||||
|         case 2: | ||||
| @@ -347,7 +358,7 @@ TINY_GSM_MODEM_GET_CSQ() | ||||
|  | ||||
| TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|  | ||||
|   bool setURAT( uint8_t urat ) { | ||||
|   bool setURAT(uint8_t urat) { | ||||
|     // AT+URAT=<SelectedAcT>[,<PreferredAct>[,<2ndPreferredAct>]] | ||||
|  | ||||
|     sendAT(GF("+COPS=2"));  // Deregister from network | ||||
| @@ -370,7 +381,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|    */ | ||||
|  | ||||
|   bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { | ||||
|     gprsDisconnect(); | ||||
|     // gprsDisconnect(); | ||||
|  | ||||
|     sendAT(GF("+CGATT=1"));  // attach to GPRS | ||||
|     if (waitResponse(360000L) != 1) { | ||||
| @@ -382,8 +393,9 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|     // serial interface.  This is the only command set supported by the LTE-M | ||||
|     // and LTE NB-IoT modules (SARA-R4xx, SARA-N4xx) | ||||
|  | ||||
|     // Set the authentication | ||||
|     if (user && strlen(user) > 0) { | ||||
|       sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"');  // Set the authentication | ||||
|       sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"'); | ||||
|       waitResponse(); | ||||
|     } | ||||
|  | ||||
| @@ -399,9 +411,10 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() | ||||
|   } | ||||
|  | ||||
|   bool gprsDisconnect() { | ||||
|     sendAT(GF("+CGACT=1,0"));  // Deactivate PDP context 1 | ||||
|     // sendAT(GF("+CGACT=0,1"));  // Deactivate PDP context 1 | ||||
|     sendAT(GF("+CGACT=0"));  // Deactivate all contexts | ||||
|     if (waitResponse(40000L) != 1) { | ||||
|       return false; | ||||
|       // return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("+CGATT=0"));  // detach from GPRS | ||||
| @@ -509,6 +522,8 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
|  | ||||
|   bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) { | ||||
|     percent = getBattPercent(); | ||||
|     chargeState = 0; | ||||
|     milliVolts = 0; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -522,10 +537,9 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
|     if (waitResponse(GF(GSM_NL "+UTEMP:")) != 1) { | ||||
|       return (float)-9999; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip units (C/F) | ||||
|     int16_t res = stream.readStringUntil('\n').toInt(); | ||||
|     float temp = -9999; | ||||
|     if (res != 65535) { | ||||
|     if (res != -1) { | ||||
|       temp = ((float)res)/10; | ||||
|     } | ||||
|     return temp; | ||||
| @@ -538,11 +552,12 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
| protected: | ||||
|  | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t* mux, | ||||
|                     bool ssl = false, int timeout_s = 120) | ||||
|   { | ||||
|                     bool ssl = false, int timeout_s = 120) { | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|     sendAT(GF("+USOCR=6"));  // create a socket | ||||
|     if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) {  // reply is +USOCR: ## of socket created | ||||
|     // create a socket | ||||
|     sendAT(GF("+USOCR=6")); | ||||
|     // reply is +USOCR: ## of socket created | ||||
|     if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     *mux = stream.readStringUntil('\n').toInt(); | ||||
| @@ -558,17 +573,31 @@ protected: | ||||
|     waitResponse(); | ||||
|  | ||||
|     // Enable KEEPALIVE, 30 sec | ||||
|     //sendAT(GF("+USOSO="), *mux, GF(",6,2,30000")); | ||||
|     //waitResponse(); | ||||
|     // sendAT(GF("+USOSO="), *mux, GF(",6,2,30000")); | ||||
|     // waitResponse(); | ||||
|  | ||||
|     // connect on the allocated socket | ||||
|     sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port); | ||||
|     int rsp = waitResponse(timeout_ms); | ||||
|     return (1 == rsp); | ||||
|  | ||||
|     // Use an asynchronous open to reduce the number of terminal freeze-ups | ||||
|     // This is still blocking until the URC arrives | ||||
|     // The SARA-R410M-02B with firmware revisions prior to L0.0.00.00.05.08 | ||||
|     // has a nasty habit of locking up when opening a socket, especially if | ||||
|     // the cellular service is poor. | ||||
|     // NOT supported on SARA-R404M / SARA-R410M-01B | ||||
|     sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port, ",1"); | ||||
|     waitResponse(timeout_ms, GF(GSM_NL "+UUSOCO: ")); | ||||
|     stream.readStringUntil(',').toInt();  // skip repeated mux | ||||
|     int connection_status = stream.readStringUntil('\n').toInt(); | ||||
|     return (0 == connection_status); | ||||
|  | ||||
|     // use synchronous open | ||||
|     // sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port, ",0"); | ||||
|     // int rsp = waitResponse(timeout_ms); | ||||
|     // return (1 == rsp); | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+USOWR="), mux, ',', len); | ||||
|     sendAT(GF("+USOWR="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF("@")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -586,15 +615,15 @@ protected: | ||||
|   } | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
|     sendAT(GF("+USORD="), mux, ',', size); | ||||
|     sendAT(GF("+USORD="), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF(GSM_NL "+USORD:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|     streamSkipUntil(',');  // Skip mux | ||||
|     size_t len = stream.readStringUntil(',').toInt(); | ||||
|     int len = stream.readStringUntil(',').toInt(); | ||||
|     streamSkipUntil('\"'); | ||||
|  | ||||
|     for (size_t i=0; i<len; i++) { | ||||
|     for (int i=0; i<len; i++) { | ||||
|       TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT | ||||
|     } | ||||
|     streamSkipUntil('\"'); | ||||
| @@ -628,8 +657,7 @@ protected: | ||||
|     // NOTE:  Querying a closed socket gives an error "operation not allowed" | ||||
|     sendAT(GF("+USOCTL="), mux, ",10"); | ||||
|     uint8_t res = waitResponse(GF(GSM_NL "+USOCTL:")); | ||||
|     if (res != 1) | ||||
|       return false; | ||||
|     if (res != 1) return false; | ||||
|  | ||||
|     streamSkipUntil(',');  // Skip mux | ||||
|     streamSkipUntil(',');  // Skip type | ||||
| @@ -660,9 +688,10 @@ TINY_GSM_MODEM_STREAM_UTILITIES() | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
|   uint8_t waitResponse(uint32_t timeout_ms, String& data, | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=GFP(GSM_CME_ERROR), GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|                        GsmConstStr r1 = GFP(GSM_OK), | ||||
|                        GsmConstStr r2 = GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3 = GFP(GSM_CME_ERROR), | ||||
|                        GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
| @@ -724,22 +753,24 @@ finish: | ||||
|       } | ||||
|       data = ""; | ||||
|     } | ||||
|     //data.replace(GSM_NL, "/"); | ||||
|     //DBG('<', index, '>', data); | ||||
|     // data.replace(GSM_NL, "/"); | ||||
|     // DBG('<', index, '>', data); | ||||
|     return index; | ||||
|   } | ||||
|  | ||||
|   uint8_t waitResponse(uint32_t timeout_ms, | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=GFP(GSM_CME_ERROR), GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|                        GsmConstStr r1 = GFP(GSM_OK), | ||||
|                        GsmConstStr r2 = GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3 = GFP(GSM_CME_ERROR), | ||||
|                        GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) { | ||||
|     String data; | ||||
|     return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5); | ||||
|   } | ||||
|  | ||||
|   uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=GFP(GSM_CME_ERROR), GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|   uint8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK), | ||||
|                        GsmConstStr r2 = GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3 = GFP(GSM_CME_ERROR), | ||||
|                        GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) { | ||||
|     return waitResponse(1000, r1, r2, r3, r4, r5); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -195,15 +195,29 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|  | ||||
|     DBG(GF("### Modem:"), getModemName()); | ||||
|  | ||||
|     int ret = getSimStatus(); | ||||
|     // if the sim isn't ready and a pin has been provided, try to unlock the sim | ||||
|     if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { | ||||
|       simUnlock(pin); | ||||
|       return (getSimStatus() == SIM_READY); | ||||
|     } | ||||
|     // if the sim is ready, or it's locked but no pin has been provided, return | ||||
|     // true | ||||
|     else { | ||||
|       return (ret == SIM_READY || ret == SIM_LOCKED); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String getModemName() { | ||||
| @@ -570,7 +584,7 @@ protected: | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("+SQNSSENDEXT="), mux, ',', len); | ||||
|     sendAT(GF("+SQNSSENDEXT="), mux, ',', (uint16_t)len); | ||||
|     waitResponse(10000L, GF(GSM_NL "> ")); | ||||
|     stream.write((uint8_t*)buff, len); | ||||
|     stream.flush(); | ||||
| @@ -605,13 +619,13 @@ protected: | ||||
|  | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
|     sendAT(GF("+SQNSRECV="), mux, ',', size); | ||||
|     sendAT(GF("+SQNSRECV="), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF("+SQNSRECV: ")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip mux | ||||
|     size_t len = stream.readStringUntil('\n').toInt(); | ||||
|     for (size_t i=0; i<len; i++) { | ||||
|     int len = stream.readStringUntil('\n').toInt(); | ||||
|     for (int i=0; i<len; i++) { | ||||
|       uint32_t startMillis = millis(); \ | ||||
|       while (!stream.available() && ((millis() - startMillis) < sockets[mux % TINY_GSM_MUX_COUNT]->_timeout)) { TINY_GSM_YIELD(); } \ | ||||
|       char c = stream.read(); \ | ||||
|   | ||||
| @@ -176,9 +176,11 @@ public: | ||||
|  | ||||
|   bool init(const char* pin = NULL) { | ||||
|     DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); | ||||
|  | ||||
|     if (!testAT()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
| @@ -535,7 +537,9 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() | ||||
|   uint8_t getBattChargeState() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) { | ||||
|     chargeState = 0; | ||||
|     percent = getBattPercent(); | ||||
|     milliVolts = 0; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -579,7 +583,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+USOWR="), mux, ',', len); | ||||
|     sendAT(GF("+USOWR="), mux, ',', (uint16_t)len); | ||||
|     if (waitResponse(GF("@")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -597,15 +601,15 @@ protected: | ||||
|   } | ||||
|  | ||||
|   size_t modemRead(size_t size, uint8_t mux) { | ||||
|     sendAT(GF("+USORD="), mux, ',', size); | ||||
|     sendAT(GF("+USORD="), mux, ',', (uint16_t)size); | ||||
|     if (waitResponse(GF(GSM_NL "+USORD:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip mux | ||||
|     size_t len = stream.readStringUntil(',').toInt(); | ||||
|     int len = stream.readStringUntil(',').toInt(); | ||||
|     streamSkipUntil('\"'); | ||||
|  | ||||
|     for (size_t i=0; i<len; i++) { | ||||
|     for (int i=0; i<len; i++) { | ||||
|       TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT | ||||
|     } | ||||
|     streamSkipUntil('\"'); | ||||
|   | ||||
| @@ -109,34 +109,25 @@ public: | ||||
|   } | ||||
|  | ||||
|   virtual int connect(IPAddress ip, uint16_t port, int timeout_s) { | ||||
|     if (timeout_s != 0) { | ||||
|       DBG("Timeout [", timeout_s, "] doesn't apply here."); | ||||
|     } | ||||
|     // NOTE:  Not caling stop() or yeild() here | ||||
|     at->streamClear();  // Empty anything in the buffer before starting | ||||
|     sock_connected = at->modemConnect(ip, port, mux, false, timeout_s); | ||||
|     sock_connected = at->modemConnect(ip, port, mux, false); | ||||
|     return sock_connected; | ||||
|   } | ||||
|   virtual int connect(IPAddress ip, uint16_t port) { | ||||
|     return connect(ip, port, 75); | ||||
|     return connect(ip, port, 0); | ||||
|   } | ||||
|  | ||||
|   virtual void stop(uint32_t maxWaitMs) { | ||||
|     at->streamClear();  // Empty anything in the buffer | ||||
|     at->commandMode(); | ||||
|     // For WiFi models, there's no direct way to close the socket.  This is a | ||||
|     // hack to shut the socket by setting the timeout to zero. | ||||
|     if (at->beeType == XBEE_S6B_WIFI) { | ||||
|       at->sendAT(GF("TM0"));  // Set socket timeout (using Digi default of 10 seconds) | ||||
|       at->waitResponse(maxWaitMs);  // This response can be slow | ||||
|       at->writeChanges(); | ||||
|     } | ||||
|     // For cellular models, per documentation: If you change the TM (socket | ||||
|     // timeout) value while in Transparent Mode, the current connection is | ||||
|     // immediately closed. | ||||
|     at->sendAT(GF("TM64"));  // Set socket timeout (using Digi default of 10 seconds) | ||||
|     at->waitResponse(maxWaitMs);  // This response can be slow | ||||
|     at->writeChanges(); | ||||
|     at->exitCommand(); | ||||
|     at->streamClear();  // Empty anything remaining in the buffer | ||||
|     // empty the saved currently-in-use destination address | ||||
|     at->modemStop(maxWaitMs); | ||||
|     at->streamClear();  // Empty anything in the buffer | ||||
|     sock_connected = false; | ||||
|  | ||||
|     // Note:  because settings are saved in flash, the XBEE will attempt to | ||||
|     // reconnect to the previous socket if it receives any outgoing data. | ||||
|     // Setting sock_connected to false after the stop ensures that connected() | ||||
| @@ -214,6 +205,10 @@ public: | ||||
|       return true; | ||||
|     } | ||||
|     return sock_connected; | ||||
|     // NOTE:  We dont't check or return | ||||
|     // modemGetConnected() because we don't | ||||
|     // want to go into command mode. | ||||
|     // return at->modemGetConnected(); | ||||
|   } | ||||
|   virtual operator bool() { return connected(); } | ||||
|  | ||||
| @@ -251,9 +246,12 @@ public: | ||||
|   } | ||||
|  | ||||
|   virtual int connect(IPAddress ip, uint16_t port, int timeout_s) { | ||||
|     if (timeout_s != 0) { | ||||
|       DBG("Timeout [", timeout_s, "] doesn't apply here."); | ||||
|     } | ||||
|     // NOTE:  Not caling stop() or yeild() here | ||||
|     at->streamClear();  // Empty anything in the buffer before starting | ||||
|     sock_connected = at->modemConnect(ip, port, mux, true, timeout_s); | ||||
|     sock_connected = at->modemConnect(ip, port, mux, true); | ||||
|     return sock_connected; | ||||
|   } | ||||
| }; | ||||
| @@ -305,6 +303,10 @@ public: | ||||
|       digitalWrite(resetPin, HIGH); | ||||
|     } | ||||
|  | ||||
|     if (pin && strlen(pin) > 0) { | ||||
|       DBG("XBee's do not support SIMs that require an unlock pin!"); | ||||
|     } | ||||
|  | ||||
|     XBEE_COMMAND_START_DECORATOR(10, false) | ||||
|  | ||||
|     sendAT(GF("AP0"));  // Put in transparent mode | ||||
| @@ -511,8 +513,15 @@ public: | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|   } | ||||
|  | ||||
|   bool poweroff() {  // Not supported | ||||
|     return false; | ||||
|   bool poweroff() {  // NOTE:  Not supported for WiFi or older cellular firmware | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|     sendAT(GF("SD")); | ||||
|     bool ret_val = waitResponse(120000L) == 1; | ||||
|     if (ret_val) { | ||||
|         ret_val &= (sendATGetString(GF("AI")) == "2D"); | ||||
|     } | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return ret_val; | ||||
|   } | ||||
|  | ||||
|   bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
| @@ -524,6 +533,9 @@ public: | ||||
|    */ | ||||
|  | ||||
|   bool simUnlock(const char *pin) {  // Not supported | ||||
|     if (pin && strlen(pin) > 0) { | ||||
|       DBG("XBee's do not support SIMs that require an unlock pin!"); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -535,7 +547,7 @@ public: | ||||
|     return sendATGetString(GF("IM")); | ||||
|   } | ||||
|  | ||||
|   SimStatus getSimStatus(unsigned long timeout_ms = 10000L) { | ||||
|   SimStatus getSimStatus() { | ||||
|     return SIM_READY;  // unsupported | ||||
|   } | ||||
|  | ||||
| @@ -680,7 +692,7 @@ public: | ||||
|     //nh For no pwd don't set setscurity or pwd | ||||
|     if (ssid == NULL) retVal = false;; | ||||
|  | ||||
|     if (pwd != NULL) | ||||
|     if (pwd && strlen(pwd) > 0) | ||||
|     { | ||||
|       sendAT(GF("EE"), 2);  // Set security to WPA2 | ||||
|       if (waitResponse() != 1) retVal = false; | ||||
| @@ -734,10 +746,19 @@ public: | ||||
|    * GPRS functions | ||||
|    */ | ||||
|  | ||||
|   bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { | ||||
|   bool gprsConnect(const char* apn, const char* user = NULL, | ||||
|                    const char* pwd = NULL) { | ||||
|     if (user && strlen(user) > 0) { | ||||
|       DBG("XBee's do not support SIMs that a user name/password!"); | ||||
|     } | ||||
|     if (pwd && strlen(pwd) > 0) { | ||||
|       DBG("XBee's do not support SIMs that a user name/password!"); | ||||
|     } | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|     sendAT(GF("AN"), apn);  // Set the APN | ||||
|     bool success = waitResponse() == 1; | ||||
|     sendAT(GF("AM0"));  // Airplane mode off | ||||
|     waitResponse(5000); | ||||
|     writeChanges(); | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return success; | ||||
| @@ -748,9 +769,9 @@ public: | ||||
|     sendAT(GF("AM1"));  // Cheating and disconnecting by turning on airplane mode | ||||
|     int8_t res = (1 == waitResponse(5000)); | ||||
|     writeChanges(); | ||||
|     sendAT(GF("AM0"));  // Airplane mode off | ||||
|     waitResponse(5000); | ||||
|     writeChanges(); | ||||
|     // sendAT(GF("AM0"));  // Airplane mode off | ||||
|     // waitResponse(5000); | ||||
|     // writeChanges(); | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return res; | ||||
|   } | ||||
| @@ -796,12 +817,30 @@ public: | ||||
|    */ | ||||
|  | ||||
|   // Use: float vBatt = modem.getBattVoltage() / 1000.0; | ||||
|   uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|   uint16_t getBattVoltage() { | ||||
|     int16_t intRes = 0; | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|     if (beeType == XBEE_UNKNOWN) getSeries(); | ||||
|     if (beeType == XBEE_S6B_WIFI) { | ||||
|       sendAT(GF("%V")); | ||||
|       intRes = readResponseInt(); | ||||
|     } | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return intRes; | ||||
|   } | ||||
|  | ||||
|   int8_t getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|   uint8_t getBattChargeState() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|   bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) { | ||||
|     chargeState = 0; | ||||
|     percent = 0; | ||||
|     milliVolts = getBattVoltage(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   float getTemperature() { | ||||
|     XBEE_COMMAND_START_DECORATOR(5, (float)-9999) | ||||
|     String res = sendATGetString(GF("TP")); | ||||
|     if (res == "") { | ||||
|       return (float)-9999; | ||||
| @@ -809,6 +848,7 @@ public: | ||||
|     char buf[5] = {0,}; | ||||
|     res.toCharArray(buf, 5); | ||||
|     int8_t intRes = (int8_t)strtol(buf, 0, 16); // degrees Celsius displayed in 8-bit two's complement format. | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return (float)intRes; | ||||
|   } | ||||
|  | ||||
| @@ -816,10 +856,35 @@ public: | ||||
|    * Client related functions | ||||
|    */ | ||||
|  | ||||
| protected: | ||||
|  protected: | ||||
|  | ||||
|   IPAddress getHostIP(const char* host, int timeout_s = 45) { | ||||
|     String strIP; strIP.reserve(16); | ||||
|   int16_t getConnectionIndicator() { | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|     sendAT(GF("CI")); | ||||
|     int16_t intRes = readResponseInt(); | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return intRes; | ||||
|   } | ||||
|  | ||||
|   IPAddress getOperatingIP() { | ||||
|     String strIP; | ||||
|     strIP.reserve(16); | ||||
|  | ||||
|     XBEE_COMMAND_START_DECORATOR(5, IPAddress(0, 0, 0, 0)) | ||||
|     sendAT(GF("OD")); | ||||
|     strIP = stream.readStringUntil('\r');  // read result | ||||
|     strIP.trim(); | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|  | ||||
|     if (strIP != "" && strIP != GF("ERROR")) { | ||||
|       return TinyGsmIpFromString(strIP); | ||||
|     } else | ||||
|       return IPAddress(0, 0, 0, 0); | ||||
|   } | ||||
|  | ||||
|   IPAddress lookupHostIP(const char* host, int timeout_s = 45) { | ||||
|     String strIP; | ||||
|     strIP.reserve(16); | ||||
|     unsigned long startMillis = millis(); | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|     bool gotIP = false; | ||||
| @@ -850,8 +915,6 @@ protected: | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, | ||||
|                     bool ssl = false, int timeout_s = 75) | ||||
|   { | ||||
|     unsigned long startMillis = millis(); | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|     bool retVal = false; | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|  | ||||
| @@ -863,12 +926,12 @@ protected: | ||||
|  | ||||
|     // If we don't have a good IP for the host, we need to do a DNS search | ||||
|     if (savedHostIP == IPAddress(0,0,0,0)) { | ||||
|       savedHostIP = getHostIP(host, timeout_s);  // This will return 0.0.0.0 if lookup fails | ||||
|       savedHostIP = lookupHostIP(host, timeout_s);  // This will return 0.0.0.0 if lookup fails | ||||
|     } | ||||
|  | ||||
|     // If we now have a valid IP address, use it to connect | ||||
|     if (savedHostIP != IPAddress(0,0,0,0)) {  // Only re-set connection information if we have an IP address | ||||
|       retVal = modemConnect(savedHostIP, port, mux, ssl, timeout_ms - (millis() - startMillis)); | ||||
|       retVal = modemConnect(savedHostIP, port, mux, ssl); | ||||
|     } | ||||
|  | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
| @@ -876,13 +939,21 @@ protected: | ||||
|     return retVal; | ||||
|   } | ||||
|  | ||||
|   bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false, int timeout_s = 75) { | ||||
|  | ||||
|   bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, | ||||
|                     bool ssl = false) { | ||||
|     bool success = true; | ||||
|     uint32_t timeout_ms = ((uint32_t)timeout_s)*1000; | ||||
|  | ||||
|     if (mux != 0) { | ||||
|       DBG("XBee only supports 1 IP channel in transparent mode!"); | ||||
|     } | ||||
|  | ||||
|     // empty the saved currelty-in-use destination address | ||||
|     savedOperatingIP = IPAddress(0, 0, 0, 0); | ||||
|  | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|  | ||||
|     if (ip != savedIP) {  // Can skip almost everything if there's no change in the IP address | ||||
|     if (ip != savedIP) {  // Can skip almost everything if there's no | ||||
|                           // change in the IP address | ||||
|       savedIP = ip;  // Set the newly requested IP address | ||||
|       String host; host.reserve(16); | ||||
|       host += ip[0]; | ||||
| @@ -909,11 +980,14 @@ protected: | ||||
|       success &= writeChanges(); | ||||
|     } | ||||
|  | ||||
|     for (unsigned long start = millis(); millis() - start < timeout_ms; ) { | ||||
|       if (modemGetConnected()) { | ||||
|         sockets[mux]->sock_connected = true; | ||||
|         break; | ||||
|     // we'll accept either unknown or connected | ||||
|     if (beeType != XBEE_S6B_WIFI) { | ||||
|       uint16_t ci = getConnectionIndicator(); | ||||
|       success &= (ci == 0x00 || ci == 0xFF || ci == 0x28); | ||||
|     } | ||||
|  | ||||
|     if (success) { | ||||
|       sockets[mux]->sock_connected = true; | ||||
|     } | ||||
|  | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
| @@ -921,9 +995,55 @@ protected: | ||||
|     return success; | ||||
|   } | ||||
|  | ||||
|   bool modemStop(uint32_t maxWaitMs) { | ||||
|     streamClear();  // Empty anything in the buffer | ||||
|     // empty the saved currently-in-use destination address | ||||
|     savedOperatingIP = IPAddress(0, 0, 0, 0); | ||||
|  | ||||
|     XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|  | ||||
|     // Get the current socket timeout | ||||
|     sendAT(GF("TM")); | ||||
|     String timeoutUsed = readResponseString(5000L); | ||||
|  | ||||
|     // For WiFi models, there's no direct way to close the socket.  This is a | ||||
|     // hack to shut the socket by setting the timeout to zero. | ||||
|     if (beeType == XBEE_S6B_WIFI) { | ||||
|       sendAT(GF("TM0"));  // Set socket timeout to 0 | ||||
|       waitResponse(maxWaitMs);  // This response can be slow | ||||
|       writeChanges(); | ||||
|     } | ||||
|  | ||||
|     // For cellular models, per documentation: If you write the TM (socket | ||||
|     // timeout) value while in Transparent Mode, the current connection is | ||||
|     // immediately closed - this works even if the TM values is unchanged | ||||
|     sendAT(GF("TM"), timeoutUsed);  // Re-set socket timeout | ||||
|     waitResponse(maxWaitMs);  // This response can be slow | ||||
|     writeChanges(); | ||||
|  | ||||
|     XBEE_COMMAND_END_DECORATOR | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   int16_t modemSend(const void* buff, size_t len, uint8_t mux = 0) { | ||||
|     if (mux != 0) { | ||||
|       DBG("XBee only supports 1 IP channel in transparent mode!"); | ||||
|     } | ||||
|     stream.write((uint8_t*)buff, len); | ||||
|     stream.flush(); | ||||
|  | ||||
|     if (beeType != XBEE_S6B_WIFI) { | ||||
|       // After a send, verify the outgoing ip if it isn't set | ||||
|       if (savedOperatingIP == IPAddress(0, 0, 0, 0)) { | ||||
|         modemGetConnected(); | ||||
|       } | ||||
|       // After sending several characters, also re-check | ||||
|       // NOTE:  I'm intentionally not checking after every single character! | ||||
|       else if (len > 5) { | ||||
|         modemGetConnected(); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return len; | ||||
|   } | ||||
|  | ||||
| @@ -937,17 +1057,11 @@ protected: | ||||
|  | ||||
|      XBEE_COMMAND_START_DECORATOR(5, false) | ||||
|  | ||||
|     // Verify that we're connected to the *right* IP address | ||||
|     // We might be connected - but to the wrong thing | ||||
|     // NOTE:  In transparent mode, there is only one connection possible - no multiplex | ||||
|     // String strIP; strIP.reserve(16); | ||||
|     // sendAT(GF("DL")); | ||||
|     // strIP = stream.readStringUntil('\r');  // read result | ||||
|     // if (TinyGsmIpFromString(strIP) != savedIP) return exitAndFail(); | ||||
|  | ||||
|     if (beeType == XBEE_UNKNOWN) getSeries();  // Need to know the bee type to interpret response | ||||
|  | ||||
|     switch (beeType){  // The wifi be can only say if it's connected to the netowrk | ||||
|     switch (beeType){ | ||||
|  | ||||
|       // The wifi be can only say if it's connected to the netowrk | ||||
|       case XBEE_S6B_WIFI: { | ||||
|         RegStatus s = getRegistrationStatus(); | ||||
|         XBEE_COMMAND_END_DECORATOR | ||||
| @@ -956,23 +1070,111 @@ protected: | ||||
|         } | ||||
|         return (s == REG_OK);  // if it's connected, we hope the sockets are too | ||||
|       } | ||||
|       default: {  // Cellular XBee's | ||||
|         sendAT(GF("CI")); | ||||
|         int16_t intRes = readResponseInt(); | ||||
|  | ||||
|       // Cellular XBee's | ||||
|       default: { | ||||
|         int16_t ci = getConnectionIndicator(); | ||||
|         // Get the operating destination address | ||||
|         IPAddress od = getOperatingIP(); | ||||
|         XBEE_COMMAND_END_DECORATOR | ||||
|         switch(intRes) { | ||||
|           case 0x00:  // 0x00 = The socket is definitely open | ||||
|           case 0x28:  // 0x28 = "Unknown." | ||||
|           case 0xFF:  // 0xFF = No known status - this is always returned prior to sending data | ||||
|             return true; | ||||
|           case 0x02:  // 0x02 = Invalid parameters (bad IP/host) | ||||
|           case 0x12:  // 0x12 = DNS query lookup failure | ||||
|           case 0x25:  // 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!) | ||||
|             savedIP = IPAddress(0,0,0,0);  // force a lookup next time! | ||||
|           default:  // If it's anything else (inc 0x02, 0x12, and 0x25)... | ||||
|             sockets[0]->sock_connected = false;  // ...it's definitely NOT connected | ||||
|  | ||||
|         switch(ci) { | ||||
|  | ||||
|           // 0x00 = The socket is definitely open | ||||
|           case 0x00: { | ||||
|             savedOperatingIP = od; | ||||
|             // but it's possible the socket is set to the wrong place | ||||
|             if (od != IPAddress(0, 0, 0, 0) && od != savedIP) { | ||||
|               sockets[0]->stop(); | ||||
|               return false; | ||||
|             } | ||||
|             return true; | ||||
|           } | ||||
|  | ||||
|           // 0x28 = "Unknown." | ||||
|           // 0xFF = No known status - always returned prior to sending data | ||||
|           case 0x28: | ||||
|           case 0xFF: { | ||||
|             // If we previously had an operating destination and we no longer do, | ||||
|             // the socket must have closed | ||||
|             if (od == IPAddress(0, 0, 0, 0) && savedOperatingIP != IPAddress(0, 0, 0, 0)) { | ||||
|               savedOperatingIP = od; | ||||
|               sockets[0]->sock_connected = false; | ||||
|               return false; | ||||
|             } | ||||
|             // else if the operating destination exists, but is wrong | ||||
|             // we need to close and re-open | ||||
|             else if (od != IPAddress(0, 0, 0, 0) && od != savedIP) { | ||||
|               sockets[0]->stop(); | ||||
|               return false; | ||||
|             } | ||||
|             // else if the operating destination exists and matches, we're | ||||
|             // good to go | ||||
|             else if (od != IPAddress(0, 0, 0, 0) && od == savedIP) { | ||||
|               savedOperatingIP = od; | ||||
|               return true; | ||||
|             } | ||||
|             // If we never had an operating destination, then sock may be open | ||||
|             // but data never sent - this is the dreaded "we don't know" | ||||
|             else { | ||||
|               savedOperatingIP = od; | ||||
|               return true; | ||||
|             } | ||||
|  | ||||
|             // // Ask for information about any open sockets | ||||
|             // sendAT(GF("SI")); | ||||
|             // String open_socks = stream.readStringUntil('\r'); | ||||
|             // open_socks.replace(GSM_NL, ""); | ||||
|             // open_socks.trim(); | ||||
|             // if (open_socks != "") { | ||||
|             //   // In transparent mode, only socket 0 should be possible | ||||
|             //   sendAT(GF("SI0")); | ||||
|             //   // read socket it | ||||
|             //   String sock_id = stream.readStringUntil('\r'); | ||||
|             //   // read socket state | ||||
|             //   String sock_state = stream.readStringUntil('\r'); | ||||
|             //   // read socket protocol (TCP/UDP) | ||||
|             //   String sock_protocol = stream.readStringUntil('\r'); | ||||
|             //   // read local port number | ||||
|             //   String local_port = stream.readStringUntil('\r'); | ||||
|             //   // read remote port number | ||||
|             //   String remote_port = stream.readStringUntil('\r'); | ||||
|             //   // read remote ip address | ||||
|             //   String remoted_address = | ||||
|             //       stream.readStringUntil('\r');  // read result | ||||
|             //   stream.readStringUntil('\r');      // final carriage return | ||||
|             // } | ||||
|           } | ||||
|  | ||||
|           // 0x21 = User closed | ||||
|           // 0x27 = Connection lost | ||||
|           // If the connection is lost or timed out on our side, | ||||
|           // we force close so it can reopen | ||||
|           case 0x21 : | ||||
|           case 0x27 : { | ||||
|             sendAT(GF("TM"));  // Get socket timeout | ||||
|             String timeoutUsed = readResponseString(5000L); | ||||
|             sendAT(GF("TM"), timeoutUsed);  // Re-set socket timeout | ||||
|             waitResponse(5000L);  // This response can be slow | ||||
|           } | ||||
|  | ||||
|           // 0x02 = Invalid parameters (bad IP/host) | ||||
|           // 0x12 = DNS query lookup failure | ||||
|           // 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!) | ||||
|           case 0x02: | ||||
|           case 0x12: | ||||
|           case 0x25: { | ||||
|             savedIP = IPAddress(0, 0, 0, 0);  // force a lookup next time! | ||||
|           } | ||||
|  | ||||
|           // If it's anything else (inc 0x02, 0x12, and 0x25)... | ||||
|           // it's definitely NOT connected | ||||
|           default: { | ||||
|             sockets[0]->sock_connected = false; | ||||
|             savedOperatingIP = od; | ||||
|             return false; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -1175,6 +1377,7 @@ protected: | ||||
|   IPAddress     savedIP; | ||||
|   String        savedHost; | ||||
|   IPAddress     savedHostIP; | ||||
|   IPAddress     savedOperatingIP; | ||||
|   bool          inCommandMode; | ||||
|   uint32_t      lastCommandModeMillis; | ||||
|   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #define TinyGsmCommon_h | ||||
|  | ||||
| // The current library version number | ||||
| #define TINYGSM_VERSION "0.9.7" | ||||
| #define TINYGSM_VERSION "0.9.17" | ||||
|  | ||||
| #if defined(SPARK) || defined(PARTICLE) | ||||
|   #include "Particle.h" | ||||
| @@ -491,8 +491,11 @@ String TinyGsmDecodeHex16bit(String &instr) { | ||||
| // Unlocks a sim via the 3GPP TS command AT+CPIN | ||||
| #define TINY_GSM_MODEM_SIM_UNLOCK_CPIN() \ | ||||
|   bool simUnlock(const char *pin) {      \ | ||||
|     if (pin && strlen(pin) > 0) { \ | ||||
|       sendAT(GF("+CPIN=\""), pin, GF("\"")); \ | ||||
|       return waitResponse() == 1; \ | ||||
|     } \ | ||||
|     return true; \ | ||||
|   } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -69,11 +69,12 @@ | ||||
| // set GSM PIN, if any | ||||
| #define GSM_PIN "" | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| // Your GPRS credentials, if any | ||||
| const char apn[]  = "YourAPN"; | ||||
| const char gprsUser[] = ""; | ||||
| const char gprsPass[] = ""; | ||||
|  | ||||
| // Your WiFi connection credentials, if applicable | ||||
| const char wifiSSID[]  = "YourSSID"; | ||||
| const char wifiPass[] = "YourWiFiPass"; | ||||
|  | ||||
| @@ -83,6 +84,20 @@ const char resource[] = "/TinyGSM/logo.txt"; | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
|  | ||||
| // Just in case someone defined the wrong thing.. | ||||
| #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS false | ||||
| #define TINY_GSM_USE_WIFI true | ||||
| #endif | ||||
| #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI | ||||
| #undef TINY_GSM_USE_GPRS | ||||
| #undef TINY_GSM_USE_WIFI | ||||
| #define TINY_GSM_USE_GPRS true | ||||
| #define TINY_GSM_USE_WIFI false | ||||
| #endif | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, SerialMon); | ||||
| @@ -111,8 +126,8 @@ void setup() { | ||||
|   SerialMon.println("Wait..."); | ||||
|  | ||||
|   // Set GSM module baud rate | ||||
|   TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX); | ||||
|   // SerialAT.begin(115200); | ||||
|   // TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX); | ||||
|   SerialAT.begin(115200); | ||||
|   delay(3000); | ||||
| } | ||||
|  | ||||
| @@ -147,6 +162,7 @@ void loop() { | ||||
| #endif | ||||
|  | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   // Wifi connection parameters must be set before waiting for the network | ||||
|   SerialMon.print(F("Setting SSID/password...")); | ||||
|   if (!modem.networkConnect(wifiSSID, wifiPass)) { | ||||
|     SerialMon.println(" fail"); | ||||
| @@ -175,7 +191,8 @@ void loop() { | ||||
|   } | ||||
|   SerialMon.println(F(" [OK]")); | ||||
|  | ||||
| #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   // GPRS connection parameters are usually set after network registration | ||||
|   SerialMon.print("Connecting to "); | ||||
|   SerialMon.print(apn); | ||||
|   if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { | ||||
| @@ -233,8 +250,14 @@ void loop() { | ||||
|   client.stop(); | ||||
|   SerialMon.println(F("Server disconnected")); | ||||
|  | ||||
| #if TINY_GSM_USE_WIFI | ||||
|   modem.networkDisconnect(); | ||||
|   SerialMon.println(F("WiFi disconnected")); | ||||
| #endif | ||||
| #if TINY_GSM_USE_GPRS | ||||
|   modem.gprsDisconnect(); | ||||
|   SerialMon.println(F("GPRS disconnected")); | ||||
| #endif | ||||
|  | ||||
|   SerialMon.println(); | ||||
|   SerialMon.println(F("************************")); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user