diff --git a/.clang-format b/.clang-format index 60ffff7..1329b59 100644 --- a/.clang-format +++ b/.clang-format @@ -58,6 +58,8 @@ IncludeCategories: Priority: 2 - Regex: '.*' Priority: 3 + - Regex: '.*.tpp' + Priority: 4 IncludeIsMainRegex: '([-_](test|unittest))?$' IndentCaseLabels: true IndentPPDirectives: None @@ -80,7 +82,7 @@ PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 60 +PenaltyExcessCharacter: 600 PenaltyReturnTypeOnItsOwnLine: 50 PointerAlignment: Left PointerBindsToType: true diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index 7ba2045..c6cab92 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -245,9 +245,9 @@ void loop() { stream.print(F("Привіііт! Print number: ")); stream.print(595); res = modem.sendSMS_UTF8_end(); - } + } DBG("UTF8 SMS:", res ? "OK" : "fail"); - + #endif #if TINY_GSM_TEST_CALL && defined(CALL_TARGET) diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index 1e80494..f686fa2 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -44,7 +44,9 @@ // Chips without internal buffering (A6/A7, ESP8266, M590) // need enough space in the buffer for the entire response // else data will be lost (and the http library will fail). +#if !defined(TINY_GSM_RX_BUFFER) #define TINY_GSM_RX_BUFFER 650 +#endif // See all AT commands, if wanted // #define DUMP_AT_COMMANDS diff --git a/src/TinyGsmBattery.tpp b/src/TinyGsmBattery.tpp new file mode 100644 index 0000000..fe84379 --- /dev/null +++ b/src/TinyGsmBattery.tpp @@ -0,0 +1,98 @@ +/** + * @file TinyGsmBattery.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMBATTERY_H_ +#define SRC_TINYGSMBATTERY_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_BATTERY + +template +class TinyGsmBattery { + public: + /* + * Battery functions + */ + uint16_t getBattVoltage() { + return thisModem().getBattVoltageImpl(); + } + int8_t getBattPercent() { + return thisModem().getBattPercentImpl(); + } + uint8_t getBattChargeState() { + return thisModem().getBattChargeStateImpl(); + } + bool getBattStats(uint8_t& chargeState, int8_t& percent, + uint16_t& milliVolts) { + return thisModem().getBattStatsImpl(chargeState, percent, milliVolts); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Battery functions + */ + protected: + // Use: float vBatt = modem.getBattVoltage() / 1000.0; + uint16_t getBattVoltageImpl() { + thisModem().sendAT(GF("+CBC")); + if (thisModem().waitResponse(GF("+CBC:")) != 1) { return 0; } + thisModem().streamSkipUntil(','); // Skip battery charge status + thisModem().streamSkipUntil(','); // Skip battery charge level + // return voltage in mV + uint16_t res = thisModem().streamGetInt(','); + // Wait for final OK + thisModem().waitResponse(); + return res; + } + + int8_t getBattPercentImpl() { + thisModem().sendAT(GF("+CBC")); + if (thisModem().waitResponse(GF("+CBC:")) != 1) { return false; } + thisModem().streamSkipUntil(','); // Skip battery charge status + // Read battery charge level + int res = thisModem().streamGetInt(','); + // Wait for final OK + thisModem().waitResponse(); + return res; + } + + uint8_t getBattChargeStateImpl() { + thisModem().sendAT(GF("+CBC")); + if (thisModem().waitResponse(GF("+CBC:")) != 1) { return false; } + // Read battery charge status + int res = thisModem().streamGetInt(','); + // Wait for final OK + thisModem().waitResponse(); + return res; + } + + bool getBattStatsImpl(uint8_t& chargeState, int8_t& percent, + uint16_t& milliVolts) { + thisModem().sendAT(GF("+CBC")); + if (thisModem().waitResponse(GF("+CBC:")) != 1) { return false; } + chargeState = thisModem().streamGetInt(','); + percent = thisModem().streamGetInt(','); + milliVolts = thisModem().streamGetInt('\n'); + // Wait for final OK + thisModem().waitResponse(); + return true; + } +}; + +#endif // SRC_TINYGSMBATTERY_H_ diff --git a/src/TinyGsmCalling.tpp b/src/TinyGsmCalling.tpp new file mode 100644 index 0000000..467fe1d --- /dev/null +++ b/src/TinyGsmCalling.tpp @@ -0,0 +1,90 @@ +/** + * @file TinyGsmCalling.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMCALLING_H_ +#define SRC_TINYGSMCALLING_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_CALLING + +template +class TinyGsmCalling { + public: + /* + * Phone Call functions + */ + bool callAnswer() { + return thisModem().callAnswerImpl(); + } + bool callNumber(const String& number) { + return thisModem().callNumberImpl(number); + } + bool callHangup() { + return thisModem().callHangupImpl(); + } + bool dtmfSend(char cmd, int duration_ms = 100) { + return thisModem().dtmfSendImpl(cmd, duration_ms); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Phone Call functions + */ + protected: + bool callAnswerImpl() { + thisModem().sendAT(GF("A")); + return thisModem().waitResponse() == 1; + } + + // Returns true on pick-up, false on error/busy + bool callNumberImpl(const String& number) { + if (number == GF("last")) { + thisModem().sendAT(GF("DL")); + } else { + thisModem().sendAT(GF("D"), number, ";"); + } + int status = thisModem().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 callHangupImpl() { + thisModem().sendAT(GF("H")); + return thisModem().waitResponse() == 1; + } + + // 0-9,*,#,A,B,C,D + bool dtmfSendImpl(char cmd, int duration_ms = 100) { + duration_ms = constrain(duration_ms, 100, 1000); + + thisModem().sendAT(GF("+VTD="), + duration_ms / 100); // VTD accepts in 1/10 of a second + thisModem().waitResponse(); + + thisModem().sendAT(GF("+VTS="), cmd); + return thisModem().waitResponse(10000L) == 1; + } +}; + +#endif // SRC_TINYGSMCALLING_H_ diff --git a/src/TinyGsmClient.h b/src/TinyGsmClient.h index fd23b11..cec5d68 100644 --- a/src/TinyGsmClient.h +++ b/src/TinyGsmClient.h @@ -6,35 +6,27 @@ * @date Nov 2016 */ -#ifndef SRC_TINYGSMCLIENT_h -#define SRC_TINYGSMCLIENT_h +#ifndef SRC_TINYGSMCLIENT_H_ +#define SRC_TINYGSMCLIENT_H_ #if defined(TINY_GSM_MODEM_SIM800) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_SSL #include "TinyGsmClientSIM800.h" typedef TinyGsmSim800 TinyGsm; typedef TinyGsmSim800::GsmClientSim800 TinyGsmClient; typedef TinyGsmSim800::GsmClientSecureSim800 TinyGsmClientSecure; #elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_SSL -#define TINY_GSM_MODEM_HAS_GPS #include "TinyGsmClientSIM808.h" typedef TinyGsmSim808 TinyGsm; typedef TinyGsmSim808::GsmClientSim800 TinyGsmClient; typedef TinyGsmSim808::GsmClientSecureSim800 TinyGsmClientSecure; #elif defined(TINY_GSM_MODEM_SIM900) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientSIM800.h" typedef TinyGsmSim800 TinyGsm; typedef TinyGsmSim800::GsmClientSim800 TinyGsmClient; #elif defined(TINY_GSM_MODEM_SIM7000) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_GPS #include "TinyGsmClientSIM7000.h" typedef TinyGsmSim7000 TinyGsm; typedef TinyGsmSim7000::GsmClientSim7000 TinyGsmClient; @@ -42,92 +34,76 @@ typedef TinyGsmSim7000::GsmClientSim7000 TinyGsmClient; #elif defined(TINY_GSM_MODEM_SIM5320) || defined(TINY_GSM_MODEM_SIM5360) || \ defined(TINY_GSM_MODEM_SIM5300) || defined(TINY_GSM_MODEM_SIM7100) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientSIM5360.h" typedef TinyGsmSim5360 TinyGsm; typedef TinyGsmSim5360::GsmClientSim5360 TinyGsmClient; #elif defined(TINY_GSM_MODEM_SIM7600) || defined(TINY_GSM_MODEM_SIM7800) || \ defined(TINY_GSM_MODEM_SIM7500) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientSIM7600.h" typedef TinyGsmSim7600 TinyGsm; typedef TinyGsmSim7600::GsmClientSim7600 TinyGsmClient; #elif defined(TINY_GSM_MODEM_UBLOX) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_SSL #include "TinyGsmClientUBLOX.h" typedef TinyGsmUBLOX TinyGsm; typedef TinyGsmUBLOX::GsmClientUBLOX TinyGsmClient; typedef TinyGsmUBLOX::GsmClientSecureUBLOX TinyGsmClientSecure; #elif defined(TINY_GSM_MODEM_SARAR4) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_SSL #include "TinyGsmClientSaraR4.h" typedef TinyGsmSaraR4 TinyGsm; typedef TinyGsmSaraR4::GsmClientSaraR4 TinyGsmClient; typedef TinyGsmSaraR4::GsmClientSecureR4 TinyGsmClientSecure; #elif defined(TINY_GSM_MODEM_M95) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientM95.h" typedef TinyGsmM95 TinyGsm; typedef TinyGsmM95::GsmClientM95 TinyGsmClient; #elif defined(TINY_GSM_MODEM_BG96) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientBG96.h" typedef TinyGsmBG96 TinyGsm; typedef TinyGsmBG96::GsmClientBG96 TinyGsmClient; #elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientA6.h" typedef TinyGsmA6 TinyGsm; typedef TinyGsmA6::GsmClientA6 TinyGsmClient; #elif defined(TINY_GSM_MODEM_M590) -#define TINY_GSM_MODEM_HAS_GPRS #include "TinyGsmClientM590.h" typedef TinyGsmM590 TinyGsm; typedef TinyGsmM590::GsmClientM590 TinyGsmClient; #elif defined(TINY_GSM_MODEM_MC60) || defined(TINY_GSM_MODEM_MC60E) #include "TinyGsmClientMC60.h" -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_GPS typedef TinyGsmMC60 TinyGsm; typedef TinyGsmMC60::GsmClientMC60 TinyGsmClient; #elif defined(TINY_GSM_MODEM_ESP8266) #define TINY_GSM_MODEM_HAS_WIFI -#define TINY_GSM_MODEM_HAS_SSL #include "TinyGsmClientESP8266.h" typedef TinyGsmESP8266 TinyGsm; typedef TinyGsmESP8266::GsmClientESP8266 TinyGsmClient; typedef TinyGsmESP8266::GsmClientSecureESP8266 TinyGsmClientSecure; #elif defined(TINY_GSM_MODEM_XBEE) -#define TINY_GSM_MODEM_HAS_GPRS #define TINY_GSM_MODEM_HAS_WIFI -#define TINY_GSM_MODEM_HAS_SSL #include "TinyGsmClientXBee.h" typedef TinyGsmXBee TinyGsm; typedef TinyGsmXBee::GsmClientXBee TinyGsmClient; typedef TinyGsmXBee::GsmClientSecureXBee TinyGsmClientSecure; #elif defined(TINY_GSM_MODEM_SEQUANS_MONARCH) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_SSL #include "TinyGsmClientSequansMonarch.h" -typedef TinyGsmSequansMonarch TinyGsm; -typedef TinyGsmSequansMonarch::GsmClientSequansMonarch TinyGsmClient; -typedef TinyGsmSequansMonarch::GsmClientSecureSequansMonarch TinyGsmClientSecure; +typedef TinyGsmSequansMonarch TinyGsm; +typedef TinyGsmSequansMonarch::GsmClientSequansMonarch TinyGsmClient; +typedef TinyGsmSequansMonarch::GsmClientSecureSequansMonarch + TinyGsmClientSecure; #else #error "Please define GSM modem model" #endif -#endif +#endif // SRC_TINYGSMCLIENT_H_ diff --git a/src/TinyGsmClientA6.h b/src/TinyGsmClientA6.h index 790b363..8fe4de9 100644 --- a/src/TinyGsmClientA6.h +++ b/src/TinyGsmClientA6.h @@ -14,7 +14,13 @@ #define TINY_GSM_MUX_COUNT 8 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmCalling.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -32,8 +38,20 @@ enum RegStatus { }; class TinyGsmA6 - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmTime, + public TinyGsmBattery { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmTime; + friend class TinyGsmBattery; /* * Inner Client @@ -70,17 +88,9 @@ class TinyGsmA6 } return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { TINY_GSM_YIELD(); at->sendAT(GF("+CIPCLOSE="), mux); sock_connected = false; @@ -158,18 +168,6 @@ class TinyGsmA6 return waitResponse() == 1; } - bool thisHasSSL() { - return false; - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -203,16 +201,10 @@ class TinyGsmA6 return (s == REG_OK_HOME || s == REG_OK_ROAMING); } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+CIFSR")); String res; - if (waitResponse(10000L, res) != 1) { - return ""; - } + if (waitResponse(10000L, res) != 1) { return ""; } res.replace(GSM_NL "OK" GSM_NL, ""); res.replace(GSM_NL, ""); res.trim(); @@ -280,9 +272,7 @@ class TinyGsmA6 protected: String getSimCCIDImpl() { sendAT(GF("+CCID")); - if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); @@ -380,18 +370,6 @@ class TinyGsmA6 } } - /* - * Location functions - */ - protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type supported - /* * Time functions */ @@ -400,7 +378,7 @@ class TinyGsmA6 // Note - the clock probably has to be set manaually first /* - * Battery & temperature functions + * Battery functions */ protected: uint16_t getBattVoltageImpl() TINY_GSM_ATTR_NOT_AVAILABLE; @@ -430,8 +408,6 @@ class TinyGsmA6 return true; } - float getTemperatureImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - /* * Client related functions */ diff --git a/src/TinyGsmClientBG96.h b/src/TinyGsmClientBG96.h index b7b7706..b102631 100644 --- a/src/TinyGsmClientBG96.h +++ b/src/TinyGsmClientBG96.h @@ -14,7 +14,13 @@ #define TINY_GSM_MUX_COUNT 12 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmCalling.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -32,8 +38,20 @@ enum RegStatus { }; class TinyGsmBG96 - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmTime, + public TinyGsmBattery { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmTime; + friend class TinyGsmBattery; /* * Inner Client @@ -70,17 +88,9 @@ class TinyGsmBG96 sock_connected = at->modemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+QICLOSE="), mux); sock_connected = false; @@ -113,13 +123,14 @@ class TinyGsmBG96 public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { stop(); TINY_GSM_YIELD(); rx.clear(); sock_connected = at->modemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; */ @@ -168,18 +179,6 @@ class TinyGsmBG96 } } - bool thisHasSSL() { - return false; // TODO(?): Add SSL support - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -222,12 +221,6 @@ class TinyGsmBG96 return (s == REG_OK_HOME || s == REG_OK_ROAMING); } - /* - * IP Address functions - */ - protected: - // Can follow all of the IP functions from the template - /* * GPRS functions */ @@ -265,9 +258,7 @@ class TinyGsmBG96 protected: String getSimCCIDImpl() { sendAT(GF("+QCCID")); - if (waitResponse(GF(GSM_NL "+QCCID:")) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL "+QCCID:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); @@ -286,18 +277,6 @@ class TinyGsmBG96 protected: // Follows all messaging functions per template - /* - * Location functions - */ - protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type supported - /* * Time functions */ @@ -305,10 +284,8 @@ class TinyGsmBG96 // Can follow the standard CCLK function in the template /* - * Battery & temperature functions + * Battery functions */ - protected: - float getTemperatureImpl() TINY_GSM_ATTR_NOT_AVAILABLE; /* * Client related functions diff --git a/src/TinyGsmClientESP8266.h b/src/TinyGsmClientESP8266.h index 2e5c37e..08bea11 100644 --- a/src/TinyGsmClientESP8266.h +++ b/src/TinyGsmClientESP8266.h @@ -14,12 +14,15 @@ #define TINY_GSM_MUX_COUNT 5 -#include "TinyGsmCommon.h" +#include "TinyGsmModem.tpp" +#include "TinyGsmSSL.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmWifi.tpp" #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 uint8_t TINY_GSM_TCP_KEEP_ALIVE = 120; +static uint8_t TINY_GSM_TCP_KEEP_ALIVE = 120; // status of ESP8266 station interface // 2 : ESP8266 station connected to an AP and has obtained IP @@ -35,8 +38,14 @@ enum RegStatus { }; class TinyGsmESP8266 - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmWifi, + public TinyGsmTCP, + public TinyGsmSSL { + friend class TinyGsmModem; + friend class TinyGsmWifi; + friend class TinyGsmTCP; + friend class TinyGsmSSL; /* * Inner Client @@ -63,24 +72,16 @@ class TinyGsmESP8266 } public: - int connect(const char* host, uint16_t port, int timeout_s) { + 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; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { TINY_GSM_YIELD(); at->sendAT(GF("+CIPCLOSE="), mux); sock_connected = false; @@ -110,13 +111,14 @@ class TinyGsmESP8266 : GsmClientESP8266(modem, mux) {} public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { stop(); TINY_GSM_YIELD(); rx.clear(); sock_connected = at->modemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; /* @@ -171,18 +173,6 @@ class TinyGsmESP8266 return res; } - bool thisHasSSL() { - return true; - } - - bool thisHasWifi() { - return true; - } - - bool thisHasGPRS() { - return false; - } - /* * Power functions */ @@ -205,12 +195,6 @@ class TinyGsmESP8266 bool sleepEnableImpl(bool enable = true) TINY_GSM_ATTR_NOT_AVAILABLE; - /* - * SIM card functions - */ - protected: - // SIM card functions don't apply - /* * Generic network functions */ @@ -257,16 +241,10 @@ class TinyGsmESP8266 } } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+CIPSTA_CUR?")); int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:")); - if (res1 != 2) { - return ""; - } + if (res1 != 2) { return ""; } String res2 = stream.readStringUntil('"'); waitResponse(); return res2; @@ -292,56 +270,6 @@ class TinyGsmESP8266 return retVal; } - /* - * Phone Call functions - */ - protected: - bool callAnswerImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool callNumberImpl(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; - bool callHangupImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool dtmfSendImpl(char cmd, - int duration_ms = 100) TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Messaging functions - */ - protected: - String sendUSSDImpl(const String& code) TINY_GSM_ATTR_NOT_AVAILABLE; - bool sendSMSImpl(const String& number, - const String& text) TINY_GSM_ATTR_NOT_AVAILABLE; - bool sendSMS_UTF16Impl(const char* const number, const void* text, - size_t len) TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Location functions - */ - protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type supported - - /* - * Time functions - */ - protected: - String - getGSMDateTimeImpl(TinyGSMDateTimeFormat format) TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Battery & temperature functions - */ - protected: - uint16_t getBattVoltageImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - int8_t getBattPercentImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - uint8_t getBattChargeStateImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool getBattStatsImpl(uint8_t& chargeState, int8_t& percent, - uint16_t& milliVolts) TINY_GSM_ATTR_NOT_AVAILABLE; - float getTemperatureImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - /* * Client related functions */ diff --git a/src/TinyGsmClientM590.h b/src/TinyGsmClientM590.h index a54357a..204a470 100644 --- a/src/TinyGsmClientM590.h +++ b/src/TinyGsmClientM590.h @@ -14,7 +14,11 @@ #define TINY_GSM_MUX_COUNT 2 -#include "TinyGsmCommon.h" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -32,8 +36,16 @@ enum RegStatus { }; class TinyGsmM590 - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSMS, + public TinyGsmTime { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSMS; + friend class TinyGsmTime; /* * Inner Client @@ -67,17 +79,9 @@ class TinyGsmM590 sock_connected = at->modemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { TINY_GSM_YIELD(); at->sendAT(GF("+TCPCLOSE="), mux); sock_connected = false; @@ -155,18 +159,6 @@ class TinyGsmM590 return waitResponse() == 1; } - bool thisHasSSL() { - return false; - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -204,15 +196,9 @@ class TinyGsmM590 return (s == REG_OK_HOME || s == REG_OK_ROAMING); } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+XIIC?")); - if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { return ""; } streamSkipUntil(','); String res = stream.readStringUntil('\n'); waitResponse(); @@ -282,16 +268,6 @@ class TinyGsmM590 protected: // Able to follow all SIM card functions as inherited from the template - /* - * Phone Call functions - */ - protected: - bool callAnswerImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool callNumberImpl(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; - bool callHangupImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool dtmfSendImpl(char cmd, - int duration_ms = 100) TINY_GSM_ATTR_NOT_AVAILABLE; - /* * Messaging functions */ @@ -299,34 +275,12 @@ class TinyGsmM590 bool sendSMS_UTF16Impl(const String& number, const void* text, size_t len) TINY_GSM_ATTR_NOT_AVAILABLE; - /* - * Location functions - */ - protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type available /* * Time functions */ protected: // Can follow the standard CCLK function in the template - /* - * Battery & temperature functions - */ - protected: - uint16_t getBattVoltageImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - int8_t getBattPercentImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - uint8_t getBattChargeStateImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool getBattStatsImpl(uint8_t& chargeState, int8_t& percent, - uint16_t& milliVolts) TINY_GSM_ATTR_NOT_AVAILABLE; - float getTemperatureImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - /* * Client related functions */ diff --git a/src/TinyGsmClientM95.h b/src/TinyGsmClientM95.h index af63f01..585c478 100644 --- a/src/TinyGsmClientM95.h +++ b/src/TinyGsmClientM95.h @@ -15,7 +15,14 @@ #define TINY_GSM_MUX_COUNT 6 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmCalling.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTemperature.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -33,8 +40,22 @@ enum RegStatus { }; class TinyGsmM95 - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmTime, + public TinyGsmBattery, + public TinyGsmTemperature { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmTime; + friend class TinyGsmBattery; + friend class TinyGsmTemperature; /* * Inner Client @@ -62,24 +83,16 @@ class TinyGsmM95 } public: - int connect(const char* host, uint16_t port, int timeout_s) { + 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; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { uint32_t startMillis = millis(); dumpModemBuffer(maxWaitMs); at->sendAT(GF("+QICLOSE="), mux); @@ -114,13 +127,14 @@ class TinyGsmM95 public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { stop(); TINY_GSM_YIELD(); rx.clear(); sock_connected = at->modemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; */ @@ -172,18 +186,6 @@ class TinyGsmM95 } } - bool thisHasSSL() { - return false; // TODO(?): Add SSL support - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -231,7 +233,6 @@ class TinyGsmM95 return (s == REG_OK_HOME || s == REG_OK_ROAMING); } - public: void setHostFormat(bool useDottedQuad) { if (useDottedQuad) { sendAT(GF("+QIDNSIP=0")); @@ -241,10 +242,6 @@ class TinyGsmM95 waitResponse(); } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+QILOCIP")); streamSkipUntil('\n'); @@ -338,9 +335,7 @@ class TinyGsmM95 protected: String getSimCCIDImpl() { sendAT(GF("+QCCID")); - if (waitResponse(GF(GSM_NL "+QCCID:")) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL "+QCCID:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); @@ -370,25 +365,18 @@ class TinyGsmM95 } /* - * Location functions + * Time functions */ protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type supported + // Can follow the standard CCLK function in the template /* - * Time functions + * Battery functions */ - protected: - // Can follow the standard CCLK function in the template + // Can follow the battery functions in the template /* - * Battery & temperature functions + * Temperature functions */ protected: float getTemperatureImpl() { diff --git a/src/TinyGsmClientMC60.h b/src/TinyGsmClientMC60.h index bb4b3e5..c6fdb40 100644 --- a/src/TinyGsmClientMC60.h +++ b/src/TinyGsmClientMC60.h @@ -17,7 +17,14 @@ #define TINY_GSM_MUX_COUNT 6 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmCalling.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmGSMLocation.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -35,8 +42,22 @@ enum RegStatus { }; class TinyGsmMC60 - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmGSMLocation, + public TinyGsmTime, + public TinyGsmBattery { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmGSMLocation; + friend class TinyGsmTime; + friend class TinyGsmBattery; /* * Inner Client @@ -64,24 +85,16 @@ class TinyGsmMC60 } public: - int connect(const char* host, uint16_t port, int timeout_s) { + 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; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { uint32_t startMillis = millis(); dumpModemBuffer(maxWaitMs); at->sendAT(GF("+QICLOSE="), mux); @@ -116,13 +129,14 @@ class TinyGsmMC60 public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { stop(); TINY_GSM_YIELD(); rx.clear(); sock_connected = at->modemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; */ @@ -174,29 +188,6 @@ class TinyGsmMC60 } } - /* - * under development - */ - // bool thisHasSSL() { - // sendAT(GF("+QIPSSL=?")); - // if (waitResponse(GF(GSM_NL "+CIPSSL:")) != 1) { - // return false; - // } - // return waitResponse() == 1; - // } - - bool thisHasSSL() { - return false; // TODO(?): Add SSL support - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -240,10 +231,6 @@ class TinyGsmMC60 return (s == REG_OK_HOME || s == REG_OK_ROAMING); } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+QILOCIP")); streamSkipUntil('\n'); @@ -321,21 +308,17 @@ class TinyGsmMC60 delay(1000); continue; } - int status = - waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), - GF("NOT INSERTED"), GF("PH_SIM PIN"), GF("PH_SIM PUK")); + int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), + GF("NOT INSERTED"), GF("PH_SIM PIN"), + GF("PH_SIM PUK")); waitResponse(); switch (status) { case 2: - case 3: - return SIM_LOCKED; + case 3: return SIM_LOCKED; case 5: - case 6: - return SIM_ANTITHEFT_LOCKED; - case 1: - return SIM_READY; - default: - return SIM_ERROR; + case 6: return SIM_ANTITHEFT_LOCKED; + case 1: return SIM_READY; + default: return SIM_ERROR; } } return SIM_ERROR; @@ -369,12 +352,6 @@ class TinyGsmMC60 protected: // Can use CIPGSMLOC as inherited from the template - /* - * GPS location functions - */ - public: - // No functions of this type supported - /* * Time functions */ @@ -382,10 +359,9 @@ class TinyGsmMC60 // Can follow the standard CCLK function in the template /* - * Battery & temperature functions + * Battery functions */ - protected: - float getTemperatureImpl() TINY_GSM_ATTR_NOT_AVAILABLE; + // Can follow battery functions as in the template /* * Client related functions diff --git a/src/TinyGsmClientSIM5360.h b/src/TinyGsmClientSIM5360.h index 8740cd1..b2a2651 100644 --- a/src/TinyGsmClientSIM5360.h +++ b/src/TinyGsmClientSIM5360.h @@ -14,7 +14,13 @@ #define TINY_GSM_MUX_COUNT 10 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTemperature.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -31,10 +37,22 @@ enum RegStatus { REG_UNKNOWN = 4, }; -class TinyGsmSim5360 : public TinyGsmModem { - friend class TinyGsmModem; +class TinyGsmSim5360 : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSMS, + public TinyGsmTime, + public TinyGsmBattery, + public TinyGsmTemperature { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSMS; + friend class TinyGsmTime; + friend class TinyGsmBattery; + friend class TinyGsmTemperature; /* * Inner Client @@ -64,24 +82,16 @@ class TinyGsmSim5360 : public TinyGsmModemmodemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+CIPCLOSE="), mux); sock_connected = false; @@ -112,13 +122,14 @@ class TinyGsmSim5360 : public TinyGsmModemmodemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; */ @@ -186,18 +197,6 @@ class TinyGsmSim5360 : public TinyGsmModem): Module supports SSL, but not yet implemented - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -258,17 +257,11 @@ class TinyGsmSim5360 : public TinyGsmModem { - friend class TinyGsmModem; +class TinyGsmSim7000 : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSMS, + public TinyGsmGSMLocation, + public TinyGsmGPS, + public TinyGsmTime, + public TinyGsmBattery { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSMS; + friend class TinyGsmGSMLocation; + friend class TinyGsmGPS; + friend class TinyGsmTime; + friend class TinyGsmBattery; /* * Inner Client @@ -64,24 +85,16 @@ class TinyGsmSim7000 : public TinyGsmModemmodemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+CIPCLOSE="), mux); sock_connected = false; @@ -113,13 +126,14 @@ class TinyGsmSim7000 : public TinyGsmModemmodemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; */ @@ -187,18 +201,6 @@ class TinyGsmSim7000 : public TinyGsmModem { - friend class TinyGsmModem; +class TinyGsmSim7600 : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSMS, + public TinyGsmGPS, + public TinyGsmTime, + public TinyGsmBattery, + public TinyGsmTemperature { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSMS; + friend class TinyGsmGPS; + friend class TinyGsmTime; + friend class TinyGsmBattery; + friend class TinyGsmTemperature; /* * Inner Client @@ -71,17 +92,9 @@ class TinyGsmSim7600 : public TinyGsmModemmodemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+CIPCLOSE="), mux); sock_connected = false; @@ -98,6 +111,32 @@ class TinyGsmSim7600 : public TinyGsmModemmodemConnect(host, port, mux, true, timeout_s); + return sock_connected; + } + TINY_GSM_CLIENT_CONNECT_OVERRIDES + }; + */ + /* * Constructor */ @@ -162,18 +201,6 @@ class TinyGsmSim7600 : public TinyGsmModem { - friend class TinyGsmModem; +class TinyGsmSim800 + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSSL, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmGSMLocation, + public TinyGsmTime, + public TinyGsmBattery { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSSL; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmGSMLocation; + friend class TinyGsmTime; + friend class TinyGsmBattery; /* * Inner Client @@ -64,24 +88,16 @@ class TinyGsmSim800 : public TinyGsmModemmodemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+CIPCLOSE="), mux, GF(",1")); // Quick close sock_connected = false; @@ -110,13 +126,14 @@ class TinyGsmSim800 : public TinyGsmModemmodemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; /* @@ -206,23 +223,17 @@ class TinyGsmSim800 : public TinyGsmModem +#include "TinyGsmClientSIM800.h" +#include "TinyGsmGPS.tpp" + +class TinyGsmSim808 : public TinyGsmSim800, public TinyGsmGPS { + friend class TinyGsmGPS; -class TinyGsmSim808 : public TinyGsmSim800 { public: explicit TinyGsmSim808(Stream& stream) : TinyGsmSim800(stream) {} + /* * GPS location functions */ - public: + protected: // enable GPS - bool enableGPS() { + bool enableGPSImpl() { // uint16_t state; sendAT(GF("+CGNSPWR=1")); @@ -30,7 +34,7 @@ class TinyGsmSim808 : public TinyGsmSim800 { return true; } - bool disableGPS() { + bool disableGPSImpl() { // uint16_t state; sendAT(GF("+CGNSPWR=0")); @@ -41,7 +45,7 @@ class TinyGsmSim808 : public TinyGsmSim800 { // get the RAW GPS output // works only with ans SIM808 V2 - String getGPSraw() { + String getGPSrawImpl() { sendAT(GF("+CGNSINF")); if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); @@ -52,8 +56,8 @@ class TinyGsmSim808 : public TinyGsmSim800 { // 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) { + bool getGPSImpl(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; @@ -90,8 +94,8 @@ class TinyGsmSim808 : public TinyGsmSim800 { // get GPS time // works only with SIM808 V2 - bool getGPSTime(int* year, int* month, int* day, int* hour, int* minute, - int* second) { + bool getGPSTimeImpl(int* year, int* month, int* day, int* hour, int* minute, + int* second) { bool fix = false; char chr_buffer[12]; sendAT(GF("+CGNSINF")); diff --git a/src/TinyGsmClientSaraR4.h b/src/TinyGsmClientSaraR4.h index 9f4e052..a700ec5 100644 --- a/src/TinyGsmClientSaraR4.h +++ b/src/TinyGsmClientSaraR4.h @@ -14,7 +14,15 @@ #define TINY_GSM_MUX_COUNT 7 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmGSMLocation.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmSSL.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTemperature.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -31,10 +39,26 @@ enum RegStatus { REG_UNKNOWN = 4, }; -class TinyGsmSaraR4 : public TinyGsmModem { - friend class TinyGsmModem; +class TinyGsmSaraR4 + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSSL, + public TinyGsmBattery, + public TinyGsmGSMLocation, + public TinyGsmSMS, + public TinyGsmTemperature, + public TinyGsmTime { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSSL; + friend class TinyGsmBattery; + friend class TinyGsmGSMLocation; + friend class TinyGsmSMS; + friend class TinyGsmTemperature; + friend class TinyGsmTime; /* * Inner Client @@ -64,7 +88,7 @@ class TinyGsmSaraR4 : public TinyGsmModemmaintain(); return sock_connected; } + virtual int connect(IPAddress ip, uint16_t port, int timeout_s) { + return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); + } + int connect(const char* host, uint16_t port) override { + return connect(host, port, 120); + } + int connect(IPAddress ip, uint16_t port) override { + return connect(ip, port, 120); + } }; /* @@ -249,18 +282,6 @@ class TinyGsmSaraR4 : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSSL, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmTime, + public TinyGsmTemperature { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSSL; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmTime; + friend class TinyGsmTemperature; /* * Inner Client @@ -77,24 +98,16 @@ class TinyGsmSequansMonarch } public: - int connect(const char* host, uint16_t port, int timeout_s) { + virtual int connect(const char* host, uint16_t port, int timeout_s) { if (sock_connected) stop(); TINY_GSM_YIELD(); rx.clear(); sock_connected = at->modemConnect(host, port, mux, false, timeout_s); return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+SQNSH="), mux); sock_connected = false; @@ -127,7 +140,7 @@ class TinyGsmSequansMonarch bool strictSSL = false; public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { stop(); TINY_GSM_YIELD(); rx.clear(); @@ -153,6 +166,7 @@ class TinyGsmSequansMonarch sock_connected = at->modemConnect(host, port, mux, true, timeout_s); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES void setStrictSSL(bool strict) { strictSSL = strict; @@ -225,18 +239,6 @@ class TinyGsmSequansMonarch while (stream.available()) { waitResponse(15, NULL, NULL); } } - bool thisHasGPRS() { - return true; - } - - bool thisHasWifi() { - return false; - } - - bool thisHasSSL() { - return true; - } - /* * Power functions */ @@ -287,16 +289,9 @@ class TinyGsmSequansMonarch RegStatus s = getRegistrationStatus(); return (s == REG_OK_HOME || s == REG_OK_ROAMING); } - - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+CGPADDR=3")); - if (waitResponse(10000L, GF("+CGPADDR: 3,\"")) != 1) { - return ""; - } + if (waitResponse(10000L, GF("+CGPADDR: 3,\"")) != 1) { return ""; } String res = stream.readStringUntil('\"'); waitResponse(); return res; @@ -344,9 +339,7 @@ class TinyGsmSequansMonarch protected: String getSimCCIDImpl() { sendAT(GF("+SQNCCID")); - if (waitResponse(GF(GSM_NL "+SQNCCID:")) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL "+SQNCCID:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); @@ -367,18 +360,6 @@ class TinyGsmSequansMonarch protected: // Follows all messaging functions per template - /* - * Location functions - */ - protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type supported - /* * Time functions */ @@ -386,14 +367,8 @@ class TinyGsmSequansMonarch // Can follow the standard CCLK function in the template /* - * Battery & temperature functions + * Temperature functions */ - protected: - uint16_t getBattVoltageImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - int8_t getBattPercentImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - uint8_t getBattChargeStateImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool getBattStatsImpl(uint8_t& chargeState, int8_t& percent, - uint16_t& milliVolts) TINY_GSM_ATTR_NOT_AVAILABLE; float getTemperatureImpl() { sendAT(GF("+SMDTH")); diff --git a/src/TinyGsmClientUBLOX.h b/src/TinyGsmClientUBLOX.h index 20751de..553abbc 100644 --- a/src/TinyGsmClientUBLOX.h +++ b/src/TinyGsmClientUBLOX.h @@ -14,7 +14,15 @@ #define TINY_GSM_MUX_COUNT 7 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmCalling.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmGSMLocation.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmSSL.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTime.tpp" #define GSM_NL "\r\n" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -32,9 +40,25 @@ enum RegStatus { }; class TinyGsmUBLOX - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmTCP, + public TinyGsmSSL, + public TinyGsmCalling, + public TinyGsmSMS, + public TinyGsmGSMLocation, + public TinyGsmTime, + public TinyGsmBattery { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmTCP; + friend class TinyGsmSSL; + friend class TinyGsmCalling; + friend class TinyGsmSMS; + friend class TinyGsmGSMLocation; + friend class TinyGsmTime; + friend class TinyGsmBattery; /* * Inner Client @@ -64,7 +88,7 @@ class TinyGsmUBLOX } public: - int connect(const char* host, uint16_t port, int timeout_s) { + virtual int connect(const char* host, uint16_t port, int timeout_s) { stop(); TINY_GSM_YIELD(); rx.clear(); @@ -80,17 +104,9 @@ class TinyGsmUBLOX return sock_connected; } - int connect(IPAddress ip, uint16_t port, int timeout_s) { - return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); - } - int connect(const char* host, uint16_t port) override { - return connect(host, port, 75); - } - int connect(IPAddress ip, uint16_t port) override { - return connect(ip, port, 75); - } + TINY_GSM_CLIENT_CONNECT_OVERRIDES - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { dumpModemBuffer(maxWaitMs); at->sendAT(GF("+USOCL="), mux); at->waitResponse(); // should return within 1s @@ -119,7 +135,7 @@ class TinyGsmUBLOX : GsmClientUBLOX(modem, mux) {} public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { stop(); TINY_GSM_YIELD(); rx.clear(); @@ -133,6 +149,7 @@ class TinyGsmUBLOX at->maintain(); return sock_connected; } + TINY_GSM_CLIENT_CONNECT_OVERRIDES }; /* @@ -212,18 +229,6 @@ class TinyGsmUBLOX return waitResponse() == 1; } - bool thisHasSSL() { - return true; - } - - bool thisHasWifi() { - return false; - } - - bool thisHasGPRS() { - return true; - } - /* * Power functions */ @@ -262,21 +267,13 @@ class TinyGsmUBLOX return false; } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { sendAT(GF("+UPSND=0,0")); - if (waitResponse(GF(GSM_NL "+UPSND:")) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL "+UPSND:")) != 1) { return ""; } streamSkipUntil(','); // Skip PSD profile streamSkipUntil('\"'); // Skip request type String res = stream.readStringUntil('\"'); - if (waitResponse() != 1) { - return ""; - } + if (waitResponse() != 1) { return ""; } return res; } @@ -370,9 +367,7 @@ class TinyGsmUBLOX protected: String getIMEIImpl() { sendAT(GF("+CGSN")); - if (waitResponse(GF(GSM_NL)) != 1) { - return ""; - } + if (waitResponse(GF(GSM_NL)) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); @@ -413,12 +408,6 @@ class TinyGsmUBLOX return res; } - /* - * GPS location functions - */ - public: - // No functions of this type supported - /* * Time functions */ @@ -426,7 +415,7 @@ class TinyGsmUBLOX // Can follow the standard CCLK function in the template /* - * Battery & temperature functions + * Battery functions */ protected: uint16_t getBattVoltageImpl() TINY_GSM_ATTR_NOT_AVAILABLE; @@ -452,6 +441,10 @@ class TinyGsmUBLOX return true; } + /* + * Temperature functions + */ + // This would only available for a small number of modules in this group // (TOBY-L) float getTemperatureImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; @@ -477,8 +470,9 @@ class TinyGsmUBLOX } // Enable NODELAY - sendAT(GF("+USOSO="), *mux, GF(",6,1,1")); - waitResponse(); + // NOTE: No delay allows data to go out faster, at the cost of using + // additional data from your cellular plan sendAT(GF("+USOSO="), *mux, + // GF(",6,1,1")); waitResponse(); // Enable KEEPALIVE, 30 sec // sendAT(GF("+USOSO="), *mux, GF(",6,2,30000")); diff --git a/src/TinyGsmClientXBee.h b/src/TinyGsmClientXBee.h index 73e0822..f553f54 100644 --- a/src/TinyGsmClientXBee.h +++ b/src/TinyGsmClientXBee.h @@ -20,7 +20,14 @@ // here) #define TINY_GSM_XBEE_GUARD_TIME 1010 -#include "TinyGsmCommon.h" +#include "TinyGsmBattery.tpp" +#include "TinyGsmGPRS.tpp" +#include "TinyGsmModem.tpp" +#include "TinyGsmSMS.tpp" +#include "TinyGsmSSL.tpp" +#include "TinyGsmTCP.tpp" +#include "TinyGsmTemperature.tpp" +#include "TinyGsmWifi.tpp" #define GSM_NL "\r" static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; @@ -59,8 +66,22 @@ enum XBeeType { }; class TinyGsmXBee - : public TinyGsmModem { - friend class TinyGsmModem; + : public TinyGsmModem, + public TinyGsmGPRS, + public TinyGsmWifi, + public TinyGsmTCP, + public TinyGsmSSL, + public TinyGsmSMS, + public TinyGsmBattery, + public TinyGsmTemperature { + friend class TinyGsmModem; + friend class TinyGsmGPRS; + friend class TinyGsmWifi; + friend class TinyGsmTCP; + friend class TinyGsmSSL; + friend class TinyGsmSMS; + friend class TinyGsmBattery; + friend class TinyGsmTemperature; /* * Inner Client @@ -93,7 +114,7 @@ class TinyGsmXBee // itself is not opened until you attempt to send data. Because all settings // are saved to flash, it is possible (or likely) that you could send data // even if you haven't "made" any connection. - int connect(const char* host, uint16_t port, int timeout_s) { + virtual int connect(const char* host, uint16_t port, int timeout_s) { // NOTE: Not caling stop() or yeild() here at->streamClear(); // Empty anything in the buffer before starting sock_connected = at->modemConnect(host, port, mux, false, timeout_s); @@ -103,7 +124,7 @@ class TinyGsmXBee return connect(host, port, 75); } - int connect(IPAddress ip, uint16_t port, int timeout_s) { + virtual int connect(IPAddress ip, uint16_t port, int timeout_s) { if (timeout_s != 0) { DBG("Timeout [", timeout_s, "] doesn't apply here."); } @@ -116,7 +137,7 @@ class TinyGsmXBee return connect(ip, port, 0); } - void stop(uint32_t maxWaitMs) { + virtual void stop(uint32_t maxWaitMs) { at->streamClear(); // Empty anything in the buffer // empty the saved currently-in-use destination address at->modemStop(maxWaitMs); @@ -236,14 +257,17 @@ class TinyGsmXBee : GsmClientXBee(modem, mux) {} public: - int connect(const char* host, uint16_t port, int timeout_s) { + int connect(const char* host, uint16_t port, int timeout_s) override { // NOTE: Not caling stop() or yeild() here at->streamClear(); // Empty anything in the buffer before starting sock_connected = at->modemConnect(host, port, mux, true, timeout_s); return sock_connected; } + int connect(const char* host, uint16_t port) override { + return connect(host, port, 75); + } - int connect(IPAddress ip, uint16_t port, int timeout_s) { + int connect(IPAddress ip, uint16_t port, int timeout_s) override { if (timeout_s != 0) { DBG("Timeout [", timeout_s, "] doesn't apply here."); } @@ -252,6 +276,9 @@ class TinyGsmXBee sock_connected = at->modemConnect(ip, port, mux, true); return sock_connected; } + int connect(IPAddress ip, uint16_t port) override { + return connect(ip, port, 0); + } }; /* @@ -405,6 +432,7 @@ class TinyGsmXBee return sendATGetString(GF("HS")); } + /* bool thisHasSSL() { if (beeType == XBEE_S6B_WIFI) return false; @@ -425,6 +453,7 @@ class TinyGsmXBee else return true; } + */ public: XBeeType getBeeType() { @@ -692,10 +721,6 @@ class TinyGsmXBee return retVal; } - /* - * IP Address functions - */ - protected: String getLocalIPImpl() { XBEE_COMMAND_START_DECORATOR(5, "") sendAT(GF("MY")); @@ -788,7 +813,9 @@ class TinyGsmXBee return isNetworkConnected(); } - String getOperatorImpl() { return sendATGetString(GF("MN")); } + String getOperatorImpl() { + return sendATGetString(GF("MN")); + } /* * SIM card functions @@ -801,24 +828,18 @@ class TinyGsmXBee return false; } - String getSimCCIDImpl() { return sendATGetString(GF("S#")); } + String getSimCCIDImpl() { + return sendATGetString(GF("S#")); + } - String getIMEIImpl() { return sendATGetString(GF("IM")); } + String getIMEIImpl() { + return sendATGetString(GF("IM")); + } SimStatus getSimStatusImpl(uint32_t) { return SIM_READY; // unsupported } - /* - * Phone Call functions - */ - protected: - bool callAnswerImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool callNumberImpl(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; - bool callHangupImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - bool dtmfSendImpl(char cmd, - int duration_ms = 100) TINY_GSM_ATTR_NOT_AVAILABLE; - /* * Messaging functions */ @@ -848,26 +869,7 @@ class TinyGsmXBee } /* - * Location functions - */ - protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * GPS location functions - */ - public: - // No functions of this type supported - - /* - * Time functions - */ - protected: - String getGSMDateTimeImpl(TinyGSMDateTimeFormat format) - TINY_GSM_ATTR_NOT_IMPLEMENTED; - - /* - * Battery & temperature functions + * Battery functions */ protected: // Use: float vBatt = modem.getBattVoltage() / 1000.0; @@ -894,6 +896,10 @@ class TinyGsmXBee return true; } + /* + * Temperature functions + */ + float getTemperatureImpl() { XBEE_COMMAND_START_DECORATOR(5, static_cast(-9999)) String res = sendATGetString(GF("TP")); diff --git a/src/TinyGsmCommon.h b/src/TinyGsmCommon.h index bae5447..683795b 100644 --- a/src/TinyGsmCommon.h +++ b/src/TinyGsmCommon.h @@ -28,8 +28,6 @@ #include #endif -#include "TinyGsmFifo.h" - #ifndef TINY_GSM_YIELD_MS #define TINY_GSM_YIELD_MS 0 #endif @@ -39,10 +37,6 @@ { delay(TINY_GSM_YIELD_MS); } #endif -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 64 -#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"))) @@ -102,7 +96,7 @@ uint32_t TinyGsmAutoBaud(T& SerialAT, uint32_t minimum = 9600, 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++) { + for (uint8_t i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) { uint32_t rate = rates[i]; if (rate < minimum || rate > maximum) continue; @@ -122,1120 +116,4 @@ uint32_t TinyGsmAutoBaud(T& SerialAT, uint32_t minimum = 9600, return 0; } -enum modemInternalBuffferType { - NO_MODEM_BUFFER = - 0, // For modules that do not store incoming data in any sort of buffer - READ_NO_CHECK = 1, // Data is stored in a buffer, but we can only read from - // the buffer, not check how much data is stored in it - READ_AND_CHECK_SIZE = 2, // Data is stored in a buffer and we can both read - // and check the size of the buffer -}; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, - SIM_ANTITHEFT_LOCKED = 3, -}; - -enum TinyGSMDateTimeFormat { DATE_FULL = 0, DATE_TIME = 1, DATE_DATE = 2 }; - -template -class TinyGsmModem { - public: - /* - * Basic functions - */ - bool begin(const char* pin = NULL) { - return thisModem().initImpl(pin); - } - bool init(const char* pin = NULL) { - return thisModem().initImpl(pin); - } - template - void sendAT(Args... cmd) { - thisModem().streamWrite("AT", cmd..., thisModem().gsmNL); - thisModem().stream.flush(); - TINY_GSM_YIELD(); /* DBG("### AT:", cmd...); */ - } - void setBaud(uint32_t baud) { - thisModem().setBaudImpl(baud); - } - // Test response to AT commands - bool testAT(uint32_t timeout_ms = 10000L) { - return thisModem().testATImpl(timeout_ms); - } - - // Asks for modem information via the V.25TER standard ATI command - // NOTE: The actual value and style of the response is quite varied - String getModemInfo() { - return thisModem().getModemInfoImpl(); - } - // Gets the modem name (as it calls itself) - String getModemName() { - return thisModem().getModemNameImpl(); - } - void maintain() { - return thisModem().maintainImpl(); - } - bool factoryDefault() { - return thisModem().factoryDefaultImpl(); - } - bool hasSSL() { - return thisModem().thisHasSSL(); - } - bool hasWifi() { - return thisModem().thisHasWifi(); - } - bool hasGPRS() { - return thisModem().thisHasGPRS(); - } - - /* - * Power functions - */ - bool restart() { - return thisModem().restartImpl(); - } - bool poweroff() { - return thisModem().powerOffImpl(); - } - bool radioOff() { - return thisModem().radioOffImpl(); - } - bool sleepEnable(bool enable = true) { - return thisModem().sleepEnableImpl(enable); - } - - /* - * SIM card functions - */ - // Unlocks the SIM - bool simUnlock(const char* pin) { - return thisModem().simUnlockImpl(pin); - } - // Gets the CCID of a sim card via AT+CCID - String getSimCCID() { - return thisModem().getSimCCIDImpl(); - } - // Asks for TA Serial Number Identification (IMEI) - String getIMEI() { - return thisModem().getIMEIImpl(); - } - SimStatus getSimStatus(uint32_t timeout_ms = 10000L) { - return thisModem().getSimStatusImpl(timeout_ms); - } - - /* - * Generic network functions - */ - // RegStatus getRegistrationStatus() {} - bool isNetworkConnected() { - return thisModem().isNetworkConnectedImpl(); - } - // Waits for network attachment - bool waitForNetwork(uint32_t timeout_ms = 60000L) { - return thisModem().waitForNetworkImpl(timeout_ms); - } - // Gets signal quality report - int16_t getSignalQuality() { - return thisModem().getSignalQualityImpl(); - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user = NULL, - const char* pwd = NULL) { - return thisModem().gprsConnectImpl(apn, user, pwd); - } - bool gprsDisconnect() { - return thisModem().gprsDisconnectImpl(); - } - // Checks if current attached to GPRS/EPS service - bool isGprsConnected() { - return thisModem().isGprsConnectedImpl(); - } - // Gets the current network operator - String getOperator() { - return thisModem().getOperatorImpl(); - } - - /* - * WiFi functions - */ - bool networkConnect(const char* ssid, const char* pwd) { - return thisModem().networkConnectImpl(ssid, pwd); - } - bool networkDisconnect() { - return thisModem().networkDisconnectImpl(); - } - - /* - * GPRS functions - */ - String getLocalIP() { - return thisModem().getLocalIPImpl(); - } - IPAddress localIP() { - return thisModem().TinyGsmIpFromString(thisModem().getLocalIP()); - } - - /* - * Phone Call functions - */ - bool callAnswer() { - return thisModem().callAnswerImpl(); - } - bool callNumber(const String& number) { - return thisModem().callNumberImpl(number); - } - bool callHangup() { - return thisModem().callHangupImpl(); - } - bool dtmfSend(char cmd, int duration_ms = 100) { - return thisModem().dtmfSendImpl(cmd, duration_ms); - } - - /* - * Messaging functions - */ - String sendUSSD(const String& code) { - return thisModem().sendUSSDImpl(code); - } - bool sendSMS(const String& number, const String& text) { - return thisModem().sendSMSImpl(number, text); - } - bool sendSMS_UTF16(const char* const number, const void* text, size_t len) { - return thisModem().sendSMS_UTF16Impl(number, text, len); - } - - /* - * Location functions - */ - String getGsmLocation() { - return thisModem().getGsmLocationImpl(); - } - - /* - * GPS location functions - */ - // No template interface or implementation of these functions - - /* - * Time functions - */ - String getGSMDateTime(TinyGSMDateTimeFormat format) { - return thisModem().getGSMDateTimeImpl(format); - } - - /* - * Battery & temperature functions - */ - uint16_t getBattVoltage() { - return thisModem().getBattVoltageImpl(); - } - int8_t getBattPercent() { - return thisModem().getBattPercentImpl(); - } - uint8_t getBattChargeState() { - return thisModem().getBattChargeStateImpl(); - } - bool getBattStats(uint8_t& chargeState, int8_t& percent, - uint16_t& milliVolts) { - return thisModem().getBattStatsImpl(chargeState, percent, milliVolts); - } - float getTemperature() { - return thisModem().getTemperatureImpl(); - } - - /* - * CRTP Helper - */ - protected: - const modemType& thisModem() const { - return static_cast(*this); - } - modemType& thisModem() { - return static_cast(*this); - } - - /* - * Inner Client - */ - public: - class GsmClient : public Client { - // Make all classes created from the modem template friends - friend class TinyGsmModem; - typedef TinyGsmFifo RxFifo; - - public: - // bool init(modemType* modem, uint8_t); - // int connect(const char* host, uint16_t port, int timeout_s); - - // Connect to a IP address given as an IPAddress object by - // converting said IP address to text - // int connect(IPAddress ip, uint16_t port, int timeout_s) { - // return connect(TinyGsmStringFromIp(ip).c_str(), port, - // timeout_s); - // } - // int connect(const char* host, uint16_t port) override { - // return connect(host, port, 75); - // } - // int connect(IPAddress ip, uint16_t port) override { - // return connect(ip, port, 75); - // } - - static String TinyGsmStringFromIp(IPAddress ip) { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return host; - } - - // void stop(uint32_t maxWaitMs); - // void stop() override { - // stop(15000L); - // } - - // Writes data out on the client using the modem send functionality - size_t write(const uint8_t* buf, size_t size) override { - TINY_GSM_YIELD(); - at->maintain(); - return at->modemSend(buf, size, mux); - } - - size_t write(uint8_t c) override { - return write(&c, 1); - } - - size_t write(const char* str) { - if (str == NULL) return 0; - return write((const uint8_t*)str, strlen(str)); - } - - int available() override { - TINY_GSM_YIELD(); - switch (bufType) { - // Returns the number of characters available in the TinyGSM fifo - case NO_MODEM_BUFFER: - if (!rx.size() && sock_connected) { at->maintain(); } - return rx.size(); - - // Returns the combined number of characters available in the TinyGSM - // fifo and the modem chips internal fifo. - case READ_NO_CHECK: - if (!rx.size()) { at->maintain(); } - return rx.size() + sock_available; - - // Returns the combined number of characters available in the TinyGSM - // fifo and the modem chips internal fifo, doing an extra check-in - // with the modem to see if anything has arrived without a UURC. - case READ_AND_CHECK_SIZE: - if (!rx.size()) { - if (millis() - prev_check > 500) { - got_data = true; - prev_check = millis(); - } - at->maintain(); - } - return rx.size() + sock_available; - } - } - - int read(uint8_t* buf, size_t size) override { - TINY_GSM_YIELD(); - size_t cnt = 0; - uint32_t _startMillis = millis(); - - switch (bufType) { - // Reads characters out of the TinyGSM fifo, waiting for any URC's - // from the modem for new data if there's nothing in the fifo. - case NO_MODEM_BUFFER: - while (cnt < size && millis() - _startMillis < _timeout) { - size_t chunk = TinyGsmMin(size - cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } /* TODO: Read directly into user buffer? */ - if (!rx.size() && sock_connected) { at->maintain(); } - } - return cnt; - - // Reads characters out of the TinyGSM fifo, and from the modem chip's - // internal fifo if avaiable. - case READ_NO_CHECK: - at->maintain(); - while (cnt < size) { - size_t chunk = TinyGsmMin(size - cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } /* TODO: Read directly into user buffer? */ - at->maintain(); - if (sock_available > 0) { - int n = at->modemRead( - TinyGsmMin((uint16_t)rx.free(), sock_available), mux); - if (n == 0) break; - } else { - break; - } - } - return cnt; - - // Reads characters out of the TinyGSM fifo, and from the modem chips - // internal fifo if avaiable, also double checking with the modem if - // data has arrived without issuing a UURC. - case READ_AND_CHECK_SIZE: - at->maintain(); - while (cnt < size) { - size_t chunk = TinyGsmMin(size - cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // Workaround: Some modules "forget" to notify about data arrival - if (millis() - prev_check > 500) { - got_data = true; - prev_check = millis(); - } - // TODO(vshymanskyy): Read directly into user buffer? - at->maintain(); - if (sock_available > 0) { - int n = at->modemRead( - TinyGsmMin((uint16_t)rx.free(), sock_available), mux); - if (n == 0) break; - } else { - break; - } - } - return cnt; - } - } - - int read() override { - uint8_t c; - if (read(&c, 1) == 1) { return c; } - return -1; - } - - // TODO(SRGDamia1): Implement peek - int peek() override { - return -1; - } - - void flush() override { - at->stream.flush(); - } - - uint8_t connected() override { - if (available()) { return true; } - return sock_connected; - } - operator bool() override { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - protected: - // Read and dump anything remaining in the modem's internal buffer. - // Using this in the client stop() function. - // The socket will appear open in response to connected() even after it - // closes until all data is read from the buffer. - // Doing it this way allows the external mcu to find and get all of the - // data that it wants from the socket even if it was closed externally. - void dumpModemBuffer(uint32_t maxWaitMs) { - TINY_GSM_YIELD(); - rx.clear(); - at->maintain(); - uint32_t startMillis = millis(); - while (sock_available > 0 && (millis() - startMillis < maxWaitMs)) { - at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux); - rx.clear(); - at->maintain(); - } - } - - modemType* at; - uint8_t mux; - uint16_t sock_available; - uint32_t prev_check; - bool sock_connected; - bool got_data; - RxFifo rx; - }; - - /* - * Inner Secure Client - */ - - /* - * Constructor - */ - - /* - * Basic functions - */ - protected: - void setBaudImpl(uint32_t baud) { - thisModem().sendAT(GF("+IPR="), baud); - thisModem().waitResponse(); - } - - bool testATImpl(uint32_t timeout_ms = 10000L) { - for (uint32_t start = millis(); millis() - start < timeout_ms;) { - thisModem().sendAT(GF("")); - if (thisModem().waitResponse(200) == 1) { return true; } - delay(100); - } - return false; - } - - String getModemInfoImpl() { - thisModem().sendAT(GF("I")); - String res; - if (thisModem().waitResponse(1000L, res) != 1) { return ""; } - // Do the replaces twice so we cover both \r and \r\n type endings - res.replace("\r\nOK\r\n", ""); - res.replace("\rOK\r", ""); - res.replace("\r\n", " "); - res.replace("\r", " "); - res.trim(); - return res; - } - - String getModemNameImpl() { - thisModem().sendAT(GF("+CGMI")); - String res1; - if (thisModem().waitResponse(1000L, res1) != 1) { return "unknown"; } - res1.replace("\r\nOK\r\n", ""); - res1.replace("\rOK\r", ""); - res1.trim(); - - thisModem().sendAT(GF("+GMM")); - String res2; - if (thisModem().waitResponse(1000L, res2) != 1) { return "unknown"; } - res1.replace("\r\nOK\r\n", ""); - res1.replace("\rOK\r", ""); - res2.trim(); - - String name = res1 + String(' ') + res2; - DBG("### Modem:", name); - return name; - } - - void maintainImpl() { - switch (bufType) { - case READ_AND_CHECK_SIZE: - // Keep listening for modem URC's and proactively iterate through - // sockets asking if any data is avaiable - for (int mux = 0; mux < muxCount; mux++) { - GsmClient* sock = thisModem().sockets[mux]; - if (sock && sock->got_data) { - sock->got_data = false; - sock->sock_available = thisModem().modemGetAvailable(mux); - } - } - while (thisModem().stream.available()) { - thisModem().waitResponse(15, NULL, NULL); - } - break; - default: - // Just listen for any URC's - thisModem().waitResponse(100, NULL, NULL); - break; - } - } - - bool factoryDefaultImpl() { - thisModem().sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write - thisModem().waitResponse(); - thisModem().sendAT(GF("+IPR=0")); // Auto-baud - thisModem().waitResponse(); - thisModem().sendAT(GF("&W")); // Write configuration - return thisModem().waitResponse() == 1; - } - - /* - * Power functions - */ - protected: - bool radioOffImpl() { - thisModem().sendAT(GF("+CFUN=0")); - if (thisModem().waitResponse(10000L) != 1) { return false; } - delay(3000); - return true; - } - - bool sleepEnableImpl(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - /* - * SIM card functions - */ - protected: - // Unlocks a sim via the 3GPP TS command AT+CPIN - bool simUnlockImpl(const char* pin) { - if (pin && strlen(pin) > 0) { - thisModem().sendAT(GF("+CPIN=\""), pin, GF("\"")); - return thisModem().waitResponse() == 1; - } - return true; - } - - // Gets the CCID of a sim card via AT+CCID - String getSimCCIDImpl() { - thisModem().sendAT(GF("+CCID")); - if (thisModem().waitResponse(GF("+CCID:")) != 1) { return ""; } - String res = thisModem().stream.readStringUntil('\n'); - thisModem().waitResponse(); - res.trim(); - return res; - } - - // Asks for TA Serial Number Identification (IMEI) via the V.25TER standard - // AT+GSN command - String getIMEIImpl() { - thisModem().sendAT(GF("+GSN")); - String res = thisModem().stream.readStringUntil('\n'); - thisModem().waitResponse(); - res.trim(); - return res; - } - - SimStatus getSimStatusImpl(uint32_t timeout_ms = 10000L) { - for (uint32_t start = millis(); millis() - start < timeout_ms;) { - thisModem().sendAT(GF("+CPIN?")); - if (thisModem().waitResponse(GF("+CPIN:")) != 1) { - delay(1000); - continue; - } - int status = thisModem().waitResponse(GF("READY"), GF("SIM PIN"), - GF("SIM PUK"), GF("NOT INSERTED"), - GF("NOT READY")); - thisModem().waitResponse(); - switch (status) { - case 2: - case 3: return SIM_LOCKED; - case 1: return SIM_READY; - default: return SIM_ERROR; - } - } - return SIM_ERROR; - } - - /* - * Generic network functions - */ - protected: - // Gets the modem's registration status via CREG/CGREG/CEREG - // CREG = Generic network registration - // CGREG = GPRS service registration - // CEREG = EPS registration for LTE modules - int getRegistrationStatusXREG(const char* regCommand) { - thisModem().sendAT('+', regCommand, '?'); - // check for any of the three for simplicity - int resp = thisModem().waitResponse(GF("+CREG:"), GF("+CGREG:"), - GF("+CEREG:")); - if (resp != 1 && resp != 2 && resp != 3) { return -1; } - thisModem().streamSkipUntil(','); /* Skip format (0) */ - int status = thisModem().streamGetInt('\n'); - thisModem().waitResponse(); - return status; - } - - bool waitForNetworkImpl(uint32_t timeout_ms = 60000L) { - for (uint32_t start = millis(); millis() - start < timeout_ms;) { - if (thisModem().isNetworkConnected()) { return true; } - delay(250); - } - return false; - } - - // Gets signal quality report according to 3GPP TS command AT+CSQ - int16_t getSignalQualityImpl() { - thisModem().sendAT(GF("+CSQ")); - if (thisModem().waitResponse(GF("+CSQ:")) != 1) { return 99; } - int res = thisModem().streamGetInt(','); - thisModem().waitResponse(); - return res; - } - - /* - * GPRS functions - */ - protected: - // Checks if current attached to GPRS/EPS service - bool isGprsConnectedImpl() { - thisModem().sendAT(GF("+CGATT?")); - if (thisModem().waitResponse(GF("+CGATT:")) != 1) { return false; } - int res = thisModem().streamGetInt('\n'); - thisModem().waitResponse(); - if (res != 1) { return false; } - - return thisModem().localIP() != IPAddress(0, 0, 0, 0); - } - - // Gets the current network operator via the 3GPP TS command AT+COPS - String getOperatorImpl() { - thisModem().sendAT(GF("+COPS?")); - if (thisModem().waitResponse(GF("+COPS:")) != 1) { return ""; } - thisModem().streamSkipUntil('"'); /* Skip mode and format */ - String res = thisModem().stream.readStringUntil('"'); - thisModem().waitResponse(); - return res; - } - - /* - * WiFi functions - */ - - bool networkConnectImpl(const char* ssid, const char* pwd) { - return false; - } - bool networkDisconnectImpl() { - return thisModem().gprsConnectImpl(); - } - - /* - * IP Address functions - */ - protected: - String getLocalIPImpl() { - thisModem().sendAT(GF("+CGPADDR=1")); - if (thisModem().waitResponse(GF("+CGPADDR:")) != 1) { return ""; } - thisModem().streamSkipUntil(','); // Skip context id - String res = thisModem().stream.readStringUntil('\r'); - if (thisModem().waitResponse() != 1) { return ""; } - return res; - } - - static IPAddress TinyGsmIpFromString(const String& strIP) { - int Parts[4] = { - 0, - }; - int Part = 0; - for (uint8_t i = 0; i < strIP.length(); i++) { - char c = strIP[i]; - if (c == '.') { - Part++; - if (Part > 3) { return IPAddress(0, 0, 0, 0); } - continue; - } else if (c >= '0' && c <= '9') { - Parts[Part] *= 10; - Parts[Part] += c - '0'; - } else { - if (Part == 3) break; - } - } - return IPAddress(Parts[0], Parts[1], Parts[2], Parts[3]); - } - - /* - * Phone Call functions - */ - protected: - bool callAnswerImpl() { - thisModem().sendAT(GF("A")); - return thisModem().waitResponse() == 1; - } - - // Returns true on pick-up, false on error/busy - bool callNumberImpl(const String& number) { - if (number == GF("last")) { - thisModem().sendAT(GF("DL")); - } else { - thisModem().sendAT(GF("D"), number, ";"); - } - int status = thisModem().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 callHangupImpl() { - thisModem().sendAT(GF("H")); - return thisModem().waitResponse() == 1; - } - - // 0-9,*,#,A,B,C,D - bool dtmfSendImpl(char cmd, int duration_ms = 100) { - duration_ms = constrain(duration_ms, 100, 1000); - - thisModem().sendAT(GF("+VTD="), - duration_ms / 100); // VTD accepts in 1/10 of a second - thisModem().waitResponse(); - - thisModem().sendAT(GF("+VTS="), cmd); - return thisModem().waitResponse(10000L) == 1; - } - - /* - * Messaging functions - */ - protected: - static inline String TinyGsmDecodeHex7bit(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 cc = reminder; - result += cc; - reminder = 0; - bitstate = 7; - } - } - return result; - } - - static inline String TinyGsmDecodeHex8bit(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 inline String TinyGsmDecodeHex16bit(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 ;( -#if defined(TINY_GSM_UNICODE_TO_HEX) - result += "\\x"; - result += instr.substring(i, i + 4); -#else - result += "?"; -#endif - } else { - buf[0] = instr[i + 2]; - buf[1] = instr[i + 3]; - b = strtol(buf, NULL, 16); - result += b; - } - } - return result; - } - - String sendUSSDImpl(const String& code) { - // Set preferred message format to text mode - thisModem().sendAT(GF("+CMGF=1")); - thisModem().waitResponse(); - // Set 8-bit hexadecimal alphabet (3GPP TS 23.038) - thisModem().sendAT(GF("+CSCS=\"HEX\"")); - thisModem().waitResponse(); - // Send the message - thisModem().sendAT(GF("+CUSD=1,\""), code, GF("\"")); - if (thisModem().waitResponse() != 1) { return ""; } - if (thisModem().waitResponse(10000L, GF("+CUSD:")) != 1) { return ""; } - thisModem().stream.readStringUntil('"'); - String hex = thisModem().stream.readStringUntil('"'); - thisModem().stream.readStringUntil(','); - int dcs = thisModem().streamGetInt('\n'); - - if (dcs == 15) { - return TinyGsmDecodeHex8bit(hex); - } else if (dcs == 72) { - return TinyGsmDecodeHex16bit(hex); - } else { - return hex; - } - } - - bool sendSMSImpl(const String& number, const String& text) { - // Set preferred message format to text mode - thisModem().sendAT(GF("+CMGF=1")); - thisModem().waitResponse(); - // Set GSM 7 bit default alphabet (3GPP TS 23.038) - thisModem().sendAT(GF("+CSCS=\"GSM\"")); - thisModem().waitResponse(); - thisModem().sendAT(GF("+CMGS=\""), number, GF("\"")); - if (thisModem().waitResponse(GF(">")) != 1) { return false; } - thisModem().stream.print(text); // Actually send the message - thisModem().stream.write(static_cast(0x1A)); // Terminate the message - thisModem().stream.flush(); - return thisModem().waitResponse(60000L) == 1; - } - - // Common methods for UTF8/UTF16 SMS. - // Supported by: BG96, M95, MC60, SIM5360, SIM7000, SIM7600, SIM800 - class UTF8Print : public Print { - public: - explicit UTF8Print(Print& p) : p(p) {} - size_t write(const uint8_t c) override { - if (prv < 0xC0) { - if (c < 0xC0) printHex(c); - prv = c; - } else { - uint16_t v = uint16_t(prv) << 8 | c; - v -= (v >> 8 == 0xD0) ? 0xCC80 : 0xCD40; - printHex(v); - prv = 0; - } - return 1; - } - - private: - Print& p; - uint8_t prv = 0; - void printHex(const uint16_t v) { - uint8_t c = v >> 8; - if (c < 0x10) p.print('0'); - p.print(c, HEX); - c = v & 0xFF; - if (c < 0x10) p.print('0'); - p.print(c, HEX); - } - }; - - bool sendSMS_UTF8_begin(const char* const number) { - thisModem().sendAT(GF("+CMGF=1")); - thisModem().waitResponse(); - thisModem().sendAT(GF("+CSCS=\"HEX\"")); - thisModem().waitResponse(); - thisModem().sendAT(GF("+CSMP=17,167,0,8")); - thisModem().waitResponse(); - - thisModem().sendAT(GF("+CMGS=\""), number, GF("\"")); - return thisModem().waitResponse(GF(">")) == 1; - } - bool sendSMS_UTF8_end() { - thisModem().stream.write(static_cast(0x1A)); - thisModem().stream.flush(); - return thisModem().waitResponse(60000L) == 1; - } - UTF8Print sendSMS_UTF8_stream() { - return UTF8Print(thisModem().stream); - } - - bool sendSMS_UTF16Impl(const char* const number, const void* text, - size_t len) { - if (!sendSMS_UTF8_begin(number)) { return false; } - - uint16_t* t = reinterpret_cast(text); - for (size_t i = 0; i < len; i++) { - uint8_t c = t[i] >> 8; - if (c < 0x10) { thisModem().stream.print('0'); } - thisModem().stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { thisModem().stream.print('0'); } - thisModem().stream.print(c, HEX); - } - - return sendSMS_UTF8_end(); - } - - /* - * Location functions - */ - protected: - String getGsmLocationImpl() { - thisModem().sendAT(GF("+CIPGSMLOC=1,1")); - if (thisModem().waitResponse(10000L, GF("+CIPGSMLOC:")) != 1) { return ""; } - String res = thisModem().stream.readStringUntil('\n'); - thisModem().waitResponse(); - res.trim(); - return res; - } - - /* - * GPS location functions - */ - public: - /* - * Time functions - */ - protected: - String getGSMDateTimeImpl(TinyGSMDateTimeFormat format) { - thisModem().sendAT(GF("+CCLK?")); - if (thisModem().waitResponse(2000L, GF("+CCLK: \"")) != 1) { return ""; } - - String res; - - switch (format) { - case DATE_FULL: res = thisModem().stream.readStringUntil('"'); break; - case DATE_TIME: - thisModem().streamSkipUntil(','); - res = thisModem().stream.readStringUntil('"'); - break; - case DATE_DATE: res = thisModem().stream.readStringUntil(','); break; - } - return res; - } - - /* - * Battery & temperature functions - */ - protected: - // Use: float vBatt = modem.getBattVoltage() / 1000.0; - uint16_t getBattVoltageImpl() { - thisModem().sendAT(GF("+CBC")); - if (thisModem().waitResponse(GF("+CBC:")) != 1) { return 0; } - thisModem().streamSkipUntil(','); // Skip battery charge status - thisModem().streamSkipUntil(','); // Skip battery charge level - // return voltage in mV - uint16_t res = thisModem().streamGetInt(','); - // Wait for final OK - thisModem().waitResponse(); - return res; - } - - int8_t getBattPercentImpl() { - thisModem().sendAT(GF("+CBC")); - if (thisModem().waitResponse(GF("+CBC:")) != 1) { return false; } - thisModem().streamSkipUntil(','); // Skip battery charge status - // Read battery charge level - int res = thisModem().streamGetInt(','); - // Wait for final OK - thisModem().waitResponse(); - return res; - } - - uint8_t getBattChargeStateImpl() { - thisModem().sendAT(GF("+CBC")); - if (thisModem().waitResponse(GF("+CBC:")) != 1) { return false; } - // Read battery charge status - int res = thisModem().streamGetInt(','); - // Wait for final OK - thisModem().waitResponse(); - return res; - } - - bool getBattStatsImpl(uint8_t& chargeState, int8_t& percent, - uint16_t& milliVolts) { - thisModem().sendAT(GF("+CBC")); - if (thisModem().waitResponse(GF("+CBC:")) != 1) { return false; } - chargeState = thisModem().streamGetInt(','); - percent = thisModem().streamGetInt(','); - milliVolts = thisModem().streamGetInt('\n'); - // Wait for final OK - thisModem().waitResponse(); - return true; - } - - float getTemperatureImpl() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Client related functions - */ - protected: - /* - Utilities - */ - - // Utility templates for writing/skipping characters on a stream - template - void streamWrite(T last) { - thisModem().stream.print(last); - } - - template - void streamWrite(T head, Args... tail) { - thisModem().stream.print(head); - thisModem().streamWrite(tail...); - } - - int16_t streamGetInt(char lastChar) { - char buf[6]; - size_t bytesRead = thisModem().stream.readBytesUntil( - lastChar, buf, static_cast(6)); - if (bytesRead) { - int16_t res = atoi(buf); - return res; - } else { - return -9999; - } - } - - float streamGetFloat(char lastChar) { - char buf[12]; - size_t bytesRead = thisModem().stream.readBytesUntil( - lastChar, buf, static_cast(12)); - if (bytesRead) { - float res = atof(buf); - return res; - } else { - return static_cast(-9999); - } - } - - bool streamSkipUntil(const char c, const uint32_t timeout_ms = 1000L) { - uint32_t startMillis = millis(); - while (millis() - startMillis < timeout_ms) { - while (millis() - startMillis < timeout_ms && - !thisModem().stream.available()) { - TINY_GSM_YIELD(); - } - if (thisModem().stream.read() == c) { return true; } - } - return false; - } - - void streamClear() { - while (thisModem().stream.available()) { - thisModem().waitResponse(50, NULL, NULL); - } - } - - // Yields up to a time-out period and then reads a character from the stream - // into the mux FIFO - // TODO(SRGDamia1): Do we need to wait two _timeout periods for no - // character return? Will wait once in the first "while - // !stream.available()" and then will wait again in the stream.read() - // function. - void moveCharFromStreamToFifo(uint8_t mux) { - uint32_t startMillis = millis(); - while (!thisModem().stream.available() && - (millis() - startMillis < thisModem().sockets[mux]->_timeout)) { - TINY_GSM_YIELD(); - } - char c = thisModem().stream.read(); - thisModem().sockets[mux]->rx.put(c); - } -}; - #endif // SRC_TINYGSMCOMMON_H_ diff --git a/src/TinyGsmGPRS.tpp b/src/TinyGsmGPRS.tpp new file mode 100644 index 0000000..00bf1b7 --- /dev/null +++ b/src/TinyGsmGPRS.tpp @@ -0,0 +1,158 @@ +/** + * @file TinyGsmGPRS.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMGPRS_H_ +#define SRC_TINYGSMGPRS_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_GPRS + +enum SimStatus { + SIM_ERROR = 0, + SIM_READY = 1, + SIM_LOCKED = 2, + SIM_ANTITHEFT_LOCKED = 3, +}; + +template +class TinyGsmGPRS { + public: + /* + * SIM card functions + */ + // Unlocks the SIM + bool simUnlock(const char* pin) { + return thisModem().simUnlockImpl(pin); + } + // Gets the CCID of a sim card via AT+CCID + String getSimCCID() { + return thisModem().getSimCCIDImpl(); + } + // Asks for TA Serial Number Identification (IMEI) + String getIMEI() { + return thisModem().getIMEIImpl(); + } + SimStatus getSimStatus(uint32_t timeout_ms = 10000L) { + return thisModem().getSimStatusImpl(timeout_ms); + } + + /* + * GPRS functions + */ + bool gprsConnect(const char* apn, const char* user = NULL, + const char* pwd = NULL) { + return thisModem().gprsConnectImpl(apn, user, pwd); + } + bool gprsDisconnect() { + return thisModem().gprsDisconnectImpl(); + } + // Checks if current attached to GPRS/EPS service + bool isGprsConnected() { + return thisModem().isGprsConnectedImpl(); + } + // Gets the current network operator + String getOperator() { + return thisModem().getOperatorImpl(); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * SIM card functions + */ + protected: + // Unlocks a sim via the 3GPP TS command AT+CPIN + bool simUnlockImpl(const char* pin) { + if (pin && strlen(pin) > 0) { + thisModem().sendAT(GF("+CPIN=\""), pin, GF("\"")); + return thisModem().waitResponse() == 1; + } + return true; + } + + // Gets the CCID of a sim card via AT+CCID + String getSimCCIDImpl() { + thisModem().sendAT(GF("+CCID")); + if (thisModem().waitResponse(GF("+CCID:")) != 1) { return ""; } + String res = thisModem().stream.readStringUntil('\n'); + thisModem().waitResponse(); + res.trim(); + return res; + } + + // Asks for TA Serial Number Identification (IMEI) via the V.25TER standard + // AT+GSN command + String getIMEIImpl() { + thisModem().sendAT(GF("+GSN")); + String res = thisModem().stream.readStringUntil('\n'); + thisModem().waitResponse(); + res.trim(); + return res; + } + + SimStatus getSimStatusImpl(uint32_t timeout_ms = 10000L) { + for (uint32_t start = millis(); millis() - start < timeout_ms;) { + thisModem().sendAT(GF("+CPIN?")); + if (thisModem().waitResponse(GF("+CPIN:")) != 1) { + delay(1000); + continue; + } + int status = thisModem().waitResponse(GF("READY"), GF("SIM PIN"), + GF("SIM PUK"), GF("NOT INSERTED"), + GF("NOT READY")); + thisModem().waitResponse(); + switch (status) { + case 2: + case 3: return SIM_LOCKED; + case 1: return SIM_READY; + default: return SIM_ERROR; + } + } + return SIM_ERROR; + } + + /* + * GPRS functions + */ + protected: + bool thisHasGPRS() { + return true; + } + // Checks if current attached to GPRS/EPS service + bool isGprsConnectedImpl() { + thisModem().sendAT(GF("+CGATT?")); + if (thisModem().waitResponse(GF("+CGATT:")) != 1) { return false; } + int res = thisModem().streamGetInt('\n'); + thisModem().waitResponse(); + if (res != 1) { return false; } + + return thisModem().localIP() != IPAddress(0, 0, 0, 0); + } + + // Gets the current network operator via the 3GPP TS command AT+COPS + String getOperatorImpl() { + thisModem().sendAT(GF("+COPS?")); + if (thisModem().waitResponse(GF("+COPS:")) != 1) { return ""; } + thisModem().streamSkipUntil('"'); /* Skip mode and format */ + String res = thisModem().stream.readStringUntil('"'); + thisModem().waitResponse(); + return res; + } +}; + +#endif // SRC_TINYGSMGPRS_H_ diff --git a/src/TinyGsmGPS.tpp b/src/TinyGsmGPS.tpp new file mode 100644 index 0000000..e6dc76a --- /dev/null +++ b/src/TinyGsmGPS.tpp @@ -0,0 +1,64 @@ +/** + * @file TinyGsmGPS.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMGPS_H_ +#define SRC_TINYGSMGPS_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_GPS + +template +class TinyGsmGPS { + public: + /* + * GPS location functions + */ + bool enableGPS() { + return thisModem().enableGPSImpl(); + } + bool disableGPS() { + return thisModem().disableGPSImpl(); + } + String getGPSraw() { + return thisModem().getGPSrawImpl(); + } + bool getGPSTime(int* year, int* month, int* day, int* hour, int* minute, + int* second) { + return thisModem().getGPSTimeImpl(year, month, day, hour, minute, second); + } + bool getGPS(float* lat, float* lon, float* speed = 0, int* alt = 0) { + return thisModem().getGPSImpl(lat, lon, speed, alt); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * GPS location functions + */ + + bool enableGPSImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool disableGPSImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; + String getGPSrawImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool getGPSTimeImpl(int* year, int* month, int* day, int* hour, int* minute, + int* second) TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool getGPSImpl(float* lat, float* lon, float* speed = 0, + int* alt = 0) TINY_GSM_ATTR_NOT_IMPLEMENTED; +}; + + +#endif // SRC_TINYGSMGPS_H_ diff --git a/src/TinyGsmGSMLocation.tpp b/src/TinyGsmGSMLocation.tpp new file mode 100644 index 0000000..d5f8e43 --- /dev/null +++ b/src/TinyGsmGSMLocation.tpp @@ -0,0 +1,51 @@ +/** + * @file TinyGsmGSMLocation.h + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMGSMLOCATION_H_ +#define SRC_TINYGSMGSMLOCATION_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_GSM_LOCATION + +template +class TinyGsmGSMLocation { + public: + /* + * Location functions + */ + String getGsmLocation() { + return thisModem().getGsmLocationImpl(); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Location functions + */ + protected: + String getGsmLocationImpl() { + thisModem().sendAT(GF("+CIPGSMLOC=1,1")); + if (thisModem().waitResponse(10000L, GF("+CIPGSMLOC:")) != 1) { return ""; } + String res = thisModem().stream.readStringUntil('\n'); + thisModem().waitResponse(); + res.trim(); + return res; + } +}; + +#endif // SRC_TINYGSMGSMLOCATION_H_ diff --git a/src/TinyGsmModem.tpp b/src/TinyGsmModem.tpp new file mode 100644 index 0000000..33c252e --- /dev/null +++ b/src/TinyGsmModem.tpp @@ -0,0 +1,301 @@ +/** + * @file TinyGsmModem.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMMODEM_H_ +#define SRC_TINYGSMMODEM_H_ + +#include "TinyGsmCommon.h" + +template +class TinyGsmModem { + public: + /* + * Basic functions + */ + bool begin(const char* pin = NULL) { + return thisModem().initImpl(pin); + } + bool init(const char* pin = NULL) { + return thisModem().initImpl(pin); + } + template + void sendAT(Args... cmd) { + thisModem().streamWrite("AT", cmd..., thisModem().gsmNL); + thisModem().stream.flush(); + TINY_GSM_YIELD(); /* DBG("### AT:", cmd...); */ + } + void setBaud(uint32_t baud) { + thisModem().setBaudImpl(baud); + } + // Test response to AT commands + bool testAT(uint32_t timeout_ms = 10000L) { + return thisModem().testATImpl(timeout_ms); + } + + // Asks for modem information via the V.25TER standard ATI command + // NOTE: The actual value and style of the response is quite varied + String getModemInfo() { + return thisModem().getModemInfoImpl(); + } + // Gets the modem name (as it calls itself) + String getModemName() { + return thisModem().getModemNameImpl(); + } + bool factoryDefault() { + return thisModem().factoryDefaultImpl(); + } + + /* + * Power functions + */ + bool restart() { + return thisModem().restartImpl(); + } + bool poweroff() { + return thisModem().powerOffImpl(); + } + bool radioOff() { + return thisModem().radioOffImpl(); + } + bool sleepEnable(bool enable = true) { + return thisModem().sleepEnableImpl(enable); + } + + /* + * Generic network functions + */ + // RegStatus getRegistrationStatus() {} + bool isNetworkConnected() { + return thisModem().isNetworkConnectedImpl(); + } + // Waits for network attachment + bool waitForNetwork(uint32_t timeout_ms = 60000L) { + return thisModem().waitForNetworkImpl(timeout_ms); + } + // Gets signal quality report + int16_t getSignalQuality() { + return thisModem().getSignalQualityImpl(); + } + String getLocalIP() { + return thisModem().getLocalIPImpl(); + } + IPAddress localIP() { + return thisModem().TinyGsmIpFromString(thisModem().getLocalIP()); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Basic functions + */ + protected: + void setBaudImpl(uint32_t baud) { + thisModem().sendAT(GF("+IPR="), baud); + thisModem().waitResponse(); + } + + bool testATImpl(uint32_t timeout_ms = 10000L) { + for (uint32_t start = millis(); millis() - start < timeout_ms;) { + thisModem().sendAT(GF("")); + if (thisModem().waitResponse(200) == 1) { return true; } + delay(100); + } + return false; + } + + String getModemInfoImpl() { + thisModem().sendAT(GF("I")); + String res; + if (thisModem().waitResponse(1000L, res) != 1) { return ""; } + // Do the replaces twice so we cover both \r and \r\n type endings + res.replace("\r\nOK\r\n", ""); + res.replace("\rOK\r", ""); + res.replace("\r\n", " "); + res.replace("\r", " "); + res.trim(); + return res; + } + + String getModemNameImpl() { + thisModem().sendAT(GF("+CGMI")); + String res1; + if (thisModem().waitResponse(1000L, res1) != 1) { return "unknown"; } + res1.replace("\r\nOK\r\n", ""); + res1.replace("\rOK\r", ""); + res1.trim(); + + thisModem().sendAT(GF("+GMM")); + String res2; + if (thisModem().waitResponse(1000L, res2) != 1) { return "unknown"; } + res1.replace("\r\nOK\r\n", ""); + res1.replace("\rOK\r", ""); + res2.trim(); + + String name = res1 + String(' ') + res2; + DBG("### Modem:", name); + return name; + } + + bool factoryDefaultImpl() { + thisModem().sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write + thisModem().waitResponse(); + thisModem().sendAT(GF("+IPR=0")); // Auto-baud + thisModem().waitResponse(); + thisModem().sendAT(GF("&W")); // Write configuration + return thisModem().waitResponse() == 1; + } + + /* + * Power functions + */ + protected: + bool radioOffImpl() { + thisModem().sendAT(GF("+CFUN=0")); + if (thisModem().waitResponse(10000L) != 1) { return false; } + delay(3000); + return true; + } + + bool sleepEnableImpl(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; + + /* + * Generic network functions + */ + protected: + // Gets the modem's registration status via CREG/CGREG/CEREG + // CREG = Generic network registration + // CGREG = GPRS service registration + // CEREG = EPS registration for LTE modules + int getRegistrationStatusXREG(const char* regCommand) { + thisModem().sendAT('+', regCommand, '?'); + // check for any of the three for simplicity + int resp = thisModem().waitResponse(GF("+CREG:"), GF("+CGREG:"), + GF("+CEREG:")); + if (resp != 1 && resp != 2 && resp != 3) { return -1; } + thisModem().streamSkipUntil(','); /* Skip format (0) */ + int status = thisModem().streamGetInt('\n'); + thisModem().waitResponse(); + return status; + } + + bool waitForNetworkImpl(uint32_t timeout_ms = 60000L) { + for (uint32_t start = millis(); millis() - start < timeout_ms;) { + if (thisModem().isNetworkConnected()) { return true; } + delay(250); + } + return false; + } + + // Gets signal quality report according to 3GPP TS command AT+CSQ + int16_t getSignalQualityImpl() { + thisModem().sendAT(GF("+CSQ")); + if (thisModem().waitResponse(GF("+CSQ:")) != 1) { return 99; } + int res = thisModem().streamGetInt(','); + thisModem().waitResponse(); + return res; + } + + String getLocalIPImpl() { + thisModem().sendAT(GF("+CGPADDR=1")); + if (thisModem().waitResponse(GF("+CGPADDR:")) != 1) { return ""; } + thisModem().streamSkipUntil(','); // Skip context id + String res = thisModem().stream.readStringUntil('\r'); + if (thisModem().waitResponse() != 1) { return ""; } + return res; + } + + static IPAddress TinyGsmIpFromString(const String& strIP) { + int Parts[4] = { + 0, + }; + int Part = 0; + for (uint8_t i = 0; i < strIP.length(); i++) { + char c = strIP[i]; + if (c == '.') { + Part++; + if (Part > 3) { return IPAddress(0, 0, 0, 0); } + continue; + } else if (c >= '0' && c <= '9') { + Parts[Part] *= 10; + Parts[Part] += c - '0'; + } else { + if (Part == 3) break; + } + } + return IPAddress(Parts[0], Parts[1], Parts[2], Parts[3]); + } + + /* + Utilities + */ + protected: + // Utility templates for writing/skipping characters on a stream + template + void inline streamWrite(T last) { + thisModem().stream.print(last); + } + + template + void inline streamWrite(T head, Args... tail) { + thisModem().stream.print(head); + thisModem().streamWrite(tail...); + } + + int16_t inline streamGetInt(char lastChar) { + char buf[6]; + size_t bytesRead = thisModem().stream.readBytesUntil( + lastChar, buf, static_cast(6)); + if (bytesRead) { + int16_t res = atoi(buf); + return res; + } else { + return -9999; + } + } + + float inline streamGetFloat(char lastChar) { + char buf[12]; + size_t bytesRead = thisModem().stream.readBytesUntil( + lastChar, buf, static_cast(12)); + if (bytesRead) { + float res = atof(buf); + return res; + } else { + return static_cast(-9999); + } + } + + bool inline streamSkipUntil(const char c, const uint32_t timeout_ms = 1000L) { + uint32_t startMillis = millis(); + while (millis() - startMillis < timeout_ms) { + while (millis() - startMillis < timeout_ms && + !thisModem().stream.available()) { + TINY_GSM_YIELD(); + } + if (thisModem().stream.read() == c) { return true; } + } + return false; + } + + void inline streamClear() { + while (thisModem().stream.available()) { + thisModem().waitResponse(50, NULL, NULL); + } + } +}; + +#endif // SRC_TINYGSMMODEM_H_ diff --git a/src/TinyGsmSMS.tpp b/src/TinyGsmSMS.tpp new file mode 100644 index 0000000..15ecc7f --- /dev/null +++ b/src/TinyGsmSMS.tpp @@ -0,0 +1,224 @@ +/** + * @file TinyGsmSMS.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMSMS_H_ +#define SRC_TINYGSMSMS_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_SMS + +template +class TinyGsmSMS { + public: + /* + * Messaging functions + */ + String sendUSSD(const String& code) { + return thisModem().sendUSSDImpl(code); + } + bool sendSMS(const String& number, const String& text) { + return thisModem().sendSMSImpl(number, text); + } + bool sendSMS_UTF16(const char* const number, const void* text, size_t len) { + return thisModem().sendSMS_UTF16Impl(number, text, len); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Messaging functions + */ + protected: + static inline String TinyGsmDecodeHex7bit(String& instr) { + String result; + byte reminder = 0; + int bitstate = 7; + for (uint8_t 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 cc = reminder; + result += cc; + reminder = 0; + bitstate = 7; + } + } + return result; + } + + static inline String TinyGsmDecodeHex8bit(String& instr) { + String result; + for (uint8_t 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 inline String TinyGsmDecodeHex16bit(String& instr) { + String result; + for (uint8_t 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 ;( +#if defined(TINY_GSM_UNICODE_TO_HEX) + result += "\\x"; + result += instr.substring(i, i + 4); +#else + result += "?"; +#endif + } else { + buf[0] = instr[i + 2]; + buf[1] = instr[i + 3]; + b = strtol(buf, NULL, 16); + result += b; + } + } + return result; + } + + String sendUSSDImpl(const String& code) { + // Set preferred message format to text mode + thisModem().sendAT(GF("+CMGF=1")); + thisModem().waitResponse(); + // Set 8-bit hexadecimal alphabet (3GPP TS 23.038) + thisModem().sendAT(GF("+CSCS=\"HEX\"")); + thisModem().waitResponse(); + // Send the message + thisModem().sendAT(GF("+CUSD=1,\""), code, GF("\"")); + if (thisModem().waitResponse() != 1) { return ""; } + if (thisModem().waitResponse(10000L, GF("+CUSD:")) != 1) { return ""; } + thisModem().stream.readStringUntil('"'); + String hex = thisModem().stream.readStringUntil('"'); + thisModem().stream.readStringUntil(','); + int dcs = thisModem().streamGetInt('\n'); + + if (dcs == 15) { + return TinyGsmDecodeHex8bit(hex); + } else if (dcs == 72) { + return TinyGsmDecodeHex16bit(hex); + } else { + return hex; + } + } + + bool sendSMSImpl(const String& number, const String& text) { + // Set preferred message format to text mode + thisModem().sendAT(GF("+CMGF=1")); + thisModem().waitResponse(); + // Set GSM 7 bit default alphabet (3GPP TS 23.038) + thisModem().sendAT(GF("+CSCS=\"GSM\"")); + thisModem().waitResponse(); + thisModem().sendAT(GF("+CMGS=\""), number, GF("\"")); + if (thisModem().waitResponse(GF(">")) != 1) { return false; } + thisModem().stream.print(text); // Actually send the message + thisModem().stream.write(static_cast(0x1A)); // Terminate the message + thisModem().stream.flush(); + return thisModem().waitResponse(60000L) == 1; + } + + // Common methods for UTF8/UTF16 SMS. + // Supported by: BG96, M95, MC60, SIM5360, SIM7000, SIM7600, SIM800 + class UTF8Print : public Print { + public: + explicit UTF8Print(Print& p) : p(p) {} + size_t write(const uint8_t c) override { + if (prv < 0xC0) { + if (c < 0xC0) printHex(c); + prv = c; + } else { + uint16_t v = uint16_t(prv) << 8 | c; + v -= (v >> 8 == 0xD0) ? 0xCC80 : 0xCD40; + printHex(v); + prv = 0; + } + return 1; + } + + private: + Print& p; + uint8_t prv = 0; + void printHex(const uint16_t v) { + uint8_t c = v >> 8; + if (c < 0x10) p.print('0'); + p.print(c, HEX); + c = v & 0xFF; + if (c < 0x10) p.print('0'); + p.print(c, HEX); + } + }; + + bool sendSMS_UTF8_begin(const char* const number) { + thisModem().sendAT(GF("+CMGF=1")); + thisModem().waitResponse(); + thisModem().sendAT(GF("+CSCS=\"HEX\"")); + thisModem().waitResponse(); + thisModem().sendAT(GF("+CSMP=17,167,0,8")); + thisModem().waitResponse(); + + thisModem().sendAT(GF("+CMGS=\""), number, GF("\"")); + return thisModem().waitResponse(GF(">")) == 1; + } + bool sendSMS_UTF8_end() { + thisModem().stream.write(static_cast(0x1A)); + thisModem().stream.flush(); + return thisModem().waitResponse(60000L) == 1; + } + UTF8Print sendSMS_UTF8_stream() { + return UTF8Print(thisModem().stream); + } + + bool sendSMS_UTF16Impl(const char* const number, const void* text, + size_t len) { + if (!sendSMS_UTF8_begin(number)) { return false; } + + uint16_t* t = + const_cast(reinterpret_cast(text)); + for (size_t i = 0; i < len; i++) { + uint8_t c = t[i] >> 8; + if (c < 0x10) { thisModem().stream.print('0'); } + thisModem().stream.print(c, HEX); + c = t[i] & 0xFF; + if (c < 0x10) { thisModem().stream.print('0'); } + thisModem().stream.print(c, HEX); + } + + return sendSMS_UTF8_end(); + } +}; + +#endif // SRC_TINYGSMSMS_H_ diff --git a/src/TinyGsmSSL.tpp b/src/TinyGsmSSL.tpp new file mode 100644 index 0000000..32bca14 --- /dev/null +++ b/src/TinyGsmSSL.tpp @@ -0,0 +1,71 @@ +/** + * @file TinyGsmSSL.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMSSL_H_ +#define SRC_TINYGSMSSL_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_SSL + + +template +class TinyGsmSSL { + public: + /* + * SSL functions + */ + bool addCertificate(const char* filename) { + return thisModem().addCertificateImpl(filename); + } + bool deleteCertificate() { + return thisModem().deleteCertificateImpl(); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Inner Secure Client + */ + /* + public: + class GsmClientSecure : public GsmClient { + public: + GsmClientSecureSim800() {} + + explicit GsmClientSecureSim800(TinyGsmSim800& modem, uint8_t mux = 1) + : GsmClientSim800(modem, mux) {} + + public: + int connect(const char* host, uint16_t port, int timeout_s) { + stop(); + TINY_GSM_YIELD(); + rx.clear(); + sock_connected = at->modemConnect(host, port, mux, true, timeout_s); + return sock_connected; + } + };*/ + + /* + * SSL functions + */ + protected: + bool addCertificateImpl(const char* filename) TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool deleteCertificateImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; +}; + +#endif // SRC_TINYGSMSSL_H_ diff --git a/src/TinyGsmTCP.tpp b/src/TinyGsmTCP.tpp index 1044159..46c71c5 100644 --- a/src/TinyGsmTCP.tpp +++ b/src/TinyGsmTCP.tpp @@ -11,7 +11,26 @@ #include "TinyGsmCommon.h" -#define TINY_GSM_HAS_TCP +#define TINY_GSM_MODEM_HAS_TCP + +#include "TinyGsmFifo.h" + +#if !defined(TINY_GSM_RX_BUFFER) +#define TINY_GSM_RX_BUFFER 64 +#endif + +// Because of the ordering of resolution of overrides in templates, hese need to +// be written out every time. This macro is to shorten that. +#define TINY_GSM_CLIENT_CONNECT_OVERRIDES \ + virtual int connect(IPAddress ip, uint16_t port, int timeout_s) { \ + return connect(TinyGsmStringFromIp(ip).c_str(), port, timeout_s); \ + } \ + int connect(const char* host, uint16_t port) override { \ + return connect(host, port, 75); \ + } \ + int connect(IPAddress ip, uint16_t port) override { \ + return connect(ip, port, 75); \ + } enum modemInternalBuffferType { NO_MODEM_BUFFER = @@ -24,15 +43,7 @@ enum modemInternalBuffferType { // The fully generic template is empty template -class TinyGsmTCP {}; - -// Partially specialized templates - -/* =========================================================================== -* Specialized template for modems no internal buffer -=========================================================================== */ -template -class TinyGsmTCP { +class TinyGsmTCP { public: /* * Basic functions @@ -58,10 +69,26 @@ class TinyGsmTCP { public: class GsmClient : public Client { // Make all classes created from the modem template friends - friend class TinyGsmModem; + friend class TinyGsmTCP; typedef TinyGsmFifo RxFifo; public: + // bool init(modemType* modem, uint8_t); + // int connect(const char* host, uint16_t port, int timeout_s); + + // Connect to a IP address given as an IPAddress object by + // converting said IP address to text + // virtual int connect(IPAddress ip, uint16_t port, int timeout_s) { + // return connect(TinyGsmStringFromIp(ip).c_str(), port, + // timeout_s); + // } + // int connect(const char* host, uint16_t port) override { + // return connect(host, port, 75); + // } + // int connect(IPAddress ip, uint16_t port) override { + // return connect(ip, port, 75); + // } + static inline String TinyGsmStringFromIp(IPAddress ip) { String host; host.reserve(16); @@ -75,6 +102,11 @@ class TinyGsmTCP { return host; } + // void stop(uint32_t maxWaitMs); + // void stop() override { + // stop(15000L); + // } + // Writes data out on the client using the modem send functionality size_t write(const uint8_t* buf, size_t size) override { TINY_GSM_YIELD(); @@ -93,17 +125,42 @@ class TinyGsmTCP { int available() override { TINY_GSM_YIELD(); + switch (bufType) { // Returns the number of characters available in the TinyGSM fifo + case NO_MODEM_BUFFER: if (!rx.size() && sock_connected) { at->maintain(); } return rx.size(); + + // Returns the combined number of characters available in the TinyGSM + // fifo and the modem chips internal fifo. + case READ_NO_CHECK: + if (!rx.size()) { at->maintain(); } + return rx.size() + sock_available; + + // Returns the combined number of characters available in the TinyGSM + // fifo and the modem chips internal fifo, doing an extra check-in + // with the modem to see if anything has arrived without a UURC. + case READ_AND_CHECK_SIZE: + if (!rx.size()) { + if (millis() - prev_check > 500) { + got_data = true; + prev_check = millis(); + } + at->maintain(); + } + return rx.size() + sock_available; + } } int read(uint8_t* buf, size_t size) override { TINY_GSM_YIELD(); size_t cnt = 0; uint32_t _startMillis = millis(); + + switch (bufType) { // Reads characters out of the TinyGSM fifo, waiting for any URC's // from the modem for new data if there's nothing in the fifo. + case NO_MODEM_BUFFER: while (cnt < size && millis() - _startMillis < _timeout) { size_t chunk = TinyGsmMin(size - cnt, rx.size()); if (chunk > 0) { @@ -115,134 +172,10 @@ class TinyGsmTCP { if (!rx.size() && sock_connected) { at->maintain(); } } return cnt; - } - - int read() override { - uint8_t c; - if (read(&c, 1) == 1) { return c; } - return -1; - } - - // TODO(SRGDamia1): Implement peek - int peek() override { - return -1; - } - - void flush() override { - at->stream.flush(); - } - - uint8_t connected() override { - if (available()) { return true; } - return sock_connected; - } - operator bool() override { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - protected: - modemType* at; - uint8_t mux; - bool sock_connected; - RxFifo rx; - }; - - /* - * Basic functions - */ - protected: - void maintainImpl() { - // Just listen for any URC's - thisModem().waitResponse(100, NULL, NULL); - } -}; - -/* =========================================================================== -* Specialized template for modems with an internal buffer that can be read -* but NOT queried for current size. -=========================================================================== */ -template -class TinyGsmTCP { - public: - /* - * Basic functions - */ - void maintain() { - return thisModem().maintainImpl(); - } - - /* - * CRTP Helper - */ - protected: - inline const modemType& thisModem() const { - return static_cast(*this); - } - inline modemType& thisModem() { - return static_cast(*this); - } - - /* - * Inner Client - */ - public: - class GsmClient : public Client { - // Make all classes created from the modem template friends - friend class TinyGsmModem; - typedef TinyGsmFifo RxFifo; - - public: - static inline String TinyGsmStringFromIp(IPAddress ip) { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return host; - } - - // Writes data out on the client using the modem send functionality - size_t write(const uint8_t* buf, size_t size) override { - TINY_GSM_YIELD(); - at->maintain(); - return at->modemSend(buf, size, mux); - } - - size_t write(uint8_t c) override { - return write(&c, 1); - } - - size_t write(const char* str) { - if (str == NULL) return 0; - return write((const uint8_t*)str, strlen(str)); - } - - int available() override { - TINY_GSM_YIELD(); - - // Returns the combined number of characters available in the TinyGSM - // fifo and the modem chips internal fifo. - if (!rx.size()) { at->maintain(); } - return rx.size() + sock_available; - } - - int read(uint8_t* buf, size_t size) override { - TINY_GSM_YIELD(); - size_t cnt = 0; - uint32_t _startMillis = millis(); // Reads characters out of the TinyGSM fifo, and from the modem chip's // internal fifo if avaiable. + case READ_NO_CHECK: at->maintain(); while (cnt < size) { size_t chunk = TinyGsmMin(size - cnt, rx.size()); @@ -262,172 +195,11 @@ class TinyGsmTCP { } } return cnt; - } - - int read() override { - uint8_t c; - if (read(&c, 1) == 1) { return c; } - return -1; - } - - // TODO(SRGDamia1): Implement peek - int peek() override { - return -1; - } - - void flush() override { - at->stream.flush(); - } - uint8_t connected() override { - if (available()) { return true; } - return sock_connected; - } - operator bool() override { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - protected: - // Read and dump anything remaining in the modem's internal buffer. - // Using this in the client stop() function. - // The socket will appear open in response to connected() even after it - // closes until all data is read from the buffer. - // Doing it this way allows the external mcu to find and get all of the - // data that it wants from the socket even if it was closed externally. - void inline dumpModemBuffer(uint32_t maxWaitMs) { - TINY_GSM_YIELD(); - rx.clear(); - at->maintain(); - uint32_t startMillis = millis(); - while (sock_available > 0 && (millis() - startMillis < maxWaitMs)) { - at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux); - rx.clear(); - at->maintain(); - } - } - - modemType* at; - uint8_t mux; - uint16_t sock_available; - bool sock_connected; - bool got_data; - RxFifo rx; - }; - - /* - * Basic functions - */ - protected: - void maintainImpl() { - // Just listen for any URC's - thisModem().waitResponse(100, NULL, NULL); - break; - } - - // Yields up to a time-out period and then reads a character from the stream - // into the mux FIFO - // TODO(SRGDamia1): Do we need to wait two _timeout periods for no - // character return? Will wait once in the first "while - // !stream.available()" and then will wait again in the stream.read() - // function. - void inline moveCharFromStreamToFifo(uint8_t mux) { - uint32_t startMillis = millis(); - while (!thisModem().stream.available() && - (millis() - startMillis < thisModem().sockets[mux]->_timeout)) { - TINY_GSM_YIELD(); - } - char c = thisModem().stream.read(); - thisModem().sockets[mux]->rx.put(c); - } -}; - - -/* =========================================================================== -* Specialized template for modems with an internal buffer that can be read -* and queried for current size. -=========================================================================== */ -template -class TinyGsmTCP { - public: - /* - * Basic functions - */ - void maintain() { return thisModem().maintainImpl(); } - - /* - * CRTP Helper - */ - protected: - inline const modemType& thisModem() const { - return static_cast(*this); - } - inline modemType& thisModem() { return static_cast(*this); } - - /* - * Inner Client - */ - public: - class GsmClient : public Client { - // Make all classes created from the modem template friends - friend class TinyGsmModem; - typedef TinyGsmFifo RxFifo; - - public: - static inline String TinyGsmStringFromIp(IPAddress ip) { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return host; - } - - // Writes data out on the client using the modem send functionality - size_t write(const uint8_t* buf, size_t size) override { - TINY_GSM_YIELD(); - at->maintain(); - return at->modemSend(buf, size, mux); - } - - size_t write(uint8_t c) override { return write(&c, 1); } - - size_t write(const char* str) { - if (str == NULL) return 0; - return write((const uint8_t*)str, strlen(str)); - } - - int available() override { - TINY_GSM_YIELD(); - // Returns the combined number of characters available in the TinyGSM - // fifo and the modem chips internal fifo, doing an extra check-in - // with the modem to see if anything has arrived without a UURC. - if (!rx.size()) { - if (millis() - prev_check > 500) { - got_data = true; - prev_check = millis(); - } - at->maintain(); - } - return rx.size() + sock_available; - } - - int read(uint8_t* buf, size_t size) override { - TINY_GSM_YIELD(); - size_t cnt = 0; - uint32_t _startMillis = millis(); // Reads characters out of the TinyGSM fifo, and from the modem chips // internal fifo if avaiable, also double checking with the modem if // data has arrived without issuing a UURC. + case READ_AND_CHECK_SIZE: at->maintain(); while (cnt < size) { size_t chunk = TinyGsmMin(size - cnt, rx.size()); @@ -439,7 +211,7 @@ class TinyGsmTCP { } // Workaround: Some modules "forget" to notify about data arrival if (millis() - prev_check > 500) { - got_data = true; + got_data = true; prev_check = millis(); } // TODO(vshymanskyy): Read directly into user buffer? @@ -453,28 +225,31 @@ class TinyGsmTCP { } } return cnt; + } } int read() override { uint8_t c; - if (read(&c, 1) == 1) { - return c; - } + if (read(&c, 1) == 1) { return c; } return -1; } // TODO(SRGDamia1): Implement peek - int peek() override { return -1; } + int peek() override { + return -1; + } - void flush() override { at->stream.flush(); } + void flush() override { + at->stream.flush(); + } uint8_t connected() override { - if (available()) { - return true; - } + if (available()) { return true; } return sock_connected; } - operator bool() override { return connected(); } + operator bool() override { + return connected(); + } /* * Extended API @@ -502,12 +277,12 @@ class TinyGsmTCP { } modemType* at; - uint8_t mux; - uint16_t sock_available; - uint32_t prev_check; - bool sock_connected; - bool got_data; - RxFifo rx; + uint8_t mux; + uint16_t sock_available; + uint32_t prev_check; + bool sock_connected; + bool got_data; + RxFifo rx; }; /* @@ -515,18 +290,26 @@ class TinyGsmTCP { */ protected: void maintainImpl() { + switch (bufType) { + case READ_AND_CHECK_SIZE: // Keep listening for modem URC's and proactively iterate through // sockets asking if any data is avaiable for (int mux = 0; mux < muxCount; mux++) { GsmClient* sock = thisModem().sockets[mux]; if (sock && sock->got_data) { - sock->got_data = false; + sock->got_data = false; sock->sock_available = thisModem().modemGetAvailable(mux); } } while (thisModem().stream.available()) { thisModem().waitResponse(15, NULL, NULL); } + break; + default: + // Just listen for any URC's + thisModem().waitResponse(100, NULL, NULL); + break; + } } // Yields up to a time-out period and then reads a character from the stream diff --git a/src/TinyGsmTemperature.tpp b/src/TinyGsmTemperature.tpp new file mode 100644 index 0000000..215f250 --- /dev/null +++ b/src/TinyGsmTemperature.tpp @@ -0,0 +1,40 @@ +/** + * @file TinyGsmTemperature.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMTEMPERATURE_H_ +#define SRC_TINYGSMTEMPERATURE_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_TEMPERATURE + +template +class TinyGsmTemperature { + public: + /* + * Temperature functions + */ + float getTemperature() { + return thisModem().getTemperatureImpl(); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + float getTemperatureImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; +}; + +#endif // SRC_TINYGSMTEMPERATURE_H_ diff --git a/src/TinyGsmTime.tpp b/src/TinyGsmTime.tpp new file mode 100644 index 0000000..f6fb796 --- /dev/null +++ b/src/TinyGsmTime.tpp @@ -0,0 +1,61 @@ +/** + * @file TinyGsmTime.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMTIME_H_ +#define SRC_TINYGSMTIME_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_TIME + +enum TinyGSMDateTimeFormat { DATE_FULL = 0, DATE_TIME = 1, DATE_DATE = 2 }; + +template +class TinyGsmTime { + public: + /* + * Time functions + */ + String getGSMDateTime(TinyGSMDateTimeFormat format) { + return thisModem().getGSMDateTimeImpl(format); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * Time functions + */ + protected: + String getGSMDateTimeImpl(TinyGSMDateTimeFormat format) { + thisModem().sendAT(GF("+CCLK?")); + if (thisModem().waitResponse(2000L, GF("+CCLK: \"")) != 1) { return ""; } + + String res; + + switch (format) { + case DATE_FULL: res = thisModem().stream.readStringUntil('"'); break; + case DATE_TIME: + thisModem().streamSkipUntil(','); + res = thisModem().stream.readStringUntil('"'); + break; + case DATE_DATE: res = thisModem().stream.readStringUntil(','); break; + } + return res; + } +}; + +#endif // SRC_TINYGSMTIME_H_ diff --git a/src/TinyGsmWifi.tpp b/src/TinyGsmWifi.tpp new file mode 100644 index 0000000..cbf92bb --- /dev/null +++ b/src/TinyGsmWifi.tpp @@ -0,0 +1,49 @@ +/** + * @file TinyGsmWifi.tpp + * @author Volodymyr Shymanskyy + * @license LGPL-3.0 + * @copyright Copyright (c) 2016 Volodymyr Shymanskyy + * @date Nov 2016 + */ + +#ifndef SRC_TINYGSMWIFI_H_ +#define SRC_TINYGSMWIFI_H_ + +#include "TinyGsmCommon.h" + +#define TINY_GSM_MODEM_HAS_WIFI + +template +class TinyGsmWifi { + public: + /* + * WiFi functions + */ + bool networkConnect(const char* ssid, const char* pwd) { + return thisModem().networkConnectImpl(ssid, pwd); + } + bool networkDisconnect() { + return thisModem().networkDisconnectImpl(); + } + + /* + * CRTP Helper + */ + protected: + inline const modemType& thisModem() const { + return static_cast(*this); + } + inline modemType& thisModem() { + return static_cast(*this); + } + + /* + * WiFi functions + */ + + bool networkConnectImpl(const char* ssid, + const char* pwd) TINY_GSM_ATTR_NOT_IMPLEMENTED; + bool networkDisconnectImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; +}; + +#endif // SRC_TINYGSMWIFI_H_ diff --git a/tools/test_build/test_build.ino b/tools/test_build/test_build.ino index e5b0db7..1e90809 100644 --- a/tools/test_build/test_build.ino +++ b/tools/test_build/test_build.ino @@ -3,15 +3,13 @@ * DO NOT USE THIS - this is just a compilation test! * **************************************************************/ -#define TINY_GSM_MODEM_SIM800 - #include TinyGsm modem(Serial); TinyGsmClient client(modem); #if defined(TINY_GSM_MODEM_HAS_SSL) - TinyGsmClientSecure client_secure(modem); +TinyGsmClientSecure client_secure(modem); #endif char server[] = "somewhere"; @@ -23,7 +21,6 @@ void setup() { } void loop() { - // Test the basic functions // modem.init(); modem.begin(); @@ -33,9 +30,6 @@ void loop() { modem.getModemInfo(); modem.getModemName(); modem.maintain(); - modem.hasSSL(); - modem.hasWifi(); - modem.hasGPRS(); // Test Power functions modem.restart(); @@ -43,27 +37,78 @@ void loop() { modem.radioOff(); modem.poweroff(); - // Test the SIM card functions - #if defined(TINY_GSM_MODEM_HAS_GPRS) +// Test the SIM card functions +#if defined(TINY_GSM_MODEM_HAS_GPRS) modem.getSimCCID(); modem.getIMEI(); modem.getSimStatus(); modem.getOperator(); - #endif +#endif + +// Test the calling functions +#if defined(TINY_GSM_MODEM_HAS_CALLING) + modem.callNumber(String("+380000000000")); + modem.callAnswer(); + modem.callHangup(); +#endif + +// Test the SMS functions +#if defined(TINY_GSM_MODEM_HAS_SMS) + modem.sendUSSD("*111#"); + modem.sendSMS(String("+380000000000"), String("Hello from ")); + modem.sendSMS_UTF16("+380000000000", "Hello", 5); +#endif + +// Test the GSM location functions +#if defined(TINY_GSM_MODEM_HAS_GSM_LOCATION) + modem.getGsmLocation(); +#endif + +// Test the Network time function +#if defined(TINY_GSM_MODEM_HAS_TIME) + modem.getGSMDateTime(DATE_FULL); +#endif + +// Test the Network time function +#if defined(TINY_GSM_MODEM_HAS_TIME) + modem.getGSMDateTime(DATE_FULL); +#endif + +// Test the GPS functions +#if defined(TINY_GSM_MODEM_HAS_GPS) + modem.enableGPS(); + modem.getGPSraw(); + float latitude = -9999; + float longitude = -9999; + modem.getGPS(&latitude, &longitude); +#endif + +// Test Battery functions +#if defined(TINY_GSM_MODEM_HAS_BATTERY) + uint8_t chargeState = 0; + int8_t chargePercent = 0; + uint16_t milliVolts = 0; + modem.getBattStats(chargeState, chargePercent, milliVolts); +#endif + +// Test the temperature function +#if defined(TINY_GSM_MODEM_HAS_TEMPERATURE) + modem.getTemperature(); +#endif // Test the Networking functions modem.getRegistrationStatus(); modem.getSignalQuality(); modem.localIP(); - #if defined(TINY_GSM_MODEM_HAS_GPRS) - modem.waitForNetwork(); - modem.gprsConnect("YourAPN", "", ""); - #endif - #if defined(TINY_GSM_MODEM_HAS_WIFI) - modem.networkConnect("YourSSID", "YourWiFiPass"); - modem.waitForNetwork(); - #endif +#if defined(TINY_GSM_MODEM_HAS_GPRS) + modem.waitForNetwork(); + modem.gprsConnect("YourAPN", "", ""); +#endif +#if defined(TINY_GSM_MODEM_HAS_WIFI) + modem.networkConnect("YourSSID", "YourWiFiPass"); + modem.waitForNetwork(); +#endif client.connect(server, 80); @@ -82,12 +127,31 @@ void loop() { client.stop(); - #if defined(TINY_GSM_MODEM_HAS_GPRS) - modem.gprsDisconnect(); - #endif - #if defined(TINY_GSM_MODEM_HAS_WIFI) - modem.networkDisconnect(); - #endif +#if defined(TINY_GSM_MODEM_HAS_SSL) + client_secure.connect(server, 443); + + // Make a HTTP GET request: + client_secure.print(String("GET ") + resource + " HTTP/1.0\r\n"); + client_secure.print(String("Host: ") + server + "\r\n"); + client_secure.print("Connection: close\r\n\r\n"); + + timeout = millis(); + while (client_secure.connected() && millis() - timeout < 10000L) { + while (client_secure.available()) { + client_secure.read(); + timeout = millis(); + } + } + + client_secure.stop(); +#endif + +#if defined(TINY_GSM_MODEM_HAS_GPRS) + modem.gprsDisconnect(); +#endif +#if defined(TINY_GSM_MODEM_HAS_WIFI) + modem.networkDisconnect(); +#endif // Test battery and temperature functions // modem.getBattVoltage();