From 640b8466620afce3ccc3a7bf81c610eaa6c9e8c2 Mon Sep 17 00:00:00 2001 From: JP Meijers Date: Thu, 13 Jun 2019 12:20:03 +0200 Subject: [PATCH 1/4] Use CREG to check registration status. Do not check if GPRS is connected as it will fail due to APN not being set. --- src/TinyGsmClientSaraR4.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TinyGsmClientSaraR4.h b/src/TinyGsmClientSaraR4.h index 67291d5..e6cb5a6 100644 --- a/src/TinyGsmClientSaraR4.h +++ b/src/TinyGsmClientSaraR4.h @@ -329,7 +329,7 @@ TINY_GSM_MODEM_GET_SIMCCID_CCID() } -TINY_GSM_MODEM_GET_REGISTRATION_XREG(CEREG) +TINY_GSM_MODEM_GET_REGISTRATION_XREG(CREG) TINY_GSM_MODEM_GET_OPERATOR_COPS() @@ -343,8 +343,8 @@ TINY_GSM_MODEM_GET_CSQ() RegStatus s = getRegistrationStatus(); if (s == REG_OK_HOME || s == REG_OK_ROAMING) return true; - else if (s == REG_UNKNOWN) // for some reason, it can hang at unknown.. - return isGprsConnected(); + // else if (s == REG_UNKNOWN) // for some reason, it can hang at unknown.. + // return isGprsConnected(); else return false; } From bd67dd63541fd34e6bf65a227e6bfd6900e3d091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanislav=20H=C3=A1jek?= Date: Fri, 2 Aug 2019 09:54:03 +0200 Subject: [PATCH 2/4] Added support for 7600 (tweak needed) --- src/TinyGsmClient.h | 6 + src/TinyGsmClientSIM7600.h | 880 +++++++++++++++++++++++++++++++++++++ 2 files changed, 886 insertions(+) create mode 100644 src/TinyGsmClientSIM7600.h diff --git a/src/TinyGsmClient.h b/src/TinyGsmClient.h index 78eb27b..f1698a8 100644 --- a/src/TinyGsmClient.h +++ b/src/TinyGsmClient.h @@ -40,6 +40,12 @@ typedef TinyGsmSim7000::GsmClient TinyGsmClient; // typedef TinyGsmSim7000::GsmClientSecure TinyGsmClientSecure; TODO! +#elif defined(TINY_GSM_MODEM_SIM7600) + #define TINY_GSM_MODEM_HAS_GPRS + #include + typedef TinyGsmSim7600 TinyGsm; + typedef TinyGsmSim7600::GsmClient TinyGsmClient; + #elif defined(TINY_GSM_MODEM_SIM5360) || defined(TINY_GSM_MODEM_SIM5320) #define TINY_GSM_MODEM_HAS_GPRS #include diff --git a/src/TinyGsmClientSIM7600.h b/src/TinyGsmClientSIM7600.h new file mode 100644 index 0000000..112f6e2 --- /dev/null +++ b/src/TinyGsmClientSIM7600.h @@ -0,0 +1,880 @@ +/** + * @file TinyGsmClientSIM7600.h + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef TinyGsmClientSIM7600_h +#define TinyGsmClientSIM7600_h + +// #define TINY_GSM_DEBUG Serial +//#define TINY_GSM_USE_HEX + +#if !defined(TINY_GSM_RX_BUFFER) + #define TINY_GSM_RX_BUFFER 64 +#endif + +#define TINY_GSM_MUX_COUNT 10 + +#include + +#define GSM_NL "\r\n" +static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; +static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; + +enum SimStatus { + SIM_ERROR = 0, + SIM_READY = 1, + SIM_LOCKED = 2, +}; + +enum RegStatus { + REG_UNREGISTERED = 0, + REG_SEARCHING = 2, + REG_DENIED = 3, + REG_OK_HOME = 1, + REG_OK_ROAMING = 5, + REG_UNKNOWN = 4, +}; + +enum TinyGSMDateTimeFormat { + DATE_FULL = 0, + DATE_TIME = 1, + DATE_DATE = 2 +}; + +class TinyGsmSim7600 +{ + +public: + +class GsmClient : public Client +{ + friend class TinyGsmSim7600; + typedef TinyGsmFifo RxFifo; + +public: + GsmClient() {} + + GsmClient(TinyGsmSim7600& modem, uint8_t mux = 0) { + init(&modem, mux); + } + + virtual ~GsmClient(){} + + bool init(TinyGsmSim7600* modem, uint8_t mux = 0) { + this->at = modem; + this->mux = mux; + sock_available = 0; + prev_check = 0; + sock_connected = false; + got_data = false; + + at->sockets[mux] = this; + + return true; + } + +public: + virtual int connect(const char *host, uint16_t port, int timeout_s) { + stop(); + TINY_GSM_YIELD(); + rx.clear(); + sock_connected = at->modemConnect(host, port, mux, false, timeout_s); + return sock_connected; + } + +TINY_GSM_CLIENT_CONNECT_OVERLOADS() + + virtual void stop(uint32_t maxWaitMs) { + TINY_GSM_CLIENT_DUMP_MODEM_BUFFER() + at->sendAT(GF("+CIPCLOSE="), mux); + sock_connected = false; + at->waitResponse(); + } + + virtual void stop() { stop(15000L); } + +TINY_GSM_CLIENT_WRITE() + +TINY_GSM_CLIENT_AVAILABLE_WITH_BUFFER_CHECK() + +TINY_GSM_CLIENT_READ_WITH_BUFFER_CHECK() + +TINY_GSM_CLIENT_PEEK_FLUSH_CONNECTED() + + /* + * Extended API + */ + + String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; + +private: + TinyGsmSim7600* at; + uint8_t mux; + uint16_t sock_available; + uint32_t prev_check; + bool sock_connected; + bool got_data; + RxFifo rx; +}; + + +public: + + TinyGsmSim7600(Stream& stream) + : stream(stream) + { + memset(sockets, 0, sizeof(sockets)); + } + + virtual ~TinyGsmSim7600(){} + + /* + * Basic functions + */ + + bool begin(const char* pin = NULL) { + return init(pin); + } + + bool init(const char* pin = NULL) { + DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); + if (!testAT()) { + return false; + } + sendAT(GF("E0")); // Echo Off + if (waitResponse() != 1) { + return false; + } + DBG(GF("### Modem:"), getModemName()); + getSimStatus(); + return true; + } + + String getModemName() { + String name = "SIMCom SIM7600"; + + sendAT(GF("+CGMM")); + String res2; + if (waitResponse(1000L, res2) != 1) { + return name; + } + res2.replace(GSM_NL "OK" GSM_NL, ""); + res2.replace("_", " "); + res2.trim(); + + name = res2; + DBG("### Modem:", name); + return name; + } + +TINY_GSM_MODEM_SET_BAUD_IPR() + +TINY_GSM_MODEM_TEST_AT() + +TINY_GSM_MODEM_MAINTAIN_CHECK_SOCKS() + + bool factoryDefault() { // these commands aren't supported + return false; + } + +TINY_GSM_MODEM_GET_INFO_ATI() + + bool hasSSL() { + return false; // TODO: Module supports SSL, but not yet implemented + } + + bool hasWifi() { + return false; + } + + bool hasGPRS() { + return true; + } + + /* + * Power functions + */ + + bool restart() { + if (!testAT()) { + return false; + } + sendAT(GF("+CRESET")); + if (waitResponse(10000L) != 1) { + return false; + } + delay(5000L); // TODO: Test this delay! + return init(); + } + + bool poweroff() { + sendAT(GF("+CPOF")); + return waitResponse() == 1; + } + + bool radioOff() { + sendAT(GF("+CFUN=4")); + if (waitResponse(10000L) != 1) { + return false; + } + delay(3000); + return true; + } + + bool sleepEnable(bool enable = true) { + sendAT(GF("+CSCLK="), enable); + return waitResponse() == 1; + } + + /* + * SIM card functions + */ + +TINY_GSM_MODEM_SIM_UNLOCK_CPIN() + +// Gets the CCID of a sim card via AT+CCID + String getSimCCID() { + sendAT(GF("+CICCID")); + if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } + +TINY_GSM_MODEM_GET_IMEI_GSN() + + SimStatus getSimStatus(unsigned long timeout_ms = 10000L) { + for (unsigned long start = millis(); millis() - start < timeout_ms; ) { + sendAT(GF("+CPIN?")); + if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) { + delay(1000); + continue; + } + int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK")); + waitResponse(); + switch (status) { + case 2: + case 3: return SIM_LOCKED; + case 1: return SIM_READY; + default: return SIM_ERROR; + } + } + return SIM_ERROR; + } + +TINY_GSM_MODEM_GET_REGISTRATION_XREG(CGREG) + +TINY_GSM_MODEM_GET_OPERATOR_COPS() + + /* + * Generic network functions + */ + +TINY_GSM_MODEM_GET_CSQ() + + bool isNetworkConnected() { + RegStatus s = getRegistrationStatus(); + return (s == REG_OK_HOME || s == REG_OK_ROAMING); + } + + String getNetworkModes() { + sendAT(GF("+CNMP=?")); + if (waitResponse(GF(GSM_NL "+CNMP:")) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + return res; + } + +TINY_GSM_MODEM_WAIT_FOR_NETWORK() + + String setNetworkMode(uint8_t mode) { + sendAT(GF("+CNMP="), mode); + if (waitResponse(GF(GSM_NL "+CNMP:")) != 1) { + return "OK"; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + return res; + } + + + /* + * GPRS functions + */ + + bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { + gprsDisconnect(); // Make sure we're not connected first + + // Define the PDP context + + // Using CGDCONT sets up an "external" PCP context, i.e. a data connection + // using the external IP stack (e.g. Windows dial up) and PPP link over the + // serial interface. Is this preferred? + + // Set the authentication + if (user && strlen(user) > 0) { + sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"'); + waitResponse(); + } + + // Define PDP context 1 + sendAT(GF("+CGSOCKCONT=1,\"IP\",\""), apn, '"'); + waitResponse(); + + sendAT(GF("+CSOCKSETPN=1")); // activate PDP profile/context 1 + if (waitResponse(75000L) != 1) { + return false; + } + + // Using CGSOCKCONT commands defines a PDP context for Embedded TCP/IP application + // CGDCONT commands could be used for an external PDP context + + + // Set the user name and password + // ?? Unsure if this step is needed - redundant with +CGAUTH + if (user && strlen(user) > 0) { + sendAT(GF("+CSOCKAUTH=1,1,\""), user, "\",\"", pwd, '"'); + waitResponse(); + } + + // Set Sending Mode - send without waiting for peer TCP ACK + sendAT(GF("+CIPSENDMODE=0")); + waitResponse(); + + // Configure TCP parameters + //AT+CIPCCFG= [][,[][,[][,[][,]][,[[][,[]]]]]]]] + // NmRetry = number of retransmission to be made for an IP packet = 10 (default) + // DelayTm = number of milliseconds to delay to output data of Receiving = 0 (default) + // Ack = sets whether reporting a string “Send ok” = 0 (don't report) + // errMode = mode of reporting error result code = 0 (numberic values) + // HeaderType = which data header of receiving data in multi-client mode = 1 (“+RECEIVE,,”) + // AsyncMode = sets mode of executing commands = 0 (synchronous command executing) + // TimeoutVal = minimum retransmission timeout in milliseconds = 75000 + sendAT(GF("+CIPCCFG=10,0,0,0,1,0,75000")); + if (waitResponse() != 1) { + return false; + } + + // Select TCP/IP application mode (command mode) + sendAT(GF("+CIPMODE=0")); + waitResponse(); + + // Configure timeouts for open and close socket + // AT+CIPTIMEOUT=[][, [][, []]] + sendAT(GF("+CIPTIMEOUT="), 75000, ',', 15000, ',', 15000); + waitResponse(); + + // attach to GPRS + // Start the socket service + // Response may be an immediate "OK" followed later by "+NETOPEN: 1". + // We to ignore any immediate response and wait for the + // URC to show it's really connected. + sendAT(GF("+NETOPEN")); + if (waitResponse(75000L, GF(GSM_NL "+NETOPEN: 0")) != 1) { + return false; + } + + return true; + } + + bool gprsDisconnect() { + + // Stop the socket service + // Note: all sockets should be closed first + sendAT(GF("+NETCLOSE")); + if (waitResponse(60000L) != 1) + return false; + + return true; + } + + bool isGprsConnected() { + sendAT(GF("+NETOPEN?")); + if (waitResponse(GF(GSM_NL "+NETOPEN: 1")) != 1) { + return false; + } + int res = stream.readStringUntil('\n').toInt(); + waitResponse(); + if (res != 1) + return false; + + sendAT(GF("+IPADDR")); // Inquire Socket PDP address + // sendAT(GF("+CGPADDR=1")); // Show PDP address + if (waitResponse() != 1) + return false; + + return true; + } + + /* + * IP Address functions + */ + + String getLocalIP() { + sendAT(GF("+IPADDR")); // Inquire Socket PDP address + // sendAT(GF("+CGPADDR=1")); // Show PDP address + String res; + if (waitResponse(10000L, res) != 1) { + return ""; + } + res.replace(GSM_NL "OK" GSM_NL, ""); + res.replace(GSM_NL, ""); + res.trim(); + return res; + } + + IPAddress localIP() { + return TinyGsmIpFromString(getLocalIP()); + } + + /* + * Phone Call functions + */ + + bool setGsmBusy() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool callAnswer() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool callNumber() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool callHangup() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool dtmfSend() TINY_GSM_ATTR_NOT_IMPLEMENTED; + + /* + * 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 TinyGsmDecodeHex8bit(hex); + } else if (dcs == 72) { + return TinyGsmDecodeHex16bit(hex); + } else { + return hex; + } + } + + bool sendSMS(const String& number, const String& text) { + + sendAT(GF("+AT+CSCA?")); + waitResponse(); + sendAT(GF("+CMGF=1")); + waitResponse(); + //Set GSM 7 bit default alphabet (3GPP TS 23.038) + sendAT(GF("+CSCS=\"GSM\"")); + waitResponse(); + sendAT(GF("+CMGS=\""), number, GF("\"")); + if (waitResponse(GF(">")) != 1) { + return false; + } + stream.print(text); + stream.write((char)0x1A); + stream.flush(); + return waitResponse(60000L) == 1; + } + + bool sendSMS_UTF16(const String& number, const void* text, size_t len) { + sendAT(GF("+CMGF=1")); + waitResponse(); + sendAT(GF("+CSCS=\"HEX\"")); + waitResponse(); + sendAT(GF("+CSMP=17,167,0,8")); + waitResponse(); + + sendAT(GF("+CMGS=\""), number, GF("\"")); + if (waitResponse(GF(">")) != 1) { + return false; + } + + uint16_t* t = (uint16_t*)text; + for (size_t i=0; i> 8; + if (c < 0x10) { stream.print('0'); } + stream.print(c, HEX); + c = t[i] & 0xFF; + if (c < 0x10) { stream.print('0'); } + stream.print(c, HEX); + } + stream.write((char)0x1A); + stream.flush(); + return waitResponse(60000L) == 1; + } + + + /* + * Location functions + */ + + String getGsmLocation() TINY_GSM_ATTR_NOT_IMPLEMENTED; + + /* + * GPS location functions + */ + // enable GPS + bool enableGPS() { + sendAT(GF("+CGPS=1")); + if (waitResponse() != 1) { + return false; + } + return true; + } + + bool disableGPS() { + sendAT(GF("+CGPS=0")); + if (waitResponse() != 1) { + return false; + } + return true; + } + + // get the RAW GPS output + String getGPSraw() { + sendAT(GF("+CGNSSINFO=32")); + if (waitResponse(GF(GSM_NL "+CGNSSINFO:")) != 1) { + return ""; + } + String res = stream.readStringUntil('\n'); + waitResponse(); + res.trim(); + return res; + } + + // get GPS informations + bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { + //String buffer = ""; + bool fix = false; + + sendAT(GF("+CGNSSINFO")); + if (waitResponse(GF(GSM_NL "+CGNSSINFO:")) != 1) { + return false; + } + + //stream.readStringUntil(','); // mode + if ( stream.readStringUntil(',').toInt() == 1 ) fix = true; + stream.readStringUntil(','); //gps + stream.readStringUntil(','); // glonass + stream.readStringUntil(','); // beidu + *lat = stream.readStringUntil(',').toFloat(); //lat + stream.readStringUntil(','); // N/S + *lon = stream.readStringUntil(',').toFloat(); //lon + stream.readStringUntil(','); // E/W + stream.readStringUntil(','); // date + stream.readStringUntil(','); // UTC time + if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //alt + if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed + stream.readStringUntil(','); //course + stream.readStringUntil(','); //time + stream.readStringUntil(',');//PDOP + stream.readStringUntil(',');//HDOP + stream.readStringUntil(',');//VDOP + //if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites + //if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites + stream.readStringUntil('\n'); + + waitResponse(); + + return fix; + } + /* + * Time functions + */ + + /* + * Battery & temperature functions + */ + + // Use: float vBatt = modem.getBattVoltage()/1000; + uint16_t getBattVoltage() { + float voltage=0; + sendAT(GF("+CBC")); + if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + return 0; + } + + // return voltage in mV + voltage = stream.readStringUntil('\n').toFloat(); + // Wait for final OK + waitResponse(); + uint16_t res = voltage*1000; + return res; + } + + int8_t getBattPercent() { + //unsupported + return 0; + } + + uint8_t getBattChargeState() { + //unsupported + return 0; + } + + bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) { + sendAT(GF("+CBC?")); + if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { + return false; + } + milliVolts = stream.readStringUntil('\n').toInt()*1000; + // Wait for final OK + waitResponse(); + return true; + } + +// get temperature in degree celsius + uint16_t getTemperature() + { + sendAT(GF("+CPMUTEMP")); + if (waitResponse(GF(GSM_NL "+CPMUTEMP:")) != 1) { + return 0; + } + // return temperature in C + uint16_t res = stream.readStringUntil('\n').toInt(); + // Wait for final OK + waitResponse(); + + return res; + } + + + /* + * Client related functions + */ + +protected: + + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout_s = 75) { + // Make sure we'll be getting data manually on this connection + sendAT(GF("+CIPRXGET=1")); + if (waitResponse() != 1) { + return false; + } + + // Establish connection in multi-socket mode + sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); + // reply is +CIPOPEN: ## of socket created + if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) { + + return false; + } + return true; + } + + int16_t modemSend(const void* buff, size_t len, uint8_t mux) { + sendAT(GF("+CIPSEND="), mux, ',', len); + if (waitResponse(GF(">")) != 1) { + return 0; + } + stream.write((uint8_t*)buff, len); + stream.flush(); + if (waitResponse(GF(GSM_NL "+CIPSEND:")) != 1) { + return 0; + } + streamSkipUntil(','); // Skip mux + streamSkipUntil(','); // Skip requested bytes to send + // TODO: make sure requested and confirmed bytes match + return stream.readStringUntil('\n').toInt(); + } + + size_t modemRead(size_t size, uint8_t mux) { +#ifdef TINY_GSM_USE_HEX + sendAT(GF("+CIPRXGET=3,"), mux, ',', size); + if (waitResponse(GF("+CIPRXGET:")) != 1) { + return 0; + } +#else + sendAT(GF("+CIPRXGET=2,"), mux, ',', size); + if (waitResponse(GF("+CIPRXGET:")) != 1) { + return 0; + } +#endif + streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX + streamSkipUntil(','); // Skip mux/cid (connecion id) + size_t len_requested = stream.readStringUntil(',').toInt(); + // ^^ Requested number of data bytes (1-1460 bytes)to be read + size_t len_confirmed = stream.readStringUntil('\n').toInt(); + // ^^ The data length which not read in the buffer + for (size_t i=0; i_timeout)) { TINY_GSM_YIELD(); } + char buf[4] = { 0, }; + buf[0] = stream.read(); + buf[1] = stream.read(); + char c = strtol(buf, NULL, 16); +#else + while (!stream.available() && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); } + char c = stream.read(); +#endif + sockets[mux]->rx.put(c); + } + DBG("### READ:", len_requested, "from", mux); + // sockets[mux]->sock_available = modemGetAvailable(mux); + sockets[mux]->sock_available = len_confirmed; + waitResponse(); + return len_requested; + } + + size_t modemGetAvailable(uint8_t mux) { + sendAT(GF("+CIPRXGET=4,"), mux); + size_t result = 0; + if (waitResponse(GF("+CIPRXGET:")) == 1) { + streamSkipUntil(','); // Skip mode 4 + streamSkipUntil(','); // Skip mux + result = stream.readStringUntil('\n').toInt(); + waitResponse(); + } + DBG("### Available:", result, "on", mux); + if (!result) { + sockets[mux]->sock_connected = modemGetConnected(mux); + } + return result; + } + + bool modemGetConnected(uint8_t mux) { + // Read the status of all sockets at once + sendAT(GF("+CIPCLOSE?")); + if (waitResponse(GF("+CIPCLOSE:")) != 1) + //return false; + for (int muxNo = 0; muxNo <= TINY_GSM_MUX_COUNT; muxNo++) { + // +CIPCLOSE:,,..., + sockets[muxNo]->sock_connected = stream.parseInt(); + streamSkipUntil(','); + } + waitResponse(); // Should be an OK at the end + return sockets[mux]->sock_connected; + } + +public: + + /* + Utilities + */ + +TINY_GSM_MODEM_STREAM_UTILITIES() + + // TODO: Optimize this! + uint8_t waitResponse(uint32_t timeout_ms, String& data, + GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), + GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) + { + /*String r1s(r1); r1s.trim(); + String r2s(r2); r2s.trim(); + String r3s(r3); r3s.trim(); + String r4s(r4); r4s.trim(); + String r5s(r5); r5s.trim(); + DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ + data.reserve(64); + int index = 0; + unsigned long startMillis = millis(); + do { + TINY_GSM_YIELD(); + while (stream.available() > 0) { + TINY_GSM_YIELD(); + int a = stream.read(); + if (a <= 0) continue; // Skip 0x00 bytes, just in case + data += (char)a; + if (r1 && data.endsWith(r1)) { + index = 1; + goto finish; + } else if (r2 && data.endsWith(r2)) { + index = 2; + goto finish; + } else if (r3 && data.endsWith(r3)) { + index = 3; + goto finish; + } else if (r4 && data.endsWith(r4)) { + index = 4; + goto finish; + } else if (r5 && data.endsWith(r5)) { + index = 5; + goto finish; + } else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) { + String mode = stream.readStringUntil(','); + if (mode.toInt() == 1) { + int mux = stream.readStringUntil('\n').toInt(); + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { + sockets[mux]->got_data = true; + } + data = ""; + DBG("### Got Data:", mux); + } else { + data += mode; + } + } else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) { + int mux = stream.readStringUntil(',').toInt(); + int len = stream.readStringUntil('\n').toInt(); + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { + sockets[mux]->got_data = true; + sockets[mux]->sock_available = len; + } + data = ""; + DBG("### Got Data:", len, "on", mux); + } else if (data.endsWith(GF("+IPCLOSE:"))) { + int mux = stream.readStringUntil(',').toInt(); + streamSkipUntil('\n'); // Skip the reason code + if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { + sockets[mux]->sock_connected = false; + } + data = ""; + DBG("### Closed: ", mux); + } + } + } while (millis() - startMillis < timeout_ms); +finish: + if (!index) { + data.trim(); + if (data.length()) { + DBG("### Unhandled:", data); + } + data = ""; + } + //data.replace(GSM_NL, "/"); + //DBG('<', index, '>', data); + return index; + } + + uint8_t waitResponse(uint32_t timeout_ms, + GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), + GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) + { + String data; + return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5); + } + + uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), + GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) + { + return waitResponse(1000, r1, r2, r3, r4, r5); + } + +public: + Stream& stream; + +protected: + GsmClient* sockets[TINY_GSM_MUX_COUNT]; +}; + +#endif From 6c1f9b3c5b8bb9b14f9adbdd9e2beb599f624f20 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Fri, 2 Aug 2019 10:09:55 -0400 Subject: [PATCH 3/4] Some comparing and changing --- src/TinyGsmClient.h | 4 +- src/TinyGsmClientSIM5360.h | 73 ++++++++++++---------- src/TinyGsmClientSIM7600.h | 121 +++++++++++++++++-------------------- 3 files changed, 101 insertions(+), 97 deletions(-) diff --git a/src/TinyGsmClient.h b/src/TinyGsmClient.h index c1b9574..0b25d28 100644 --- a/src/TinyGsmClient.h +++ b/src/TinyGsmClient.h @@ -41,13 +41,13 @@ // typedef TinyGsmSim7000::GsmClientSecure TinyGsmClientSecure; TODO! #elif defined(TINY_GSM_MODEM_SIM5320) || defined(TINY_GSM_MODEM_SIM5360) || \ - defined(TINY_GSM_MODEM_SIM5300) + defined(TINY_GSM_MODEM_SIM5300) || defined(TINY_GSM_MODEM_SIM7100) #define TINY_GSM_MODEM_HAS_GPRS #include typedef TinyGsmSim5360 TinyGsm; typedef TinyGsmSim5360::GsmClient TinyGsmClient; -#elif defined(TINY_GSM_MODEM_SIM7600) || defined(TINY_GSM_MODEM_SIM7100) || \ +#elif defined(TINY_GSM_MODEM_SIM7600) || defined(TINY_GSM_MODEM_SIM7800) || \ defined(TINY_GSM_MODEM_SIM7500) #define TINY_GSM_MODEM_HAS_GPRS #include diff --git a/src/TinyGsmClientSIM5360.h b/src/TinyGsmClientSIM5360.h index 41da9b8..a19b83a 100644 --- a/src/TinyGsmClientSIM5360.h +++ b/src/TinyGsmClientSIM5360.h @@ -58,13 +58,13 @@ class GsmClient : public Client public: GsmClient() {} - GsmClient(TinyGsmSim5360& modem, uint8_t mux = 1) { + GsmClient(TinyGsmSim5360& modem, uint8_t mux = 0) { init(&modem, mux); } virtual ~GsmClient(){} - bool init(TinyGsmSim5360* modem, uint8_t mux = 1) { + bool init(TinyGsmSim5360* modem, uint8_t mux = 0) { this->at = modem; this->mux = mux; sock_available = 0; @@ -324,7 +324,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() waitResponse(); } - // Define PDP context 1 + // Define external PDP context 1 sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"',",\"0.0.0.0\",0,0"); waitResponse(); @@ -399,24 +399,12 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } // Stop the socket service - // Note: all sockets should be closed first + // Note: all sockets should be closed first - on 3G/4G models the sockets must be closed manually sendAT(GF("+NETCLOSE")); if (waitResponse(60000L, GF(GSM_NL "+NETCLOSE: 0")) != 1) { return false; } - // Deactivate PDP context 1 - sendAT(GF("+CGACT=1,0")); - if (waitResponse(40000L) != 1) { - return false; - } - - // Detach from GPRS - sendAT(GF("+CGATT=0")); - if (waitResponse(360000L) != 1) { - return false; - } - return true; } @@ -473,8 +461,10 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() */ String sendUSSD(const String& code) { + // Select message format (1=text) sendAT(GF("+CMGF=1")); waitResponse(); + // Select TE character set sendAT(GF("+CSCS=\"HEX\"")); waitResponse(); sendAT(GF("+CUSD=1,\""), code, GF("\"")); @@ -499,14 +489,16 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } bool sendSMS(const String& number, const String& text) { - + // Get SMS service centre address sendAT(GF("+AT+CSCA?")); waitResponse(); + // Select message format (1=text) sendAT(GF("+CMGF=1")); waitResponse(); //Set GSM 7 bit default alphabet (3GPP TS 23.038) sendAT(GF("+CSCS=\"GSM\"")); waitResponse(); + // Send the message! sendAT(GF("+CMGS=\""), number, GF("\"")); if (waitResponse(GF(">")) != 1) { return false; @@ -518,13 +510,16 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } bool sendSMS_UTF16(const String& number, const void* text, size_t len) { + // Select message format (1=text) sendAT(GF("+CMGF=1")); waitResponse(); + // Select TE character set sendAT(GF("+CSCS=\"HEX\"")); waitResponse(); + // Set text mode parameters sendAT(GF("+CSMP=17,167,0,8")); waitResponse(); - + // Send the message sendAT(GF("+CMGS=\""), number, GF("\"")); if (waitResponse(GF(">")) != 1) { return false; @@ -571,10 +566,12 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } streamSkipUntil(','); // Skip battery charge status streamSkipUntil(','); // Skip battery charge level - // return voltage in mV - uint16_t res = stream.readStringUntil(',').toInt(); + // get voltage in VOLTS + float voltage = stream.readStringUntil('\n').toFloat(); // Wait for final OK waitResponse(); + // Return millivolts + uint16_t res = voltage*1000; return res; } @@ -610,17 +607,31 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } chargeState = stream.readStringUntil(',').toInt(); percent = stream.readStringUntil(',').toInt(); - milliVolts = stream.readStringUntil('\n').toInt(); + // get voltage in VOLTS + float voltage = stream.readStringUntil('\n').toFloat(); + milliVolts = voltage*1000; // Wait for final OK waitResponse(); return true; } - float getTemperature() TINY_GSM_ATTR_NOT_AVAILABLE; - // ToDo: - // # Enable Temparature Reading: - //AT+CMTE=1 - //AT+CMTE? + // get temperature in degree celsius + float getTemperature() { + // Enable Temparature Reading + sendAT(GF("+CMTE=1")); + if (waitResponse() != 1) { + return 0; + } + // Get Temparature Value + sendAT(GF("+CMTE?")); + if (waitResponse(GF(GSM_NL "+CMTE:")) != 1) { + return false; + } + float res = stream.readStringUntil('\n').toFloat(); + // Wait for final OK + waitResponse(); + return res; + } /* * Client related functions @@ -636,9 +647,9 @@ protected: return false; } - // Establish a connection in multi-socket mode + // Establish a connection in multi-socket mode sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - // The reply is +CIPOPEN: ## of socket created + // The reply is +CIPOPEN: ## of socket created if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) { return false; } @@ -693,7 +704,6 @@ protected: #endif sockets[mux]->rx.put(c); } - DBG("### READ:", len_requested, "from", mux); // sockets[mux]->sock_available = modemGetAvailable(mux); sockets[mux]->sock_available = len_confirmed; @@ -719,9 +729,10 @@ protected: bool modemGetConnected(uint8_t mux) { // Read the status of all sockets at once - sendAT(GF("+CIPCLOSE?"), mux); - if (waitResponse(GFP(GSM_OK), GF("+CIPCLOSE: ")) != 2) + sendAT(GF("+CIPCLOSE?")); + if (waitResponse(GF("+CIPCLOSE:")) != 1) { return false; + } for (int muxNo = 0; muxNo <= TINY_GSM_MUX_COUNT; muxNo++) { // +CIPCLOSE:,,..., sockets[muxNo]->sock_connected = stream.parseInt(); diff --git a/src/TinyGsmClientSIM7600.h b/src/TinyGsmClientSIM7600.h index 112f6e2..94026ee 100644 --- a/src/TinyGsmClientSIM7600.h +++ b/src/TinyGsmClientSIM7600.h @@ -316,41 +316,29 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() // Define the PDP context - // Using CGDCONT sets up an "external" PCP context, i.e. a data connection - // using the external IP stack (e.g. Windows dial up) and PPP link over the - // serial interface. Is this preferred? + // The CGDCONT commands set up the "external" PDP context - // Set the authentication + // Set the external authentication if (user && strlen(user) > 0) { sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"'); waitResponse(); } - // Define PDP context 1 - sendAT(GF("+CGSOCKCONT=1,\"IP\",\""), apn, '"'); + // Define external PDP context 1 + sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"',",\"0.0.0.0\",0,0"); waitResponse(); - sendAT(GF("+CSOCKSETPN=1")); // activate PDP profile/context 1 - if (waitResponse(75000L) != 1) { - return false; - } - - // Using CGSOCKCONT commands defines a PDP context for Embedded TCP/IP application - // CGDCONT commands could be used for an external PDP context - + // Configure TCP parameters - // Set the user name and password - // ?? Unsure if this step is needed - redundant with +CGAUTH - if (user && strlen(user) > 0) { - sendAT(GF("+CSOCKAUTH=1,1,\""), user, "\",\"", pwd, '"'); - waitResponse(); - } + // Select TCP/IP application mode (command mode) + sendAT(GF("+CIPMODE=0")); + waitResponse(); // Set Sending Mode - send without waiting for peer TCP ACK sendAT(GF("+CIPSENDMODE=0")); waitResponse(); - // Configure TCP parameters + // Configure socket parameters //AT+CIPCCFG= [][,[][,[][,[][,]][,[[][,[]]]]]]]] // NmRetry = number of retransmission to be made for an IP packet = 10 (default) // DelayTm = number of milliseconds to delay to output data of Receiving = 0 (default) @@ -364,18 +352,16 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() return false; } - // Select TCP/IP application mode (command mode) - sendAT(GF("+CIPMODE=0")); - waitResponse(); - - // Configure timeouts for open and close socket + // Configure timeouts for opening and closing sockets // AT+CIPTIMEOUT=[][, [][, []]] sendAT(GF("+CIPTIMEOUT="), 75000, ',', 15000, ',', 15000); waitResponse(); - // attach to GPRS - // Start the socket service - // Response may be an immediate "OK" followed later by "+NETOPEN: 1". + // Start the socket service + + // This activates and attaches to the external PDP context that is tied + // to the embedded context for TCP/IP (ie AT+CGACT=1,1 and AT+CGATT=1) + // Response may be an immediate "OK" followed later by "+NETOPEN: 0". // We to ignore any immediate response and wait for the // URC to show it's really connected. sendAT(GF("+NETOPEN")); @@ -388,29 +374,29 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() bool gprsDisconnect() { - // Stop the socket service - // Note: all sockets should be closed first + // Close all sockets and stop the socket service + // Note: On the LTE models, this single command closes all sockets and the service sendAT(GF("+NETCLOSE")); - if (waitResponse(60000L) != 1) + if (waitResponse(60000L, GF(GSM_NL "+NETCLOSE: 0")) != 1) { return false; + } return true; } bool isGprsConnected() { sendAT(GF("+NETOPEN?")); + // May return +NETOPEN: 1, 0. We just confirm that the first number is 1 if (waitResponse(GF(GSM_NL "+NETOPEN: 1")) != 1) { return false; } - int res = stream.readStringUntil('\n').toInt(); waitResponse(); - if (res != 1) - return false; sendAT(GF("+IPADDR")); // Inquire Socket PDP address // sendAT(GF("+CGPADDR=1")); // Show PDP address - if (waitResponse() != 1) + if (waitResponse() != 1) { return false; + } return true; } @@ -451,8 +437,10 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() */ String sendUSSD(const String& code) { + // Select message format (1=text) sendAT(GF("+CMGF=1")); waitResponse(); + // Select TE character set sendAT(GF("+CSCS=\"HEX\"")); waitResponse(); sendAT(GF("+CUSD=1,\""), code, GF("\"")); @@ -477,14 +465,16 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } bool sendSMS(const String& number, const String& text) { - + // Get SMS service centre address sendAT(GF("+AT+CSCA?")); waitResponse(); + // Select message format (1=text) sendAT(GF("+CMGF=1")); waitResponse(); //Set GSM 7 bit default alphabet (3GPP TS 23.038) sendAT(GF("+CSCS=\"GSM\"")); waitResponse(); + // Send the message! sendAT(GF("+CMGS=\""), number, GF("\"")); if (waitResponse(GF(">")) != 1) { return false; @@ -496,13 +486,16 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() } bool sendSMS_UTF16(const String& number, const void* text, size_t len) { + // Select message format (1=text) sendAT(GF("+CMGF=1")); waitResponse(); + // Select TE character set sendAT(GF("+CSCS=\"HEX\"")); waitResponse(); + // Set text mode parameters sendAT(GF("+CSMP=17,167,0,8")); waitResponse(); - + // Send the message sendAT(GF("+CMGS=\""), number, GF("\"")); if (waitResponse(GF(">")) != 1) { return false; @@ -605,46 +598,41 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() * Battery & temperature functions */ - // Use: float vBatt = modem.getBattVoltage()/1000; + // Use: float vBatt = modem.getBattVoltage() / 1000.0; uint16_t getBattVoltage() { - float voltage=0; sendAT(GF("+CBC")); if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { return 0; } - // return voltage in mV - voltage = stream.readStringUntil('\n').toFloat(); + // get voltage in VOLTS + float voltage = stream.readStringUntil('\n').toFloat(); // Wait for final OK waitResponse(); + // Return millivolts uint16_t res = voltage*1000; return res; } - int8_t getBattPercent() { - //unsupported - return 0; - } + int8_t getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; - uint8_t getBattChargeState() { - //unsupported - return 0; - } + uint8_t getBattChargeState() TINY_GSM_ATTR_NOT_AVAILABLE; bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) { sendAT(GF("+CBC?")); if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { return false; } - milliVolts = stream.readStringUntil('\n').toInt()*1000; + // get voltage in VOLTS + float voltage = stream.readStringUntil('\n').toFloat(); + milliVolts = voltage*1000; // Wait for final OK waitResponse(); return true; } -// get temperature in degree celsius - uint16_t getTemperature() - { + // get temperature in degree celsius + uint16_t getTemperature() { sendAT(GF("+CPMUTEMP")); if (waitResponse(GF(GSM_NL "+CPMUTEMP:")) != 1) { return 0; @@ -653,11 +641,9 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() uint16_t res = stream.readStringUntil('\n').toInt(); // Wait for final OK waitResponse(); - return res; } - - + /* * Client related functions */ @@ -672,14 +658,13 @@ protected: return false; } - // Establish connection in multi-socket mode + // Establish a connection in multi-socket mode sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - // reply is +CIPOPEN: ## of socket created + // The reply is +CIPOPEN: ## of socket created if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) { - return false; } - return true; + return true; } int16_t modemSend(const void* buff, size_t len, uint8_t mux) { @@ -756,12 +741,12 @@ protected: bool modemGetConnected(uint8_t mux) { // Read the status of all sockets at once sendAT(GF("+CIPCLOSE?")); - if (waitResponse(GF("+CIPCLOSE:")) != 1) - //return false; + if (waitResponse(GF("+CIPCLOSE:")) != 1) { + // return false; // TODO: Why does this not read correctly? + } for (int muxNo = 0; muxNo <= TINY_GSM_MUX_COUNT; muxNo++) { // +CIPCLOSE:,,..., sockets[muxNo]->sock_connected = stream.parseInt(); - streamSkipUntil(','); } waitResponse(); // Should be an OK at the end return sockets[mux]->sock_connected; @@ -840,6 +825,14 @@ TINY_GSM_MODEM_STREAM_UTILITIES() } data = ""; DBG("### Closed: ", mux); + } else if (data.endsWith(GF("+CIPEVENT:"))) { + // Need to close all open sockets and release the network library. + // User will then need to reconnect. + DBG("### Network error!"); + if (!isGprsConnected()) { + gprsDisconnect(); + } + data = ""; } } } while (millis() - startMillis < timeout_ms); From 71244964516d92717786129631debc8e2d7cfb6e Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Fri, 2 Aug 2019 10:46:10 -0400 Subject: [PATCH 4/4] Update Travis --- .github/ISSUE_TEMPLATE.md | 2 +- .travis.yml | 3 ++- library.json | 2 +- library.properties | 2 +- src/TinyGsmCommon.h | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 6d8a267..5c74ec1 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -23,7 +23,7 @@ with your board before submitting any issues. Main processor board: Modem: -TinyGSM version: +TinyGSM version: Code: ### Scenario, steps to reproduce diff --git a/.travis.yml b/.travis.yml index b30789b..1e3ec6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,8 @@ env: - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_MC60' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM808' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM5360' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM5360' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7600' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7000' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SARAR4' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" diff --git a/library.json b/library.json index 1dd9926..1309c16 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TinyGSM", - "version": "0.9.6", + "version": "0.9.7", "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports many GSM, LTE, and WiFi modules with AT command interfaces.", "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM7000, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968, M95, MC60, MC60E, BG96, ublox, Quectel, SIMCOM, AI Thinker, LTE, LTE-M", "authors": diff --git a/library.properties b/library.properties index 8f9275b..46aa51e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TinyGSM -version=0.9.6 +version=0.9.7 author=Volodymyr Shymanskyy maintainer=Volodymyr Shymanskyy sentence=A small Arduino library for GPRS modules, that just works. diff --git a/src/TinyGsmCommon.h b/src/TinyGsmCommon.h index c0ec41d..658bc68 100644 --- a/src/TinyGsmCommon.h +++ b/src/TinyGsmCommon.h @@ -10,7 +10,7 @@ #define TinyGsmCommon_h // The current library version number -#define TINYGSM_VERSION "0.9.6" +#define TINYGSM_VERSION "0.9.7" #if defined(SPARK) || defined(PARTICLE) #include "Particle.h"