v2.9
This commit is contained in:
224
lib/TinyGSM/src/TinyGsmSMS.tpp
Normal file
224
lib/TinyGSM/src/TinyGsmSMS.tpp
Normal file
@ -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 modemType>
|
||||
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<const modemType&>(*this);
|
||||
}
|
||||
inline modemType& thisModem() {
|
||||
return static_cast<modemType&>(*this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
protected:
|
||||
static inline String TinyGsmDecodeHex7bit(String& instr) {
|
||||
String result;
|
||||
byte reminder = 0;
|
||||
int8_t 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 (uint16_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 (uint16_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(',');
|
||||
int8_t dcs = thisModem().streamGetIntBefore('\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<char>(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<char>(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<uint16_t*>(reinterpret_cast<const uint16_t*>(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_
|
Reference in New Issue
Block a user