diff --git a/examples/AllFunctions/AllFunctions.ino b/examples/AllFunctions/AllFunctions.ino index 7a8fb99..7164086 100644 --- a/examples/AllFunctions/AllFunctions.ino +++ b/examples/AllFunctions/AllFunctions.ino @@ -239,8 +239,15 @@ void loop() { DBG("SMS:", res ? "OK" : "fail"); // This is only supported on SIMxxx series - res = modem.sendSMS_UTF16(SMS_TARGET, u"Привіііт!", 9); - DBG("UTF16 SMS:", res ? "OK" : "fail"); + res = modem.sendSMS_UTF8_begin(SMS_TARGET); + if(res) { + auto stream = modem.sendSMS_UTF8_stream(); + 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/src/TinyGsmClientA6.h b/src/TinyGsmClientA6.h index 67dc515..14dc15a 100644 --- a/src/TinyGsmClientA6.h +++ b/src/TinyGsmClientA6.h @@ -123,8 +123,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmA6() {} - /* * Basic functions */ diff --git a/src/TinyGsmClientBG96.h b/src/TinyGsmClientBG96.h index a689e3d..cd738d7 100644 --- a/src/TinyGsmClientBG96.h +++ b/src/TinyGsmClientBG96.h @@ -40,7 +40,7 @@ enum RegStatus { }; -class TinyGsmBG96 +class TinyGsmBG96: public TinyGsmUTFSMS { public: @@ -146,7 +146,6 @@ public: { memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmBG96() {} /* * Basic functions @@ -416,33 +415,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - /* * Location functions diff --git a/src/TinyGsmClientESP8266.h b/src/TinyGsmClientESP8266.h index b993805..3ea8e98 100644 --- a/src/TinyGsmClientESP8266.h +++ b/src/TinyGsmClientESP8266.h @@ -141,8 +141,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmESP8266() {} - /* * Basic functions */ diff --git a/src/TinyGsmClientM590.h b/src/TinyGsmClientM590.h index 3add9fe..ba6851c 100644 --- a/src/TinyGsmClientM590.h +++ b/src/TinyGsmClientM590.h @@ -121,8 +121,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmM590() {} - /* * Basic functions */ diff --git a/src/TinyGsmClientM95.h b/src/TinyGsmClientM95.h index 290b575..752d8e2 100644 --- a/src/TinyGsmClientM95.h +++ b/src/TinyGsmClientM95.h @@ -40,7 +40,7 @@ enum RegStatus { }; -class TinyGsmM95 +class TinyGsmM95: public TinyGsmUTFSMS { public: @@ -143,8 +143,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmM95() {} - /* * Basic functions */ @@ -479,33 +477,6 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - /** Delete all SMS */ bool deleteAllSMS() { sendAT(GF("+QMGDA=6")); diff --git a/src/TinyGsmClientMC60.h b/src/TinyGsmClientMC60.h index ff28d81..740ea06 100644 --- a/src/TinyGsmClientMC60.h +++ b/src/TinyGsmClientMC60.h @@ -44,7 +44,7 @@ enum RegStatus { }; -class TinyGsmMC60 +class TinyGsmMC60: public TinyGsmUTFSMS { public: @@ -147,8 +147,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmMC60() {} - /* * Basic functions */ @@ -460,33 +458,6 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - /** Delete all SMS */ bool deleteAllSMS() { sendAT(GF("+QMGDA=6")); diff --git a/src/TinyGsmClientSIM5360.h b/src/TinyGsmClientSIM5360.h index 46b5eaf..e306a2e 100644 --- a/src/TinyGsmClientSIM5360.h +++ b/src/TinyGsmClientSIM5360.h @@ -45,7 +45,7 @@ enum TinyGSMDateTimeFormat { DATE_DATE = 2 }; -class TinyGsmSim5360 +class TinyGsmSim5360: public TinyGsmUTFSMS { public: @@ -130,8 +130,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmSim5360(){} - /* * Basic functions */ @@ -522,36 +520,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - // Select message format (1=text) - sendAT(GF("+CMGF=1")); - waitResponse(); - // Select TE character set - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - // Set text mode parameters - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - // Send the message - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - /* * Location functions diff --git a/src/TinyGsmClientSIM7000.h b/src/TinyGsmClientSIM7000.h index ad13af1..5f56091 100644 --- a/src/TinyGsmClientSIM7000.h +++ b/src/TinyGsmClientSIM7000.h @@ -45,7 +45,7 @@ enum TinyGSMDateTimeFormat { DATE_DATE = 2 }; -class TinyGsmSim7000 +class TinyGsmSim7000: public TinyGsmUTFSMS { public: @@ -154,8 +154,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmSim7000() {} - /* * Basic functions */ @@ -564,33 +562,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - /* * Location functions diff --git a/src/TinyGsmClientSIM7600.h b/src/TinyGsmClientSIM7600.h index b9d767a..c1ec12f 100644 --- a/src/TinyGsmClientSIM7600.h +++ b/src/TinyGsmClientSIM7600.h @@ -45,7 +45,7 @@ enum TinyGSMDateTimeFormat { DATE_DATE = 2 }; -class TinyGsmSim7600 +class TinyGsmSim7600: public TinyGsmUTFSMS { public: @@ -130,8 +130,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmSim7600(){} - /* * Basic functions */ @@ -498,36 +496,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - // Select message format (1=text) - sendAT(GF("+CMGF=1")); - waitResponse(); - // Select TE character set - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - // Set text mode parameters - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - // Send the message - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - /* * Location functions diff --git a/src/TinyGsmClientSIM800.h b/src/TinyGsmClientSIM800.h index 229e986..5b0fa3d 100644 --- a/src/TinyGsmClientSIM800.h +++ b/src/TinyGsmClientSIM800.h @@ -46,7 +46,7 @@ enum TinyGSMDateTimeFormat { DATE_DATE = 2 }; -class TinyGsmSim800 +class TinyGsmSim800 : public TinyGsmUTFSMS { public: @@ -153,8 +153,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmSim800() {} - /* * Basic functions */ @@ -597,34 +595,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() return waitResponse(60000L) == 1; } - bool sendSMS_UTF16(const String& number, const void* text, size_t len) { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { stream.print('0'); } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - - /* * Location functions */ diff --git a/src/TinyGsmClientSIM808.h b/src/TinyGsmClientSIM808.h index ecd07a1..35754a0 100644 --- a/src/TinyGsmClientSIM808.h +++ b/src/TinyGsmClientSIM808.h @@ -22,8 +22,6 @@ public: : TinyGsmSim800(stream) {} - virtual ~TinyGsmSim808(){} - /* * GPS location functions */ diff --git a/src/TinyGsmClientSaraR4.h b/src/TinyGsmClientSaraR4.h index 313ff2c..afb35ba 100644 --- a/src/TinyGsmClientSaraR4.h +++ b/src/TinyGsmClientSaraR4.h @@ -202,8 +202,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmSaraR4(){} - /* * Basic functions */ diff --git a/src/TinyGsmClientSequansMonarch.h b/src/TinyGsmClientSequansMonarch.h index 8e65d93..c333ed1 100644 --- a/src/TinyGsmClientSequansMonarch.h +++ b/src/TinyGsmClientSequansMonarch.h @@ -179,8 +179,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmSequansMonarch() {} - /* * Basic functions */ diff --git a/src/TinyGsmClientUBLOX.h b/src/TinyGsmClientUBLOX.h index 09702b1..c35f10f 100644 --- a/src/TinyGsmClientUBLOX.h +++ b/src/TinyGsmClientUBLOX.h @@ -164,8 +164,6 @@ public: memset(sockets, 0, sizeof(sockets)); } - virtual ~TinyGsmUBLOX() {} - /* * Basic functions */ diff --git a/src/TinyGsmClientXBee.h b/src/TinyGsmClientXBee.h index 9662ee0..79e743e 100644 --- a/src/TinyGsmClientXBee.h +++ b/src/TinyGsmClientXBee.h @@ -287,9 +287,6 @@ public: inCommandMode = false; memset(sockets, 0, sizeof(sockets)); } - - virtual ~TinyGsmXBee() {} - /* * Basic functions */ diff --git a/src/TinyGsmCommon.h b/src/TinyGsmCommon.h index 6e8bf37..f3a2ea3 100644 --- a/src/TinyGsmCommon.h +++ b/src/TinyGsmCommon.h @@ -645,4 +645,77 @@ String TinyGsmDecodeHex16bit(String &instr) { } +//Common methods for UTF8/UTF16 SMS. +//Supported by: BG96, M95, MC60, SIM5360, SIM7000, SIM7600, SIM800 +template +class TinyGsmUTFSMS { +public: + + class UTF8Print : public Print { + public: + UTF8Print(Print& p) : p(p) {} + virtual 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) { + static_cast(this)->sendAT(GF("+CMGF=1")); + static_cast(this)->waitResponse(); + static_cast(this)->sendAT(GF("+CSCS=\"HEX\"")); + static_cast(this)->waitResponse(); + static_cast(this)->sendAT(GF("+CSMP=17,167,0,8")); + static_cast(this)->waitResponse(); + + static_cast(this)->sendAT(GF("+CMGS=\""), number, GF("\"")); + return static_cast(this)->waitResponse(GF(">")) == 1; + } + bool sendSMS_UTF8_end() { + static_cast(this)->stream.write((char)0x1A); + static_cast(this)->stream.flush(); + return static_cast(this)->waitResponse(60000L) == 1; + } + UTF8Print sendSMS_UTF8_stream() { + return UTF8Print(static_cast(this)->stream); + } + + bool sendSMS_UTF16(const char* const number, const void* text, size_t len) { + if (!sendSMS_UTF8_begin(number)) { + return false; + } + + uint16_t* t = (uint16_t*)text; + for (size_t i=0; i> 8; + if (c < 0x10) { static_cast(this)->stream.print('0'); } + static_cast(this)->stream.print(c, HEX); + c = t[i] & 0xFF; + if (c < 0x10) { static_cast(this)->stream.print('0'); } + static_cast(this)->stream.print(c, HEX); + } + + return sendSMS_UTF8_end(); + } +}; + #endif