mirror of
				https://github.com/KevinMidboe/TinyGSM.git
				synced 2025-10-29 18:00:18 +00:00 
			
		
		
		
	Re-aligned with vshymanskyy-master
This commit is contained in:
		
							
								
								
									
										61
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								README.md
									
									
									
									
									
								
							| @@ -14,9 +14,12 @@ If you like **TinyGSM** - give it a star, or fork it and contribute! | |||||||
| [](https://github.com/vshymanskyy/TinyGSM/stargazers)  | [](https://github.com/vshymanskyy/TinyGSM/stargazers)  | ||||||
| [](https://github.com/vshymanskyy/TinyGSM/network) | [](https://github.com/vshymanskyy/TinyGSM/network) | ||||||
|  |  | ||||||
|  | You can also join our chat: | ||||||
|  | [](https://gitter.im/tinygsm) | ||||||
|  |  | ||||||
| ### Arduino Client interface support | ### Arduino Client interface support | ||||||
| This library is easy to integrate with lots of sketches, which use Ethernet or WiFi.   | This library is easy to integrate with lots of sketches, which use Ethernet or WiFi.   | ||||||
| Examples for **PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **Web Client** and **File Download** are provided. | **PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **HTTP Client** and **File Download** examples are provided. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -30,7 +33,38 @@ Arduino GSM library uses 15868 bytes (49%) of Flash and 1113 bytes (54%) of RAM | |||||||
| TinyGSM also pulls data gently from the modem (whenever possible), so it can operate on very little RAM.   | TinyGSM also pulls data gently from the modem (whenever possible), so it can operate on very little RAM.   | ||||||
| **Now, you have more space for your experiments.** | **Now, you have more space for your experiments.** | ||||||
|  |  | ||||||
| ### Supported modem models | ## Features | ||||||
|  |  | ||||||
|  | Feature \ Modem              | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 | ||||||
|  | ---                          | ---    | ---    | ---       | ---  | --- | ||||||
|  | **Data connections** | ||||||
|  | TCP (HTTP, MQTT, Blynk, ...) | ✔      | ✔      | ✔         | ✔    | ✔ | ||||||
|  | UDP                          |        |        |           |      |  | ||||||
|  | SSL/TLS (HTTPS)              | ✔¹     | ✔¹     | 🅧        | 🅧   | ◌ | ||||||
|  | **USSD** | ||||||
|  | Sending USSD requests        | ✔      | ✔      | ✔         | ✔    |  | ||||||
|  | Decoding 7,8,16-bit response | ✔      | ✔      | ✔         | ✔    |  | ||||||
|  | **SMS** | ||||||
|  | Sending                      | ✔      | ✔      | ✔         | ✔    |  | ||||||
|  | Sending Unicode              | ✔      | ✔      | ◌         | 🅧   |  | ||||||
|  | Reading                      |        |        |           |      |  | ||||||
|  | Incoming message event       |        |        |           | ?    |  | ||||||
|  | **Calls** | ||||||
|  | Dial, hangup                 | ✔      | ✔      | ✔         | 🅧   |  | ||||||
|  | Receiving calls              | ✔      | ✔      | ✔         | 🅧   |  | ||||||
|  | Incoming event (RING)        | ◌      | ◌      | ◌         | 🅧   |  | ||||||
|  | DTMF sending                 | ◌      | ◌      | ◌         | 🅧   |  | ||||||
|  | DTMF decoding                | ◌      | ◌      | 🅧        | 🅧   |  | ||||||
|  | **Location** | ||||||
|  | GSM location service         | ✔      | ✔      | 🅧        | 🅧   |  | ||||||
|  | GPS/GNSS                     | 🅧     | ✔²     | ◌¹        | 🅧   |  | ||||||
|  |  | ||||||
|  | ✔ - implemented  ◌ - planned  🅧 - not available for this modem   | ||||||
|  | ¹ - only some device models or firmware revisions have this feature   | ||||||
|  | ² - current implementation only supports SIM808 V2 GPS | ||||||
|  |  | ||||||
|  | ## Supported modems | ||||||
|  |  | ||||||
| - [x] SIMCom SIM800 series (SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868) | - [x] SIMCom SIM800 series (SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868) | ||||||
| - [x] SIMCom SIM900 series (SIM900A, SIM900D, SIM908, SIM968) | - [x] SIMCom SIM900 series (SIM900A, SIM900D, SIM908, SIM968) | ||||||
| - [x] AI-Thinker A6, A6C, A7 | - [x] AI-Thinker A6, A6C, A7 | ||||||
| @@ -53,6 +87,19 @@ More modems may be supported later: | |||||||
|  |  | ||||||
| Watch this repo for new updates! And of course, contributions are welcome ;) | Watch this repo for new updates! And of course, contributions are welcome ;) | ||||||
|  |  | ||||||
|  | ## Donation | ||||||
|  |  | ||||||
|  | [](https://salt.bountysource.com/checkout/amount?team=tinygsm-dev) | ||||||
|  | [](http://tny.im/aen) | ||||||
|  |  | ||||||
|  | If you have found TinyGSM to be useful in your work, research or company, please consider making a donation to the project commensurate with your resources. Any amount helps!   | ||||||
|  | **All donations will be used strictly to fund the development of TinyGSM:** | ||||||
|  | - Covering cellular network expences | ||||||
|  | - Buying new hardware and modems for integration | ||||||
|  | - Bounty Budget (to reward other developers for their contributions) | ||||||
|  | - Implementing new features | ||||||
|  | - Quality Assurance | ||||||
|  |  | ||||||
| ## Getting Started | ## Getting Started | ||||||
|  |  | ||||||
|   1. Using your phone: |   1. Using your phone: | ||||||
| @@ -65,6 +112,16 @@ Watch this repo for new updates! And of course, contributions are welcome ;) | |||||||
|      Send an ```AT``` command using [this sketch](tools/AT_Debug/AT_Debug.ino) |      Send an ```AT``` command using [this sketch](tools/AT_Debug/AT_Debug.ino) | ||||||
|   5. Check if GSM antenna is attached |   5. Check if GSM antenna is attached | ||||||
|  |  | ||||||
|  | ## How does it work? | ||||||
|  |  | ||||||
|  | Many GSM modems, WiFi and radio modules can be controlled by sending AT commands over Serial.   | ||||||
|  | TinyGSM knows which commands to send, and how to handle AT responses, and wraps that into standard Arduino Client interface. | ||||||
|  |  | ||||||
|  | ## API Reference | ||||||
|  |  | ||||||
|  | For GPRS data streams, this library provides the standard [Arduino Client](https://www.arduino.cc/en/Reference/ClientConstructor) interface.   | ||||||
|  | For additional functions, please refer to [this example sketch](examples/AllFunctions/AllFunctions.ino) | ||||||
|  |  | ||||||
| ## Troubleshooting | ## Troubleshooting | ||||||
|  |  | ||||||
| ### SoftwareSerial problems | ### SoftwareSerial problems | ||||||
|   | |||||||
| @@ -11,14 +11,32 @@ | |||||||
|  |  | ||||||
| #if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900) | #if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900) | ||||||
|   #include <TinyGsmClientSIM800.h> |   #include <TinyGsmClientSIM800.h> | ||||||
|  |   typedef TinyGsmSim800 TinyGsm; | ||||||
|  |   typedef TinyGsmSim800::GsmClient TinyGsmClient; | ||||||
|  |   typedef TinyGsmSim800::GsmClientSecure TinyGsmClientSecure; | ||||||
|  |  | ||||||
|  | #elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) | ||||||
|  |   #include <TinyGsmClientSIM808.h> | ||||||
|  |   typedef TinyGsmSim808 TinyGsm; | ||||||
|  |   typedef TinyGsmSim808::GsmClient TinyGsmClient; | ||||||
|  |   typedef TinyGsmSim808::GsmClientSecure TinyGsmClientSecure; | ||||||
|  |  | ||||||
| #elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) | #elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) | ||||||
|   #include <TinyGsmClientA6.h> |   #include <TinyGsmClientA6.h> | ||||||
|  |   typedef TinyGsm::GsmClient TinyGsmClient; | ||||||
|  |  | ||||||
| #elif defined(TINY_GSM_MODEM_M590) | #elif defined(TINY_GSM_MODEM_M590) | ||||||
|   #include <TinyGsmClientM590.h> |   #include <TinyGsmClientM590.h> | ||||||
|  |   typedef TinyGsm::GsmClient TinyGsmClient; | ||||||
|  |  | ||||||
| #elif defined(TINY_GSM_MODEM_ESP8266) | #elif defined(TINY_GSM_MODEM_ESP8266) | ||||||
|   #include <TinyGsmClientESP8266.h> |   #include <TinyGsmClientESP8266.h> | ||||||
|  |   typedef TinyGsm::GsmClient TinyGsmClient; | ||||||
|  |  | ||||||
| #elif defined(TINY_GSM_MODEM_XBEE) | #elif defined(TINY_GSM_MODEM_XBEE) | ||||||
|   #include <TinyGsmClientXBee.h> |   #include <TinyGsmClientXBee.h> | ||||||
|  |   typedef TinyGsm::GsmClient TinyGsmClient; | ||||||
|  |  | ||||||
| #else | #else | ||||||
|   #error "Please define GSM modem model" |   #error "Please define GSM modem model" | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -15,6 +15,8 @@ | |||||||
|   #define TINY_GSM_RX_BUFFER 256 |   #define TINY_GSM_RX_BUFFER 256 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define TINY_GSM_MUX_COUNT 8 | ||||||
|  |  | ||||||
| #include <TinyGsmCommon.h> | #include <TinyGsmCommon.h> | ||||||
|  |  | ||||||
| #define GSM_NL "\r\n" | #define GSM_NL "\r\n" | ||||||
| @@ -40,11 +42,6 @@ enum RegStatus { | |||||||
| class TinyGsm | class TinyGsm | ||||||
| { | { | ||||||
|  |  | ||||||
| public: |  | ||||||
|   TinyGsm(Stream& stream) |  | ||||||
|     : stream(stream) |  | ||||||
|   {} |  | ||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
| class GsmClient : public Client | class GsmClient : public Client | ||||||
| @@ -111,7 +108,7 @@ public: | |||||||
|  |  | ||||||
|   virtual int available() { |   virtual int available() { | ||||||
|     TINY_GSM_YIELD(); |     TINY_GSM_YIELD(); | ||||||
|     if (!rx.size()) { |     if (!rx.size() && sock_connected) { | ||||||
|       at->maintain(); |       at->maintain(); | ||||||
|     } |     } | ||||||
|     return rx.size(); |     return rx.size(); | ||||||
| @@ -155,6 +152,13 @@ public: | |||||||
|     return sock_connected; |     return sock_connected; | ||||||
|   } |   } | ||||||
|   virtual operator bool() { return connected(); } |   virtual operator bool() { return connected(); } | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |    * Extended API | ||||||
|  |    */ | ||||||
|  |  | ||||||
|  |   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   TinyGsm*      at; |   TinyGsm*      at; | ||||||
|   uint8_t       mux; |   uint8_t       mux; | ||||||
| @@ -164,6 +168,12 @@ private: | |||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  |   TinyGsm(Stream& stream) | ||||||
|  |     : stream(stream) | ||||||
|  |   { | ||||||
|  |     memset(sockets, 0, sizeof(sockets)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Basic functions |    * Basic functions | ||||||
|    */ |    */ | ||||||
| @@ -211,6 +221,18 @@ public: | |||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   String getModemInfo() { | ||||||
|  |     sendAT(GF("I")); | ||||||
|  |     String res; | ||||||
|  |     if (waitResponse(1000L, res) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||||
|  |     res.replace(GSM_NL, " "); | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Power functions |    * Power functions | ||||||
|    */ |    */ | ||||||
| @@ -224,6 +246,11 @@ public: | |||||||
|     return init(); |     return init(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool poweroff() { | ||||||
|  |     sendAT(GF("+CPOF")); | ||||||
|  |     return waitResponse() == 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * SIM card functions |    * SIM card functions | ||||||
|    */ |    */ | ||||||
| @@ -235,7 +262,7 @@ public: | |||||||
|  |  | ||||||
|   String getSimCCID() { |   String getSimCCID() { | ||||||
|     sendAT(GF("+CCID")); |     sendAT(GF("+CCID")); | ||||||
|     if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { |     if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) { | ||||||
|       return ""; |       return ""; | ||||||
|     } |     } | ||||||
|     String res = streamReadUntil('\n'); |     String res = streamReadUntil('\n'); | ||||||
| @@ -303,7 +330,7 @@ public: | |||||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { |     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||||
|       return 99; |       return 99; | ||||||
|     } |     } | ||||||
|     int res = streamReadUntil(',').toInt(); |     int res = stream.readStringUntil(',').toInt(); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
| @@ -336,9 +363,17 @@ public: | |||||||
|   bool gprsConnect(const char* apn, const char* user, const char* pwd) { |   bool gprsConnect(const char* apn, const char* user, const char* pwd) { | ||||||
|     gprsDisconnect(); |     gprsDisconnect(); | ||||||
|  |  | ||||||
|  |     sendAT(GF("+CGATT=1")); | ||||||
|  |     if (waitResponse(60000L) != 1) | ||||||
|  |       return false; | ||||||
|  |  | ||||||
|  |     // TODO: wait AT+CGATT? | ||||||
|  |  | ||||||
|     sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); |     sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|  |  | ||||||
|  |     if (!user) user = ""; | ||||||
|  |     if (!pwd)  pwd = ""; | ||||||
|     sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); |     sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); | ||||||
|     if (waitResponse(60000L) != 1) { |     if (waitResponse(60000L) != 1) { | ||||||
|       return false; |       return false; | ||||||
| @@ -347,24 +382,11 @@ public: | |||||||
|     sendAT(GF("+CGACT=1,1")); |     sendAT(GF("+CGACT=1,1")); | ||||||
|     waitResponse(60000L); |     waitResponse(60000L); | ||||||
|  |  | ||||||
|     sendAT(GF("+CGATT=1")); |  | ||||||
|     if (waitResponse(60000L) != 1) |  | ||||||
|       return false; |  | ||||||
|  |  | ||||||
|     // TODO: wait AT+CGATT? |  | ||||||
|  |  | ||||||
|     sendAT(GF("+CIPMUX=1")); |     sendAT(GF("+CIPMUX=1")); | ||||||
|     if (waitResponse() != 1) { |     if (waitResponse() != 1) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /*sendAT(GF("+CIFSR")); |  | ||||||
|     String data; |  | ||||||
|     if (waitResponse(10000L, data) != 1) { |  | ||||||
|       data.replace(GSM_NL, ""); |  | ||||||
|       return false; |  | ||||||
|     }*/ |  | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -373,22 +395,58 @@ public: | |||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   String getLocalIP() { | ||||||
|  |     sendAT(GF("+CIFSR")); | ||||||
|  |     String res; | ||||||
|  |     if (waitResponse(10000L, res) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   IPAddress localIP() { | ||||||
|  |     IPAddress res; | ||||||
|  |     res.fromString(getLocalIP()); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Phone Call functions |    * Phone Call functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|  |  | ||||||
|   bool callAnswer() { |   bool callAnswer() { | ||||||
|     sendAT(GF("A")); |     sendAT(GF("A")); | ||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Returns true on pick-up, false on error/busy | ||||||
|   bool callNumber(const String& number) { |   bool callNumber(const String& number) { | ||||||
|     sendAT(GF("D"), number); |     sendAT(GF("D\""), number, "\";"); | ||||||
|     return waitResponse() == 1; |     if (waitResponse() != 1) { | ||||||
|  |       return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   bool callHangup(const String& number) { |     if (waitResponse(60000L, GF(GSM_NL "+CIEV: \"CALL\",1"), GF(GSM_NL "+CIEV: \"CALL\",0")) != 1) { | ||||||
|     sendAT(GF("H"), number); |       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 callRedial() { | ||||||
|  |   //  sendAT(GF("DLST")); | ||||||
|  |   //  return waitResponse() == 1; | ||||||
|  |   //} | ||||||
|  |  | ||||||
|  |   bool callHangup() { | ||||||
|  |     sendAT(GF("H")); | ||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -396,6 +454,32 @@ public: | |||||||
|    * Messaging functions |    * Messaging functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   String sendUSSD(const String& code) { | ||||||
|  |     sendAT(GF("+CMGF=1")); | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("+CSCS=\"HEX\"")); | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("+CUSD=1,\""), code, GF("\",15")); | ||||||
|  |     if (waitResponse(10000L) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CUSD:")) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     stream.readStringUntil('"'); | ||||||
|  |     String hex = stream.readStringUntil('"'); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     int dcs = stream.readStringUntil('\n').toInt(); | ||||||
|  |  | ||||||
|  |     if (dcs == 15) { | ||||||
|  |       return decodeHex7bit(hex); | ||||||
|  |     } else if (dcs == 72) { | ||||||
|  |       return decodeHex16bit(hex); | ||||||
|  |     } else { | ||||||
|  |       return hex; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool sendSMS(const String& number, const String& text) { |   bool sendSMS(const String& number, const String& text) { | ||||||
|     sendAT(GF("+CMGF=1")); |     sendAT(GF("+CMGF=1")); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
| @@ -405,24 +489,41 @@ public: | |||||||
|     } |     } | ||||||
|     stream.print(text); |     stream.print(text); | ||||||
|     stream.write((char)0x1A); |     stream.write((char)0x1A); | ||||||
|  |     stream.flush(); | ||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Location functions |    * Location functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Battery functions |    * Battery functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|  |  | ||||||
|  |   int getBattPercent() { | ||||||
|  |     sendAT(GF("+CBC?")); | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     int res = stream.readStringUntil('\n').toInt(); | ||||||
|  |     waitResponse(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   int modemConnect(const char* host, uint16_t port, uint8_t* mux) { |  | ||||||
|  |   bool modemConnect(const char* host, uint16_t port, uint8_t* mux) { | ||||||
|     sendAT(GF("+CIPSTART="),  GF("\"TCP"), GF("\",\""), host, GF("\","), port); |     sendAT(GF("+CIPSTART="),  GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||||
|  |  | ||||||
|     if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { |     if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { | ||||||
|       return -1; |       return false; | ||||||
|     } |     } | ||||||
|     int newMux = streamReadUntil('\n').toInt(); |     int newMux = streamReadUntil('\n').toInt(); | ||||||
|  |  | ||||||
| @@ -431,7 +532,7 @@ private: | |||||||
|                            GF("CONNECT FAIL" GSM_NL), |                            GF("CONNECT FAIL" GSM_NL), | ||||||
|                            GF("ALREADY CONNECT" GSM_NL)); |                            GF("ALREADY CONNECT" GSM_NL)); | ||||||
|     if (waitResponse() != 1) { |     if (waitResponse() != 1) { | ||||||
|       return -1; |       return false; | ||||||
|     } |     } | ||||||
|     *mux = newMux; |     *mux = newMux; | ||||||
|  |  | ||||||
| @@ -440,7 +541,7 @@ private: | |||||||
|  |  | ||||||
|   int modemSend(const void* buff, size_t len, uint8_t mux) { |   int modemSend(const void* buff, size_t len, uint8_t mux) { | ||||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); |     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||||
|     if (waitResponse(10000L, GF(GSM_NL ">")) != 1) { |     if (waitResponse(2000L, GF(GSM_NL ">")) != 1) { | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|     stream.write((uint8_t*)buff, len); |     stream.write((uint8_t*)buff, len); | ||||||
| @@ -451,14 +552,61 @@ private: | |||||||
|     return len; |     return len; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool modemGetConnected(uint8_t mux) { //TODO mux? |   bool modemGetConnected(uint8_t mux) { | ||||||
|     sendAT(GF("+CIPSTATUS")); |     sendAT(GF("+CIPSTATUS")); //TODO mux? | ||||||
|     int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); |     int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|     return 1 == res; |     return 1 == res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Private Utilities */ |   static String decodeHex7bit(String &instr) { | ||||||
|  |     String result; | ||||||
|  |     byte reminder = 0; | ||||||
|  |     int bitstate = 7; | ||||||
|  |     for (unsigned i=0; i<instr.length(); i+=2) { | ||||||
|  |       char buf[4] = { 0, }; | ||||||
|  |       buf[0] = instr[i]; | ||||||
|  |       buf[1] = instr[i+1]; | ||||||
|  |       byte b = strtol(buf, NULL, 16); | ||||||
|  |  | ||||||
|  |       byte bb = b << (7 - bitstate); | ||||||
|  |       char c = (bb + reminder) & 0x7F; | ||||||
|  |       result += c; | ||||||
|  |       reminder = b >> bitstate; | ||||||
|  |       bitstate--; | ||||||
|  |       if (bitstate == 0) { | ||||||
|  |         char c = reminder; | ||||||
|  |         result += c; | ||||||
|  |         reminder = 0; | ||||||
|  |         bitstate = 7; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static String decodeHex16bit(String &instr) { | ||||||
|  |     String result; | ||||||
|  |     for (unsigned i=0; i<instr.length(); i+=4) { | ||||||
|  |       char buf[4] = { 0, }; | ||||||
|  |       buf[0] = instr[i]; | ||||||
|  |       buf[1] = instr[i+1]; | ||||||
|  |       char b = strtol(buf, NULL, 16); | ||||||
|  |       if (b) { // If high byte is non-zero, we can't handle it ;( | ||||||
|  |         b = '?'; | ||||||
|  |       } else { | ||||||
|  |         buf[0] = instr[i+2]; | ||||||
|  |         buf[1] = instr[i+3]; | ||||||
|  |         b = strtol(buf, NULL, 16); | ||||||
|  |       } | ||||||
|  |       result += b; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  |   /* Utilities */ | ||||||
|  |  | ||||||
|   template<typename T> |   template<typename T> | ||||||
|   void streamWrite(T last) { |   void streamWrite(T last) { | ||||||
|     stream.print(last); |     stream.print(last); | ||||||
| @@ -470,17 +618,6 @@ private: | |||||||
|     streamWrite(tail...); |     streamWrite(tail...); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int streamRead() { return stream.read(); } |  | ||||||
|  |  | ||||||
|   String streamReadUntil(char c) { |  | ||||||
|     String return_string = stream.readStringUntil(c); |  | ||||||
|     return_string.trim(); |  | ||||||
|     if (String(c) == GSM_NL || String(c) == "\n"){ |  | ||||||
|       DBG(return_string, c, "    "); |  | ||||||
|     } else DBG(return_string, c); |  | ||||||
|     return return_string; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool streamSkipUntil(char c) { |   bool streamSkipUntil(char c) { | ||||||
|     String skipped = stream.readStringUntil(c); |     String skipped = stream.readStringUntil(c); | ||||||
|     skipped.trim(); |     skipped.trim(); | ||||||
| @@ -520,7 +657,7 @@ private: | |||||||
|     do { |     do { | ||||||
|       TINY_GSM_YIELD(); |       TINY_GSM_YIELD(); | ||||||
|       while (stream.available() > 0) { |       while (stream.available() > 0) { | ||||||
|         int a = streamRead(); |         int a = stream.read(); | ||||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case |         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||||
|         data += (char)a; |         data += (char)a; | ||||||
|         if (r1 && data.endsWith(r1)) { |         if (r1 && data.endsWith(r1)) { | ||||||
| @@ -539,24 +676,25 @@ private: | |||||||
|           index = 5; |           index = 5; | ||||||
|           goto finish; |           goto finish; | ||||||
|         } else if (data.endsWith(GF("+CIPRCV:"))) { |         } else if (data.endsWith(GF("+CIPRCV:"))) { | ||||||
|           mux = stream.readStringUntil(',').toInt(); |           int mux = stream.readStringUntil(',').toInt(); | ||||||
|           data += mux; |           int len = stream.readStringUntil(',').toInt(); | ||||||
|           data += (','); |           if (len > sockets[mux]->rx.free()) { | ||||||
|           len = stream.readStringUntil(',').toInt(); |             DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); | ||||||
|           data += len; |           } else { | ||||||
|           data += (','); |             DBG("### Got: ", len, "->", sockets[mux]->rx.free()); | ||||||
|           gotData = true; |           } | ||||||
|           index = 6; |           while (len--) { | ||||||
|           goto finish; |             while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|  |             sockets[mux]->rx.put(stream.read()); | ||||||
|  |           } | ||||||
|  |           data = ""; | ||||||
|         } else if (data.endsWith(GF("+TCPCLOSED:"))) { |         } else if (data.endsWith(GF("+TCPCLOSED:"))) { | ||||||
|           mux = stream.readStringUntil(',').toInt(); |           int mux = stream.readStringUntil('\n').toInt(); | ||||||
|           data += mux; |           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||||
|           data += (','); |  | ||||||
|           String concl = stream.readStringUntil('\n'); |  | ||||||
|           data += concl; |  | ||||||
|             sockets[mux]->sock_connected = false; |             sockets[mux]->sock_connected = false; | ||||||
|           index = 7; |           } | ||||||
|           goto finish; |           data = ""; | ||||||
|  |           DBG("### Closed: ", mux); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } while (millis() - startMillis < timeout); |     } while (millis() - startMillis < timeout); | ||||||
| @@ -611,9 +749,7 @@ private: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|   Stream&       stream; |   Stream&       stream; | ||||||
|   GsmClient*    sockets[8]; |   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef TinyGsm::GsmClient TinyGsmClient; |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| /** | /** | ||||||
|  * @file       TinyWiFiClientESP8266.h |  * @file       TinyGsmClientESP8266.h | ||||||
|  * @author     Volodymyr Shymanskyy |  * @author     Volodymyr Shymanskyy | ||||||
|  * @license    LGPL-3.0 |  * @license    LGPL-3.0 | ||||||
|  * @copyright  Copyright (c) 2016 Volodymyr Shymanskyy |  * @copyright  Copyright (c) 2016 Volodymyr Shymanskyy | ||||||
|  * @date       Nov 2016 |  * @date       Nov 2016 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef TinyWiFiClientESP8266_h | #ifndef TinyGsmClientESP8266_h | ||||||
| #define TinyWiFiClientESP8266_h | #define TinyGsmClientESP8266_h | ||||||
|  |  | ||||||
| //#define TINY_GSM_DEBUG Serial | //#define TINY_GSM_DEBUG Serial | ||||||
|  |  | ||||||
| @@ -15,21 +15,18 @@ | |||||||
|   #define TINY_GSM_RX_BUFFER 256 |   #define TINY_GSM_RX_BUFFER 256 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define TINY_GSM_MUX_COUNT 5 | ||||||
|  |  | ||||||
| #include <TinyGsmCommon.h> | #include <TinyGsmCommon.h> | ||||||
|  |  | ||||||
| #define GSM_NL "\r\n" | #define GSM_NL "\r\n" | ||||||
| static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; | static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; | ||||||
| static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; | static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; | ||||||
| static unsigned int TCP_KEEP_ALIVE = 120; | static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; | ||||||
|  |  | ||||||
| class TinyGsm | class TinyGsm | ||||||
| { | { | ||||||
|  |  | ||||||
| public: |  | ||||||
|   TinyGsm(Stream& stream) |  | ||||||
|     : stream(stream) |  | ||||||
|   {} |  | ||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
| class GsmClient : public Client | class GsmClient : public Client | ||||||
| @@ -94,7 +91,7 @@ public: | |||||||
|  |  | ||||||
|   virtual int available() { |   virtual int available() { | ||||||
|     TINY_GSM_YIELD(); |     TINY_GSM_YIELD(); | ||||||
|     if (!rx.size()) { |     if (!rx.size() && sock_connected) { | ||||||
|       at->maintain(); |       at->maintain(); | ||||||
|     } |     } | ||||||
|     return rx.size(); |     return rx.size(); | ||||||
| @@ -138,6 +135,13 @@ public: | |||||||
|     return sock_connected; |     return sock_connected; | ||||||
|   } |   } | ||||||
|   virtual operator bool() { return connected(); } |   virtual operator bool() { return connected(); } | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |    * Extended API | ||||||
|  |    */ | ||||||
|  |  | ||||||
|  |   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   TinyGsm*      at; |   TinyGsm*      at; | ||||||
|   uint8_t       mux; |   uint8_t       mux; | ||||||
| @@ -147,6 +151,12 @@ private: | |||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  |   TinyGsm(Stream& stream) | ||||||
|  |     : stream(stream) | ||||||
|  |   { | ||||||
|  |     memset(sockets, 0, sizeof(sockets)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Basic functions |    * Basic functions | ||||||
|    */ |    */ | ||||||
| @@ -273,20 +283,21 @@ public: | |||||||
|     return waitResponse(10000L) == 1; |     return waitResponse(10000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|  |  | ||||||
|  |   IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * GPRS functions |    * GPRS functions | ||||||
|    */ |    */ | ||||||
|   bool gprsConnect(const char* apn, const char* user, const char* pwd) { |   bool gprsConnect(const char* apn, const char* user, const char* pwd) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|     return false; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool gprsDisconnect() { |   bool gprsDisconnect() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|     return false; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |  | ||||||
|   int modemConnect(const char* host, uint16_t port, uint8_t mux) { |   int modemConnect(const char* host, uint16_t port, uint8_t mux) { | ||||||
|     sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TCP_KEEP_ALIVE); |     sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE); | ||||||
|     int rsp = waitResponse(75000L, |     int rsp = waitResponse(75000L, | ||||||
|                            GFP(GSM_OK), |                            GFP(GSM_OK), | ||||||
|                            GFP(GSM_ERROR), |                            GFP(GSM_ERROR), | ||||||
| @@ -301,6 +312,7 @@ private: | |||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|     stream.write((uint8_t*)buff, len); |     stream.write((uint8_t*)buff, len); | ||||||
|  |     stream.flush(); | ||||||
|     if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) { |     if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) { | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
| @@ -314,7 +326,10 @@ private: | |||||||
|     return 1 == res; |     return 1 == res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Private Utilities */ | public: | ||||||
|  |  | ||||||
|  |   /* Utilities */ | ||||||
|  |  | ||||||
|   template<typename T> |   template<typename T> | ||||||
|   void streamWrite(T last) { |   void streamWrite(T last) { | ||||||
|     stream.print(last); |     stream.print(last); | ||||||
| @@ -326,7 +341,14 @@ private: | |||||||
|     streamWrite(tail...); |     streamWrite(tail...); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int streamRead() { return stream.read(); } |   bool streamSkipUntil(char c) { //TODO: timeout | ||||||
|  |     while (true) { | ||||||
|  |       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|  |       if (stream.read() == c) | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   String streamReadUntil(char c) { |   String streamReadUntil(char c) { | ||||||
|     String return_string = stream.readStringUntil(c); |     String return_string = stream.readStringUntil(c); | ||||||
| @@ -376,7 +398,7 @@ private: | |||||||
|     do { |     do { | ||||||
|       TINY_GSM_YIELD(); |       TINY_GSM_YIELD(); | ||||||
|       while (stream.available() > 0) { |       while (stream.available() > 0) { | ||||||
|         int a = streamRead(); |         int a = stream.read(); | ||||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case |         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||||
|         data += (char)a; |         data += (char)a; | ||||||
|         if (r1 && data.endsWith(r1)) { |         if (r1 && data.endsWith(r1)) { | ||||||
| @@ -395,16 +417,20 @@ private: | |||||||
|           index = 5; |           index = 5; | ||||||
|           goto finish; |           goto finish; | ||||||
|         } else if (data.endsWith(GF(GSM_NL "+IPD,"))) { |         } else if (data.endsWith(GF(GSM_NL "+IPD,"))) { | ||||||
|           mux = stream.readStringUntil(',').toInt(); |           int mux = stream.readStringUntil(',').toInt(); | ||||||
|           data += mux; |           int len = stream.readStringUntil(':').toInt(); | ||||||
|           data += (','); |           if (len > sockets[mux]->rx.free()) { | ||||||
|           len = stream.readStringUntil(':').toInt(); |             DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); | ||||||
|           data += len; |           } else { | ||||||
|           data += (':'); |             DBG("### Got: ", len, "->", sockets[mux]->rx.free()); | ||||||
|           gotData = true; |           } | ||||||
|           index = 6; |           while (len--) { | ||||||
|           goto finish; |             while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|         } else if (data.endsWith(GF("1,CLOSED" GSM_NL))) { //TODO: use mux |             sockets[mux]->rx.put(stream.read()); | ||||||
|  |           } | ||||||
|  |           data = ""; | ||||||
|  |           return index; | ||||||
|  |         } else if (data.endsWith(GF(GSM_NL "1,CLOSED" GSM_NL))) { //TODO: use mux | ||||||
|           sockets[1]->sock_connected = false; |           sockets[1]->sock_connected = false; | ||||||
|           index = 7; |           index = 7; | ||||||
|           goto finish; |           goto finish; | ||||||
| @@ -462,9 +488,7 @@ private: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|   Stream&       stream; |   Stream&       stream; | ||||||
|   GsmClient*    sockets[5]; |   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef TinyGsm::GsmClient TinyGsmClient; |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -15,6 +15,8 @@ | |||||||
|   #define TINY_GSM_RX_BUFFER 256 |   #define TINY_GSM_RX_BUFFER 256 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define TINY_GSM_MUX_COUNT 2 | ||||||
|  |  | ||||||
| #include <TinyGsmCommon.h> | #include <TinyGsmCommon.h> | ||||||
|  |  | ||||||
| #define GSM_NL "\r\n" | #define GSM_NL "\r\n" | ||||||
| @@ -40,11 +42,6 @@ enum RegStatus { | |||||||
| class TinyGsm | class TinyGsm | ||||||
| { | { | ||||||
|  |  | ||||||
| public: |  | ||||||
|   TinyGsm(Stream& stream) |  | ||||||
|     : stream(stream) |  | ||||||
|   {} |  | ||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
| class GsmClient : public Client | class GsmClient : public Client | ||||||
| @@ -108,7 +105,7 @@ public: | |||||||
|  |  | ||||||
|   virtual int available() { |   virtual int available() { | ||||||
|     TINY_GSM_YIELD(); |     TINY_GSM_YIELD(); | ||||||
|     if (!rx.size()) { |     if (!rx.size() && sock_connected) { | ||||||
|       at->maintain(); |       at->maintain(); | ||||||
|     } |     } | ||||||
|     return rx.size(); |     return rx.size(); | ||||||
| @@ -152,6 +149,13 @@ public: | |||||||
|     return sock_connected; |     return sock_connected; | ||||||
|   } |   } | ||||||
|   virtual operator bool() { return connected(); } |   virtual operator bool() { return connected(); } | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |    * Extended API | ||||||
|  |    */ | ||||||
|  |  | ||||||
|  |   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   TinyGsm*      at; |   TinyGsm*      at; | ||||||
|   uint8_t       mux; |   uint8_t       mux; | ||||||
| @@ -161,6 +165,12 @@ private: | |||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  |   TinyGsm(Stream& stream) | ||||||
|  |     : stream(stream) | ||||||
|  |   { | ||||||
|  |     memset(sockets, 0, sizeof(sockets)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Basic functions |    * Basic functions | ||||||
|    */ |    */ | ||||||
| @@ -216,6 +226,18 @@ public: | |||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   String getModemInfo() { | ||||||
|  |     sendAT(GF("I")); | ||||||
|  |     String res; | ||||||
|  |     if (waitResponse(1000L, res) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||||
|  |     res.replace(GSM_NL, " "); | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Power functions |    * Power functions | ||||||
|    */ |    */ | ||||||
| @@ -233,6 +255,11 @@ public: | |||||||
|     return init(); |     return init(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool poweroff() { | ||||||
|  |     sendAT(GF("+CPWROFF")); | ||||||
|  |     return waitResponse(3000L) == 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * SIM card functions |    * SIM card functions | ||||||
|    */ |    */ | ||||||
| @@ -312,7 +339,7 @@ public: | |||||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { |     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||||
|       return 99; |       return 99; | ||||||
|     } |     } | ||||||
|     int res = streamReadUntil(',').toInt(); |     int res = stream.readStringUntil(',').toInt(); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
| @@ -364,13 +391,15 @@ public: | |||||||
|     sendAT(GF("+XIIC?")); |     sendAT(GF("+XIIC?")); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|  |  | ||||||
|     /*sendAT(GF("+DNSSERVER=1,8.8.8.8")); |     /* | ||||||
|  |     sendAT(GF("+DNSSERVER=1,8.8.8.8")); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|  |  | ||||||
|     sendAT(GF("+DNSSERVER=2,8.8.4.4")); |     sendAT(GF("+DNSSERVER=2,8.8.4.4")); | ||||||
|     if (waitResponse() != 1) { |     if (waitResponse() != 1) { | ||||||
|       return false; |       return false; | ||||||
|     }*/ |     } | ||||||
|  |     */ | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| @@ -380,30 +409,72 @@ public: | |||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 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() { | ||||||
|  |     IPAddress res; | ||||||
|  |     res.fromString(getLocalIP()); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Phone Call functions |    * Phone Call functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|   bool callAnswer() { |   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|     sendAT(GF("A")); |  | ||||||
|     return waitResponse() == 1; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool callNumber(const String& number) { |   bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|     sendAT(GF("D"), number); |  | ||||||
|     return waitResponse() == 1; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool callHangup(const String& number) { |   bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|     sendAT(GF("H"), number); |  | ||||||
|     return waitResponse() == 1; |   bool callRedial() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|   } |  | ||||||
|  |   bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Messaging functions |    * Messaging functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   String sendUSSD(const String& code) { | ||||||
|  |     sendAT(GF("+CMGF=1")); | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("+CSCS=\"HEX\"")); | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("D"), code); | ||||||
|  |     if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     stream.readStringUntil('"'); | ||||||
|  |     String hex = stream.readStringUntil('"'); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     int dcs = stream.readStringUntil('\n').toInt(); | ||||||
|  |  | ||||||
|  |     if (waitResponse() != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (dcs == 15) { | ||||||
|  |       return decodeHex8bit(hex); | ||||||
|  |     } else if (dcs == 72) { | ||||||
|  |       return decodeHex16bit(hex); | ||||||
|  |     } else { | ||||||
|  |       return hex; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool sendSMS(const String& number, const String& text) { |   bool sendSMS(const String& number, const String& text) { | ||||||
|  |     sendAT(GF("+CSCS=\"GSM\"")); | ||||||
|  |     waitResponse(); | ||||||
|     sendAT(GF("+CMGF=1")); |     sendAT(GF("+CMGF=1")); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|     sendAT(GF("+CMGS=\""), number, GF("\"")); |     sendAT(GF("+CMGS=\""), number, GF("\"")); | ||||||
| @@ -412,31 +483,31 @@ public: | |||||||
|     } |     } | ||||||
|     stream.print(text); |     stream.print(text); | ||||||
|     stream.write((char)0x1A); |     stream.write((char)0x1A); | ||||||
|  |     stream.flush(); | ||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool sendSMS_UTF16(const String& number, const void* text, size_t len) | ||||||
|  |   TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Location functions |    * Location functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Battery functions |    * Battery functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
| private: |   uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|   String dnsIpQuery(const char* host) { |  | ||||||
|    sendAT(GF("+DNS=\""), host, GF("\"")); |  | ||||||
|    if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) { |  | ||||||
|      return ""; |  | ||||||
|    } |  | ||||||
|    String res = streamReadUntil('\n'); |  | ||||||
|    waitResponse(GF("+DNS:OK" GSM_NL)); |  | ||||||
|    res.trim(); |  | ||||||
|    return res; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   int modemConnect(const char* host, uint16_t port, uint8_t mux) { |   int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||||
|     for (int i=0; i<3; i++) { |  | ||||||
|  | private: | ||||||
|  |  | ||||||
|  |   bool modemConnect(const char* host, uint16_t port, uint8_t mux) { | ||||||
|  |     for (int i=0; i<3; i++) { // TODO: no need for loop? | ||||||
|       String ip = dnsIpQuery(host); |       String ip = dnsIpQuery(host); | ||||||
|  |  | ||||||
|       sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); |       sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); | ||||||
| @@ -462,7 +533,7 @@ private: | |||||||
|     } |     } | ||||||
|     stream.write((uint8_t*)buff, len); |     stream.write((uint8_t*)buff, len); | ||||||
|     stream.write((char)0x0D); |     stream.write((char)0x0D); | ||||||
|  |     stream.flush(); | ||||||
|     if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { |     if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
| @@ -477,7 +548,52 @@ private: | |||||||
|     return 1 == res; |     return 1 == res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Private Utilities */ |   String dnsIpQuery(const char* host) { | ||||||
|  |     sendAT(GF("+DNS=\""), host, GF("\"")); | ||||||
|  |     if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     String res = stream.readStringUntil('\n'); | ||||||
|  |     waitResponse(GF("+DNS:OK" GSM_NL)); | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static String decodeHex8bit(String &instr) { | ||||||
|  |     String result; | ||||||
|  |     for (unsigned i=0; i<instr.length(); i+=2) { | ||||||
|  |       char buf[4] = { 0, }; | ||||||
|  |       buf[0] = instr[i]; | ||||||
|  |       buf[1] = instr[i+1]; | ||||||
|  |       char b = strtol(buf, NULL, 16); | ||||||
|  |       result += b; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static String decodeHex16bit(String &instr) { | ||||||
|  |     String result; | ||||||
|  |     for (unsigned i=0; i<instr.length(); i+=4) { | ||||||
|  |       char buf[4] = { 0, }; | ||||||
|  |       buf[0] = instr[i]; | ||||||
|  |       buf[1] = instr[i+1]; | ||||||
|  |       char b = strtol(buf, NULL, 16); | ||||||
|  |       if (b) { // If high byte is non-zero, we can't handle it ;( | ||||||
|  |         b = '?'; | ||||||
|  |       } else { | ||||||
|  |         buf[0] = instr[i+2]; | ||||||
|  |         buf[1] = instr[i+3]; | ||||||
|  |         b = strtol(buf, NULL, 16); | ||||||
|  |       } | ||||||
|  |       result += b; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  |   /* Utilities */ | ||||||
|  |  | ||||||
|   template<typename T> |   template<typename T> | ||||||
|   void streamWrite(T last) { |   void streamWrite(T last) { | ||||||
|     stream.print(last); |     stream.print(last); | ||||||
| @@ -489,26 +605,13 @@ private: | |||||||
|     streamWrite(tail...); |     streamWrite(tail...); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int streamRead() { return stream.read(); } |   bool streamSkipUntil(char c) { //TODO: timeout | ||||||
|  |     while (true) { | ||||||
|   String streamReadUntil(char c) { |       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|     String return_string = stream.readStringUntil(c); |       if (stream.read() == c) | ||||||
|     return_string.trim(); |  | ||||||
|     if (String(c) == GSM_NL || String(c) == "\n"){ |  | ||||||
|       DBG(return_string, c, "    "); |  | ||||||
|     } else DBG(return_string, c); |  | ||||||
|     return return_string; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool streamSkipUntil(char c) { |  | ||||||
|     String skipped = stream.readStringUntil(c); |  | ||||||
|     skipped.trim(); |  | ||||||
|     if (skipped.length()) { |  | ||||||
|       if (String(c) == GSM_NL || String(c) == "\n"){ |  | ||||||
|         DBG(skipped, c, "    "); |  | ||||||
|       } else DBG(skipped, c); |  | ||||||
|         return true; |         return true; | ||||||
|     } else return false; |     } | ||||||
|  |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template<typename... Args> |   template<typename... Args> | ||||||
| @@ -539,7 +642,7 @@ private: | |||||||
|     do { |     do { | ||||||
|       TINY_GSM_YIELD(); |       TINY_GSM_YIELD(); | ||||||
|       while (stream.available() > 0) { |       while (stream.available() > 0) { | ||||||
|         int a = streamRead(); |         int a = stream.read(); | ||||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case |         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||||
|         data += (char)a; |         data += (char)a; | ||||||
|         if (r1 && data.endsWith(r1)) { |         if (r1 && data.endsWith(r1)) { | ||||||
| @@ -558,24 +661,26 @@ private: | |||||||
|           index = 5; |           index = 5; | ||||||
|           goto finish; |           goto finish; | ||||||
|         } else if (data.endsWith(GF("+TCPRECV:"))) { |         } else if (data.endsWith(GF("+TCPRECV:"))) { | ||||||
|           mux = stream.readStringUntil(',').toInt(); |           int mux = stream.readStringUntil(',').toInt(); | ||||||
|           data += mux; |           int len = stream.readStringUntil(',').toInt(); | ||||||
|           data += (','); |           if (len > sockets[mux]->rx.free()) { | ||||||
|           len = stream.readStringUntil(',').toInt(); |             DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); | ||||||
|           data += len; |           } else { | ||||||
|           data += (','); |             DBG("### Got: ", len, "->", sockets[mux]->rx.free()); | ||||||
|           gotData = true; |           } | ||||||
|           index = 6; |           while (len--) { | ||||||
|           goto finish; |             while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|  |             sockets[mux]->rx.put(stream.read()); | ||||||
|  |           } | ||||||
|  |           data = ""; | ||||||
|         } else if (data.endsWith(GF("+TCPCLOSE:"))) { |         } else if (data.endsWith(GF("+TCPCLOSE:"))) { | ||||||
|           mux = stream.readStringUntil(',').toInt(); |           int mux = stream.readStringUntil(',').toInt(); | ||||||
|           data += mux; |           stream.readStringUntil('\n'); | ||||||
|           data += (','); |           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||||
|           String concl = stream.readStringUntil('\n'); |  | ||||||
|           data += concl; |  | ||||||
|             sockets[mux]->sock_connected = false; |             sockets[mux]->sock_connected = false; | ||||||
|           index = 7; |           } | ||||||
|           goto finish; |           data = ""; | ||||||
|  |           DBG("### Closed: ", mux); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } while (millis() - startMillis < timeout); |     } while (millis() - startMillis < timeout); | ||||||
| @@ -630,9 +735,7 @@ private: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|   Stream&       stream; |   Stream&       stream; | ||||||
|   GsmClient*    sockets[2]; |   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef TinyGsm::GsmClient TinyGsmClient; |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -16,6 +16,8 @@ | |||||||
|   #define TINY_GSM_RX_BUFFER 64 |   #define TINY_GSM_RX_BUFFER 64 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define TINY_GSM_MUX_COUNT 5 | ||||||
|  |  | ||||||
| #include <TinyGsmCommon.h> | #include <TinyGsmCommon.h> | ||||||
|  |  | ||||||
| #define GSM_NL "\r\n" | #define GSM_NL "\r\n" | ||||||
| @@ -38,33 +40,30 @@ enum RegStatus { | |||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| class TinyGsm | class TinyGsmSim800 | ||||||
| { | { | ||||||
|  |  | ||||||
| public: |  | ||||||
|   TinyGsm(Stream& stream) |  | ||||||
|     : stream(stream) |  | ||||||
|   {} |  | ||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
| class GsmClient : public Client | class GsmClient : public Client | ||||||
| { | { | ||||||
|   friend class TinyGsm; |   friend class TinyGsmSim800; | ||||||
|   typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo; |   typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo; | ||||||
|  |  | ||||||
| public: | public: | ||||||
|   GsmClient() {} |   GsmClient() {} | ||||||
|  |  | ||||||
|   GsmClient(TinyGsm& modem, uint8_t mux = 1) { |   GsmClient(TinyGsmSim800& modem, uint8_t mux = 1) { | ||||||
|     init(&modem, mux); |     init(&modem, mux); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool init(TinyGsm* modem, uint8_t mux = 1) { |   bool init(TinyGsmSim800* modem, uint8_t mux = 1) { | ||||||
|     this->at = modem; |     this->at = modem; | ||||||
|     this->mux = mux; |     this->mux = mux; | ||||||
|     sock_available = 0; |     sock_available = 0; | ||||||
|  |     prev_check = 0; | ||||||
|     sock_connected = false; |     sock_connected = false; | ||||||
|  |     got_data = false; | ||||||
|  |  | ||||||
|     at->sockets[mux] = this; |     at->sockets[mux] = this; | ||||||
|  |  | ||||||
| @@ -110,7 +109,14 @@ public: | |||||||
|  |  | ||||||
|   virtual int available() { |   virtual int available() { | ||||||
|     TINY_GSM_YIELD(); |     TINY_GSM_YIELD(); | ||||||
|     if (!rx.size()) { |     if (!rx.size() && sock_connected) { | ||||||
|  |       // Workaround: sometimes SIM800 forgets to notify about data arrival. | ||||||
|  |       // TODO: Currently we ping the module periodically, | ||||||
|  |       // but maybe there's a better indicator that we need to poll | ||||||
|  |       if (millis() - prev_check > 500) { | ||||||
|  |         got_data = true; | ||||||
|  |         prev_check = millis(); | ||||||
|  |       } | ||||||
|       at->maintain(); |       at->maintain(); | ||||||
|     } |     } | ||||||
|     return rx.size() + sock_available; |     return rx.size() + sock_available; | ||||||
| @@ -157,15 +163,48 @@ public: | |||||||
|     return sock_connected; |     return sock_connected; | ||||||
|   } |   } | ||||||
|   virtual operator bool() { return connected(); } |   virtual operator bool() { return connected(); } | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |    * Extended API | ||||||
|  |    */ | ||||||
|  |  | ||||||
|  |   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   TinyGsm*      at; |   TinyGsmSim800*      at; | ||||||
|   uint8_t       mux; |   uint8_t       mux; | ||||||
|   uint16_t      sock_available; |   uint16_t      sock_available; | ||||||
|  |   uint32_t      prev_check; | ||||||
|   bool          sock_connected; |   bool          sock_connected; | ||||||
|  |   bool          got_data; | ||||||
|   RxFifo        rx; |   RxFifo        rx; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class GsmClientSecure : public GsmClient | ||||||
|  | { | ||||||
| public: | public: | ||||||
|  |   GsmClientSecure() {} | ||||||
|  |  | ||||||
|  |   GsmClientSecure(TinyGsmSim800& modem, uint8_t mux = 1) | ||||||
|  |     : GsmClient(modem, mux) | ||||||
|  |   {} | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |   virtual int connect(const char *host, uint16_t port) { | ||||||
|  |     TINY_GSM_YIELD(); | ||||||
|  |     rx.clear(); | ||||||
|  |     sock_connected = at->modemConnect(host, port, mux, true); | ||||||
|  |     return sock_connected; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  |   TinyGsmSim800(Stream& stream) | ||||||
|  |     : stream(stream) | ||||||
|  |   { | ||||||
|  |     memset(sockets, 0, sizeof(sockets)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Basic functions |    * Basic functions | ||||||
| @@ -178,7 +217,9 @@ public: | |||||||
|     if (!autoBaud()) { |     if (!autoBaud()) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|     sendAT(GF("&FZE0"));  // Factory + Reset + Echo Off |     sendAT(GF("&FZ"));  // Factory + Reset | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("E0"));   // Echo Off | ||||||
|     if (waitResponse() != 1) { |     if (waitResponse() != 1) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
| @@ -187,7 +228,7 @@ public: | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool autoBaud(unsigned long timeout = 10000L) { |   bool autoBaud(unsigned long timeout = 10000L) { | ||||||
|     streamWrite(GF("AAAAAAAAAAAAA"));  // extra A's to help detect the baud rate |     //streamWrite(GF("AAAAA" GSM_NL));  // TODO: extra A's to help detect the baud rate | ||||||
|     for (unsigned long start = millis(); millis() - start < timeout; ) { |     for (unsigned long start = millis(); millis() - start < timeout; ) { | ||||||
|       sendAT(GF("")); |       sendAT(GF("")); | ||||||
|       if (waitResponse(200) == 1) { |       if (waitResponse(200) == 1) { | ||||||
| @@ -200,6 +241,13 @@ public: | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void maintain() { |   void maintain() { | ||||||
|  |     for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { | ||||||
|  |       GsmClient* sock = sockets[mux]; | ||||||
|  |       if (sock && sock->got_data) { | ||||||
|  |         sock->got_data = false; | ||||||
|  |         sock->sock_available = modemGetAvailable(mux); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     while (stream.available()) { |     while (stream.available()) { | ||||||
|       waitResponse(10, NULL, NULL); |       waitResponse(10, NULL, NULL); | ||||||
|     } |     } | ||||||
| @@ -220,6 +268,26 @@ public: | |||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   String getModemInfo() { | ||||||
|  |     sendAT(GF("I")); | ||||||
|  |     String res; | ||||||
|  |     if (waitResponse(1000L, res) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     res.replace(GSM_NL "OK" GSM_NL, ""); | ||||||
|  |     res.replace(GSM_NL, " "); | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool hasSSL() { | ||||||
|  |     sendAT(GF("+CIPSSL=?")); | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CIPSSL:")) != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     return waitResponse() == 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Power functions |    * Power functions | ||||||
|    */ |    */ | ||||||
| @@ -240,6 +308,23 @@ public: | |||||||
|     return init(); |     return init(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool poweroff() { | ||||||
|  |     sendAT(GF("+CPOWD=1")); | ||||||
|  |     return waitResponse(GF("NORMAL POWER DOWN")) == 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool radioOff() { | ||||||
|  |     if (!autoBaud()) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     sendAT(GF("+CFUN=0")); | ||||||
|  |     if (waitResponse(10000L) != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     delay(3000); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * SIM card functions |    * SIM card functions | ||||||
|    */ |    */ | ||||||
| @@ -319,7 +404,7 @@ public: | |||||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { |     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||||
|       return 99; |       return 99; | ||||||
|     } |     } | ||||||
|     int res = streamReadUntil(',').toInt(); |     int res = stream.readStringUntil(',').toInt(); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
| @@ -413,9 +498,7 @@ public: | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     sendAT(GF("+CIFSR;E0")); |     sendAT(GF("+CIFSR;E0")); | ||||||
|     String data; |     if (waitResponse(10000L) != 1) { | ||||||
|     if (waitResponse(10000L, data) != 1) { |  | ||||||
|       data.replace(GSM_NL, ""); |  | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -432,6 +515,22 @@ public: | |||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   String getLocalIP() { | ||||||
|  |     sendAT(GF("+CIFSR;E0")); | ||||||
|  |     String res; | ||||||
|  |     if (waitResponse(10000L, res) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   IPAddress localIP() { | ||||||
|  |     IPAddress res; | ||||||
|  |     res.fromString(getLocalIP()); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Phone Call functions |    * Phone Call functions | ||||||
|    */ |    */ | ||||||
| @@ -446,13 +545,25 @@ public: | |||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Returns true on pick-up, false on error/busy | ||||||
|   bool callNumber(const String& number) { |   bool callNumber(const String& number) { | ||||||
|     sendAT(GF("D"), number); |     sendAT(GF("D"), number, ";"); | ||||||
|     return waitResponse() == 1; |     int status = waitResponse(60000L, GF("OK"), GF("BUSY"), GF("NO ANSWER"), GF("NO CARRIER")); | ||||||
|  |     switch (status) { | ||||||
|  |     case 1:  return true; | ||||||
|  |     case 2: | ||||||
|  |     case 3:  return false; | ||||||
|  |     default: return false; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool callHangup(const String& number) { |   //bool callRedial() { | ||||||
|     sendAT(GF("H"), number); |   //  sendAT(GF("DL")); | ||||||
|  |   //  return waitResponse() == 1; | ||||||
|  |   //} | ||||||
|  |  | ||||||
|  |   bool callHangup() { | ||||||
|  |     sendAT(GF("H")); | ||||||
|     return waitResponse() == 1; |     return waitResponse() == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -460,6 +571,32 @@ public: | |||||||
|    * Messaging functions |    * Messaging functions | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  |   String sendUSSD(const String& code) { | ||||||
|  |     sendAT(GF("+CMGF=1")); | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("+CSCS=\"HEX\"")); | ||||||
|  |     waitResponse(); | ||||||
|  |     sendAT(GF("+CUSD=1,\""), code, GF("\"")); | ||||||
|  |     if (waitResponse() != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     stream.readStringUntil('"'); | ||||||
|  |     String hex = stream.readStringUntil('"'); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     int dcs = stream.readStringUntil('\n').toInt(); | ||||||
|  |  | ||||||
|  |     if (dcs == 15) { | ||||||
|  |       return decodeHex8bit(hex); | ||||||
|  |     } else if (dcs == 72) { | ||||||
|  |       return decodeHex16bit(hex); | ||||||
|  |     } else { | ||||||
|  |       return hex; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool sendSMS(const String& number, const String& text) { |   bool sendSMS(const String& number, const String& text) { | ||||||
|     sendAT(GF("+CMGF=1")); |     sendAT(GF("+CMGF=1")); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
| @@ -469,6 +606,7 @@ public: | |||||||
|     } |     } | ||||||
|     stream.print(text); |     stream.print(text); | ||||||
|     stream.write((char)0x1A); |     stream.write((char)0x1A); | ||||||
|  |     stream.flush(); | ||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -495,6 +633,7 @@ public: | |||||||
|       stream.print(c, HEX); |       stream.print(c, HEX); | ||||||
|     } |     } | ||||||
|     stream.write((char)0x1A); |     stream.write((char)0x1A); | ||||||
|  |     stream.flush(); | ||||||
|     return waitResponse(60000L) == 1; |     return waitResponse(60000L) == 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -505,11 +644,12 @@ public: | |||||||
|  |  | ||||||
|   String getGsmLocation() { |   String getGsmLocation() { | ||||||
|     sendAT(GF("+CIPGSMLOC=1,1")); |     sendAT(GF("+CIPGSMLOC=1,1")); | ||||||
|     if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) { |     if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { | ||||||
|       return ""; |       return ""; | ||||||
|     } |     } | ||||||
|     String res = streamReadUntil('\n'); |     String res = stream.readStringUntil('\n'); | ||||||
|     waitResponse(); |     waitResponse(); | ||||||
|  |     res.trim(); | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -530,10 +670,27 @@ public: | |||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| private: |   int getBattPercent() { | ||||||
|   int modemConnect(const char* host, uint16_t port, uint8_t mux) { |     sendAT(GF("+CBC")); | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     int res = stream.readStringUntil(',').toInt(); | ||||||
|  |     waitResponse(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  |  | ||||||
|  |   bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { | ||||||
|  |     sendAT(GF("+CIPSSL="), ssl); | ||||||
|  |     int rsp = waitResponse(); | ||||||
|  |     if (ssl && rsp != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|     sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); |     sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||||
|     int rsp = waitResponse(75000L, |     rsp = waitResponse(75000L, | ||||||
|                        GF("CONNECT OK" GSM_NL), |                        GF("CONNECT OK" GSM_NL), | ||||||
|                        GF("CONNECT FAIL" GSM_NL), |                        GF("CONNECT FAIL" GSM_NL), | ||||||
|                        GF("ALREADY CONNECT" GSM_NL)); |                        GF("ALREADY CONNECT" GSM_NL)); | ||||||
| @@ -573,16 +730,15 @@ private: | |||||||
|  |  | ||||||
|     for (size_t i=0; i<len; i++) { |     for (size_t i=0; i<len; i++) { | ||||||
| #ifdef TINY_GSM_USE_HEX | #ifdef TINY_GSM_USE_HEX | ||||||
|       while (stream.available() < 2) {} |       while (stream.available() < 2) { TINY_GSM_YIELD(); } | ||||||
|       char buf[4] = { 0, }; |       char buf[4] = { 0, }; | ||||||
|       buf[0] = streamRead(); |       buf[0] = streamRead(); | ||||||
|       buf[1] = streamRead(); |       buf[1] = streamRead(); | ||||||
|       char c = strtol(buf, NULL, 16); |       char c = strtol(buf, NULL, 16); | ||||||
|       DBG(c); |       DBG(c); | ||||||
| #else | #else | ||||||
|       while (!stream.available()) {} |       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|       char c = streamRead(); |       char c = stream.read(); | ||||||
|       DBG(c); |  | ||||||
| #endif | #endif | ||||||
|       sockets[mux]->rx.put(c); |       sockets[mux]->rx.put(c); | ||||||
|     } |     } | ||||||
| @@ -612,7 +768,41 @@ private: | |||||||
|     return 1 == res; |     return 1 == res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Private Utilities */ |   static String decodeHex8bit(String &instr) { | ||||||
|  |     String result; | ||||||
|  |     for (unsigned i=0; i<instr.length(); i+=2) { | ||||||
|  |       char buf[4] = { 0, }; | ||||||
|  |       buf[0] = instr[i]; | ||||||
|  |       buf[1] = instr[i+1]; | ||||||
|  |       char b = strtol(buf, NULL, 16); | ||||||
|  |       result += b; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static String decodeHex16bit(String &instr) { | ||||||
|  |     String result; | ||||||
|  |     for (unsigned i=0; i<instr.length(); i+=4) { | ||||||
|  |       char buf[4] = { 0, }; | ||||||
|  |       buf[0] = instr[i]; | ||||||
|  |       buf[1] = instr[i+1]; | ||||||
|  |       char b = strtol(buf, NULL, 16); | ||||||
|  |       if (b) { // If high byte is non-zero, we can't handle it ;( | ||||||
|  |         b = '?'; | ||||||
|  |       } else { | ||||||
|  |         buf[0] = instr[i+2]; | ||||||
|  |         buf[1] = instr[i+3]; | ||||||
|  |         b = strtol(buf, NULL, 16); | ||||||
|  |       } | ||||||
|  |       result += b; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  |   /* Utilities */ | ||||||
|  |  | ||||||
|   template<typename T> |   template<typename T> | ||||||
|   void streamWrite(T last) { |   void streamWrite(T last) { | ||||||
|     stream.print(last); |     stream.print(last); | ||||||
| @@ -624,26 +814,13 @@ private: | |||||||
|     streamWrite(tail...); |     streamWrite(tail...); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int streamRead() { return stream.read(); } |   bool streamSkipUntil(char c) { //TODO: timeout | ||||||
|  |     while (true) { | ||||||
|   String streamReadUntil(char c) { |       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||||
|     String return_string = stream.readStringUntil(c); |       if (stream.read() == c) | ||||||
|     return_string.trim(); |  | ||||||
|     if (String(c) == GSM_NL || String(c) == "\n"){ |  | ||||||
|       DBG(return_string, c, "    "); |  | ||||||
|     } else DBG(return_string, c); |  | ||||||
|     return return_string; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool streamSkipUntil(char c) { |  | ||||||
|     String skipped = stream.readStringUntil(c); |  | ||||||
|     skipped.trim(); |  | ||||||
|     if (skipped.length()) { |  | ||||||
|       if (String(c) == GSM_NL || String(c) == "\n"){ |  | ||||||
|         DBG(skipped, c, "    "); |  | ||||||
|       } else DBG(skipped, c); |  | ||||||
|         return true; |         return true; | ||||||
|     } else return false; |     } | ||||||
|  |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template<typename... Args> |   template<typename... Args> | ||||||
| @@ -666,14 +843,12 @@ private: | |||||||
|     String r5s(r5); r5s.trim(); |     String r5s(r5); r5s.trim(); | ||||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ |     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||||
|     data.reserve(64); |     data.reserve(64); | ||||||
|     bool gotData = false; |  | ||||||
|     int mux = -1; |  | ||||||
|     int index = 0; |     int index = 0; | ||||||
|     unsigned long startMillis = millis(); |     unsigned long startMillis = millis(); | ||||||
|     do { |     do { | ||||||
|       TINY_GSM_YIELD(); |       TINY_GSM_YIELD(); | ||||||
|       while (stream.available() > 0) { |       while (stream.available() > 0) { | ||||||
|         int a = streamRead(); |         int a = stream.read(); | ||||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case |         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||||
|         data += (char)a; |         data += (char)a; | ||||||
|         if (r1 && data.endsWith(r1)) { |         if (r1 && data.endsWith(r1)) { | ||||||
| @@ -695,8 +870,11 @@ private: | |||||||
|           index = 6; |           index = 6; | ||||||
|           String mode = streamReadUntil(','); |           String mode = streamReadUntil(','); | ||||||
|           if (mode.toInt() == 1) { |           if (mode.toInt() == 1) { | ||||||
|             mux = streamReadUntil('\n').toInt(); |             int mux = stream.readStringUntil('\n').toInt(); | ||||||
|             gotData = true; |             if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||||
|  |               sockets[mux]->got_data = true; | ||||||
|  |             } | ||||||
|  |             data = ""; | ||||||
|           } else { |           } else { | ||||||
|             data += mode; |             data += mode; | ||||||
|           } |           } | ||||||
| @@ -704,10 +882,12 @@ private: | |||||||
|           index = 7; |           index = 7; | ||||||
|           int nl = data.lastIndexOf(GSM_NL, data.length()-8); |           int nl = data.lastIndexOf(GSM_NL, data.length()-8); | ||||||
|           int coma = data.indexOf(',', nl+2); |           int coma = data.indexOf(',', nl+2); | ||||||
|           mux = data.substring(nl+2, coma).toInt(); |           int mux = data.substring(nl+2, coma).toInt(); | ||||||
|           if (mux) { |           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||||
|             sockets[mux]->sock_connected = false; |             sockets[mux]->sock_connected = false; | ||||||
|           } |           } | ||||||
|  |           data = ""; | ||||||
|  |           DBG("### Closed: ", mux); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } while (millis() - startMillis < timeout); |     } while (millis() - startMillis < timeout); | ||||||
| @@ -718,17 +898,6 @@ private: | |||||||
|         DBG(GSM_NL, "### Unhandled:", data); |         DBG(GSM_NL, "### Unhandled:", data); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     else { |  | ||||||
|       data.trim(); |  | ||||||
|       data.replace(GSM_NL GSM_NL, GSM_NL); |  | ||||||
|       data.replace(GSM_NL, GSM_NL "    "); |  | ||||||
|       if (data.length()) { |  | ||||||
|         DBG(GSM_NL, "<<< ", data); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     if (gotData) { |  | ||||||
|       sockets[mux]->sock_available = modemGetAvailable(mux); |  | ||||||
|     } |  | ||||||
|     return index; |     return index; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -746,11 +915,9 @@ private: | |||||||
|     return waitResponse(1000, r1, r2, r3, r4, r5); |     return waitResponse(1000, r1, r2, r3, r4, r5); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| private: | protected: | ||||||
|   Stream&       stream; |   Stream&       stream; | ||||||
|   GsmClient*    sockets[5]; |   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef TinyGsm::GsmClient TinyGsmClient; |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										148
									
								
								TinyGsmClientSIM808.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								TinyGsmClientSIM808.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | |||||||
|  | /** | ||||||
|  |  * @file     TinyGsmClientSIM808.h | ||||||
|  |  * @author   Volodymyr Shymanskyy | ||||||
|  |  * @license  LGPL-3.0 | ||||||
|  |  * @copyright  Copyright (c) 2016 Volodymyr Shymanskyy | ||||||
|  |  * @date     Nov 2016 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TinyGsmClientSIM808_h | ||||||
|  | #define TinyGsmClientSIM808_h | ||||||
|  |  | ||||||
|  | #include <TinyGsmClientSIM800.h> | ||||||
|  |  | ||||||
|  | class TinyGsmSim808: public TinyGsmSim800 | ||||||
|  | { | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  |   TinyGsmSim808(Stream& stream) | ||||||
|  |     : TinyGsmSim800(stream) | ||||||
|  |   {} | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |    * GPS location functions | ||||||
|  |    */ | ||||||
|  |  | ||||||
|  |   // enable GPS | ||||||
|  |   bool enableGPS() { | ||||||
|  |     uint16_t state; | ||||||
|  |  | ||||||
|  |     sendAT(GF("+CGNSPWR=1")); | ||||||
|  |     if (waitResponse() != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool disableGPS() { | ||||||
|  |     uint16_t state; | ||||||
|  |  | ||||||
|  |     sendAT(GF("+CGNSPWR=0")); | ||||||
|  |     if (waitResponse() != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // get the RAW GPS output | ||||||
|  |   // works only with ans SIM808 V2 | ||||||
|  |   String getGPSraw() { | ||||||
|  |     sendAT(GF("+CGNSINF")); | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |     String res = stream.readStringUntil('\n'); | ||||||
|  |     waitResponse(); | ||||||
|  |     res.trim(); | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // get GPS informations | ||||||
|  |   // works only with ans SIM808 V2 | ||||||
|  |   bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { | ||||||
|  |     //String buffer = ""; | ||||||
|  |     char chr_buffer[12]; | ||||||
|  |     bool fix = false; | ||||||
|  |  | ||||||
|  |     sendAT(GF("+CGNSINF")); | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     stream.readStringUntil(','); // mode | ||||||
|  |     if ( stream.readStringUntil(',').toInt() == 1 ) fix = true; | ||||||
|  |     stream.readStringUntil(','); //utctime | ||||||
|  |     *lat =  stream.readStringUntil(',').toFloat(); //lat | ||||||
|  |     *lon =  stream.readStringUntil(',').toFloat(); //lon | ||||||
|  |     if (alt != NULL) *alt =  stream.readStringUntil(',').toFloat(); //lon | ||||||
|  |     if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     stream.readStringUntil(','); | ||||||
|  |     if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites | ||||||
|  |     if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites | ||||||
|  |     stream.readStringUntil('\n'); | ||||||
|  |  | ||||||
|  |     waitResponse(); | ||||||
|  |  | ||||||
|  |     return fix; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // get GPS time | ||||||
|  |   // works only with SIM808 V2 | ||||||
|  |   bool getGPSTime(int *year, int *month, int *day, int *hour, int *minute, int *second) { | ||||||
|  |     bool fix = false; | ||||||
|  |     char chr_buffer[12]; | ||||||
|  |     sendAT(GF("+CGNSINF")); | ||||||
|  |     if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < 3; i++) { | ||||||
|  |       String buffer = stream.readStringUntil(','); | ||||||
|  |       buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); | ||||||
|  |       switch (i) { | ||||||
|  |         case 0: | ||||||
|  |           //mode | ||||||
|  |           break; | ||||||
|  |         case 1: | ||||||
|  |           //fixstatus | ||||||
|  |           if ( buffer.toInt() == 1 ) { | ||||||
|  |             fix = buffer.toInt(); | ||||||
|  |           } | ||||||
|  |           break; | ||||||
|  |         case 2: | ||||||
|  |           *year = buffer.substring(0,4).toInt(); | ||||||
|  |           *month = buffer.substring(4,6).toInt(); | ||||||
|  |           *day = buffer.substring(6,8).toInt(); | ||||||
|  |           *hour = buffer.substring(8,10).toInt(); | ||||||
|  |           *minute = buffer.substring(10,12).toInt(); | ||||||
|  |           *second = buffer.substring(12,14).toInt(); | ||||||
|  |           break; | ||||||
|  |  | ||||||
|  |         default: | ||||||
|  |           // if nothing else matches, do the default | ||||||
|  |           // default is optional | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     String res = stream.readStringUntil('\n'); | ||||||
|  |     waitResponse(); | ||||||
|  |  | ||||||
|  |     if (fix) { | ||||||
|  |       return true; | ||||||
|  |     } else { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -26,6 +26,9 @@ | |||||||
|   #define TINY_GSM_YIELD() { delay(0); } |   #define TINY_GSM_YIELD() { delay(0); } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type"))) | ||||||
|  | #define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) | ||||||
|  |  | ||||||
| #if defined(__AVR__) | #if defined(__AVR__) | ||||||
|   #define TINY_GSM_PROGMEM PROGMEM |   #define TINY_GSM_PROGMEM PROGMEM | ||||||
|   typedef const __FlashStringHelper* GsmConstStr; |   typedef const __FlashStringHelper* GsmConstStr; | ||||||
| @@ -69,4 +72,26 @@ const T& TinyGsmMax(const T& a, const T& b) | |||||||
|     return (b < a) ? a : b; |     return (b < a) ? a : b; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template<class T> | ||||||
|  | uint32_t TinyGsmAutoBaud(T& SerialAT) | ||||||
|  | { | ||||||
|  |   static uint32_t rates[] = { 115200, 57600, 38400, 19200, 9600, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 }; | ||||||
|  |  | ||||||
|  |   for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) { | ||||||
|  |     uint32_t rate = rates[i]; | ||||||
|  |     DBG("Trying baud rate", rate, "..."); | ||||||
|  |     SerialAT.begin(rate); | ||||||
|  |     delay(10); | ||||||
|  |     for (int i=0; i<3; i++) { | ||||||
|  |       SerialAT.print("AT\r\n"); | ||||||
|  |       String input = SerialAT.readString(); | ||||||
|  |       if (input.indexOf("OK") >= 0) { | ||||||
|  |         DBG("Modem responded at rate", rate); | ||||||
|  |         return rate; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										172
									
								
								examples/AllFunctions/AllFunctions.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								examples/AllFunctions/AllFunctions.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | |||||||
|  | /************************************************************** | ||||||
|  |  * | ||||||
|  |  * TinyGSM Getting Started guide: | ||||||
|  |  *   http://tiny.cc/tiny-gsm-readme | ||||||
|  |  * | ||||||
|  |  * NOTE: | ||||||
|  |  * Some of the functions may be unavailable for your modem. | ||||||
|  |  * Just comment them out. | ||||||
|  |  * | ||||||
|  |  **************************************************************/ | ||||||
|  |  | ||||||
|  | // Select your modem: | ||||||
|  | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
|  | // #define TINY_GSM_MODEM_SIM900 | ||||||
|  | // #define TINY_GSM_MODEM_A6 | ||||||
|  | // #define TINY_GSM_MODEM_A7 | ||||||
|  | // #define TINY_GSM_MODEM_M590 | ||||||
|  |  | ||||||
|  | // Set serial for debug console (to the Serial Monitor, speed 115200) | ||||||
|  | #define SerialMon Serial | ||||||
|  |  | ||||||
|  | // Set serial for AT commands (to the module) | ||||||
|  | // Use Hardware Serial on Mega, Leonardo, Micro | ||||||
|  | #define SerialAT Serial1 | ||||||
|  |  | ||||||
|  | // or Software Serial on Uno, Nano | ||||||
|  | //#include <SoftwareSerial.h> | ||||||
|  | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //#define DUMP_AT_COMMANDS | ||||||
|  | #define TINY_GSM_DEBUG SerialMon | ||||||
|  |  | ||||||
|  | // Set phone numbers, if you want to test SMS and Calls | ||||||
|  | //#define SMS_TARGET  "+380xxxxxxxxx" | ||||||
|  | //#define CALL_TARGET "+380xxxxxxxxx" | ||||||
|  |  | ||||||
|  | // Your GPRS credentials | ||||||
|  | // Leave empty, if missing user or pass | ||||||
|  | const char apn[]  = "YourAPN"; | ||||||
|  | const char user[] = ""; | ||||||
|  | const char pass[] = ""; | ||||||
|  |  | ||||||
|  | #include <TinyGsmClient.h> | ||||||
|  |  | ||||||
|  | #ifdef DUMP_AT_COMMANDS | ||||||
|  |   #include <StreamDebugger.h> | ||||||
|  |   StreamDebugger debugger(SerialAT, SerialMon); | ||||||
|  |   TinyGsm modem(debugger); | ||||||
|  | #else | ||||||
|  |   TinyGsm modem(SerialAT); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | void setup() { | ||||||
|  |   // Set console baud rate | ||||||
|  |   SerialMon.begin(115200); | ||||||
|  |   delay(10); | ||||||
|  |  | ||||||
|  |   // Set GSM module baud rate | ||||||
|  |   TinyGsmAutoBaud(SerialAT); | ||||||
|  |   delay(3000); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void loop() { | ||||||
|  |  | ||||||
|  |   // Restart takes quite some time | ||||||
|  |   // To skip it, call init() instead of restart() | ||||||
|  |   DBG("Initializing modem..."); | ||||||
|  |   if (!modem.restart()) { | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   DBG("Modem:", modemInfo); | ||||||
|  |  | ||||||
|  |   // Unlock your SIM card with a PIN | ||||||
|  |   //modem.simUnlock("1234"); | ||||||
|  |  | ||||||
|  |   DBG("Waiting for network..."); | ||||||
|  |   if (!modem.waitForNetwork()) { | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   DBG("Connecting to", apn); | ||||||
|  |   if (!modem.gprsConnect(apn, user, pass)) { | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool res; | ||||||
|  |  | ||||||
|  |   String ccid = modem.getSimCCID(); | ||||||
|  |   DBG("CCID:", ccid); | ||||||
|  |  | ||||||
|  |   String imei = modem.getIMEI(); | ||||||
|  |   DBG("IMEI:", imei); | ||||||
|  |  | ||||||
|  |   String cop = modem.getOperator(); | ||||||
|  |   DBG("Operator:", cop); | ||||||
|  |    | ||||||
|  |   IPAddress local = modem.localIP(); | ||||||
|  |   DBG("Local IP:", local); | ||||||
|  |  | ||||||
|  |   int csq = modem.getSignalQuality(); | ||||||
|  |   DBG("Signal quality:", csq); | ||||||
|  |  | ||||||
|  |   // This is NOT supported on M590 | ||||||
|  |   int battLevel = modem.getBattPercent(); | ||||||
|  |   DBG("Battery lavel:", battLevel); | ||||||
|  |  | ||||||
|  |   // This is only supported on SIMxxx series | ||||||
|  |   float battVoltage = modem.getBattVoltage() / 1000.0F; | ||||||
|  |   DBG("Battery voltage:", battVoltage); | ||||||
|  |  | ||||||
|  |   // This is only supported on SIMxxx series | ||||||
|  |   String gsmLoc = modem.getGsmLocation(); | ||||||
|  |   DBG("GSM location:", gsmLoc); | ||||||
|  |  | ||||||
|  |   String ussd_balance = modem.sendUSSD("*111#"); | ||||||
|  |   DBG("Balance (USSD):", ussd_balance); | ||||||
|  |  | ||||||
|  |   String ussd_phone_num = modem.sendUSSD("*161#"); | ||||||
|  |   DBG("Phone number (USSD):", ussd_phone_num); | ||||||
|  |  | ||||||
|  | #if defined(TINY_GSM_MODEM_SIM808) | ||||||
|  |   modem.enableGPS(); | ||||||
|  |   String gps_raw = modem.getGPSraw(); | ||||||
|  |   modem.disableGPS(); | ||||||
|  |   DBG("GPS raw data:", gps_raw); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(SMS_TARGET) | ||||||
|  |   res = modem.sendSMS(SMS_TARGET, String("Hello from ") + imei); | ||||||
|  |   DBG("SMS:", res ? "OK" : "fail"); | ||||||
|  |  | ||||||
|  |   // This is only supported on SIMxxx series | ||||||
|  |   res = modem.sendSMS_UTF16(SMS_TARGET, u"Привіііт!", 9); | ||||||
|  |   DBG("UTF16 SMS:", res ? "OK" : "fail"); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(CALL_TARGET) | ||||||
|  |   DBG("Calling:", CALL_TARGET); | ||||||
|  |  | ||||||
|  |   // This is NOT supported on M590 | ||||||
|  |   res = modem.callNumber(CALL_TARGET); | ||||||
|  |   DBG("Call:", res ? "OK" : "fail"); | ||||||
|  |  | ||||||
|  |   if (res) { | ||||||
|  |     delay(5000L); | ||||||
|  |    | ||||||
|  |     res = modem.callHangup(); | ||||||
|  |     DBG("Hang up:", res ? "OK" : "fail"); | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   modem.gprsDisconnect(); | ||||||
|  |   DBG("GPRS disconnected"); | ||||||
|  |  | ||||||
|  |   // Try to power-off (modem may decide to restart automatically) | ||||||
|  |   // To turn off modem completely, please use Reset/Enable pins | ||||||
|  |   modem.poweroff(); | ||||||
|  |   DBG("Poweroff."); | ||||||
|  |  | ||||||
|  |   // Do nothing forevermore | ||||||
|  |   while (true) { | ||||||
|  |     modem.maintain(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -30,6 +30,7 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| @@ -74,6 +75,10 @@ void setup() | |||||||
|   Serial.println("Initializing modem..."); |   Serial.println("Initializing modem..."); | ||||||
|   modem.restart(); |   modem.restart(); | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   Serial.print("Modem: "); | ||||||
|  |   Serial.println(modemInfo); | ||||||
|  |  | ||||||
|   // Unlock your SIM card with a PIN |   // Unlock your SIM card with a PIN | ||||||
|   //modem.simUnlock("1234"); |   //modem.simUnlock("1234"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| /************************************************************** | /************************************************************** | ||||||
|  * |  * | ||||||
|  * For this example, you need to install CRC32 library: |  * For this example, you need to install CRC32 library: | ||||||
|  *   https://github.com/vshymanskyy/CRC32.git |  *   https://github.com/bakercp/CRC32 | ||||||
|  *   or from http://librarymanager/all#CRC32+checksum |  *   or from http://librarymanager/all#CRC32+checksum | ||||||
|  * |  * | ||||||
|  * TinyGSM Getting Started guide: |  * TinyGSM Getting Started guide: | ||||||
| @@ -14,6 +14,7 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| @@ -24,8 +25,8 @@ | |||||||
| // Increase RX buffer | // Increase RX buffer | ||||||
| #define TINY_GSM_RX_BUFFER 1030 | #define TINY_GSM_RX_BUFFER 1030 | ||||||
|  |  | ||||||
| #include <TinyGsmClient.h> | //#define DUMP_AT_COMMANDS | ||||||
| #include <CRC32.h> | //#define TINY_GSM_DEBUG Serial | ||||||
|  |  | ||||||
| // Your GPRS credentials | // Your GPRS credentials | ||||||
| // Leave empty, if missing user or pass | // Leave empty, if missing user or pass | ||||||
| @@ -40,10 +41,21 @@ const char pass[] = ""; | |||||||
| //#include <SoftwareSerial.h> | //#include <SoftwareSerial.h> | ||||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
|  | #include <TinyGsmClient.h> | ||||||
|  | #include <CRC32.h> | ||||||
|  |  | ||||||
|  | #ifdef DUMP_AT_COMMANDS | ||||||
|  |   #include <StreamDebugger.h> | ||||||
|  |   StreamDebugger debugger(SerialAT, Serial); | ||||||
|  |   TinyGsm modem(debugger); | ||||||
|  | #else | ||||||
|   TinyGsm modem(SerialAT); |   TinyGsm modem(SerialAT); | ||||||
|  | #endif | ||||||
| TinyGsmClient client(modem); | TinyGsmClient client(modem); | ||||||
|  |  | ||||||
| const char server[] = "cdn.rawgit.com"; | const char server[] = "cdn.rawgit.com"; | ||||||
|  | const int  port     = 80; | ||||||
|  |  | ||||||
| const char resource[]  = "/vshymanskyy/tinygsm/master/extras/test_1k.bin"; | const char resource[]  = "/vshymanskyy/tinygsm/master/extras/test_1k.bin"; | ||||||
| uint32_t knownCRC32    = 0x6f50d767; | uint32_t knownCRC32    = 0x6f50d767; | ||||||
| uint32_t knownFileSize = 1024;   // In case server does not send it | uint32_t knownFileSize = 1024;   // In case server does not send it | ||||||
| @@ -62,6 +74,10 @@ void setup() { | |||||||
|   Serial.println("Initializing modem..."); |   Serial.println("Initializing modem..."); | ||||||
|   modem.restart(); |   modem.restart(); | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   Serial.print("Modem: "); | ||||||
|  |   Serial.println(modemInfo); | ||||||
|  |  | ||||||
|   // Unlock your SIM card with a PIN |   // Unlock your SIM card with a PIN | ||||||
|   //modem.simUnlock("1234"); |   //modem.simUnlock("1234"); | ||||||
| } | } | ||||||
| @@ -99,7 +115,7 @@ void loop() { | |||||||
|   Serial.print(server); |   Serial.print(server); | ||||||
|  |  | ||||||
|   // if you get a connection, report back via serial: |   // if you get a connection, report back via serial: | ||||||
|   if (!client.connect(server, 80)) { |   if (!client.connect(server, port)) { | ||||||
|     Serial.println(" fail"); |     Serial.println(" fail"); | ||||||
|     delay(10000); |     delay(10000); | ||||||
|     return; |     return; | ||||||
|   | |||||||
							
								
								
									
										152
									
								
								examples/HttpClient/HttpClient.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								examples/HttpClient/HttpClient.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | |||||||
|  | /************************************************************** | ||||||
|  |  * | ||||||
|  |  * This sketch connects to a website and downloads a page. | ||||||
|  |  * It can be used to perform HTTP/RESTful API calls. | ||||||
|  |  * | ||||||
|  |  * For this example, you need to install ArduinoHttpClient library: | ||||||
|  |  *   https://github.com/arduino-libraries/ArduinoHttpClient | ||||||
|  |  *   or from http://librarymanager/all#ArduinoHttpClient | ||||||
|  |  * | ||||||
|  |  * TinyGSM Getting Started guide: | ||||||
|  |  *   http://tiny.cc/tiny-gsm-readme | ||||||
|  |  * | ||||||
|  |  **************************************************************/ | ||||||
|  |  | ||||||
|  | // Select your modem: | ||||||
|  | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
|  | // #define TINY_GSM_MODEM_SIM900 | ||||||
|  | // #define TINY_GSM_MODEM_A6 | ||||||
|  | // #define TINY_GSM_MODEM_A7 | ||||||
|  | // #define TINY_GSM_MODEM_M590 | ||||||
|  | // #define TINY_GSM_MODEM_ESP8266 | ||||||
|  |  | ||||||
|  | // Increase RX buffer | ||||||
|  | #define TINY_GSM_RX_BUFFER 512 | ||||||
|  |  | ||||||
|  | // Use Hardware Serial on Mega, Leonardo, Micro | ||||||
|  | #define SerialAT Serial1 | ||||||
|  |  | ||||||
|  | // or Software Serial on Uno, Nano | ||||||
|  | //#include <SoftwareSerial.h> | ||||||
|  | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
|  | //#define DUMP_AT_COMMANDS | ||||||
|  | //#define TINY_GSM_DEBUG Serial | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Your GPRS credentials | ||||||
|  | // Leave empty, if missing user or pass | ||||||
|  | const char apn[]  = "YourAPN"; | ||||||
|  | const char user[] = ""; | ||||||
|  | const char pass[] = ""; | ||||||
|  |  | ||||||
|  | // Name of the server we want to connect to | ||||||
|  | const char server[] = "cdn.rawgit.com"; | ||||||
|  | const int  port     = 443; | ||||||
|  | // Path to download (this is the bit after the hostname in the URL) | ||||||
|  | const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | ||||||
|  |  | ||||||
|  | #include <TinyGsmClient.h> | ||||||
|  | #include <ArduinoHttpClient.h> | ||||||
|  |  | ||||||
|  | #ifdef DUMP_AT_COMMANDS | ||||||
|  |   #include <StreamDebugger.h> | ||||||
|  |   StreamDebugger debugger(SerialAT, Serial); | ||||||
|  |   TinyGsm modem(debugger); | ||||||
|  | #else | ||||||
|  |   TinyGsm modem(SerialAT); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | TinyGsmClient client(modem); | ||||||
|  | HttpClient http(client, server, port); | ||||||
|  |  | ||||||
|  | void setup() { | ||||||
|  |   // Set console baud rate | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   delay(10); | ||||||
|  |  | ||||||
|  |   // Set GSM module baud rate | ||||||
|  |   SerialAT.begin(115200); | ||||||
|  |   delay(3000); | ||||||
|  |  | ||||||
|  |   // Restart takes quite some time | ||||||
|  |   // To skip it, call init() instead of restart() | ||||||
|  |   Serial.println("Initializing modem..."); | ||||||
|  |   modem.restart(); | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   Serial.print("Modem: "); | ||||||
|  |   Serial.println(modemInfo); | ||||||
|  |  | ||||||
|  |   // Unlock your SIM card with a PIN | ||||||
|  |   //modem.simUnlock("1234"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void loop() { | ||||||
|  |   Serial.print(F("Waiting for network...")); | ||||||
|  |   if (!modem.waitForNetwork()) { | ||||||
|  |     Serial.println(" fail"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   Serial.println(" OK"); | ||||||
|  |  | ||||||
|  |   Serial.print(F("Connecting to ")); | ||||||
|  |   Serial.print(apn); | ||||||
|  |   if (!modem.gprsConnect(apn, user, pass)) { | ||||||
|  |     Serial.println(" fail"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   Serial.println(" OK"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   Serial.print(F("Performing HTTP GET request... ")); | ||||||
|  |   int err = http.get(resource); | ||||||
|  |   if (err != 0) { | ||||||
|  |     Serial.println("failed to connect"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int status = http.responseStatusCode(); | ||||||
|  |   Serial.println(status); | ||||||
|  |   if (!status) { | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   while (http.headerAvailable()) { | ||||||
|  |     String headerName = http.readHeaderName(); | ||||||
|  |     String headerValue = http.readHeaderValue(); | ||||||
|  |     //Serial.println(headerName + " : " + headerValue); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int length = http.contentLength(); | ||||||
|  |   if (length >= 0) { | ||||||
|  |     Serial.println(String("Content length is: ") + length); | ||||||
|  |   } | ||||||
|  |   if (http.isResponseChunked()) { | ||||||
|  |     Serial.println("This response is chunked"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   String body = http.responseBody(); | ||||||
|  |   Serial.println("Response:"); | ||||||
|  |   Serial.println(body); | ||||||
|  |  | ||||||
|  |   Serial.println(String("Body length is: ") + body.length()); | ||||||
|  |  | ||||||
|  |   // Shutdown | ||||||
|  |  | ||||||
|  |   http.stop(); | ||||||
|  |  | ||||||
|  |   modem.gprsDisconnect(); | ||||||
|  |   Serial.println("GPRS disconnected"); | ||||||
|  |  | ||||||
|  |   // Do nothing forevermore | ||||||
|  |   while (true) { | ||||||
|  |     delay(1000); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										155
									
								
								examples/HttpsClient/HttpsClient.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								examples/HttpsClient/HttpsClient.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | |||||||
|  | /************************************************************** | ||||||
|  |  * | ||||||
|  |  * This sketch connects to a website and downloads a page. | ||||||
|  |  * It can be used to perform HTTP/RESTful API calls. | ||||||
|  |  * | ||||||
|  |  * For this example, you need to install ArduinoHttpClient library: | ||||||
|  |  *   https://github.com/arduino-libraries/ArduinoHttpClient | ||||||
|  |  *   or from http://librarymanager/all#ArduinoHttpClient | ||||||
|  |  * | ||||||
|  |  * TinyGSM Getting Started guide: | ||||||
|  |  *   http://tiny.cc/tiny-gsm-readme | ||||||
|  |  * | ||||||
|  |  **************************************************************/ | ||||||
|  |  | ||||||
|  | // Select your modem | ||||||
|  | // SSL/TLS is currently supported only with SIM8xx series | ||||||
|  | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | #define TINY_GSM_MODEM_SIM808 | ||||||
|  |  | ||||||
|  | // Increase RX buffer | ||||||
|  | #define TINY_GSM_RX_BUFFER 64 | ||||||
|  |  | ||||||
|  | // Use Hardware Serial on Mega, Leonardo, Micro | ||||||
|  | #define SerialAT Serial1 | ||||||
|  |  | ||||||
|  | // or Software Serial on Uno, Nano | ||||||
|  | //#include <SoftwareSerial.h> | ||||||
|  | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
|  | //#define DUMP_AT_COMMANDS | ||||||
|  | //#define TINY_GSM_DEBUG Serial | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Your GPRS credentials | ||||||
|  | // Leave empty, if missing user or pass | ||||||
|  | const char apn[]  = "YourAPN"; | ||||||
|  | const char user[] = ""; | ||||||
|  | const char pass[] = ""; | ||||||
|  |  | ||||||
|  | // Name of the server we want to connect to | ||||||
|  | const char server[] = "cdn.rawgit.com"; | ||||||
|  | const int  port     = 443; | ||||||
|  | // Path to download (this is the bit after the hostname in the URL) | ||||||
|  | const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | ||||||
|  |  | ||||||
|  | #include <TinyGsmClient.h> | ||||||
|  | #include <ArduinoHttpClient.h> | ||||||
|  |  | ||||||
|  | #ifdef DUMP_AT_COMMANDS | ||||||
|  |   #include <StreamDebugger.h> | ||||||
|  |   StreamDebugger debugger(SerialAT, Serial); | ||||||
|  |   TinyGsm modem(debugger); | ||||||
|  | #else | ||||||
|  |   TinyGsm modem(SerialAT); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | TinyGsmClientSecure client(modem); | ||||||
|  | HttpClient http(client, server, port); | ||||||
|  |  | ||||||
|  | void setup() { | ||||||
|  |   // Set console baud rate | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   delay(10); | ||||||
|  |  | ||||||
|  |   // Set GSM module baud rate | ||||||
|  |   SerialAT.begin(115200); | ||||||
|  |   delay(3000); | ||||||
|  |  | ||||||
|  |   // Restart takes quite some time | ||||||
|  |   // To skip it, call init() instead of restart() | ||||||
|  |   Serial.println("Initializing modem..."); | ||||||
|  |   modem.restart(); | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   Serial.print("Modem: "); | ||||||
|  |   Serial.println(modemInfo); | ||||||
|  |  | ||||||
|  |   // Unlock your SIM card with a PIN | ||||||
|  |   //modem.simUnlock("1234"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void loop() { | ||||||
|  |   if (!modem.hasSSL()) { | ||||||
|  |     Serial.println("SSL is not supported by this modem"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Serial.print(F("Waiting for network...")); | ||||||
|  |   if (!modem.waitForNetwork()) { | ||||||
|  |     Serial.println(" fail"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   Serial.println(" OK"); | ||||||
|  |  | ||||||
|  |   Serial.print(F("Connecting to ")); | ||||||
|  |   Serial.print(apn); | ||||||
|  |   if (!modem.gprsConnect(apn, user, pass)) { | ||||||
|  |     Serial.println(" fail"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   Serial.println(" OK"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   Serial.print(F("Performing HTTP GET request... ")); | ||||||
|  |   http.connectionKeepAlive(); // Currently, this is needed for HTTPS | ||||||
|  |   int err = http.get(resource); | ||||||
|  |   if (err != 0) { | ||||||
|  |     Serial.println("failed to connect"); | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int status = http.responseStatusCode(); | ||||||
|  |   Serial.println(status); | ||||||
|  |   if (!status) { | ||||||
|  |     delay(10000); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   while (http.headerAvailable()) { | ||||||
|  |     String headerName = http.readHeaderName(); | ||||||
|  |     String headerValue = http.readHeaderValue(); | ||||||
|  |     //Serial.println(headerName + " : " + headerValue); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int length = http.contentLength(); | ||||||
|  |   if (length >= 0) { | ||||||
|  |     Serial.println(String("Content length is: ") + length); | ||||||
|  |   } | ||||||
|  |   if (http.isResponseChunked()) { | ||||||
|  |     Serial.println("This response is chunked"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   String body = http.responseBody(); | ||||||
|  |   Serial.println("Response:"); | ||||||
|  |   Serial.println(body); | ||||||
|  |  | ||||||
|  |   Serial.println(String("Body length is: ") + body.length()); | ||||||
|  |  | ||||||
|  |   // Shutdown | ||||||
|  |  | ||||||
|  |   http.stop(); | ||||||
|  |  | ||||||
|  |   modem.gprsDisconnect(); | ||||||
|  |   Serial.println("GPRS disconnected"); | ||||||
|  |  | ||||||
|  |   // Do nothing forevermore | ||||||
|  |   while (true) { | ||||||
|  |     delay(1000); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -27,6 +27,7 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| @@ -81,6 +82,10 @@ void setup() { | |||||||
|   Serial.println("Initializing modem..."); |   Serial.println("Initializing modem..."); | ||||||
|   modem.restart(); |   modem.restart(); | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   Serial.print("Modem: "); | ||||||
|  |   Serial.println(modemInfo); | ||||||
|  |  | ||||||
|   // Unlock your SIM card with a PIN |   // Unlock your SIM card with a PIN | ||||||
|   //modem.simUnlock("1234"); |   //modem.simUnlock("1234"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,12 +10,12 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| // #define TINY_GSM_MODEM_M590 | // #define TINY_GSM_MODEM_M590 | ||||||
| // #define TINY_GSM_MODEM_ESP8266 | // #define TINY_GSM_MODEM_ESP8266 | ||||||
| // #define TINY_GSM_MODEM_XBEE  |  | ||||||
|  |  | ||||||
| #include <TinyGsmClient.h> | #include <TinyGsmClient.h> | ||||||
|  |  | ||||||
| @@ -38,7 +38,7 @@ TinyGsmClient client(modem); | |||||||
| const char server[] = "cdn.rawgit.com"; | const char server[] = "cdn.rawgit.com"; | ||||||
| const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | ||||||
|  |  | ||||||
| int port = 80; | const int port = 80; | ||||||
|  |  | ||||||
| void setup() { | void setup() { | ||||||
|   // Set console baud rate |   // Set console baud rate | ||||||
| @@ -54,6 +54,10 @@ void setup() { | |||||||
|   Serial.println(F("Initializing modem...")); |   Serial.println(F("Initializing modem...")); | ||||||
|   modem.restart(); |   modem.restart(); | ||||||
|  |  | ||||||
|  |   String modemInfo = modem.getModemInfo(); | ||||||
|  |   Serial.print("Modem: "); | ||||||
|  |   Serial.println(modemInfo); | ||||||
|  |  | ||||||
|   // Unlock your SIM card with a PIN |   // Unlock your SIM card with a PIN | ||||||
|   //modem.simUnlock("1234"); |   //modem.simUnlock("1234"); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| ####################################### | ####################################### | ||||||
| TinyGsm	KEYWORD1 | TinyGsm	KEYWORD1 | ||||||
| TinyGsmClient	KEYWORD1 | TinyGsmClient	KEYWORD1 | ||||||
|  | TinyGsmClientSecure	KEYWORD1 | ||||||
|  |  | ||||||
| SerialAT	KEYWORD1 | SerialAT	KEYWORD1 | ||||||
| SerialMon	KEYWORD1 | SerialMon	KEYWORD1 | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "TinyGSM", |   "name": "TinyGSM", | ||||||
|   "version": "0.1.8", |   "version": "0.3.1", | ||||||
|   "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968", |   "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", |   "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968", | ||||||
|   "authors": |   "authors": | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| name=TinyGSM | name=TinyGSM | ||||||
| version=0.1.8 | version=0.3.1 | ||||||
| author=Volodymyr Shymanskyy | author=Volodymyr Shymanskyy | ||||||
| maintainer=Volodymyr Shymanskyy | maintainer=Volodymyr Shymanskyy | ||||||
| sentence=A small Arduino library for GPRS modules, that just works. | sentence=A small Arduino library for GPRS modules, that just works. | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| @@ -30,7 +31,9 @@ | |||||||
| //#include <SoftwareSerial.h> | //#include <SoftwareSerial.h> | ||||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
| TinyGsm modem(SerialAT); | #define TINY_GSM_DEBUG SerialMon | ||||||
|  |  | ||||||
|  | #include <TinyGsmClient.h> | ||||||
|  |  | ||||||
| // Module baud rate | // Module baud rate | ||||||
| uint32_t rate = 0; // Set to 0 for Auto-Detect | uint32_t rate = 0; // Set to 0 for Auto-Detect | ||||||
| @@ -44,21 +47,7 @@ void setup() { | |||||||
| void loop() { | void loop() { | ||||||
|  |  | ||||||
|   if (!rate) { |   if (!rate) { | ||||||
|       static uint32_t rates[] = { 115200, 9600, 57600, 19200, 38400, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 }; |     rate = TinyGsmAutoBaud(SerialAT); | ||||||
|  |  | ||||||
|       SerialMon.println("Autodetecting baud rate"); |  | ||||||
|       for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) { |  | ||||||
|         SerialMon.print(String("Trying baud rate ") + rates[i] + "... "); |  | ||||||
|         SerialAT.begin(rates[i]); |  | ||||||
|         delay(10); |  | ||||||
|         if (modem.autoBaud(1000)) { |  | ||||||
|           rate = rates[i]; |  | ||||||
|           SerialMon.println(F("OK")); |  | ||||||
|           break; |  | ||||||
|         } else { |  | ||||||
|           SerialMon.println(F("fail")); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!rate) { |   if (!rate) { | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| @@ -18,11 +19,10 @@ | |||||||
| // #define TINY_GSM_MODEM_ESP8266 | // #define TINY_GSM_MODEM_ESP8266 | ||||||
| // #define TINY_GSM_MODEM_XBEE | // #define TINY_GSM_MODEM_XBEE | ||||||
|  |  | ||||||
| // Increase buffer fo see less commands | // Increase the buffer | ||||||
| #define TINY_GSM_RX_BUFFER 256 | #define TINY_GSM_RX_BUFFER 512 | ||||||
|  |  | ||||||
| #include <TinyGsmClient.h> | #include <TinyGsmClient.h> | ||||||
| #include <StreamDebugger.h> |  | ||||||
|  |  | ||||||
| // Your GPRS credentials | // Your GPRS credentials | ||||||
| // Leave empty, if missing user or pass | // Leave empty, if missing user or pass | ||||||
| @@ -42,12 +42,13 @@ const char pass[] = ""; | |||||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include <StreamDebugger.h> | ||||||
| StreamDebugger debugger(SerialAT, SerialMon); | StreamDebugger debugger(SerialAT, SerialMon); | ||||||
| TinyGsm modem(debugger); | TinyGsm modem(debugger); | ||||||
| TinyGsmClient client(modem); | TinyGsmClient client(modem); | ||||||
|  |  | ||||||
| const char server[] = "cdn.rawgit.com"; | const char server[] = "cdn.rawgit.com"; | ||||||
| const char resource[] = "/vshymanskyy/tinygsm/master/extras/test_simple.txt"; | const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | ||||||
|  |  | ||||||
| void setup() { | void setup() { | ||||||
|   // Set console baud rate |   // Set console baud rate | ||||||
| @@ -146,7 +147,7 @@ void loop() { | |||||||
|   SerialMon.print(bytesReceived); |   SerialMon.print(bytesReceived); | ||||||
|   SerialMon.println(" bytes"); |   SerialMon.println(" bytes"); | ||||||
|   SerialMon.print  (" Test:     "); |   SerialMon.print  (" Test:     "); | ||||||
|   SerialMon.println((bytesReceived == 1000) ? "PASSED" : "FAIL"); |   SerialMon.println((bytesReceived == 121) ? "PASSED" : "FAILED"); | ||||||
|   SerialMon.println("************************"); |   SerialMon.println("************************"); | ||||||
|  |  | ||||||
|   // Do nothing forevermore |   // Do nothing forevermore | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| // Select your modem: | // Select your modem: | ||||||
| #define TINY_GSM_MODEM_SIM800 | #define TINY_GSM_MODEM_SIM800 | ||||||
|  | // #define TINY_GSM_MODEM_SIM808 | ||||||
| // #define TINY_GSM_MODEM_SIM900 | // #define TINY_GSM_MODEM_SIM900 | ||||||
| // #define TINY_GSM_MODEM_A6 | // #define TINY_GSM_MODEM_A6 | ||||||
| // #define TINY_GSM_MODEM_A7 | // #define TINY_GSM_MODEM_A7 | ||||||
| @@ -19,7 +20,6 @@ | |||||||
| // #define TINY_GSM_MODEM_XBEE | // #define TINY_GSM_MODEM_XBEE | ||||||
|  |  | ||||||
| #include <TinyGsmClient.h> | #include <TinyGsmClient.h> | ||||||
| #include <StreamDebugger.h> |  | ||||||
|  |  | ||||||
| // Set serial for debug console (to the Serial Monitor, speed 115200) | // Set serial for debug console (to the Serial Monitor, speed 115200) | ||||||
| #define SerialMon Serial | #define SerialMon Serial | ||||||
| @@ -32,6 +32,7 @@ | |||||||
| //#include <SoftwareSerial.h> | //#include <SoftwareSerial.h> | ||||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||||
|  |  | ||||||
|  | #include <StreamDebugger.h> | ||||||
| StreamDebugger debugger(SerialAT, SerialMon); | StreamDebugger debugger(SerialAT, SerialMon); | ||||||
| TinyGsm modem(debugger); | TinyGsm modem(debugger); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user