Merge branch 'master' into master
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Digi XBee 3G Global Users Guide - 90001541.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Digi XBee 3G Global Users Guide - 90001541.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Digi XBee3 LTEC1 Users Guide - 90002253.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Digi XBee3 LTEC1 Users Guide - 90002253.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/ESP8266 - AT Command Examples 1.3.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/ESP8266 - AT Command Examples 1.3.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/ESP8266 - AT Instruction Set v2.0.0.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/ESP8266 - AT Instruction Set v2.0.0.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Gemalto ELS31 AT Commands.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Gemalto ELS31 AT Commands.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/SIM800 Series AT Command Manual V1.09.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/SIM800 Series AT Command Manual V1.09.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/SIM800 Series AT Command Manual V1.10.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/SIM800 Series AT Command Manual V1.10.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/SIM800+Series Bluetooth Application Note V1.04.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/SIM800+Series Bluetooth Application Note V1.04.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/SIM800+Series Email Application Note V1.00.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/SIM800+Series Email Application Note V1.00.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Sequans Monarch AT Commands.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Sequans Monarch AT Commands.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Telit CE910 AT Commands Reference Guide r5.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Telit CE910 AT Commands Reference Guide r5.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Telit HE910 AT Command Reference Guide r0.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Telit HE910 AT Command Reference Guide r0.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Telit LE910 AT Commands Reference Guide r14.1.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Telit LE910 AT Commands Reference Guide r14.1.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Telit ME910C1 AT Commands Reference Guide r2.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Telit ME910C1 AT Commands Reference Guide r2.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								extras/doc/Telit Modules Software User Guide 2G3G4G r20.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								extras/doc/Telit Modules Software User Guide 2G3G4G r20.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										21
									
								
								library.json
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								library.json
									
									
									
									
									
								
							| @@ -1,18 +1,25 @@ | ||||
