9 #ifndef TinyGsmClientM590_h 
   10 #define TinyGsmClientM590_h 
   14 #if !defined(TINY_GSM_RX_BUFFER) 
   15 #define TINY_GSM_RX_BUFFER 256 
   18 #define TINY_GSM_MUX_COUNT 2 
   20 #include "TinyGsmCommon.h" 
   23 static const char GSM_OK[] TINY_GSM_PROGMEM = 
"OK" GSM_NL;
 
   24 static const char GSM_ERROR[] TINY_GSM_PROGMEM = 
"ERROR" GSM_NL;
 
   47     class GsmClient : 
public Client
 
   55         GsmClient(
TinyGsm& modem, uint8_t mux = 1)
 
   60         bool init(
TinyGsm* modem, uint8_t mux = 1)
 
   64             sock_connected = 
false;
 
   66             at->sockets[mux] = 
this;
 
   72         virtual int connect(
const char *host, uint16_t port)
 
   77             sock_connected = at->modemConnect(host, port, mux);
 
   78             return sock_connected;
 
   81         virtual int connect(
IPAddress ip, uint16_t port)
 
   92             return connect(host.c_str(), port);
 
   98             at->sendAT(GF(
"+TCPCLOSE="), mux);
 
   99             sock_connected = 
false;
 
  104         virtual size_t write(
const uint8_t *buf, 
size_t size)
 
  108             return at->modemSend(buf, size, mux);
 
  111         virtual size_t write(uint8_t c)
 
  116         virtual int available()
 
  119             if (!rx.size() && sock_connected) {
 
  125         virtual int read(uint8_t *buf, 
size_t size)
 
  130                 size_t chunk = TinyGsmMin(size-cnt, rx.size());
 
  138                 if (!rx.size() && sock_connected) {
 
  149             if (read(&c, 1) == 1) {
 
  164         virtual uint8_t connected()
 
  169             return sock_connected;
 
  171         virtual operator bool()
 
  180         String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
 
  191     explicit 
TinyGsm(Stream& stream)
 
  194         memset(sockets, 0, 
sizeof(sockets));
 
  211         if (waitResponse() != 1) {
 
  214 #ifdef TINY_GSM_DEBUG 
  215         sendAT(GF(
"+CMEE=2"));
 
  223     void setBaud(
unsigned long baud)
 
  225         sendAT(GF(
"+IPR="), baud);
 
  228     bool testAT(
unsigned long timeout = 10000L)
 
  230         for (
unsigned long start = millis(); millis() - start < timeout; ) {
 
  232             if (waitResponse(200) == 1) {
 
  244         waitResponse(10, NULL, NULL);
 
  248     bool factoryDefault()
 
  250         sendAT(GF(
"&FZE0&W"));  
 
  252         sendAT(GF(
"+ICF=3,1")); 
 
  254         sendAT(GF(
"+ENPWRSAVE=0")); 
 
  256         sendAT(GF(
"+XISP=0"));  
 
  259         return waitResponse() == 1;
 
  262     String getModemInfo()
 
  266         if (waitResponse(1000L, res) != 1) {
 
  269         res.replace(GSM_NL 
"OK" GSM_NL, 
"");
 
  270         res.replace(GSM_NL, 
" ");
 
  289         sendAT(GF(
"+CFUN=15"));
 
  290         if (waitResponse(10000L) != 1) {
 
  294         waitResponse(60000L, GF(GSM_NL 
"+PBREADY" GSM_NL));
 
  300         sendAT(GF(
"+CPWROFF"));
 
  301         return waitResponse(3000L) == 1;
 
  304     bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
 
  306     bool sleepEnable(
bool enable = true)
 
  308         sendAT(GF(
"+ENPWRSAVE="), enable);
 
  309         return waitResponse() == 1;
 
  316     bool simUnlock(
const char *pin)
 
  318         sendAT(GF(
"+CPIN=\""), pin, GF(
"\""));
 
  319         return waitResponse() == 1;
 
  325         if (waitResponse(GF(GSM_NL 
"+CCID:")) != 1) {
 
  328         String res = stream.readStringUntil(
'\n');
 
  337         if (waitResponse(GF(GSM_NL)) != 1) {
 
  340         String res = stream.readStringUntil(
'\n');
 
  346     SimStatus getSimStatus(
unsigned long timeout = 10000L)
 
  348         for (
unsigned long start = millis(); millis() - start < timeout; ) {
 
  349             sendAT(GF(
"+CPIN?"));
 
  350             if (waitResponse(GF(GSM_NL 
"+CPIN:")) != 1) {
 
  354             int status = waitResponse(GF(
"READY"), GF(
"SIM PIN"), GF(
"SIM PUK"));
 
  369     RegStatus getRegistrationStatus()
 
  371         sendAT(GF(
"+CREG?"));
 
  372         if (waitResponse(GF(GSM_NL 
"+CREG:")) != 1) {
 
  375         streamSkipUntil(
','); 
 
  376         int status = stream.readStringUntil(
'\n').toInt();
 
  378         return (RegStatus)status;
 
  383         sendAT(GF(
"+COPS?"));
 
  384         if (waitResponse(GF(GSM_NL 
"+COPS:")) != 1) {
 
  387         streamSkipUntil(
'"'); 
 
  388         String res = stream.readStringUntil(
'"');
 
  397     int getSignalQuality()
 
  400         if (waitResponse(GF(GSM_NL 
"+CSQ:")) != 1) {
 
  403         int res = stream.readStringUntil(
',').toInt();
 
  408     bool isNetworkConnected()
 
  410         RegStatus s = getRegistrationStatus();
 
  411         return (s == REG_OK_HOME || s == REG_OK_ROAMING);
 
  414     bool waitForNetwork(
unsigned long timeout = 60000L)
 
  416         for (
unsigned long start = millis(); millis() - start < timeout; ) {
 
  417             if (isNetworkConnected()) {
 
  428     bool gprsConnect(
const char* apn, 
const char* user = NULL, 
const char* pwd = NULL)
 
  432         sendAT(GF(
"+XISP=0"));
 
  435         sendAT(GF(
"+CGDCONT=1,\"IP\",\""), apn, 
'"');
 
  444         sendAT(GF(
"+XGAUTH=1,1,\""), user, GF(
"\",\""), pwd, GF(
"\""));
 
  447         sendAT(GF(
"+XIIC=1"));
 
  450         const unsigned long timeout = 60000L;
 
  451         for (
unsigned long start = millis(); millis() - start < timeout; ) {
 
  452             if (isGprsConnected()) {
 
  461         sendAT(GF(
"+DNSSERVER=1,8.8.8.8"));
 
  464         sendAT(GF(
"+DNSSERVER=2,8.8.4.4"));
 
  470     bool gprsDisconnect()
 
  477     bool isGprsConnected()
 
  479         sendAT(GF(
"+XIIC?"));
 
  480         if (waitResponse(GF(GSM_NL 
"+XIIC:")) != 1) {
 
  483         int res = stream.readStringUntil(
',').toInt();
 
  490         sendAT(GF(
"+XIIC?"));
 
  491         if (waitResponse(GF(GSM_NL 
"+XIIC:")) != 1) {
 
  494         stream.readStringUntil(
',');
 
  495         String res = stream.readStringUntil(
'\n');
 
  503         return TinyGsmIpFromString(getLocalIP());
 
  510     bool setGsmBusy(
bool busy = 
true) TINY_GSM_ATTR_NOT_AVAILABLE;
 
  512     bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE;
 
  514     bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE;
 
  516     bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE;
 
  522     String sendUSSD(const String& code)
 
  524         sendAT(GF(
"+CMGF=1"));
 
  526         sendAT(GF(
"+CSCS=\"HEX\""));
 
  528         sendAT(GF(
"D"), code);
 
  529         if (waitResponse(10000L, GF(GSM_NL 
"+CUSD:")) != 1) {
 
  532         stream.readStringUntil(
'"');
 
  533         String hex = stream.readStringUntil(
'"');
 
  534         stream.readStringUntil(
',');
 
  535         int dcs = stream.readStringUntil(
'\n').toInt();
 
  537         if (waitResponse() != 1) {
 
  542             return TinyGsmDecodeHex8bit(hex);
 
  543         } 
else if (dcs == 72) {
 
  544             return TinyGsmDecodeHex16bit(hex);
 
  550     bool sendSMS(
const String& number, 
const String& text)
 
  552         sendAT(GF(
"+CSCS=\"GSM\""));
 
  554         sendAT(GF(
"+CMGF=1"));
 
  556         sendAT(GF(
"+CMGS=\""), number, GF(
"\""));
 
  557         if (waitResponse(GF(
">")) != 1) {
 
  561         stream.write((
char)0x1A);
 
  563         return waitResponse(60000L) == 1;
 
  566     bool sendSMS_UTF16(
const String& number, 
const void* text, 
size_t len)
 
  567     TINY_GSM_ATTR_NOT_AVAILABLE;
 
  573     String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
 
  579     uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
 
  581     int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
 
  585     bool modemConnect(const 
char* host, uint16_t port, uint8_t mux)
 
  587         for (
int i=0; i<3; i++) { 
 
  588             String ip = dnsIpQuery(host);
 
  590             sendAT(GF(
"+TCPSETUP="), mux, GF(
","), ip, GF(
","), port);
 
  591             int rsp = waitResponse(75000L,
 
  594                                    GF(
"+TCPSETUP:Error" GSM_NL));
 
  597             } 
else if (3 == rsp) {
 
  598                 sendAT(GF(
"+TCPCLOSE="), mux);
 
  606     int modemSend(
const void* buff, 
size_t len, uint8_t mux)
 
  608         sendAT(GF(
"+TCPSEND="), mux, 
',', len);
 
  609         if (waitResponse(GF(
">")) != 1) {
 
  612         stream.write((uint8_t*)buff, len);
 
  613         stream.write((
char)0x0D);
 
  615         if (waitResponse(30000L, GF(GSM_NL 
"+TCPSEND:")) != 1) {
 
  618         stream.readStringUntil(
'\n');
 
  622     bool modemGetConnected(uint8_t mux)
 
  624         sendAT(GF(
"+CIPSTATUS="), mux);
 
  625         int res = waitResponse(GF(
",\"CONNECTED\""), GF(
",\"CLOSED\""), GF(
",\"CLOSING\""),
 
  631     String dnsIpQuery(
const char* host)
 
  633         sendAT(GF(
"+DNS=\""), host, GF(
"\""));
 
  634         if (waitResponse(10000L, GF(GSM_NL 
"+DNS:")) != 1) {
 
  637         String res = stream.readStringUntil(
'\n');
 
  638         waitResponse(GF(
"+DNS:OK" GSM_NL));
 
  648     void streamWrite(T 
last)
 
  653     template<
typename T, 
typename... Args>
 
  654     void streamWrite(T head, Args... tail)
 
  657         streamWrite(tail...);
 
  660     bool streamSkipUntil(
char c)   
 
  663             while (!stream.available()) {
 
  666             if (stream.read() == c) {
 
  673     template<
typename... Args>
 
  674     void sendAT(Args... cmd)
 
  676         streamWrite(
"AT", cmd..., GSM_NL);
 
  683     uint8_t waitResponse(uint32_t timeout, String& 
data,
 
  684                          GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
 
  685                          GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
 
  695         unsigned long startMillis = millis();
 
  698             while (stream.available() > 0) {
 
  699                 int a = stream.read();
 
  704                 if (r1 && 
data.endsWith(r1)) {
 
  707                 } 
else if (r2 && 
data.endsWith(r2)) {
 
  710                 } 
else if (r3 && 
data.endsWith(r3)) {
 
  713                 } 
else if (r4 && 
data.endsWith(r4)) {
 
  716                 } 
else if (r5 && 
data.endsWith(r5)) {
 
  719                 } 
else if (
data.endsWith(GF(
"+TCPRECV:"))) {
 
  720                     int mux = stream.readStringUntil(
',').toInt();
 
  721                     int len = stream.readStringUntil(
',').toInt();
 
  723                     if (len > sockets[mux]->rx.free()) {
 
  724                         DBG(
"### Buffer overflow: ", len, 
"->", sockets[mux]->rx.free());
 
  726                         DBG(
"### Got: ", len, 
"->", sockets[mux]->rx.free());
 
  729                         while (!stream.available()) {
 
  732                         sockets[mux]->rx.put(stream.read());
 
  734                     if (len_orig > sockets[mux]->available()) { 
 
  735                         DBG(
"### Fewer characters received than expected: ", sockets[mux]->available(), 
" vs ", len_orig);
 
  738                 } 
else if (
data.endsWith(GF(
"+TCPCLOSE:"))) {
 
  739                     int mux = stream.readStringUntil(
',').toInt();
 
  740                     stream.readStringUntil(
'\n');
 
  741                     if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) {
 
  742                         sockets[mux]->sock_connected = 
false;
 
  745                     DBG(
"### Closed: ", mux);
 
  748         } 
while (millis() - startMillis < timeout);
 
  753                 DBG(
"### Unhandled:", 
data);
 
  760     uint8_t waitResponse(uint32_t timeout,
 
  761                          GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
 
  762                          GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
 
  765         return waitResponse(timeout, 
data, r1, r2, r3, r4, r5);
 
  768     uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
 
  769                          GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
 
  771         return waitResponse(1000, r1, r2, r3, r4, r5);
 
  778     GsmClient*    sockets[TINY_GSM_MUX_COUNT];