mirror of
				https://github.com/KevinMidboe/TinyGSM.git
				synced 2025-10-29 18:00:18 +00:00 
			
		
		
		
	Merge branch '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/network) | ||||
|  | ||||
| You can also join our chat: | ||||
| [](https://gitter.im/tinygsm) | ||||
|  | ||||
| ### Arduino Client interface support | ||||
| This library is easy to integrate with lots of sketches, which use Ethernet or WiFi.   | ||||
| Examples for **PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **Web Client** and **File Download** are provided. | ||||
| **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.   | ||||
| **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 SIM900 series (SIM900A, SIM900D, SIM908, SIM968) | ||||
| - [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 ;) | ||||
|  | ||||
| ## 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 | ||||
|  | ||||
|   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) | ||||
|   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 | ||||
|  | ||||
| ### SoftwareSerial problems | ||||
|   | ||||
| @@ -11,14 +11,32 @@ | ||||
|  | ||||
| #if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900) | ||||
|   #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) | ||||
|   #include <TinyGsmClientA6.h> | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #elif defined(TINY_GSM_MODEM_M590) | ||||
|   #include <TinyGsmClientM590.h> | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #elif defined(TINY_GSM_MODEM_ESP8266) | ||||
|   #include <TinyGsmClientESP8266.h> | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #elif defined(TINY_GSM_MODEM_XBEE) | ||||
|   #include <TinyGsmClientXBee.h> | ||||
|   typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #else | ||||
|   #error "Please define GSM modem model" | ||||
| #endif | ||||
|   | ||||
| @@ -15,6 +15,8 @@ | ||||
|   #define TINY_GSM_RX_BUFFER 256 | ||||
| #endif | ||||
|  | ||||
| #define TINY_GSM_MUX_COUNT 8 | ||||
|  | ||||
| #include <TinyGsmCommon.h> | ||||
|  | ||||
| #define GSM_NL "\r\n" | ||||
| @@ -40,11 +42,6 @@ enum RegStatus { | ||||
| class TinyGsm | ||||
| { | ||||
|  | ||||
| public: | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   {} | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| @@ -111,7 +108,7 @@ public: | ||||
|  | ||||
|   virtual int available() { | ||||
|     TINY_GSM_YIELD(); | ||||
|     if (!rx.size()) { | ||||
|     if (!rx.size() && sock_connected) { | ||||
|       at->maintain(); | ||||
|     } | ||||
|     return rx.size(); | ||||
| @@ -155,6 +152,13 @@ public: | ||||
|     return sock_connected; | ||||
|   } | ||||
|   virtual operator bool() { return connected(); } | ||||
|  | ||||
|   /* | ||||
|    * Extended API | ||||
|    */ | ||||
|  | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   uint8_t       mux; | ||||
| @@ -164,6 +168,12 @@ private: | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Basic functions | ||||
|    */ | ||||
| @@ -211,6 +221,18 @@ public: | ||||
|     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 | ||||
|    */ | ||||
| @@ -224,6 +246,11 @@ public: | ||||
|     return init(); | ||||
|   } | ||||
|  | ||||
|   bool poweroff() { | ||||
|     sendAT(GF("+CPOF")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * SIM card functions | ||||
|    */ | ||||
| @@ -235,7 +262,7 @@ public: | ||||
|  | ||||
|   String getSimCCID() { | ||||
|     sendAT(GF("+CCID")); | ||||
|     if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { | ||||
|     if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     String res = streamReadUntil('\n'); | ||||
| @@ -295,7 +322,7 @@ public: | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Generic network functions  | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|   int getSignalQuality() { | ||||
| @@ -303,7 +330,7 @@ public: | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
|       return 99; | ||||
|     } | ||||
|     int res = streamReadUntil(',').toInt(); | ||||
|     int res = stream.readStringUntil(',').toInt(); | ||||
|     waitResponse(); | ||||
|     return res; | ||||
|   } | ||||
| @@ -336,9 +363,17 @@ public: | ||||
|   bool gprsConnect(const char* apn, const char* user, const char* pwd) { | ||||
|     gprsDisconnect(); | ||||
|  | ||||
|     sendAT(GF("+CGATT=1")); | ||||
|     if (waitResponse(60000L) != 1) | ||||
|       return false; | ||||
|  | ||||
|     // TODO: wait AT+CGATT? | ||||
|  | ||||
|     sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); | ||||
|     waitResponse(); | ||||
|  | ||||
|     if (!user) user = ""; | ||||
|     if (!pwd)  pwd = ""; | ||||
|     sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); | ||||
|     if (waitResponse(60000L) != 1) { | ||||
|       return false; | ||||
| @@ -347,24 +382,11 @@ public: | ||||
|     sendAT(GF("+CGACT=1,1")); | ||||
|     waitResponse(60000L); | ||||
|  | ||||
|     sendAT(GF("+CGATT=1")); | ||||
|     if (waitResponse(60000L) != 1) | ||||
|       return false; | ||||
|  | ||||
|     // TODO: wait AT+CGATT? | ||||
|  | ||||
|     sendAT(GF("+CIPMUX=1")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     /*sendAT(GF("+CIFSR")); | ||||
|     String data; | ||||
|     if (waitResponse(10000L, data) != 1) { | ||||
|       data.replace(GSM_NL, ""); | ||||
|       return false; | ||||
|     }*/ | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -373,22 +395,58 @@ public: | ||||
|     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 | ||||
|    */ | ||||
|  | ||||
|   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callAnswer() { | ||||
|     sendAT(GF("A")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   // Returns true on pick-up, false on error/busy | ||||
|   bool callNumber(const String& number) { | ||||
|     sendAT(GF("D"), number); | ||||
|     return waitResponse() == 1; | ||||
|     sendAT(GF("D\""), number, "\";"); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (waitResponse(60000L, GF(GSM_NL "+CIEV: \"CALL\",1"), GF(GSM_NL "+CIEV: \"CALL\",0")) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     int rsp = waitResponse(60000L, GF(GSM_NL "+CIEV: \"SOUNDER\",0"), GF(GSM_NL "+CIEV: \"CALL\",0")); | ||||
|  | ||||
|     int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL), GF(GSM_NL "NO ANSWER" GSM_NL)); | ||||
|  | ||||
|     return rsp == 1 && rsp2 == 0; | ||||
|   } | ||||
|  | ||||
|   bool callHangup(const String& number) { | ||||
|     sendAT(GF("H"), number); | ||||
|   //bool callRedial() { | ||||
|   //  sendAT(GF("DLST")); | ||||
|   //  return waitResponse() == 1; | ||||
|   //} | ||||
|  | ||||
|   bool callHangup() { | ||||
|     sendAT(GF("H")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
| @@ -396,6 +454,32 @@ public: | ||||
|    * 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) { | ||||
|     sendAT(GF("+CMGF=1")); | ||||
|     waitResponse(); | ||||
| @@ -405,24 +489,41 @@ public: | ||||
|     } | ||||
|     stream.print(text); | ||||
|     stream.write((char)0x1A); | ||||
|     stream.flush(); | ||||
|     return waitResponse(60000L) == 1; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* | ||||
|    * Location functions | ||||
|    */ | ||||
|  | ||||
|   String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * 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: | ||||
|   int modemConnect(const char* host, uint16_t port, uint8_t* mux) { | ||||
|  | ||||
|   bool modemConnect(const char* host, uint16_t port, uint8_t* mux) { | ||||
|     sendAT(GF("+CIPSTART="),  GF("\"TCP"), GF("\",\""), host, GF("\","), port); | ||||
|  | ||||
|     if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { | ||||
|       return -1; | ||||
|       return false; | ||||
|     } | ||||
|     int newMux = streamReadUntil('\n').toInt(); | ||||
|  | ||||
| @@ -431,7 +532,7 @@ private: | ||||
|                            GF("CONNECT FAIL" GSM_NL), | ||||
|                            GF("ALREADY CONNECT" GSM_NL)); | ||||
|     if (waitResponse() != 1) { | ||||
|       return -1; | ||||
|       return false; | ||||
|     } | ||||
|     *mux = newMux; | ||||
|  | ||||
| @@ -440,7 +541,7 @@ private: | ||||
|  | ||||
|   int modemSend(const void* buff, size_t len, uint8_t mux) { | ||||
|     sendAT(GF("+CIPSEND="), mux, ',', len); | ||||
|     if (waitResponse(10000L, GF(GSM_NL ">")) != 1) { | ||||
|     if (waitResponse(2000L, GF(GSM_NL ">")) != 1) { | ||||
|       return -1; | ||||
|     } | ||||
|     stream.write((uint8_t*)buff, len); | ||||
| @@ -451,14 +552,61 @@ private: | ||||
|     return len; | ||||
|   } | ||||
|  | ||||
|   bool modemGetConnected(uint8_t mux) { //TODO mux? | ||||
|     sendAT(GF("+CIPSTATUS")); | ||||
|   bool modemGetConnected(uint8_t mux) { | ||||
|     sendAT(GF("+CIPSTATUS")); //TODO mux? | ||||
|     int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\"")); | ||||
|     waitResponse(); | ||||
|     return 1 == res; | ||||
|   } | ||||
|  | ||||
|   /* 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> | ||||
|   void streamWrite(T last) { | ||||
|     stream.print(last); | ||||
| @@ -470,17 +618,6 @@ private: | ||||
|     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) { | ||||
|     String skipped = stream.readStringUntil(c); | ||||
|     skipped.trim(); | ||||
| @@ -520,7 +657,7 @@ private: | ||||
|     do { | ||||
|       TINY_GSM_YIELD(); | ||||
|       while (stream.available() > 0) { | ||||
|         int a = streamRead(); | ||||
|         int a = stream.read(); | ||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||
|         data += (char)a; | ||||
|         if (r1 && data.endsWith(r1)) { | ||||
| @@ -539,24 +676,25 @@ private: | ||||
|           index = 5; | ||||
|           goto finish; | ||||
|         } else if (data.endsWith(GF("+CIPRCV:"))) { | ||||
|           mux = stream.readStringUntil(',').toInt(); | ||||
|           data += mux; | ||||
|           data += (','); | ||||
|           len = stream.readStringUntil(',').toInt(); | ||||
|           data += len; | ||||
|           data += (','); | ||||
|           gotData = true; | ||||
|           index = 6; | ||||
|           goto finish; | ||||
|           int mux = stream.readStringUntil(',').toInt(); | ||||
|           int len = stream.readStringUntil(',').toInt(); | ||||
|           if (len > sockets[mux]->rx.free()) { | ||||
|             DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); | ||||
|           } else { | ||||
|             DBG("### Got: ", len, "->", sockets[mux]->rx.free()); | ||||
|           } | ||||
|           while (len--) { | ||||
|             while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|             sockets[mux]->rx.put(stream.read()); | ||||
|           } | ||||
|           data = ""; | ||||
|         } else if (data.endsWith(GF("+TCPCLOSED:"))) { | ||||
|           mux = stream.readStringUntil(',').toInt(); | ||||
|           data += mux; | ||||
|           data += (','); | ||||
|           String concl = stream.readStringUntil('\n'); | ||||
|           data += concl; | ||||
|          sockets[mux]->sock_connected = false; | ||||
|           index = 7; | ||||
|           goto finish; | ||||
|           int mux = stream.readStringUntil('\n').toInt(); | ||||
|           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||
|             sockets[mux]->sock_connected = false; | ||||
|           } | ||||
|           data = ""; | ||||
|           DBG("### Closed: ", mux); | ||||
|         } | ||||
|       } | ||||
|     } while (millis() - startMillis < timeout); | ||||
| @@ -611,9 +749,7 @@ private: | ||||
|  | ||||
| private: | ||||
|   Stream&       stream; | ||||
|   GsmClient*    sockets[8]; | ||||
|   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||
| }; | ||||
|  | ||||
| typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| /** | ||||
|  * @file       TinyWiFiClientESP8266.h | ||||
|  * @file       TinyGsmClientESP8266.h | ||||
|  * @author     Volodymyr Shymanskyy | ||||
|  * @license    LGPL-3.0 | ||||
|  * @copyright  Copyright (c) 2016 Volodymyr Shymanskyy | ||||
|  * @date       Nov 2016 | ||||
|  */ | ||||
|  | ||||
| #ifndef TinyWiFiClientESP8266_h | ||||
| #define TinyWiFiClientESP8266_h | ||||
| #ifndef TinyGsmClientESP8266_h | ||||
| #define TinyGsmClientESP8266_h | ||||
|  | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
|  | ||||
| @@ -15,21 +15,18 @@ | ||||
|   #define TINY_GSM_RX_BUFFER 256 | ||||
| #endif | ||||
|  | ||||
| #define TINY_GSM_MUX_COUNT 5 | ||||
|  | ||||
| #include <TinyGsmCommon.h> | ||||
|  | ||||
| #define GSM_NL "\r\n" | ||||
| static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; | ||||
| static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; | ||||
| static unsigned int TCP_KEEP_ALIVE = 120; | ||||
| static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; | ||||
|  | ||||
| class TinyGsm | ||||
| { | ||||
|  | ||||
| public: | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   {} | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| @@ -94,7 +91,7 @@ public: | ||||
|  | ||||
|   virtual int available() { | ||||
|     TINY_GSM_YIELD(); | ||||
|     if (!rx.size()) { | ||||
|     if (!rx.size() && sock_connected) { | ||||
|       at->maintain(); | ||||
|     } | ||||
|     return rx.size(); | ||||
| @@ -138,6 +135,13 @@ public: | ||||
|     return sock_connected; | ||||
|   } | ||||
|   virtual operator bool() { return connected(); } | ||||
|  | ||||
|   /* | ||||
|    * Extended API | ||||
|    */ | ||||
|  | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   uint8_t       mux; | ||||
| @@ -147,6 +151,12 @@ private: | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Basic functions | ||||
|    */ | ||||
| @@ -273,20 +283,21 @@ public: | ||||
|     return waitResponse(10000L) == 1; | ||||
|   } | ||||
|  | ||||
|   String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   /* | ||||
|    * GPRS functions | ||||
|    */ | ||||
|   bool gprsConnect(const char* apn, const char* user, const char* pwd) { | ||||
|     return false; | ||||
|   } | ||||
|   bool gprsConnect(const char* apn, const char* user, const char* pwd) TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
|   bool gprsDisconnect() { | ||||
|     return false; | ||||
|   } | ||||
|   bool gprsDisconnect() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|  | ||||
|   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, | ||||
|                            GFP(GSM_OK), | ||||
|                            GFP(GSM_ERROR), | ||||
| @@ -301,6 +312,7 @@ private: | ||||
|       return -1; | ||||
|     } | ||||
|     stream.write((uint8_t*)buff, len); | ||||
|     stream.flush(); | ||||
|     if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) { | ||||
|       return -1; | ||||
|     } | ||||
| @@ -314,7 +326,10 @@ private: | ||||
|     return 1 == res; | ||||
|   } | ||||
|  | ||||
|   /* Private Utilities */ | ||||
| public: | ||||
|  | ||||
|   /* Utilities */ | ||||
|  | ||||
|   template<typename T> | ||||
|   void streamWrite(T last) { | ||||
|     stream.print(last); | ||||
| @@ -326,7 +341,14 @@ private: | ||||
|     streamWrite(tail...); | ||||
|   } | ||||
|  | ||||
|   int streamRead() { return stream.read(); } | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   String streamReadUntil(char c) { | ||||
|     String return_string = stream.readStringUntil(c); | ||||
| @@ -376,7 +398,7 @@ private: | ||||
|     do { | ||||
|       TINY_GSM_YIELD(); | ||||
|       while (stream.available() > 0) { | ||||
|         int a = streamRead(); | ||||
|         int a = stream.read(); | ||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||
|         data += (char)a; | ||||
|         if (r1 && data.endsWith(r1)) { | ||||
| @@ -395,16 +417,20 @@ private: | ||||
|           index = 5; | ||||
|           goto finish; | ||||
|         } else if (data.endsWith(GF(GSM_NL "+IPD,"))) { | ||||
|           mux = stream.readStringUntil(',').toInt(); | ||||
|           data += mux; | ||||
|           data += (','); | ||||
|           len = stream.readStringUntil(':').toInt(); | ||||
|           data += len; | ||||
|           data += (':'); | ||||
|           gotData = true; | ||||
|           index = 6; | ||||
|           goto finish; | ||||
|         } else if (data.endsWith(GF("1,CLOSED" GSM_NL))) { //TODO: use mux | ||||
|           int mux = stream.readStringUntil(',').toInt(); | ||||
|           int len = stream.readStringUntil(':').toInt(); | ||||
|           if (len > sockets[mux]->rx.free()) { | ||||
|             DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); | ||||
|           } else { | ||||
|             DBG("### Got: ", len, "->", sockets[mux]->rx.free()); | ||||
|           } | ||||
|           while (len--) { | ||||
|             while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|             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; | ||||
|           index = 7; | ||||
|           goto finish; | ||||
| @@ -462,9 +488,7 @@ private: | ||||
|  | ||||
| private: | ||||
|   Stream&       stream; | ||||
|   GsmClient*    sockets[5]; | ||||
|   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||
| }; | ||||
|  | ||||
| typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -15,6 +15,8 @@ | ||||
|   #define TINY_GSM_RX_BUFFER 256 | ||||
| #endif | ||||
|  | ||||
| #define TINY_GSM_MUX_COUNT 2 | ||||
|  | ||||
| #include <TinyGsmCommon.h> | ||||
|  | ||||
| #define GSM_NL "\r\n" | ||||
| @@ -40,11 +42,6 @@ enum RegStatus { | ||||
| class TinyGsm | ||||
| { | ||||
|  | ||||
| public: | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   {} | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| @@ -108,7 +105,7 @@ public: | ||||
|  | ||||
|   virtual int available() { | ||||
|     TINY_GSM_YIELD(); | ||||
|     if (!rx.size()) { | ||||
|     if (!rx.size() && sock_connected) { | ||||
|       at->maintain(); | ||||
|     } | ||||
|     return rx.size(); | ||||
| @@ -152,6 +149,13 @@ public: | ||||
|     return sock_connected; | ||||
|   } | ||||
|   virtual operator bool() { return connected(); } | ||||
|  | ||||
|   /* | ||||
|    * Extended API | ||||
|    */ | ||||
|  | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   uint8_t       mux; | ||||
| @@ -161,6 +165,12 @@ private: | ||||
|  | ||||
| public: | ||||
|  | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   { | ||||
|     memset(sockets, 0, sizeof(sockets)); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Basic functions | ||||
|    */ | ||||
| @@ -216,6 +226,18 @@ public: | ||||
|     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 | ||||
|    */ | ||||
| @@ -233,6 +255,11 @@ public: | ||||
|     return init(); | ||||
|   } | ||||
|  | ||||
|   bool poweroff() { | ||||
|     sendAT(GF("+CPWROFF")); | ||||
|     return waitResponse(3000L) == 1; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * SIM card functions | ||||
|    */ | ||||
| @@ -303,16 +330,16 @@ public: | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|  /* | ||||
|   * Generic network functions | ||||
|   */ | ||||
|   /* | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CSQ")); | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
|       return 99; | ||||
|     } | ||||
|     int res = streamReadUntil(',').toInt(); | ||||
|     int res = stream.readStringUntil(',').toInt(); | ||||
|     waitResponse(); | ||||
|     return res; | ||||
|   } | ||||
| @@ -364,13 +391,15 @@ public: | ||||
|     sendAT(GF("+XIIC?")); | ||||
|     waitResponse(); | ||||
|  | ||||
|     /*sendAT(GF("+DNSSERVER=1,8.8.8.8")); | ||||
|     /* | ||||
|     sendAT(GF("+DNSSERVER=1,8.8.8.8")); | ||||
|     waitResponse(); | ||||
|  | ||||
|     sendAT(GF("+DNSSERVER=2,8.8.4.4")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     }*/ | ||||
|     } | ||||
|     */ | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
| @@ -380,30 +409,72 @@ public: | ||||
|     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 | ||||
|    */ | ||||
|  | ||||
|   bool callAnswer() { | ||||
|     sendAT(GF("A")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|   bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callNumber(const String& number) { | ||||
|     sendAT(GF("D"), number); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|   bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callHangup(const String& number) { | ||||
|     sendAT(GF("H"), number); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|   bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callRedial() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * 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) { | ||||
|     sendAT(GF("+CSCS=\"GSM\"")); | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CMGF=1")); | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CMGS=\""), number, GF("\"")); | ||||
| @@ -412,31 +483,31 @@ public: | ||||
|     } | ||||
|     stream.print(text); | ||||
|     stream.write((char)0x1A); | ||||
|     stream.flush(); | ||||
|     return waitResponse(60000L) == 1; | ||||
|   } | ||||
|  | ||||
|   bool sendSMS_UTF16(const String& number, const void* text, size_t len) | ||||
|   TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * Location functions | ||||
|    */ | ||||
|  | ||||
|   String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   /* | ||||
|    * Battery functions | ||||
|    */ | ||||
|  | ||||
| private: | ||||
|   String dnsIpQuery(const char* host) { | ||||
|    sendAT(GF("+DNS=\""), host, GF("\"")); | ||||
|    if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) { | ||||
|      return ""; | ||||
|    } | ||||
|    String res = streamReadUntil('\n'); | ||||
|    waitResponse(GF("+DNS:OK" GSM_NL)); | ||||
|    res.trim(); | ||||
|    return res; | ||||
|   } | ||||
|   uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
|   int modemConnect(const char* host, uint16_t port, uint8_t mux) { | ||||
|     for (int i=0; i<3; i++) { | ||||
|   int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; | ||||
|  | ||||
| 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); | ||||
|  | ||||
|       sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); | ||||
| @@ -462,7 +533,7 @@ private: | ||||
|     } | ||||
|     stream.write((uint8_t*)buff, len); | ||||
|     stream.write((char)0x0D); | ||||
|  | ||||
|     stream.flush(); | ||||
|     if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { | ||||
|       return 0; | ||||
|     } | ||||
| @@ -477,7 +548,52 @@ private: | ||||
|     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> | ||||
|   void streamWrite(T last) { | ||||
|     stream.print(last); | ||||
| @@ -489,26 +605,13 @@ private: | ||||
|     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) { | ||||
|     String skipped = stream.readStringUntil(c); | ||||
|     skipped.trim(); | ||||
|     if (skipped.length()) { | ||||
|       if (String(c) == GSM_NL || String(c) == "\n"){ | ||||
|         DBG(skipped, c, "    "); | ||||
|       } else DBG(skipped, c); | ||||
|       return true; | ||||
|     } else return false; | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   template<typename... Args> | ||||
| @@ -539,7 +642,7 @@ private: | ||||
|     do { | ||||
|       TINY_GSM_YIELD(); | ||||
|       while (stream.available() > 0) { | ||||
|         int a = streamRead(); | ||||
|         int a = stream.read(); | ||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||
|         data += (char)a; | ||||
|         if (r1 && data.endsWith(r1)) { | ||||
| @@ -558,24 +661,26 @@ private: | ||||
|           index = 5; | ||||
|           goto finish; | ||||
|         } else if (data.endsWith(GF("+TCPRECV:"))) { | ||||
|           mux = stream.readStringUntil(',').toInt(); | ||||
|           data += mux; | ||||
|           data += (','); | ||||
|           len = stream.readStringUntil(',').toInt(); | ||||
|           data += len; | ||||
|           data += (','); | ||||
|           gotData = true; | ||||
|           index = 6; | ||||
|           goto finish; | ||||
|           int mux = stream.readStringUntil(',').toInt(); | ||||
|           int len = stream.readStringUntil(',').toInt(); | ||||
|           if (len > sockets[mux]->rx.free()) { | ||||
|             DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); | ||||
|           } else { | ||||
|             DBG("### Got: ", len, "->", sockets[mux]->rx.free()); | ||||
|           } | ||||
|           while (len--) { | ||||
|             while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|             sockets[mux]->rx.put(stream.read()); | ||||
|           } | ||||
|           data = ""; | ||||
|         } else if (data.endsWith(GF("+TCPCLOSE:"))) { | ||||
|           mux = stream.readStringUntil(',').toInt(); | ||||
|           data += mux; | ||||
|           data += (','); | ||||
|           String concl = stream.readStringUntil('\n'); | ||||
|           data += concl; | ||||
|           sockets[mux]->sock_connected = false; | ||||
|           index = 7; | ||||
|           goto finish; | ||||
|           int mux = stream.readStringUntil(',').toInt(); | ||||
|           stream.readStringUntil('\n'); | ||||
|           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||
|             sockets[mux]->sock_connected = false; | ||||
|           } | ||||
|           data = ""; | ||||
|           DBG("### Closed: ", mux); | ||||
|         } | ||||
|       } | ||||
|     } while (millis() - startMillis < timeout); | ||||
| @@ -630,9 +735,7 @@ private: | ||||
|  | ||||
| private: | ||||
|   Stream&       stream; | ||||
|   GsmClient*    sockets[2]; | ||||
|   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||
| }; | ||||
|  | ||||
| typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -16,6 +16,8 @@ | ||||
|   #define TINY_GSM_RX_BUFFER 64 | ||||
| #endif | ||||
|  | ||||
| #define TINY_GSM_MUX_COUNT 5 | ||||
|  | ||||
| #include <TinyGsmCommon.h> | ||||
|  | ||||
| #define GSM_NL "\r\n" | ||||
| @@ -38,33 +40,30 @@ enum RegStatus { | ||||
| }; | ||||
|  | ||||
|  | ||||
| class TinyGsm | ||||
| class TinyGsmSim800 | ||||
| { | ||||
|  | ||||
| public: | ||||
|   TinyGsm(Stream& stream) | ||||
|     : stream(stream) | ||||
|   {} | ||||
|  | ||||
| public: | ||||
|  | ||||
| class GsmClient : public Client | ||||
| { | ||||
|   friend class TinyGsm; | ||||
|   friend class TinyGsmSim800; | ||||
|   typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo; | ||||
|  | ||||
| public: | ||||
|   GsmClient() {} | ||||
|  | ||||
|   GsmClient(TinyGsm& modem, uint8_t mux = 1) { | ||||
|   GsmClient(TinyGsmSim800& modem, uint8_t mux = 1) { | ||||
|     init(&modem, mux); | ||||
|   } | ||||
|  | ||||
|   bool init(TinyGsm* modem, uint8_t mux = 1) { | ||||
|   bool init(TinyGsmSim800* modem, uint8_t mux = 1) { | ||||
|     this->at = modem; | ||||
|     this->mux = mux; | ||||
|     sock_available = 0; | ||||
|     prev_check = 0; | ||||
|     sock_connected = false; | ||||
|     got_data = false; | ||||
|  | ||||
|     at->sockets[mux] = this; | ||||
|  | ||||
| @@ -110,7 +109,14 @@ public: | ||||
|  | ||||
|   virtual int available() { | ||||
|     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(); | ||||
|     } | ||||
|     return rx.size() + sock_available; | ||||
| @@ -157,15 +163,48 @@ public: | ||||
|     return sock_connected; | ||||
|   } | ||||
|   virtual operator bool() { return connected(); } | ||||
|  | ||||
|   /* | ||||
|    * Extended API | ||||
|    */ | ||||
|  | ||||
|   String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; | ||||
|  | ||||
| private: | ||||
|   TinyGsm*      at; | ||||
|   TinyGsmSim800*      at; | ||||
|   uint8_t       mux; | ||||
|   uint16_t      sock_available; | ||||
|   uint32_t      prev_check; | ||||
|   bool          sock_connected; | ||||
|   bool          got_data; | ||||
|   RxFifo        rx; | ||||
| }; | ||||
|  | ||||
| class GsmClientSecure : public GsmClient | ||||
| { | ||||
| 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 | ||||
| @@ -178,7 +217,9 @@ public: | ||||
|     if (!autoBaud()) { | ||||
|       return false; | ||||
|     } | ||||
|     sendAT(GF("&FZE0"));  // Factory + Reset + Echo Off | ||||
|     sendAT(GF("&FZ"));  // Factory + Reset | ||||
|     waitResponse(); | ||||
|     sendAT(GF("E0"));   // Echo Off | ||||
|     if (waitResponse() != 1) { | ||||
|       return false; | ||||
|     } | ||||
| @@ -187,7 +228,7 @@ public: | ||||
|   } | ||||
|  | ||||
|   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; ) { | ||||
|       sendAT(GF("")); | ||||
|       if (waitResponse(200) == 1) { | ||||
| @@ -200,6 +241,13 @@ public: | ||||
|   } | ||||
|  | ||||
|   void maintain() { | ||||
|     for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { | ||||
|       GsmClient* sock = sockets[mux]; | ||||
|       if (sock && sock->got_data) { | ||||
|         sock->got_data = false; | ||||
|         sock->sock_available = modemGetAvailable(mux); | ||||
|       } | ||||
|     } | ||||
|     while (stream.available()) { | ||||
|       waitResponse(10, NULL, NULL); | ||||
|     } | ||||
| @@ -220,6 +268,26 @@ public: | ||||
|     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 | ||||
|    */ | ||||
| @@ -240,6 +308,23 @@ public: | ||||
|     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 | ||||
|    */ | ||||
| @@ -310,16 +395,16 @@ public: | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|  /* | ||||
|   * Generic network functions | ||||
|   */ | ||||
|   /* | ||||
|    * Generic network functions | ||||
|    */ | ||||
|  | ||||
|   int getSignalQuality() { | ||||
|     sendAT(GF("+CSQ")); | ||||
|     if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { | ||||
|       return 99; | ||||
|     } | ||||
|     int res = streamReadUntil(',').toInt(); | ||||
|     int res = stream.readStringUntil(',').toInt(); | ||||
|     waitResponse(); | ||||
|     return res; | ||||
|   } | ||||
| @@ -413,9 +498,7 @@ public: | ||||
|     } | ||||
|  | ||||
|     sendAT(GF("+CIFSR;E0")); | ||||
|     String data; | ||||
|     if (waitResponse(10000L, data) != 1) { | ||||
|       data.replace(GSM_NL, ""); | ||||
|     if (waitResponse(10000L) != 1) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| @@ -432,6 +515,22 @@ public: | ||||
|     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 | ||||
|    */ | ||||
| @@ -446,13 +545,25 @@ public: | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
|   // Returns true on pick-up, false on error/busy | ||||
|   bool callNumber(const String& number) { | ||||
|     sendAT(GF("D"), number); | ||||
|     return waitResponse() == 1; | ||||
|     sendAT(GF("D"), number, ";"); | ||||
|     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) { | ||||
|     sendAT(GF("H"), number); | ||||
|   //bool callRedial() { | ||||
|   //  sendAT(GF("DL")); | ||||
|   //  return waitResponse() == 1; | ||||
|   //} | ||||
|  | ||||
|   bool callHangup() { | ||||
|     sendAT(GF("H")); | ||||
|     return waitResponse() == 1; | ||||
|   } | ||||
|  | ||||
| @@ -460,6 +571,32 @@ public: | ||||
|    * Messaging functions | ||||
|    */ | ||||
|  | ||||
|   String sendUSSD(const String& code) { | ||||
|     sendAT(GF("+CMGF=1")); | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CSCS=\"HEX\"")); | ||||
|     waitResponse(); | ||||
|     sendAT(GF("+CUSD=1,\""), code, GF("\"")); | ||||
|     if (waitResponse() != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     stream.readStringUntil('"'); | ||||
|     String hex = stream.readStringUntil('"'); | ||||
|     stream.readStringUntil(','); | ||||
|     int dcs = stream.readStringUntil('\n').toInt(); | ||||
|  | ||||
|     if (dcs == 15) { | ||||
|       return decodeHex8bit(hex); | ||||
|     } else if (dcs == 72) { | ||||
|       return decodeHex16bit(hex); | ||||
|     } else { | ||||
|       return hex; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   bool sendSMS(const String& number, const String& text) { | ||||
|     sendAT(GF("+CMGF=1")); | ||||
|     waitResponse(); | ||||
| @@ -469,6 +606,7 @@ public: | ||||
|     } | ||||
|     stream.print(text); | ||||
|     stream.write((char)0x1A); | ||||
|     stream.flush(); | ||||
|     return waitResponse(60000L) == 1; | ||||
|   } | ||||
|  | ||||
| @@ -495,6 +633,7 @@ public: | ||||
|       stream.print(c, HEX); | ||||
|     } | ||||
|     stream.write((char)0x1A); | ||||
|     stream.flush(); | ||||
|     return waitResponse(60000L) == 1; | ||||
|   } | ||||
|  | ||||
| @@ -505,11 +644,12 @@ public: | ||||
|  | ||||
|   String getGsmLocation() { | ||||
|     sendAT(GF("+CIPGSMLOC=1,1")); | ||||
|     if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) { | ||||
|     if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { | ||||
|       return ""; | ||||
|     } | ||||
|     String res = streamReadUntil('\n'); | ||||
|     String res = stream.readStringUntil('\n'); | ||||
|     waitResponse(); | ||||
|     res.trim(); | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
| @@ -530,13 +670,30 @@ public: | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   int modemConnect(const char* host, uint16_t port, uint8_t mux) { | ||||
|   int getBattPercent() { | ||||
|     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); | ||||
|     int rsp = waitResponse(75000L, | ||||
|                            GF("CONNECT OK" GSM_NL), | ||||
|                            GF("CONNECT FAIL" GSM_NL), | ||||
|                            GF("ALREADY CONNECT" GSM_NL)); | ||||
|     rsp = waitResponse(75000L, | ||||
|                        GF("CONNECT OK" GSM_NL), | ||||
|                        GF("CONNECT FAIL" GSM_NL), | ||||
|                        GF("ALREADY CONNECT" GSM_NL)); | ||||
|     return (1 == rsp); | ||||
|   } | ||||
|  | ||||
| @@ -573,16 +730,15 @@ private: | ||||
|  | ||||
|     for (size_t i=0; i<len; i++) { | ||||
| #ifdef TINY_GSM_USE_HEX | ||||
|       while (stream.available() < 2) {} | ||||
|       while (stream.available() < 2) { TINY_GSM_YIELD(); } | ||||
|       char buf[4] = { 0, }; | ||||
|       buf[0] = streamRead(); | ||||
|       buf[1] = streamRead(); | ||||
|       char c = strtol(buf, NULL, 16); | ||||
|       DBG(c); | ||||
| #else | ||||
|       while (!stream.available()) {} | ||||
|       char c = streamRead(); | ||||
|       DBG(c); | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|       char c = stream.read(); | ||||
| #endif | ||||
|       sockets[mux]->rx.put(c); | ||||
|     } | ||||
| @@ -612,7 +768,41 @@ private: | ||||
|     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> | ||||
|   void streamWrite(T last) { | ||||
|     stream.print(last); | ||||
| @@ -624,26 +814,13 @@ private: | ||||
|     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) { | ||||
|     String skipped = stream.readStringUntil(c); | ||||
|     skipped.trim(); | ||||
|     if (skipped.length()) { | ||||
|       if (String(c) == GSM_NL || String(c) == "\n"){ | ||||
|         DBG(skipped, c, "    "); | ||||
|       } else DBG(skipped, c); | ||||
|       return true; | ||||
|     } else return false; | ||||
|   bool streamSkipUntil(char c) { //TODO: timeout | ||||
|     while (true) { | ||||
|       while (!stream.available()) { TINY_GSM_YIELD(); } | ||||
|       if (stream.read() == c) | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   template<typename... Args> | ||||
| @@ -666,14 +843,12 @@ private: | ||||
|     String r5s(r5); r5s.trim(); | ||||
|     DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ | ||||
|     data.reserve(64); | ||||
|     bool gotData = false; | ||||
|     int mux = -1; | ||||
|     int index = 0; | ||||
|     unsigned long startMillis = millis(); | ||||
|     do { | ||||
|       TINY_GSM_YIELD(); | ||||
|       while (stream.available() > 0) { | ||||
|         int a = streamRead(); | ||||
|         int a = stream.read(); | ||||
|         if (a <= 0) continue; // Skip 0x00 bytes, just in case | ||||
|         data += (char)a; | ||||
|         if (r1 && data.endsWith(r1)) { | ||||
| @@ -695,8 +870,11 @@ private: | ||||
|           index = 6; | ||||
|           String mode = streamReadUntil(','); | ||||
|           if (mode.toInt() == 1) { | ||||
|             mux = streamReadUntil('\n').toInt(); | ||||
|             gotData = true; | ||||
|             int mux = stream.readStringUntil('\n').toInt(); | ||||
|             if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||
|               sockets[mux]->got_data = true; | ||||
|             } | ||||
|             data = ""; | ||||
|           } else { | ||||
|             data += mode; | ||||
|           } | ||||
| @@ -704,10 +882,12 @@ private: | ||||
|           index = 7; | ||||
|           int nl = data.lastIndexOf(GSM_NL, data.length()-8); | ||||
|           int coma = data.indexOf(',', nl+2); | ||||
|           mux = data.substring(nl+2, coma).toInt(); | ||||
|           if (mux) { | ||||
|           int mux = data.substring(nl+2, coma).toInt(); | ||||
|           if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { | ||||
|             sockets[mux]->sock_connected = false; | ||||
|           } | ||||
|           data = ""; | ||||
|           DBG("### Closed: ", mux); | ||||
|         } | ||||
|       } | ||||
|     } while (millis() - startMillis < timeout); | ||||
| @@ -718,17 +898,6 @@ private: | ||||
|         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; | ||||
|   } | ||||
|  | ||||
| @@ -746,11 +915,9 @@ private: | ||||
|     return waitResponse(1000, r1, r2, r3, r4, r5); | ||||
|   } | ||||
|  | ||||
| private: | ||||
| protected: | ||||
|   Stream&       stream; | ||||
|   GsmClient*    sockets[5]; | ||||
|   GsmClient*    sockets[TINY_GSM_MUX_COUNT]; | ||||
| }; | ||||
|  | ||||
| typedef TinyGsm::GsmClient TinyGsmClient; | ||||
|  | ||||
| #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); } | ||||
| #endif | ||||
|  | ||||
| #define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type"))) | ||||
| #define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) | ||||
|  | ||||
| #if defined(__AVR__) | ||||
|   #define TINY_GSM_PROGMEM PROGMEM | ||||
|   typedef const __FlashStringHelper* GsmConstStr; | ||||
| @@ -69,4 +72,26 @@ const T& TinyGsmMax(const T& a, const T& 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 | ||||
|   | ||||
							
								
								
									
										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,12 +30,13 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
| // #define TINY_GSM_MODEM_XBEE | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
| #include <BlynkSimpleSIM800.h> | ||||
| @@ -74,6 +75,10 @@ void setup() | ||||
|   Serial.println("Initializing modem..."); | ||||
|   modem.restart(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   Serial.print("Modem: "); | ||||
|   Serial.println(modemInfo); | ||||
|  | ||||
|   // Unlock your SIM card with a PIN | ||||
|   //modem.simUnlock("1234"); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /************************************************************** | ||||
|  * | ||||
|  * For this example, you need to install CRC32 library: | ||||
|  *   https://github.com/vshymanskyy/CRC32.git | ||||
|  *   https://github.com/bakercp/CRC32 | ||||
|  *   or from http://librarymanager/all#CRC32+checksum | ||||
|  * | ||||
|  * TinyGSM Getting Started guide: | ||||
| @@ -14,18 +14,19 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
| // #define TINY_GSM_MODEM_XBEE | ||||
|  | ||||
| // Increase RX buffer | ||||
| #define TINY_GSM_RX_BUFFER 1030 | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
| #include <CRC32.h> | ||||
| //#define DUMP_AT_COMMANDS | ||||
| //#define TINY_GSM_DEBUG Serial | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| @@ -40,12 +41,23 @@ const char pass[] = ""; | ||||
| //#include <SoftwareSerial.h> | ||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||
|  | ||||
| TinyGsm modem(SerialAT); | ||||
| #include <TinyGsmClient.h> | ||||
| #include <CRC32.h> | ||||
|  | ||||
| #ifdef DUMP_AT_COMMANDS | ||||
|   #include <StreamDebugger.h> | ||||
|   StreamDebugger debugger(SerialAT, Serial); | ||||
|   TinyGsm modem(debugger); | ||||
| #else | ||||
|   TinyGsm modem(SerialAT); | ||||
| #endif | ||||
| TinyGsmClient client(modem); | ||||
|  | ||||
| const char server[] = "cdn.rawgit.com"; | ||||
| const char resource[] = "/vshymanskyy/tinygsm/master/extras/test_1k.bin"; | ||||
| uint32_t knownCRC32 = 0x6f50d767; | ||||
| const int  port     = 80; | ||||
|  | ||||
| const char resource[]  = "/vshymanskyy/tinygsm/master/extras/test_1k.bin"; | ||||
| uint32_t knownCRC32    = 0x6f50d767; | ||||
| uint32_t knownFileSize = 1024;   // In case server does not send it | ||||
|  | ||||
| void setup() { | ||||
| @@ -62,6 +74,10 @@ void setup() { | ||||
|   Serial.println("Initializing modem..."); | ||||
|   modem.restart(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   Serial.print("Modem: "); | ||||
|   Serial.println(modemInfo); | ||||
|  | ||||
|   // Unlock your SIM card with a PIN | ||||
|   //modem.simUnlock("1234"); | ||||
| } | ||||
| @@ -99,7 +115,7 @@ void loop() { | ||||
|   Serial.print(server); | ||||
|  | ||||
|   // if you get a connection, report back via serial: | ||||
|   if (!client.connect(server, 80)) { | ||||
|   if (!client.connect(server, port)) { | ||||
|     Serial.println(" fail"); | ||||
|     delay(10000); | ||||
|     return; | ||||
|   | ||||
							
								
								
									
										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,12 +27,13 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
| // #define TINY_GSM_MODEM_XBEE | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
| #include <PubSubClient.h> | ||||
| @@ -81,6 +82,10 @@ void setup() { | ||||
|   Serial.println("Initializing modem..."); | ||||
|   modem.restart(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   Serial.print("Modem: "); | ||||
|   Serial.println(modemInfo); | ||||
|  | ||||
|   // Unlock your SIM card with a PIN | ||||
|   //modem.simUnlock("1234"); | ||||
|  | ||||
|   | ||||
| @@ -10,12 +10,12 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
|  | ||||
| @@ -38,7 +38,7 @@ TinyGsmClient client(modem); | ||||
| const char server[] = "cdn.rawgit.com"; | ||||
| const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | ||||
|  | ||||
| int port = 80; | ||||
| const int port = 80; | ||||
|  | ||||
| void setup() { | ||||
|   // Set console baud rate | ||||
| @@ -54,6 +54,10 @@ void setup() { | ||||
|   Serial.println(F("Initializing modem...")); | ||||
|   modem.restart(); | ||||
|  | ||||
|   String modemInfo = modem.getModemInfo(); | ||||
|   Serial.print("Modem: "); | ||||
|   Serial.println(modemInfo); | ||||
|  | ||||
|   // Unlock your SIM card with a PIN | ||||
|   //modem.simUnlock("1234"); | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| ####################################### | ||||
| TinyGsm	KEYWORD1 | ||||
| TinyGsmClient	KEYWORD1 | ||||
| TinyGsmClientSecure	KEYWORD1 | ||||
|  | ||||
| SerialAT	KEYWORD1 | ||||
| SerialMon	KEYWORD1 | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "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", | ||||
|   "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968", | ||||
|   "authors": | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| name=TinyGSM | ||||
| version=0.1.8 | ||||
| version=0.3.1 | ||||
| author=Volodymyr Shymanskyy | ||||
| maintainer=Volodymyr Shymanskyy | ||||
| sentence=A small Arduino library for GPRS modules, that just works. | ||||
|   | ||||
| @@ -10,12 +10,13 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
| // #define TINY_GSM_MODEM_XBEE | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
|  | ||||
| @@ -30,7 +31,9 @@ | ||||
| //#include <SoftwareSerial.h> | ||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||
|  | ||||
| TinyGsm modem(SerialAT); | ||||
| #define TINY_GSM_DEBUG SerialMon | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
|  | ||||
| // Module baud rate | ||||
| uint32_t rate = 0; // Set to 0 for Auto-Detect | ||||
| @@ -44,21 +47,7 @@ void setup() { | ||||
| void loop() { | ||||
|  | ||||
|   if (!rate) { | ||||
|       static uint32_t rates[] = { 115200, 9600, 57600, 19200, 38400, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 }; | ||||
|  | ||||
|       SerialMon.println("Autodetecting baud rate"); | ||||
|       for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) { | ||||
|         SerialMon.print(String("Trying baud rate ") + rates[i] + "... "); | ||||
|         SerialAT.begin(rates[i]); | ||||
|         delay(10); | ||||
|         if (modem.autoBaud(1000)) { | ||||
|           rate = rates[i]; | ||||
|           SerialMon.println(F("OK")); | ||||
|           break; | ||||
|         } else { | ||||
|           SerialMon.println(F("fail")); | ||||
|         } | ||||
|       } | ||||
|     rate = TinyGsmAutoBaud(SerialAT); | ||||
|   } | ||||
|  | ||||
|   if (!rate) { | ||||
|   | ||||
| @@ -11,18 +11,18 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
| // #define TINY_GSM_MODEM_XBEE | ||||
|  | ||||
| // Increase buffer fo see less commands | ||||
| #define TINY_GSM_RX_BUFFER 256 | ||||
| // Increase the buffer | ||||
| #define TINY_GSM_RX_BUFFER 512 | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
| #include <StreamDebugger.h> | ||||
|  | ||||
| // Your GPRS credentials | ||||
| // Leave empty, if missing user or pass | ||||
| @@ -42,12 +42,13 @@ const char pass[] = ""; | ||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||
|  | ||||
|  | ||||
| #include <StreamDebugger.h> | ||||
| StreamDebugger debugger(SerialAT, SerialMon); | ||||
| TinyGsm modem(debugger); | ||||
| TinyGsmClient client(modem); | ||||
|  | ||||
| const char server[] = "cdn.rawgit.com"; | ||||
| const char resource[] = "/vshymanskyy/tinygsm/master/extras/test_simple.txt"; | ||||
| const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | ||||
|  | ||||
| void setup() { | ||||
|   // Set console baud rate | ||||
| @@ -144,9 +145,9 @@ void loop() { | ||||
|   SerialMon.println("************************"); | ||||
|   SerialMon.print  (" Received: "); | ||||
|   SerialMon.print(bytesReceived); | ||||
|   SerialMon.println("bytes"); | ||||
|   SerialMon.println(" bytes"); | ||||
|   SerialMon.print  (" Test:     "); | ||||
|   SerialMon.println((bytesReceived == 1000) ? "PASSED" : "FAIL"); | ||||
|   SerialMon.println((bytesReceived == 121) ? "PASSED" : "FAILED"); | ||||
|   SerialMon.println("************************"); | ||||
|  | ||||
|   // Do nothing forevermore | ||||
|   | ||||
| @@ -11,15 +11,15 @@ | ||||
|  | ||||
| // 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 | ||||
| // #define TINY_GSM_MODEM_XBEE  | ||||
| // #define TINY_GSM_MODEM_XBEE | ||||
|  | ||||
| #include <TinyGsmClient.h> | ||||
| #include <StreamDebugger.h> | ||||
|  | ||||
| // Set serial for debug console (to the Serial Monitor, speed 115200) | ||||
| #define SerialMon Serial | ||||
| @@ -32,6 +32,7 @@ | ||||
| //#include <SoftwareSerial.h> | ||||
| //SoftwareSerial SerialAT(2, 3); // RX, TX | ||||
|  | ||||
| #include <StreamDebugger.h> | ||||
| StreamDebugger debugger(SerialAT, SerialMon); | ||||
| TinyGsm modem(debugger); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user