| { | ||||
|   "name": "TinyGSM", | ||||
|   "version": "0.3.3", | ||||
|   "version": "0.3.30", | ||||
|   "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968", | ||||
|   "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968", | ||||
|   "authors": | ||||
|   { | ||||
|     "name":  "Volodymyr Shymanskyy", | ||||
|     "url":   "https://github.com/vshymanskyy", | ||||
|     "maintainer": true | ||||
|   }, | ||||
|   [ | ||||
|     { | ||||
|         "name": "Sara Damiano", | ||||
|         "email": "sdamiano@stroudcenter.org", | ||||
|         "url": "https://envirodiy.org/", | ||||
|         "maintainer": true | ||||
|     }, | ||||
|     { | ||||
|       "name":  "Volodymyr Shymanskyy", | ||||
|       "url":   "https://github.com/vshymanskyy" | ||||
|     } | ||||
| ], | ||||
|   "repository": | ||||
|   { | ||||
|     "type": "git", | ||||
|     "url": "https://github.com/vshymanskyy/TinyGSM.git" | ||||
|     "url": "https://github.com/EnviroDIY/TinyGSM.git" | ||||
|   }, | ||||
|   "homepage": "https://github.com/vshymanskyy/TinyGSM", | ||||
|   "export": { | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| name=TinyGSM | ||||
| version=0.3.3 | ||||
| version=0.3.30 | ||||
| author=Volodymyr Shymanskyy | ||||
| maintainer=Volodymyr Shymanskyy | ||||
| sentence=A small Arduino library for GPRS modules, that just works. | ||||
|   | ||||
| @@ -34,11 +34,13 @@ | ||||
| #elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) | ||||
|   #define TINY_GSM_MODEM_HAS_GPRS | ||||
|   #include <TinyGsmClientA6.h> | ||||
|   typedef TinyGsmA6 TinyGsm; | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #elif defined(TINY_GSM_MODEM_M590) | ||||
|   #define TINY_GSM_MODEM_HAS_GPRS | ||||
|   #include <TinyGsmClientM590.h> | ||||
|   typedef TinyGsmM590 TinyGsm; | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #elif defined(TINY_GSM_MODEM_U201) | ||||
| @@ -51,6 +53,7 @@ | ||||
| #elif defined(TINY_GSM_MODEM_ESP8266) | ||||
|   #define TINY_GSM_MODEM_HAS_WIFI | ||||
|   #include <TinyGsmClientESP8266.h> | ||||
|   typedef TinyGsmESP8266 TinyGsm; | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|   typedef TinyGsm::GsmClientSecure TinyGsmClientSecure; | ||||
|  | ||||
| @@ -58,7 +61,9 @@ | ||||
|   #define TINY_GSM_MODEM_HAS_GPRS | ||||
|   #define TINY_GSM_MODEM_HAS_WIFI | ||||
|   #include <TinyGsmClientXBee.h> | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|   typedef TinyGsmXBee TinyGsm; | ||||
|   typedef TinyGsmXBee::GsmClient TinyGsmClient; | ||||
|   typedef TinyGsmXBee::GsmClientSecure TinyGsmClientSecure; | ||||
|  | ||||
| #else | ||||
|   #error "Please define GSM modem model" | ||||
|   | ||||
| @@ -39,24 +39,40 @@ enum RegStatus { | ||||
| }; | ||||
|  | ||||
|  | ||||
| class TinyGsm | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                       Declaration of the TinyGsmA6 Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
|  | ||||
| class TinyGsmA6 | ||||
| { | ||||
|  | ||||
| public: | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The A6 Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| class GsmClient : public Client | ||||
| { | ||||
|   friend class TinyGsm; | ||||
|   friend class TinyGsmA6; | ||||
|   typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo; | ||||
|  | ||||
| public: | ||||
|   GsmClient() {} | ||||
|  | ||||
|   GsmClient(TinyGsm& modem) { | ||||
|   GsmClient(TinyGsmA6& modem) { | ||||
|     init(&modem); | ||||
|   } | ||||
|  | ||||
|   bool init(TinyGsm* modem) { | ||||
|   bool init(TinyGsmA6* modem) { | ||||
|     this->at = modem; | ||||
|     this->mux = -1; | ||||
|     sock_connected = false; | ||||
| @@ -119,7 +135,8 @@ public: | ||||
|   virtual int read(uint8_t *buf, size_t size) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     size_t cnt = 0; | ||||
|     while (cnt < size) { | ||||
|     uint32_t _startMillis = millis(); | ||||
|     while (cnt < size && millis() - _startMillis < _timeout) { | ||||
|       size_t chunk = TinyGsmMin(size-cnt, rx.size()); | ||||
|       if (chunk > 0) { | ||||
|         rx.get(buf, chunk); | ||||
| @@ -162,15 +179,34 @@ public: | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   uint8_t       mux; | ||||
|   bool          sock_connected; | ||||
|   RxFifo        rx; | ||||
|   TinyGsmA6*  at; | ||||
|   uint8_t     mux; | ||||
|   bool        sock_connected; | ||||
|   RxFifo      rx; | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The A6 Does not have a secure client! | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The A6 Modem Functions | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
| #ifdef GSM_DEFAULT_STREAM | ||||
|   TinyGsmA6(Stream& stream = GSM_DEFAULT_STREAM) | ||||
| #else | ||||
|   TinyGsmA6(Stream& stream) | ||||
| #endif | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
| @@ -316,17 +352,6 @@ public: | ||||
|     return SIM_ERROR; | ||||
|   } | ||||
|  | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     sendAT(GF("+CREG?")); | ||||
|     if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { | ||||
|       return REG_UNKNOWN; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip format (0) | ||||
|     int status = stream.readStringUntil('\n').toInt(); | ||||
|     waitResponse(); | ||||
|     return (RegStatus)status; | ||||
|   } | ||||
|  | ||||
|   String getOperator() { | ||||
|     sendAT(GF("+COPS=3,0")); // Set format | ||||
|     waitResponse(); | ||||
| @@ -345,6 +370,17 @@ public: | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|    RegStatus getRegistrationStatus() { | ||||
|      sendAT(GF("+CREG?")); | ||||
|      if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { | ||||
|        return REG_UNKNOWN; | ||||
|      } | ||||
|      streamSkipUntil(','); // Skip format (0) | ||||
|      int status = stream.readStringUntil('\n').toInt(); | ||||
|      waitResponse(); | ||||
|      return (RegStatus)status; | ||||
|    } | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CSQ")); | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
| @@ -370,6 +406,26 @@ public: | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIFSR")); | ||||
|     String res; | ||||
|     if (waitResponse(10000L, res) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||
|     res.replace(GSM_NL, ""); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
| @@ -428,104 +484,6 @@ public: | ||||
|     return (res == 1); | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIFSR")); | ||||
|     String res; | ||||
|     if (waitResponse(10000L, res) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||
|     res.replace(GSM_NL, ""); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Phone Call functions | ||||
|    */ | ||||
|  | ||||
|   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callAnswer() { | ||||
|     sendAT(GF("A")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   // Returns true on pick-up, false on error/busy | ||||
|   bool callNumber(const String& number) { | ||||
|     if (number == GF("last")) { | ||||
|       sendAT(GF("DLST")); | ||||
|     } else { | ||||
|       sendAT(GF("D\""), number, "\";"); | ||||
|     } | ||||
|  | ||||
|     if (waitResponse(5000L) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (waitResponse(60000L, | ||||
|         GF(GSM_NL "+CIEV: \"CALL\",1"), | ||||
|         GF(GSM_NL "+CIEV: \"CALL\",0"), | ||||
|         GFP(GSM_ERROR)) != 1) | ||||
|     { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     int rsp = waitResponse(60000L, | ||||
|               GF(GSM_NL "+CIEV: \"SOUNDER\",0"), | ||||
|               GF(GSM_NL "+CIEV: \"CALL\",0")); | ||||
|  | ||||
|     int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL), GF(GSM_NL "NO ANSWER" GSM_NL)); | ||||
|  | ||||
|     return rsp == 1 && rsp2 == 0; | ||||
|   } | ||||
|  | ||||
|   bool callHangup() { | ||||
|     sendAT(GF("H")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   // 0-9,*,#,A,B,C,D | ||||
|   bool dtmfSend(char cmd, unsigned duration_ms = 100) { | ||||
|     duration_ms = constrain(duration_ms, 100, 1000); | ||||
|  | ||||
|     // The duration parameter is not working, so we simulate it using delay.. | ||||
|     // TODO: Maybe there's another way... | ||||
|  | ||||
|     //sendAT(GF("+VTD="), duration_ms / 100); | ||||
|     //waitResponse(); | ||||
|  | ||||
|     sendAT(GF("+VTS="), cmd); | ||||
|     if (waitResponse(10000L) == 1) { | ||||
|       delay(duration_ms); | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Audio functions | ||||
|    */ | ||||
|  | ||||
|   bool audioSetHeadphones() { | ||||
|     sendAT(GF("+SNFS=0")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   bool audioSetSpeaker() { | ||||
|     sendAT(GF("+SNFS=1")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   bool audioMuteMic(bool mute) { | ||||
|     sendAT(GF("+CMUT="), mute); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Messaging functions | ||||
|    */ | ||||
| @@ -650,9 +608,13 @@ public: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|   bool streamSkipUntil(char c) { | ||||
|     const unsigned long timeout = 1000L; | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (millis() - startMillis < timeout) { | ||||
|       while (millis() - startMillis < timeout && !stream.available()) { | ||||
|         TINY_GSM_YIELD(); | ||||
|       } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
| @@ -664,7 +626,7 @@ public: | ||||
|     streamWrite("AT", cmd..., GSM_NL); | ||||
|     stream.flush(); | ||||
|     TINY_GSM_YIELD(); | ||||
|     //DBG("### AT:", cmd...); | ||||
|     DBG("### AT:", cmd...); | ||||
|   } | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
| @@ -672,12 +634,12 @@ public: | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
|     String r4s(r4); r4s.trim(); | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); | ||||
|     data.reserve(64); | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
| @@ -737,6 +699,7 @@ finish: | ||||
|       } | ||||
|       data = ""; | ||||
|     } | ||||
|     DBG('<', index, '>'); | ||||
|     return index; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #ifndef TinyGsmClientESP8266_h | ||||
| #define TinyGsmClientESP8266_h | ||||
|  | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
| // #define TINY_GSM_DEBUG Serial | ||||
|  | ||||
| #if !defined(TINY_GSM_RX_BUFFER) | ||||
|   #define TINY_GSM_RX_BUFFER 512 | ||||
| @@ -24,24 +24,51 @@ static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; | ||||
| static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; | ||||
| static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; | ||||
|  | ||||
| class TinyGsm | ||||
| // <stat> status of ESP8266 station interface | ||||
| // 2 : ESP8266 station connected to an AP and has obtained IP | ||||
| // 3 : ESP8266 station created a TCP or UDP transmission | ||||
| // 4 : the TCP or UDP transmission of ESP8266 station disconnected | ||||
| // 5 : ESP8266 station did NOT connect to an AP | ||||
| enum RegStatus { | ||||
|   REG_OK_IP        = 2, | ||||
|   REG_OK_TCP       = 3, | ||||
|   REG_UNREGISTERED = 4, | ||||
|   REG_DENIED       = 5, | ||||
|   REG_UNKNOWN      = 6, | ||||
| }; | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                     Declaration of the TinyGsmESP8266 Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| class TinyGsmESP8266 | ||||
| { | ||||
|  | ||||
|   //============================================================================// | ||||
|   //============================================================================// | ||||
|   //                          The ESP8266 Client Class | ||||
|   //============================================================================// | ||||
|   //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| { | ||||
|   friend class TinyGsm; | ||||
|   friend class TinyGsmESP8266; | ||||
|   typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo; | ||||
|  | ||||
| public: | ||||
|   GsmClient() {} | ||||
|  | ||||
|   GsmClient(TinyGsm& modem, uint8_t mux = 1) { | ||||
|   GsmClient(TinyGsmESP8266& modem, uint8_t mux = 1) { | ||||
|     init(&modem, mux); | ||||
|   } | ||||
|  | ||||
|   bool init(TinyGsm* modem, uint8_t mux = 1) { | ||||
|   bool init(TinyGsmESP8266* modem, uint8_t mux = 1) { | ||||
|     this->at = modem; | ||||
|     this->mux = mux; | ||||
|     sock_connected = false; | ||||
| @@ -101,7 +128,8 @@ public: | ||||
|   virtual int read(uint8_t *buf, size_t size) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     size_t cnt = 0; | ||||
|     while (cnt < size) { | ||||
|     uint32_t _startMillis = millis(); | ||||
|     while (cnt < size && millis() - _startMillis < _timeout) { | ||||
|       size_t chunk = TinyGsmMin(size-cnt, rx.size()); | ||||
|       if (chunk > 0) { | ||||
|         rx.get(buf, chunk); | ||||
| @@ -144,18 +172,25 @@ public: | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   uint8_t       mux; | ||||
|   bool          sock_connected; | ||||
|   RxFifo        rx; | ||||
|   TinyGsmESP8266*  at; | ||||
|   uint8_t          mux; | ||||
|   bool             sock_connected; | ||||
|   RxFifo           rx; | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The Secure ESP8266 Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| class GsmClientSecure : public GsmClient | ||||
| { | ||||
| public: | ||||
|   GsmClientSecure() {} | ||||
|  | ||||
|   GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) | ||||
|   GsmClientSecure(TinyGsmESP8266& modem, uint8_t mux = 1) | ||||
|     : GsmClient(modem, mux) | ||||
|   {} | ||||
|  | ||||
| @@ -169,9 +204,20 @@ public: | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The ESP8266 Modem Functions | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
| #ifdef GSM_DEFAULT_STREAM | ||||
|   TinyGsmESP8266(Stream& stream = GSM_DEFAULT_STREAM) | ||||
| #else | ||||
|   TinyGsmESP8266(Stream& stream) | ||||
| #endif | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
| @@ -192,6 +238,14 @@ public: | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     sendAT(GF("+CIPMUX=1"));  // Enable Multiple Connections | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     sendAT(GF("+CWMODE_CUR=1"));  // Put into "station" mode | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -232,9 +286,7 @@ public: | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   bool hasSSL() { | ||||
|     return true; | ||||
|   } | ||||
|   bool hasSSL() { return true; } | ||||
|  | ||||
|   /* | ||||
|    * Power functions | ||||
| @@ -255,11 +307,30 @@ public: | ||||
|     return init(); | ||||
|   } | ||||
|  | ||||
|   bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|  | ||||
|   /* | ||||
|    * SIM card functions | ||||
|    */ | ||||
|  | ||||
|  | ||||
|   /* | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|    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")); | ||||
|      waitResponse();  // Returns an OK after the status | ||||
|     return (RegStatus)status; | ||||
|    } | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CWJAP_CUR?")); | ||||
|     int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:")); | ||||
| @@ -275,21 +346,9 @@ public: | ||||
|     return res2; | ||||
|   } | ||||
|  | ||||
|   bool isNetworkConnected() { | ||||
|     sendAT(GF("+CIPSTATUS")); | ||||
|     int res1 = waitResponse(3000, GF("STATUS:")); | ||||
|     int res2 = 0; | ||||
|     if (res1 == 1) { | ||||
|       res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); | ||||
|     } | ||||
|     // <stat> status of ESP8266 station interface | ||||
|     // 2 : ESP8266 station connected to an AP and has obtained IP | ||||
|     // 3 : ESP8266 station created a TCP or UDP transmission | ||||
|     // 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected) | ||||
|     // 5 : ESP8266 station did NOT connect to an AP | ||||
|     waitResponse();  // Returns an OK after the status | ||||
|     if (res2 == 2 || res2 == 3 || res2 == 4) return true; | ||||
|     else return false; | ||||
|   bool isNetworkConnected()  { | ||||
|     RegStatus s = getRegistrationStatus(); | ||||
|     return (s == REG_OK_IP || s == REG_OK_TCP); | ||||
|   } | ||||
|  | ||||
|   bool waitForNetwork(unsigned long timeout = 60000L) { | ||||
| @@ -298,7 +357,7 @@ public: | ||||
|       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 || res2 == 4) { | ||||
|         if (res2 == 2 || res2 == 3) { | ||||
|             waitResponse(); | ||||
|             return true; | ||||
|          } | ||||
| @@ -308,36 +367,6 @@ public: | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|   bool networkConnect(const char* ssid, const char* pwd) { | ||||
|  | ||||
|     sendAT(GF("+CIPMUX=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("+CWMODE_CUR=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("+CWJAP_CUR=\""), ssid, GF("\",\""), pwd, GF("\"")); | ||||
|     if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL "FAIL" GSM_NL)) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool networkDisconnect() { | ||||
|     sendAT(GF("+CWQAP")); | ||||
|     bool retVal = waitResponse(10000L) == 1; | ||||
|     waitResponse(GF("WIFI DISCONNECT")); | ||||
|     return retVal; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIPSTA_CUR??")); | ||||
|     int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:")); | ||||
| @@ -353,6 +382,46 @@ public: | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|   bool networkConnect(const char* ssid, const char* pwd) { | ||||
|     sendAT(GF("+CWJAP_CUR=\""), ssid, GF("\",\""), pwd, GF("\"")); | ||||
|     if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL "FAIL" GSM_NL)) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool networkDisconnect() { | ||||
|     sendAT(GF("+CWQAP")); | ||||
|     bool retVal = waitResponse(10000L) == 1; | ||||
|     waitResponse(GF("WIFI DISCONNECT")); | ||||
|     return retVal; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
|  | ||||
|   /* | ||||
|    * Messaging functions | ||||
|    */ | ||||
|  | ||||
|   /* | ||||
|    * Location functions | ||||
|    */ | ||||
|  | ||||
|   String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * Battery functions | ||||
|    */ | ||||
|  | ||||
|   uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
| protected: | ||||
|  | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { | ||||
| @@ -384,21 +453,8 @@ protected: | ||||
|   } | ||||
|  | ||||
|   bool modemGetConnected(uint8_t mux) { | ||||
|     // TODO: re-check this | ||||
|     sendAT(GF("+CIPSTATUS="), mux); | ||||
|     int res1 = waitResponse(3000, GF("STATUS:")); | ||||
|     int res2; | ||||
|     if (res1 == 1) { | ||||
|       res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); | ||||
|     } | ||||
|     // <stat> status of ESP8266 station interface | ||||
|     // 2 : ESP8266 station connected to an AP and has obtained IP | ||||
|     // 3 : ESP8266 station created a TCP or UDP transmission | ||||
|     // 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected) | ||||
|     // 5 : ESP8266 station did NOT connect to an AP | ||||
|     waitResponse();  // Returns an OK after the status | ||||
|     if (res2 == 2 || res2 == 3 || res2 == 4) return true; | ||||
|     else return false; | ||||
|     RegStatus s = getRegistrationStatus(); | ||||
|     return (s == REG_OK_IP || s == REG_OK_TCP); | ||||
|   } | ||||
|  | ||||
| public: | ||||
| @@ -416,9 +472,13 @@ public: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|   bool streamSkipUntil(char c) { | ||||
|     const unsigned long timeout = 1000L; | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (millis() - startMillis < timeout) { | ||||
|       while (millis() - startMillis < timeout && !stream.available()) { | ||||
|         TINY_GSM_YIELD(); | ||||
|       } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
| @@ -430,7 +490,7 @@ public: | ||||
|     streamWrite("AT", cmd..., GSM_NL); | ||||
|     stream.flush(); | ||||
|     TINY_GSM_YIELD(); | ||||
|     //DBG("### AT:", cmd...); | ||||
|     DBG("### AT:", cmd...); | ||||
|   } | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
| @@ -438,12 +498,12 @@ public: | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
|     String r4s(r4); r4s.trim(); | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); | ||||
|     data.reserve(64); | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
| @@ -505,6 +565,7 @@ finish: | ||||
|       } | ||||
|       data = ""; | ||||
|     } | ||||
|     DBG('<', index, '>'); | ||||
|     return index; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #ifndef TinyGsmClientM590_h | ||||
| #define TinyGsmClientM590_h | ||||
|  | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
| // #define TINY_GSM_DEBUG Serial | ||||
|  | ||||
| #if !defined(TINY_GSM_RX_BUFFER) | ||||
|   #define TINY_GSM_RX_BUFFER 256 | ||||
| @@ -39,24 +39,36 @@ enum RegStatus { | ||||
| }; | ||||
|  | ||||
|  | ||||
| class TinyGsm | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                    Declaration of the TinyGsmM590 Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| class TinyGsmM590 | ||||
| { | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The M590 Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| { | ||||
|   friend class TinyGsm; | ||||
|   friend class TinyGsmM590; | ||||
|   typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo; | ||||
|  | ||||
| public: | ||||
|   GsmClient() {} | ||||
|  | ||||
|   GsmClient(TinyGsm& modem, uint8_t mux = 1) { | ||||
|   GsmClient(TinyGsmM590& modem, uint8_t mux = 1) { | ||||
|     init(&modem, mux); | ||||
|   } | ||||
|  | ||||
|   bool init(TinyGsm* modem, uint8_t mux = 1) { | ||||
|   bool init(TinyGsmM590* modem, uint8_t mux = 1) { | ||||
|     this->at = modem; | ||||
|     this->mux = mux; | ||||
|     sock_connected = false; | ||||
| @@ -116,7 +128,8 @@ public: | ||||
|   virtual int read(uint8_t *buf, size_t size) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     size_t cnt = 0; | ||||
|     while (cnt < size) { | ||||
|     uint32_t _startMillis = millis(); | ||||
|     while (cnt < size && millis() - _startMillis < _timeout) { | ||||
|       size_t chunk = TinyGsmMin(size-cnt, rx.size()); | ||||
|       if (chunk > 0) { | ||||
|         rx.get(buf, chunk); | ||||
| @@ -159,15 +172,33 @@ public: | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   TinyGsmM590*  at; | ||||
|   uint8_t       mux; | ||||
|   bool          sock_connected; | ||||
|   RxFifo        rx; | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The M590 Has no Secure client! | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The M590 Modem Functions | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
| #ifdef GSM_DEFAULT_STREAM | ||||
|   TinyGsmM590(Stream& stream = GSM_DEFAULT_STREAM) | ||||
| #else | ||||
|   TinyGsmM590(Stream& stream) | ||||
| #endif | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
| @@ -327,17 +358,6 @@ public: | ||||
|     return SIM_ERROR; | ||||
|   } | ||||
|  | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     sendAT(GF("+CREG?")); | ||||
|     if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { | ||||
|       return REG_UNKNOWN; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip format (0) | ||||
|     int status = stream.readStringUntil('\n').toInt(); | ||||
|     waitResponse(); | ||||
|     return (RegStatus)status; | ||||
|   } | ||||
|  | ||||
|   String getOperator() { | ||||
|     sendAT(GF("+COPS?")); | ||||
|     if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { | ||||
| @@ -353,6 +373,17 @@ public: | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|    RegStatus getRegistrationStatus() { | ||||
|      sendAT(GF("+CREG?")); | ||||
|      if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { | ||||
|        return REG_UNKNOWN; | ||||
|      } | ||||
|      streamSkipUntil(','); // Skip format (0) | ||||
|      int status = stream.readStringUntil('\n').toInt(); | ||||
|      waitResponse(); | ||||
|      return (RegStatus)status; | ||||
|    } | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CSQ")); | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
| @@ -378,6 +409,26 @@ public: | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+XIIC?")); | ||||
|     if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     stream.readStringUntil(','); | ||||
|     String res = stream.readStringUntil('\n'); | ||||
|     waitResponse(); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
| @@ -408,12 +459,12 @@ public: | ||||
|     } | ||||
|     return false; | ||||
|  | ||||
| set_dns: | ||||
|     sendAT(GF("+DNSSERVER=1,8.8.8.8")); | ||||
|     waitResponse(); | ||||
|  | ||||
|     sendAT(GF("+DNSSERVER=2,8.8.4.4")); | ||||
|     waitResponse(); | ||||
| // set_dns:  // TODO | ||||
| //     sendAT(GF("+DNSSERVER=1,8.8.8.8")); | ||||
| //     waitResponse(); | ||||
| // | ||||
| //     sendAT(GF("+DNSSERVER=2,8.8.4.4")); | ||||
| //     waitResponse(); | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
| @@ -434,34 +485,6 @@ set_dns: | ||||
|     return res == 1; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+XIIC?")); | ||||
|     if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     stream.readStringUntil(','); | ||||
|     String res = stream.readStringUntil('\n'); | ||||
|     waitResponse(); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Phone Call functions | ||||
|    */ | ||||
|  | ||||
|   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * Messaging functions | ||||
|    */ | ||||
| @@ -595,9 +618,13 @@ public: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|   bool streamSkipUntil(char c) { | ||||
|     const unsigned long timeout = 1000L; | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (millis() - startMillis < timeout) { | ||||
|       while (millis() - startMillis < timeout && !stream.available()) { | ||||
|         TINY_GSM_YIELD(); | ||||
|       } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
| @@ -609,7 +636,7 @@ public: | ||||
|     streamWrite("AT", cmd..., GSM_NL); | ||||
|     stream.flush(); | ||||
|     TINY_GSM_YIELD(); | ||||
|     //DBG("### AT:", cmd...); | ||||
|     DBG("### AT:", cmd...); | ||||
|   } | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
| @@ -617,12 +644,12 @@ public: | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
|     String r4s(r4); r4s.trim(); | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); | ||||
|     data.reserve(64); | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
| @@ -683,6 +710,7 @@ finish: | ||||
|       } | ||||
|       data = ""; | ||||
|     } | ||||
|     DBG('<', index, '>'); | ||||
|     return index; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -9,8 +9,8 @@ | ||||
| #ifndef TinyGsmClientSIM800_h | ||||
| #define TinyGsmClientSIM800_h | ||||
|  | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
| //#define TINY_GSM_USE_HEX | ||||
| // #define TINY_GSM_DEBUG Serial | ||||
| // #define TINY_GSM_USE_HEX | ||||
|  | ||||
| #if !defined(TINY_GSM_RX_BUFFER) | ||||
|   #define TINY_GSM_RX_BUFFER 64 | ||||
| @@ -40,9 +40,22 @@ enum RegStatus { | ||||
| }; | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                    Declaration of the TinyGsmSim800 Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| class TinyGsmSim800 | ||||
| { | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The Sim800 Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| @@ -173,15 +186,22 @@ public: | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsmSim800* at; | ||||
|   uint8_t       mux; | ||||
|   uint16_t      sock_available; | ||||
|   uint32_t      prev_check; | ||||
|   bool          sock_connected; | ||||
|   bool          got_data; | ||||
|   RxFifo        rx; | ||||
|   TinyGsmSim800*  at; | ||||
|   uint8_t         mux; | ||||
|   uint16_t        sock_available; | ||||
|   uint32_t        prev_check; | ||||
|   bool            sock_connected; | ||||
|   bool            got_data; | ||||
|   RxFifo          rx; | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The SIM800 Secure Client | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| class GsmClientSecure : public GsmClient | ||||
| { | ||||
| public: | ||||
| @@ -201,9 +221,19 @@ public: | ||||
|   } | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The SIM800 Modem Functions | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
| #ifdef GSM_DEFAULT_STREAM | ||||
|   TinyGsmSim800(Stream& stream = GSM_DEFAULT_STREAM) | ||||
| #else | ||||
|   TinyGsmSim800(Stream& stream) | ||||
| #endif | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
| @@ -226,6 +256,11 @@ public: | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     // PREFERRED SMS STORAGE | ||||
|     sendAT(GF("+CPMS="), GF("\"SM\""), GF(","), GF("\"SM\""), GF(","), GF("\"SM\"")); | ||||
|     waitResponse(); | ||||
|  | ||||
|     getSimStatus(); | ||||
|     return true; | ||||
|   } | ||||
| @@ -393,17 +428,6 @@ public: | ||||
|     return SIM_ERROR; | ||||
|   } | ||||
|  | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     sendAT(GF("+CREG?")); | ||||
|     if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { | ||||
|       return REG_UNKNOWN; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip format (0) | ||||
|     int status = stream.readStringUntil('\n').toInt(); | ||||
|     waitResponse(); | ||||
|     return (RegStatus)status; | ||||
|   } | ||||
|  | ||||
|   String getOperator() { | ||||
|     sendAT(GF("+COPS?")); | ||||
|     if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { | ||||
| @@ -419,6 +443,17 @@ public: | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|    RegStatus getRegistrationStatus() { | ||||
|      sendAT(GF("+CREG?")); | ||||
|      if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { | ||||
|        return REG_UNKNOWN; | ||||
|      } | ||||
|      streamSkipUntil(','); // Skip format (0) | ||||
|      int status = stream.readStringUntil('\n').toInt(); | ||||
|      waitResponse(); | ||||
|      return (RegStatus)status; | ||||
|    } | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CSQ")); | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
| @@ -444,6 +479,26 @@ public: | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIFSR;E0")); | ||||
|     String res; | ||||
|     if (waitResponse(10000L, res) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||
|     res.replace(GSM_NL, ""); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
| @@ -564,72 +619,6 @@ public: | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIFSR;E0")); | ||||
|     String res; | ||||
|     if (waitResponse(10000L, res) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||
|     res.replace(GSM_NL, ""); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Phone Call functions | ||||
|    */ | ||||
|  | ||||
|   bool setGsmBusy(bool busy = true) { | ||||
|     sendAT(GF("+GSMBUSY="), busy ? 1 : 0); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   bool callAnswer() { | ||||
|     sendAT(GF("A")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   // Returns true on pick-up, false on error/busy | ||||
|   bool callNumber(const String& number) { | ||||
|     if (number == GF("last")) { | ||||
|       sendAT(GF("DL")); | ||||
|     } else { | ||||
|       sendAT(GF("D"), number, ";"); | ||||
|     } | ||||
|     int status = waitResponse(60000L, | ||||
|                               GFP(GSM_OK), | ||||
|                               GF("BUSY" GSM_NL), | ||||
|                               GF("NO ANSWER" GSM_NL), | ||||
|                               GF("NO CARRIER" GSM_NL)); | ||||
|     switch (status) { | ||||
|     case 1:  return true; | ||||
|     case 2: | ||||
|     case 3:  return false; | ||||
|     default: return false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   bool callHangup() { | ||||
|     sendAT(GF("H")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   // 0-9,*,#,A,B,C,D | ||||
|   bool dtmfSend(char cmd, int duration_ms = 100) { | ||||
|     duration_ms = constrain(duration_ms, 100, 1000); | ||||
|  | ||||
|     sendAT(GF("+VTD="), duration_ms / 100); // VTD accepts in 1/10 of a second | ||||
|     waitResponse(); | ||||
|  | ||||
|     sendAT(GF("+VTS="), cmd); | ||||
|     return waitResponse(10000L) == 1; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Messaging functions | ||||
|    */ | ||||
| @@ -722,6 +711,7 @@ public: | ||||
|   /* | ||||
|    * Battery functions | ||||
|    */ | ||||
|  | ||||
|   // Use: float vBatt = modem.getBattVoltage() / 1000.0; | ||||
|   uint16_t getBattVoltage() { | ||||
|     sendAT(GF("+CBC")); | ||||
| @@ -854,9 +844,13 @@ public: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|   bool streamSkipUntil(char c) { | ||||
|     const unsigned long timeout = 1000L; | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (millis() - startMillis < timeout) { | ||||
|       while (millis() - startMillis < timeout && !stream.available()) { | ||||
|         TINY_GSM_YIELD(); | ||||
|       } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
| @@ -868,7 +862,7 @@ public: | ||||
|     streamWrite("AT", cmd..., GSM_NL); | ||||
|     stream.flush(); | ||||
|     TINY_GSM_YIELD(); | ||||
|     //DBG("### AT:", cmd...); | ||||
|     DBG("### AT:", cmd...); | ||||
|   } | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
| @@ -876,12 +870,12 @@ public: | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
|     String r4s(r4); r4s.trim(); | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); | ||||
|     data.reserve(64); | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
| @@ -937,6 +931,7 @@ finish: | ||||
|       } | ||||
|       data = ""; | ||||
|     } | ||||
|     DBG('<', index, '>'); | ||||
|     return index; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,13 @@ | ||||
|  | ||||
| #include <TinyGsmClientSIM800.h> | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //              Declaration and Definitio of the TinyGsmSim808 Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| class TinyGsmSim808: public TinyGsmSim800 | ||||
| { | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #ifndef TinyGsmClientU201_h | ||||
| #define TinyGsmClientU201_h | ||||
|  | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
| // #define TINY_GSM_DEBUG Serial | ||||
|  | ||||
| #if !defined(TINY_GSM_RX_BUFFER) | ||||
|   #define TINY_GSM_RX_BUFFER 64 | ||||
| @@ -39,9 +39,22 @@ enum RegStatus { | ||||
| }; | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                   Declaration of the TinyGsmU201 Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| class TinyGsmU201 | ||||
| { | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The U201 Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| @@ -171,6 +184,13 @@ private: | ||||
|   RxFifo        rx; | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The Secure U201 Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| class GsmClientSecure : public GsmClient | ||||
| { | ||||
| public: | ||||
| @@ -191,6 +211,13 @@ public: | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The U201 Modem Functions | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
| #ifdef GSM_DEFAULT_STREAM | ||||
| @@ -285,6 +312,10 @@ public: | ||||
|  | ||||
|   bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   /* | ||||
|    * SIM card functions | ||||
|    */ | ||||
| @@ -335,17 +366,6 @@ public: | ||||
|     return SIM_ERROR; | ||||
|   } | ||||
|  | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     sendAT(GF("+CGREG?")); | ||||
|     if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) { | ||||
|       return REG_UNKNOWN; | ||||
|     } | ||||
|     streamSkipUntil(','); // Skip format (0) | ||||
|     int status = stream.readStringUntil('\n').toInt(); | ||||
|     waitResponse(); | ||||
|     return (RegStatus)status; | ||||
|   } | ||||
|  | ||||
|   String getOperator() { | ||||
|     sendAT(GF("+COPS?")); | ||||
|     if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { | ||||
| @@ -361,6 +381,17 @@ public: | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|    RegStatus getRegistrationStatus() { | ||||
|      sendAT(GF("+CGREG?")); | ||||
|      if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) { | ||||
|        return REG_UNKNOWN; | ||||
|      } | ||||
|      streamSkipUntil(','); // Skip format (0) | ||||
|      int status = stream.readStringUntil('\n').toInt(); | ||||
|      waitResponse(); | ||||
|      return (RegStatus)status; | ||||
|    } | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CSQ")); | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
| @@ -386,6 +417,24 @@ public: | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIFSR;E0")); | ||||
|     String res; | ||||
|     if (waitResponse(10000L, res) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
| @@ -450,32 +499,6 @@ public: | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     sendAT(GF("+CIFSR;E0")); | ||||
|     String res; | ||||
|     if (waitResponse(10000L, res) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Phone Call functions | ||||
|    */ | ||||
|  | ||||
|   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool callAnswer() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool callNumber(const String& number) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool callHangup() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   /* | ||||
|    * Messaging functions | ||||
|    */ | ||||
| @@ -505,6 +528,7 @@ public: | ||||
|   /* | ||||
|    * Battery functions | ||||
|    */ | ||||
|  | ||||
|   // Use: float vBatt = modem.getBattVoltage() / 1000.0; | ||||
|   uint16_t getBattVoltage() { | ||||
|     sendAT(GF("+CIND")); | ||||
| @@ -615,9 +639,13 @@ public: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|   bool streamSkipUntil(char c) { | ||||
|     const unsigned long timeout = 1000L; | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (millis() - startMillis < timeout) { | ||||
|       while (millis() - startMillis < timeout && !stream.available()) { | ||||
|         TINY_GSM_YIELD(); | ||||
|       } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
| @@ -629,7 +657,7 @@ public: | ||||
|     streamWrite("AT", cmd..., GSM_NL); | ||||
|     stream.flush(); | ||||
|     TINY_GSM_YIELD(); | ||||
|     //DBG("### AT:", cmd...); | ||||
|     DBG("### AT:", cmd...); | ||||
|   } | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
| @@ -637,12 +665,12 @@ public: | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
|     String r4s(r4); r4s.trim(); | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); | ||||
|     data.reserve(64); | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
| @@ -650,7 +678,7 @@ public: | ||||
|       TINY_GSM_YIELD(); | ||||
|       while (stream.available() > 0) { | ||||
|         int a = stream.read(); | ||||
|         if (a < 0) continue; | ||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||
|         data += (char)a; | ||||
|         if (r1 && data.endsWith(r1)) { | ||||
|           index = 1; | ||||
| @@ -691,6 +719,7 @@ finish: | ||||
|       } | ||||
|       data = ""; | ||||
|     } | ||||
|     DBG('<', index, '>'); | ||||
|     return index; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -11,9 +11,6 @@ | ||||
|  | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
|  | ||||
| #if !defined(TINY_GSM_RX_BUFFER) | ||||
|   #define TINY_GSM_RX_BUFFER 256 | ||||
| #endif | ||||
|  | ||||
| #define TINY_GSM_MUX_COUNT 1  // Multi-plexing isn't supported using command mode | ||||
|  | ||||
| @@ -29,38 +26,55 @@ enum SimStatus { | ||||
|   SIM_LOCKED = 2, | ||||
| }; | ||||
|  | ||||
| enum XBeeType { | ||||
|   S6B    = 0, | ||||
|   LTEC1  = 1, | ||||
| }; | ||||
|  | ||||
| enum RegStatus { | ||||
|   REG_UNREGISTERED = 0, | ||||
|   REG_OK           = 0, | ||||
|   REG_UNREGISTERED = 1, | ||||
|   REG_SEARCHING    = 2, | ||||
|   REG_DENIED       = 3, | ||||
|   REG_OK_HOME      = 1, | ||||
|   REG_OK_ROAMING   = 5, | ||||
|   REG_UNKNOWN      = 4, | ||||
| }; | ||||
|  | ||||
| // These are responses to the HS command to get "hardware series" | ||||
| enum XBeeType { | ||||
|   XBEE_S6B_WIFI  = 0x601,  // Digi XBee® Wi-Fi | ||||
|   XBEE_LTE1_VZN  = 0xB01,  // Digi XBee® Cellular LTE Cat 1 | ||||
|   XBEE_3G        = 0xB02,  // Digi XBee® Cellular 3G | ||||
|   XBEE3_LTE1_ATT = 1,  // Digi XBee3™ Cellular LTE CAT 1  -- HS unknown to SRGD | ||||
|   XBEE3_LTEM_ATT = 2,  // Digi XBee3™ Cellular LTE-M  -- HS unknown to SRGD | ||||
|   XBEE3_LTENB    = 3,  // Digi XBee3™ Cellular NB-IoT  -- HS unknown to SRGD | ||||
| }; | ||||
|  | ||||
| class TinyGsm | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                   Declaration of the TinyGsmXBee Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| class TinyGsmXBee | ||||
| { | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The XBee Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| { | ||||
|   friend class TinyGsm; | ||||
|   friend class TinyGsmXBee; | ||||
|  | ||||
| public: | ||||
|   GsmClient() {} | ||||
|  | ||||
|   GsmClient(TinyGsm& modem, uint8_t mux = 0) { | ||||
|   GsmClient(TinyGsmXBee& modem, uint8_t mux = 0) { | ||||
|     init(&modem, mux); | ||||
|   } | ||||
|  | ||||
|   bool init(TinyGsm* modem, uint8_t mux = 0) { | ||||
|   bool init(TinyGsmXBee* modem, uint8_t mux = 0) { | ||||
|     this->at = modem; | ||||
|     this->mux = mux; | ||||
|     sock_connected = false; | ||||
| @@ -73,19 +87,25 @@ public: | ||||
| public: | ||||
|   virtual int connect(const char *host, uint16_t port) { | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     at->commandMode(); | ||||
|     sock_connected = at->modemConnect(host, port, mux, false); | ||||
|     at->writeChanges(); | ||||
|     at->exitCommand(); | ||||
|     bool sock_connected = false; | ||||
|     if (at->commandMode())  {  // Don't try if we didn't successfully get into command mode | ||||
|       sock_connected = at->modemConnect(host, port, mux, false); | ||||
|       at->writeChanges(); | ||||
|       at->exitCommand(); | ||||
|     } | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     return sock_connected; | ||||
|   } | ||||
|  | ||||
|   virtual int connect(IPAddress ip, uint16_t port) { | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     at->commandMode(); | ||||
|     sock_connected = at->modemConnect(ip, port, mux, false); | ||||
|     at->writeChanges(); | ||||
|     at->exitCommand(); | ||||
|     bool sock_connected = false; | ||||
|     if (at->commandMode())  {  // Don't try if we didn't successfully get into command mode | ||||
|       sock_connected = at->modemConnect(ip, port, mux, false); | ||||
|       at->writeChanges(); | ||||
|       at->exitCommand(); | ||||
|     } | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     return sock_connected; | ||||
|   } | ||||
|  | ||||
| @@ -100,7 +120,7 @@ public: | ||||
|     at->exitCommand(); | ||||
|     at->modemSend("", 1, mux); | ||||
|     at->commandMode(); | ||||
|     at->sendAT(GF("TM64"));  // Set socket timeout back to 10seconds; | ||||
|     at->sendAT(GF("TM64"));  // Set socket timeout back to 10 seconds; | ||||
|     at->waitResponse(); | ||||
|     at->writeChanges(); | ||||
|     at->exitCommand(); | ||||
| @@ -110,7 +130,6 @@ public: | ||||
|  | ||||
|   virtual size_t write(const uint8_t *buf, size_t size) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     //at->maintain(); | ||||
|     return at->modemSend(buf, size, mux); | ||||
|   } | ||||
|  | ||||
| @@ -125,7 +144,7 @@ public: | ||||
|  | ||||
|   virtual int read(uint8_t *buf, size_t size) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     return at->stream.readBytes(buf, size); | ||||
|     return at->stream.readBytes((char*)buf, size); | ||||
|   } | ||||
|  | ||||
|   virtual int read() { | ||||
| @@ -151,47 +170,69 @@ public: | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   TinyGsmXBee*  at; | ||||
|   uint8_t       mux; | ||||
|   bool          sock_connected; | ||||
| }; | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The Secure XBee Client Class | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
|  | ||||
| class GsmClientSecure : public GsmClient | ||||
| { | ||||
| public: | ||||
|   GsmClientSecure() {} | ||||
|  | ||||
|   GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) | ||||
|   GsmClientSecure(TinyGsmXBee& modem, uint8_t mux = 1) | ||||
|     : GsmClient(modem, mux) | ||||
|   {} | ||||
|  | ||||
| public: | ||||
|   virtual int connect(const char *host, uint16_t port) { | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     at->commandMode(); | ||||
|     sock_connected = at->modemConnect(host, port, mux, true); | ||||
|     at->writeChanges(); | ||||
|     at->exitCommand(); | ||||
|     bool sock_connected = false; | ||||
|     if (at->commandMode())  {  // Don't try if we didn't successfully get into command mode | ||||
|       sock_connected = at->modemConnect(host, port, mux, true); | ||||
|       at->writeChanges(); | ||||
|       at->exitCommand(); | ||||
|     } | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     return sock_connected; | ||||
|   } | ||||
|  | ||||
|   virtual int connect(IPAddress ip, uint16_t port) { | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     at->commandMode(); | ||||
|     sock_connected = at->modemConnect(ip, port, mux, true); | ||||
|     at->writeChanges(); | ||||
|     at->exitCommand(); | ||||
|     bool sock_connected = false; | ||||
|     if (at->commandMode())  {  // Don't try if we didn't successfully get into command mode | ||||
|       sock_connected = at->modemConnect(ip, port, mux, true); | ||||
|       at->writeChanges(); | ||||
|       at->exitCommand(); | ||||
|     } | ||||
|     at->streamClear();  // Empty anything remaining in the buffer; | ||||
|     return sock_connected; | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
| //                          The XBee Modem Functions | ||||
| //============================================================================// | ||||
| //============================================================================// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
| #ifdef GSM_DEFAULT_STREAM | ||||
|   TinyGsmXBee(Stream& stream = GSM_DEFAULT_STREAM) | ||||
| #else | ||||
|   TinyGsmXBee(Stream& stream) | ||||
| #endif | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
|   } | ||||
|   {} | ||||
|  | ||||
|   /* | ||||
|    * Basic functions | ||||
| @@ -201,23 +242,53 @@ public: | ||||
|   } | ||||
|  | ||||
|   bool init() { | ||||
|     guardTime = 1100; | ||||
|     commandMode(); | ||||
|     guardTime = 1100;  // Start with a default guard time of 1 second | ||||
|  | ||||
|     if (!commandMode(10)) return false;  // Try up to 10 times for the init | ||||
|  | ||||
|     sendAT(GF("AP0"));  // Put in transparent mode | ||||
|     waitResponse(); | ||||
|     bool ret_val = waitResponse() == 1; | ||||
|     ret_val &= writeChanges(); | ||||
|  | ||||
|     sendAT(GF("GT64")); // shorten the guard time to 100ms | ||||
|     ret_val &= waitResponse(); | ||||
|     ret_val &= writeChanges(); | ||||
|     if (ret_val) guardTime = 125; | ||||
|  | ||||
|     sendAT(GF("HS"));  // Get the "Hardware Series"; | ||||
|     String res = readResponse(); | ||||
|     char buf[4] = {0,};  // Set up buffer for response | ||||
|     res.toCharArray(buf, 4); | ||||
|     int intRes = strtol(buf, 0, 16); | ||||
|     beeType = (XBeeType)intRes; | ||||
|  | ||||
|     exitCommand(); | ||||
|     return ret_val; | ||||
|   } | ||||
|  | ||||
|   void setBaud(unsigned long baud) { | ||||
|     if (!commandMode()) return; | ||||
|     switch(baud) | ||||
|     { | ||||
|       case 2400: sendAT(GF("BD1")); break; | ||||
|       case 4800: sendAT(GF("BD2")); break; | ||||
|       case 9600: sendAT(GF("BD3")); break; | ||||
|       case 19200: sendAT(GF("BD4")); break; | ||||
|       case 38400: sendAT(GF("BD5")); break; | ||||
|       case 57600: sendAT(GF("BD6")); break; | ||||
|       case 115200: sendAT(GF("BD7")); break; | ||||
|       case 230400: sendAT(GF("BD8")); break; | ||||
|       case 460800: sendAT(GF("BD9")); break; | ||||
|       case 921600: sendAT(GF("BDA")); break; | ||||
|       default: { | ||||
|           DBG(GF("Specified baud rate is unsupported! Setting to 9600 baud.")); | ||||
|           sendAT(GF("BD3")); // Set to default of 9600 | ||||
|           break; | ||||
|       } | ||||
|     } | ||||
|     waitResponse(); | ||||
|     writeChanges(); | ||||
|     sendAT(GF("HS"));  // Get the "Hardware Series"; 0x601 for S6B (Wifi) | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < 1000) {}; | ||||
|     String res = streamReadUntil('\r');  // Does not send an OK, just the result | ||||
|     exitCommand(); | ||||
|     if (res == "601") beeType = S6B; | ||||
|     else beeType = LTEC1; | ||||
|     guardTime = 125; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool testAT(unsigned long timeout = 10000L) { | ||||
| @@ -238,52 +309,100 @@ public: | ||||
|   void maintain() {} | ||||
|  | ||||
|   bool factoryDefault() { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return false;  // Return immediately | ||||
|     sendAT(GF("RE")); | ||||
|     bool ret_val = waitResponse() == 1; | ||||
|     writeChanges(); | ||||
|     ret_val &= writeChanges(); | ||||
|     exitCommand(); | ||||
|     return ret_val; | ||||
|   } | ||||
|  | ||||
|   String getModemInfo() { | ||||
|     String modemInf = ""; | ||||
|     if (!commandMode()) return modemInf;  // Try up to 10 times for the init | ||||
|  | ||||
|     sendAT(GF("HS"));  // Get the "Hardware Series" | ||||
|     modemInf += readResponse(); | ||||
|  | ||||
|     exitCommand(); | ||||
|     return modemInf; | ||||
|   } | ||||
|  | ||||
|   bool hasSSL() { | ||||
|     if (beeType == S6B) return false; | ||||
|     if (beeType == XBEE_S6B_WIFI) return false; | ||||
|     else return true; | ||||
|   } | ||||
|  | ||||
|   XBeeType getBeeType() { | ||||
|     return beeType; | ||||
|   } | ||||
|  | ||||
|   String getBeeName() { | ||||
|     switch (beeType){ | ||||
|       case XBEE_S6B_WIFI: return "Digi XBee® Wi-Fi"; | ||||
|       case XBEE_LTE1_VZN: return "Digi XBee® Cellular LTE Cat 1"; | ||||
|       case XBEE_3G: return "Digi XBee® Cellular 3G"; | ||||
|       case XBEE3_LTE1_ATT: return "Digi XBee3™ Cellular LTE CAT 1"; | ||||
|       case XBEE3_LTEM_ATT: return "Digi XBee3™ Cellular LTE-M"; | ||||
|       case XBEE3_LTENB: return "Digi XBee3™ Cellular NB-IoT"; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Power functions | ||||
|    */ | ||||
|  | ||||
|   bool restart() { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return false;  // Return immediately | ||||
|     sendAT(GF("AM1"));  // Digi suggests putting into airplane mode before restarting | ||||
|                        // This allows the sockets and connections to close cleanly | ||||
|     writeChanges(); | ||||
|     if (waitResponse() != 1) goto fail; | ||||
|     sendAT(GF("FR")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|     if (waitResponse() != 1) goto fail; | ||||
|  | ||||
|     delay (2000);  // Actually resets about 2 seconds later | ||||
|  | ||||
|     // Wait until reboot complete and responds to command mode call again | ||||
|     for (unsigned long start = millis(); millis() - start < 60000L; ) { | ||||
|       if (commandMode()) { | ||||
|       if (commandMode(1)) { | ||||
|         sendAT(GF("AM0"));  // Turn off airplane mode | ||||
|         writeChanges(); | ||||
|         exitCommand(); | ||||
|         return true; | ||||
|         delay(250);  // wait a litle before trying again | ||||
|       } | ||||
|     } | ||||
|     exitCommand(); | ||||
|     return false;; | ||||
|     return true; | ||||
|  | ||||
|  | ||||
|     fail: | ||||
|       exitCommand(); | ||||
|       return false; | ||||
|   } | ||||
|  | ||||
|   void setupPinSleep() { | ||||
|     commandMode(); | ||||
|     sendAT(GF("SM"),1); | ||||
|   void setupPinSleep(bool maintainAssociation = false) { | ||||
|     if (!commandMode()) return;  // Return immediately | ||||
|     sendAT(GF("SM"),1);  // Pin sleep | ||||
|     waitResponse(); | ||||
|     if (beeType == S6B) { | ||||
|         sendAT(GF("SO"),200); | ||||
|     if (beeType == XBEE_S6B_WIFI && !maintainAssociation) { | ||||
|         sendAT(GF("SO"),200);  // For lowest power, dissassociated deep sleep | ||||
|         waitResponse(); | ||||
|     } | ||||
|     else if (!maintainAssociation){ | ||||
|         sendAT(GF("SO"),1);  // For lowest power, dissassociated deep sleep | ||||
|                              // Not supported by all modules, will return "ERROR" | ||||
|         waitResponse(); | ||||
|     } | ||||
|     writeChanges(); | ||||
|     exitCommand(); | ||||
|   } | ||||
|  | ||||
|   bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   /* | ||||
|    * SIM card functions | ||||
|    */ | ||||
| @@ -293,23 +412,17 @@ public: | ||||
|   } | ||||
|  | ||||
|   String getSimCCID() { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return "";  // Return immediately | ||||
|     sendAT(GF("S#")); | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < 1000) {}; | ||||
|     String res = streamReadUntil('\r');  // Does not send an OK, just the result | ||||
|     String res = readResponse(); | ||||
|     exitCommand(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   String getIMEI() { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return "";  // Return immediately | ||||
|     sendAT(GF("IM")); | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < 1000) {}; | ||||
|     String res = streamReadUntil('\r');  // Does not send an OK, just the result | ||||
|     String res = readResponse(); | ||||
|     exitCommand(); | ||||
|     return res; | ||||
|   } | ||||
| @@ -318,38 +431,10 @@ public: | ||||
|     return SIM_READY;  // unsupported | ||||
|   } | ||||
|  | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     commandMode(); | ||||
|     sendAT(GF("AI")); | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < 1000) {}; | ||||
|     String res = streamReadUntil('\r');  // Does not send an OK, just the result | ||||
|     exitCommand(); | ||||
|  | ||||
|     if(res == GF("0")) | ||||
|       return REG_OK_HOME; | ||||
|  | ||||
|     else if(res == GF("13") || res == GF("2A")) | ||||
|       return REG_UNREGISTERED; | ||||
|  | ||||
|     else if(res == GF("FF") || res == GF("22") || res == GF("23") || | ||||
|             res == GF("40") || res == GF("41") || res == GF("42")) | ||||
|       return REG_SEARCHING; | ||||
|  | ||||
|     else if(res == GF("24") || res == GF("25") || res == GF("27")) | ||||
|       return REG_DENIED; | ||||
|  | ||||
|     else return REG_UNKNOWN; | ||||
|   } | ||||
|  | ||||
|   String getOperator() { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return "";  // Return immediately | ||||
|     sendAT(GF("MN")); | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < 1000) {}; | ||||
|     String res = streamReadUntil('\r');  // Does not send an OK, just the result | ||||
|     String res = readResponse(); | ||||
|     exitCommand(); | ||||
|     return res; | ||||
|   } | ||||
| @@ -358,26 +443,95 @@ public: | ||||
|   * Generic network functions | ||||
|   */ | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     commandMode(); | ||||
|     if (beeType == S6B) sendAT(GF("LM"));  // ask for the "link margin" - the dB above sensitivity | ||||
|     else sendAT(GF("DB"));  // ask for the cell strength in dBm | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < 1000) {}; | ||||
|     char buf[2] = {0};  // Set up buffer for response | ||||
|     buf[0] = streamRead(); | ||||
|     buf[1] = streamRead(); | ||||
|     // DBG(buf[0], buf[1], "\n"); | ||||
|   RegStatus getRegistrationStatus() { | ||||
|     if (!commandMode()) return REG_UNKNOWN;  // Return immediately | ||||
|  | ||||
|     sendAT(GF("AI")); | ||||
|     String res = readResponse(); | ||||
|     char buf[3] = {0,};  // Set up buffer for response | ||||
|     res.toCharArray(buf, 3); | ||||
|     int intRes = strtol(buf, 0, 16); | ||||
|     RegStatus stat = REG_UNKNOWN; | ||||
|  | ||||
|     switch (beeType){ | ||||
|       case XBEE_S6B_WIFI: { | ||||
|         if(intRes == 0x00)  // 0x00 Successfully joined an access point, established IP addresses and IP listening sockets | ||||
|           stat = REG_OK; | ||||
|         else if(intRes == 0x01)  // 0x01 Wi-Fi transceiver initialization in progress. | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0x02)  // 0x02 Wi-Fi transceiver initialized, but not yet scanning for access point. | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0x13) { // 0x13 Disconnecting from access point. | ||||
|           restart();  // Restart the device; the S6B tends to get stuck "disconnecting" | ||||
|           stat = REG_UNREGISTERED; | ||||
|         } | ||||
|         else if(intRes == 0x23)  // 0x23 SSID not configured. | ||||
|           stat = REG_UNREGISTERED; | ||||
|         else if(intRes == 0x24)  // 0x24 Encryption key invalid (either NULL or invalid length for WEP). | ||||
|           stat = REG_DENIED; | ||||
|         else if(intRes == 0x27)  // 0x27 SSID was found, but join failed. | ||||
|           stat = REG_DENIED; | ||||
|         else if(intRes == 0x40)  // 0x40 Waiting for WPA or WPA2 Authentication. | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0x41)  // 0x41 Device joined a network and is waiting for IP configuration to complete | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0x42)  // 0x42 Device is joined, IP is configured, and listening sockets are being set up. | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0xFF)  // 0xFF Device is currently scanning for the configured SSID. | ||||
|           stat = REG_SEARCHING; | ||||
|         else stat = REG_UNKNOWN; | ||||
|         break; | ||||
|       } | ||||
|       default: { | ||||
|         if(intRes == 0x00)  // 0x00 Connected to the Internet. | ||||
|           stat = REG_OK; | ||||
|         else if(intRes == 0x22)  // 0x22 Registering to cellular network. | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0x23)  // 0x23 Connecting to the Internet. | ||||
|           stat = REG_SEARCHING; | ||||
|         else if(intRes == 0x24)  // 0x24 The cellular component is missing, corrupt, or otherwise in error. | ||||
|           stat = REG_UNKNOWN; | ||||
|         else if(intRes == 0x25)  // 0x25 Cellular network registration denied. | ||||
|           stat = REG_DENIED; | ||||
|         else if(intRes == 0x2A) {  // 0x2A Airplane mode. | ||||
|           sendAT(GF("AM0"));  // Turn off airplane mode | ||||
|           waitResponse(); | ||||
|           writeChanges(); | ||||
|           stat = REG_UNKNOWN; | ||||
|         } | ||||
|         else if(intRes == 0x2F) {  // 0x2F Bypass mode active. | ||||
|           sendAT(GF("AP0"));  // Set back to transparent mode | ||||
|           waitResponse(); | ||||
|           writeChanges(); | ||||
|           stat = REG_UNKNOWN; | ||||
|         } | ||||
|         else if(intRes == 0xFF)  // 0xFF Device is currently scanning for the configured SSID. | ||||
|           stat = REG_SEARCHING; | ||||
|         else stat = REG_UNKNOWN; | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     exitCommand(); | ||||
|     int intr = strtol(buf, 0, 16); | ||||
|     if (beeType == S6B) return -93 + intr;  // the maximum sensitivity is -93dBm | ||||
|     else return -1*intr; // need to convert to negative number | ||||
|     return stat; | ||||
|   } | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     if (!commandMode()) return 0;  // Return immediately | ||||
|     if (beeType == XBEE_S6B_WIFI) sendAT(GF("LM"));  // ask for the "link margin" - the dB above sensitivity | ||||
|     else sendAT(GF("DB"));  // ask for the cell strength in dBm | ||||
|     String res = readResponse();  // it works better if we read in as a string | ||||
|     exitCommand(); | ||||
|     char buf[3] = {0,};  // Set up buffer for response | ||||
|     res.toCharArray(buf, 3); | ||||
|     int intRes = strtol(buf, 0, 16); | ||||
|     if (beeType == XBEE_S6B_WIFI) return -93 + intRes;  // the maximum sensitivity is -93dBm | ||||
|     else return -1*intRes; // need to convert to negative number | ||||
|   } | ||||
|  | ||||
|   bool isNetworkConnected() { | ||||
|     RegStatus s = getRegistrationStatus(); | ||||
|     return (s == REG_OK_HOME || s == REG_OK_ROAMING); | ||||
|     return (s == REG_OK); | ||||
|   } | ||||
|  | ||||
|   bool waitForNetwork(unsigned long timeout = 60000L) { | ||||
| @@ -385,30 +539,41 @@ public: | ||||
|       if (isNetworkConnected()) { | ||||
|         return true; | ||||
|       } | ||||
|       delay(250); | ||||
|       // delay(250);  // Enough delay going in and out of command mode | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     if (!commandMode()) return "";  // Return immediately | ||||
|     sendAT(GF("MY")); | ||||
|     String IPaddr; IPaddr.reserve(16); | ||||
|     // wait for the response - this response can be very slow | ||||
|     IPaddr = readResponse(30000); | ||||
|     exitCommand(); | ||||
|     IPaddr.trim(); | ||||
|     return IPaddr; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * WiFi functions | ||||
|    */ | ||||
|   bool networkConnect(const char* ssid, const char* pwd) { | ||||
|  | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return false;  // return immediately | ||||
|  | ||||
|     sendAT(GF("EE"), 2);  // Set security to WPA2 | ||||
|     waitResponse(); | ||||
|     if (waitResponse() != 1) goto fail; | ||||
|  | ||||
|     sendAT(GF("ID"), ssid); | ||||
|     if (waitResponse() != 1) { | ||||
|       goto fail; | ||||
|     } | ||||
|     if (waitResponse() != 1) goto fail; | ||||
|  | ||||
|     sendAT(GF("PK"), pwd); | ||||
|     if (waitResponse() != 1) { | ||||
|       goto fail; | ||||
|     } | ||||
|     if (waitResponse() != 1) goto fail; | ||||
|  | ||||
|     writeChanges(); | ||||
|     exitCommand(); | ||||
| @@ -421,29 +586,19 @@ fail: | ||||
|   } | ||||
|  | ||||
|   bool networkDisconnect() { | ||||
|     return false;  // Doesn't support disconnecting | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() { | ||||
|     commandMode(); | ||||
|     sendAT(GF("MY")); | ||||
|     String IPaddr; IPaddr.reserve(16); | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (stream.available() < 8 && millis() - startMillis < 30000) {}; | ||||
|     IPaddr = streamReadUntil('\r');  // read result | ||||
|     return IPaddr; | ||||
|   } | ||||
|  | ||||
|   IPAddress localIP() { | ||||
|     return TinyGsmIpFromString(getLocalIP()); | ||||
|     if (!commandMode()) return false;  // return immediately | ||||
|     sendAT(GF("NR0"));  // Do a network reset in order to disconnect | ||||
|     int res = (1 == waitResponse(5000)); | ||||
|     writeChanges(); | ||||
|     exitCommand(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
|   bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return false;  // Return immediately | ||||
|     sendAT(GF("AN"), apn);  // Set the APN | ||||
|     waitResponse(); | ||||
|     writeChanges(); | ||||
| @@ -451,8 +606,20 @@ fail: | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool gprsDisconnect() {  // TODO | ||||
|     return false; | ||||
|   bool gprsDisconnect() { | ||||
|     if (!commandMode()) return false;  // return immediately | ||||
|     sendAT(GF("AM1"));  // Cheating and disconnecting by turning on airplane mode | ||||
|     int res = (1 == waitResponse(5000)); | ||||
|     writeChanges(); | ||||
|     sendAT(GF("AM0"));  // Airplane mode off | ||||
|     waitResponse(5000); | ||||
|     writeChanges(); | ||||
|     exitCommand(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   bool isGprsConnected() { | ||||
|     return isNetworkConnected(); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
| @@ -462,35 +629,69 @@ fail: | ||||
|   String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool sendSMS(const String& number, const String& text) { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return false;  // Return immediately | ||||
|  | ||||
|     sendAT(GF("IP"), 2);  // Put in text messaging mode | ||||
|     waitResponse(); | ||||
|     if (waitResponse() !=1) goto fail; | ||||
|     sendAT(GF("PH"), number);  // Set the phone number | ||||
|     waitResponse(); | ||||
|     sendAT(GF("TDD"));  // Set the text delimiter to the standard 0x0D (carriabe return) | ||||
|     waitResponse(); | ||||
|     writeChanges(); | ||||
|     if (waitResponse() !=1) goto fail; | ||||
|     sendAT(GF("TDD"));  // Set the text delimiter to the standard 0x0D (carriage return) | ||||
|     if (waitResponse() !=1) goto fail; | ||||
|     if (!writeChanges()) goto fail; | ||||
|  | ||||
|     exitCommand(); | ||||
|     stream.print(text); | ||||
|     streamWrite(text); | ||||
|     stream.write((char)0x0D);  // close off with the carriage return | ||||
|     return true; | ||||
|  | ||||
|     fail: | ||||
|       exitCommand(); | ||||
|       return false; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Location functions | ||||
|    */ | ||||
|  | ||||
|   String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * Battery functions | ||||
|    */ | ||||
|  | ||||
|   uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
| protected: | ||||
|  | ||||
| private: | ||||
|  | ||||
|   int modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) { | ||||
|     sendAT(GF("LA"), host); | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) { | ||||
|     String strIP; strIP.reserve(16); | ||||
|     // wait for the response | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (stream.available() < 8 && millis() - startMillis < 30000) {}; | ||||
|     strIP = streamReadUntil('\r');  // read result | ||||
|     IPAddress ip = TinyGsmIpFromString(strIP); | ||||
|     return modemConnect(ip, port, mux, ssl); | ||||
|     bool gotIP = false; | ||||
|     // XBee's require a numeric IP address for connection, but do provide the | ||||
|     // functionality to look up the IP address from a fully qualified domain name | ||||
|     while (!gotIP && millis() - startMillis < 45000L)  // the lookup can take a while | ||||
|     { | ||||
|       sendAT(GF("LA"), host); | ||||
|       while (stream.available() < 4) {};  // wait for any response | ||||
|       strIP = stream.readStringUntil('\r');  // read result | ||||
|       strIP.trim(); | ||||
|       DBG("<<< ", strIP); | ||||
|       if (!strIP.endsWith(GF("ERROR"))) gotIP = true; | ||||
|       delay(100);  // short wait before trying again | ||||
|     } | ||||
|     if (gotIP) {  // No reason to continue if we don't know the IP address | ||||
|       IPAddress ip = TinyGsmIpFromString(strIP); | ||||
|       return modemConnect(ip, port, mux, ssl); | ||||
|     } | ||||
|     else return false; | ||||
|   } | ||||
|  | ||||
|   int modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) { | ||||
|   bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) { | ||||
|     bool success = true; | ||||
|     String host; host.reserve(16); | ||||
|     host += ip[0]; | ||||
|     host += "."; | ||||
| @@ -500,17 +701,17 @@ private: | ||||
|     host += "."; | ||||
|     host += ip[3]; | ||||
|     if (ssl) { | ||||
|       sendAT(GF("IP"), 4);  // Put in TCP mode | ||||
|       waitResponse(); | ||||
|       sendAT(GF("IP"), 4);  // Put in SSL over TCP communication mode | ||||
|       success &= (1 == waitResponse()); | ||||
|     } else { | ||||
|       sendAT(GF("IP"), 1);  // Put in TCP mode | ||||
|       waitResponse(); | ||||
|       success &= (1 == waitResponse()); | ||||
|     } | ||||
|     sendAT(GF("DL"), host);  // Set the "Destination Address Low" | ||||
|     waitResponse(); | ||||
|     success &= (1 == waitResponse()); | ||||
|     sendAT(GF("DE"), String(port, HEX));  // Set the destination port | ||||
|     int rsp = waitResponse(); | ||||
|     return rsp; | ||||
|     success &= (1 == waitResponse()); | ||||
|     return success; | ||||
|   } | ||||
|  | ||||
|   int modemSend(const void* buff, size_t len, uint8_t mux = 0) { | ||||
| @@ -520,7 +721,7 @@ private: | ||||
|   } | ||||
|  | ||||
|   bool modemGetConnected(uint8_t mux = 0) { | ||||
|     commandMode(); | ||||
|     if (!commandMode()) return false; | ||||
|     sendAT(GF("AI")); | ||||
|     int res = waitResponse(GF("0")); | ||||
|     exitCommand(); | ||||
| @@ -542,32 +743,33 @@ public: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   int streamRead() { return stream.read(); } | ||||
|  | ||||
|   String streamReadUntil(char c) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     String return_string = stream.readStringUntil(c); | ||||
|     return_string.trim(); | ||||
|     // DBG(return_string, c); | ||||
|     return return_string; | ||||
|   } | ||||
|  | ||||
|   void streamClear(void) { | ||||
|     while (stream.available()) { streamRead(); } | ||||
|     TINY_GSM_YIELD(); | ||||
|     while (stream.available()) { stream.read(); } | ||||
|   } | ||||
|  | ||||
|   bool commandMode(void) { | ||||
|     delay(guardTime);  // cannot send anything for 1 second before entering command mode | ||||
|     streamWrite(GF("+++"));  // enter command mode | ||||
|     // DBG("\r\n+++\r\n"); | ||||
|     return 1 == waitResponse(guardTime*2); | ||||
|   bool commandMode(int retries = 2) { | ||||
|     int triesMade = 0; | ||||
|     bool success = false; | ||||
|     streamClear();  // Empty everything in the buffer before starting | ||||
|     while (!success and triesMade < retries) { | ||||
|       // Cannot send anything for 1 "guard time" before entering command mode | ||||
|       // Default guard time is 1s, but the init fxn decreases it to 250 ms | ||||
|       delay(guardTime); | ||||
|       streamWrite(GF("+++"));  // enter command mode | ||||
|       DBG("\r\n+++"); | ||||
|       success = (1 == waitResponse(guardTime*2)); | ||||
|       triesMade ++; | ||||
|     } | ||||
|     return success; | ||||
|   } | ||||
|  | ||||
|   void writeChanges(void) { | ||||
|   bool writeChanges(void) { | ||||
|     sendAT(GF("WR"));  // Write changes to flash | ||||
|     waitResponse(); | ||||
|     if (1 != waitResponse()) return false; | ||||
|     sendAT(GF("AC"));  // Apply changes | ||||
|     waitResponse(); | ||||
|     if (1 != waitResponse()) return false; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   void exitCommand(void) { | ||||
| @@ -575,12 +777,22 @@ public: | ||||
|     waitResponse(); | ||||
|   } | ||||
|  | ||||
|   String readResponse(uint32_t timeout = 1000) { | ||||
|     TINY_GSM_YIELD(); | ||||
|     unsigned long startMillis = millis(); | ||||
|     while (!stream.available() && millis() - startMillis < timeout) {}; | ||||
|     String res = stream.readStringUntil('\r');  // lines end with carriage returns | ||||
|     res.trim(); | ||||
|     DBG("<<< ", res); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   template<typename... Args> | ||||
|   void sendAT(Args... cmd) { | ||||
|     streamWrite("AT", cmd..., GSM_NL); | ||||
|     stream.flush(); | ||||
|     TINY_GSM_YIELD(); | ||||
|     //DBG("### AT:", cmd...); | ||||
|     DBG("### AT:", cmd...); | ||||
|   } | ||||
|  | ||||
|   // TODO: Optimize this! | ||||
| @@ -588,19 +800,19 @@ public: | ||||
|                        GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), | ||||
|                        GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | ||||
|   { | ||||
|     /*String r1s(r1); r1s.trim(); | ||||
|     String r1s(r1); r1s.trim(); | ||||
|     String r2s(r2); r2s.trim(); | ||||
|     String r3s(r3); r3s.trim(); | ||||
|     String r4s(r4); r4s.trim(); | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     data.reserve(64); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); | ||||
|     data.reserve(16);  // Should never be getting much here for the XBee | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
|     do { | ||||
|       TINY_GSM_YIELD(); | ||||
|       while (stream.available() > 0) { | ||||
|         int a = streamRead(); | ||||
|         int a = stream.read(); | ||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||
|         data += (char)a; | ||||
|         if (r1 && data.endsWith(r1)) { | ||||
| @@ -625,7 +837,7 @@ finish: | ||||
|     if (!index) { | ||||
|       data.trim(); | ||||
|       data.replace(GSM_NL GSM_NL, GSM_NL); | ||||
|       data.replace(GSM_NL, "\r\n" "    "); | ||||
|       data.replace(GSM_NL, "\r\n    "); | ||||
|       if (data.length()) { | ||||
|         DBG("### Unhandled:", data, "\r\n"); | ||||
|       } else { | ||||
| @@ -636,7 +848,7 @@ finish: | ||||
|       data.replace(GSM_NL GSM_NL, GSM_NL); | ||||
|       data.replace(GSM_NL, "\r\n    "); | ||||
|       if (data.length()) { | ||||
|         // DBG("<<< ", data); | ||||
|         DBG("<<< ", data); | ||||
|       } | ||||
|     } | ||||
|     return index; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user