9 #ifndef TinyGsmClientSIM800_h
10 #define TinyGsmClientSIM800_h
15 #if !defined(TINY_GSM_RX_BUFFER)
16 #define TINY_GSM_RX_BUFFER 64
19 #define TINY_GSM_MUX_COUNT 5
21 #include "TinyGsmCommon.h"
24 static const char GSM_OK[] TINY_GSM_PROGMEM =
"OK" GSM_NL;
25 static const char GSM_ERROR[] TINY_GSM_PROGMEM =
"ERROR" GSM_NL;
67 sock_connected =
false;
70 at->sockets[mux] =
this;
76 virtual int connect(
const char *host, uint16_t port)
81 sock_connected = at->modemConnect(host, port, mux);
82 return sock_connected;
85 virtual int connect(
IPAddress ip, uint16_t port)
96 return connect(host.c_str(), port);
102 at->sendAT(GF(
"+CIPCLOSE="), mux);
103 sock_connected =
false;
108 virtual size_t write(
const uint8_t *buf,
size_t size)
112 return at->modemSend(buf, size, mux);
115 virtual size_t write(uint8_t c)
120 virtual int available()
123 if (!rx.size() && sock_connected) {
127 if (millis() - prev_check > 500) {
129 prev_check = millis();
133 return rx.size() + sock_available;
136 virtual int read(uint8_t *buf,
size_t size)
141 while (cnt < size && sock_connected) {
142 size_t chunk = TinyGsmMin(size-cnt, rx.size());
151 if (sock_available > 0) {
152 at->modemRead(rx.free(), mux);
163 if (read(&c, 1) == 1) {
178 virtual uint8_t connected()
183 return sock_connected;
185 virtual operator bool()
194 String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
199 uint16_t sock_available;
216 virtual int connect(
const char *host, uint16_t port)
221 sock_connected = at->modemConnect(host, port, mux,
true);
222 return sock_connected;
231 memset(sockets, 0,
sizeof(sockets));
250 if (waitResponse() != 1) {
257 void setBaud(
unsigned long baud)
259 sendAT(GF(
"+IPR="), baud);
262 bool testAT(
unsigned long timeout = 10000L)
265 for (
unsigned long start = millis(); millis() - start < timeout; ) {
267 if (waitResponse(200) == 1) {
278 for (
int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) {
279 GsmClient* sock = sockets[mux];
280 if (sock && sock->got_data) {
281 sock->got_data =
false;
282 sock->sock_available = modemGetAvailable(mux);
285 while (stream.available()) {
286 waitResponse(10, NULL, NULL);
290 bool factoryDefault()
292 sendAT(GF(
"&FZE0&W"));
294 sendAT(GF(
"+IPR=0"));
296 sendAT(GF(
"+IFC=0,0"));
298 sendAT(GF(
"+ICF=3,3"));
300 sendAT(GF(
"+CSCLK=0"));
303 return waitResponse() == 1;
306 String getModemInfo()
310 if (waitResponse(1000L, res) != 1) {
313 res.replace(GSM_NL
"OK" GSM_NL,
"");
314 res.replace(GSM_NL,
" ");
321 #if defined(TINY_GSM_MODEM_SIM900)
324 sendAT(GF(
"+CIPSSL=?"));
325 if (waitResponse(GF(GSM_NL
"+CIPSSL:")) != 1) {
328 return waitResponse() == 1;
341 sendAT(GF(
"+CFUN=0"));
342 if (waitResponse(10000L) != 1) {
345 sendAT(GF(
"+CFUN=1,1"));
346 if (waitResponse(10000L) != 1) {
355 sendAT(GF(
"+CPOWD=1"));
356 return waitResponse(GF(
"NORMAL POWER DOWN")) == 1;
361 sendAT(GF(
"+CFUN=0"));
362 if (waitResponse(10000L) != 1) {
374 bool sleepEnable(
bool enable =
true)
376 sendAT(GF(
"+CSCLK="), enable);
377 return waitResponse() == 1;
384 bool simUnlock(
const char *pin)
386 sendAT(GF(
"+CPIN=\""), pin, GF(
"\""));
387 return waitResponse() == 1;
392 sendAT(GF(
"+ICCID"));
393 if (waitResponse(GF(GSM_NL
"+ICCID:")) != 1) {
396 String res = stream.readStringUntil(
'\n');
405 if (waitResponse(GF(GSM_NL)) != 1) {
408 String res = stream.readStringUntil(
'\n');
414 SimStatus getSimStatus(
unsigned long timeout = 10000L)
416 for (
unsigned long start = millis(); millis() - start < timeout; ) {
417 sendAT(GF(
"+CPIN?"));
418 if (waitResponse(GF(GSM_NL
"+CPIN:")) != 1) {
422 int status = waitResponse(GF(
"READY"), GF(
"SIM PIN"), GF(
"SIM PUK"), GF(
"NOT INSERTED"));
437 RegStatus getRegistrationStatus()
439 sendAT(GF(
"+CREG?"));
440 if (waitResponse(GF(GSM_NL
"+CREG:")) != 1) {
443 streamSkipUntil(
',');
444 int status = stream.readStringUntil(
'\n').toInt();
446 return (RegStatus)status;
451 sendAT(GF(
"+COPS?"));
452 if (waitResponse(GF(GSM_NL
"+COPS:")) != 1) {
455 streamSkipUntil(
'"');
456 String res = stream.readStringUntil(
'"');
465 int getSignalQuality()
468 if (waitResponse(GF(GSM_NL
"+CSQ:")) != 1) {
471 int res = stream.readStringUntil(
',').toInt();
476 bool isNetworkConnected()
478 RegStatus s = getRegistrationStatus();
479 return (s == REG_OK_HOME || s == REG_OK_ROAMING);
482 bool waitForNetwork(
unsigned long timeout = 60000L)
484 for (
unsigned long start = millis(); millis() - start < timeout; ) {
485 if (isNetworkConnected()) {
496 bool gprsConnect(
const char* apn,
const char* user = NULL,
const char* pwd = NULL)
501 sendAT(GF(
"+SAPBR=3,1,\"Contype\",\"GPRS\""));
504 sendAT(GF(
"+SAPBR=3,1,\"APN\",\""), apn,
'"');
507 if (user && strlen(user) > 0) {
508 sendAT(GF(
"+SAPBR=3,1,\"USER\",\""), user,
'"');
511 if (pwd && strlen(pwd) > 0) {
512 sendAT(GF(
"+SAPBR=3,1,\"PWD\",\""), pwd,
'"');
517 sendAT(GF(
"+CGDCONT=1,\"IP\",\""), apn,
'"');
521 sendAT(GF(
"+CGACT=1,1"));
522 waitResponse(60000L);
525 sendAT(GF(
"+SAPBR=1,1"));
526 waitResponse(85000L);
528 sendAT(GF(
"+SAPBR=2,1"));
529 if (waitResponse(30000L) != 1) {
534 sendAT(GF(
"+CGATT=1"));
535 if (waitResponse(60000L) != 1) {
542 sendAT(GF(
"+CIPMUX=1"));
543 if (waitResponse() != 1) {
548 sendAT(GF(
"+CIPQSEND=1"));
549 if (waitResponse() != 1) {
554 sendAT(GF(
"+CIPRXGET=1"));
555 if (waitResponse() != 1) {
560 sendAT(GF(
"+CSTT=\""), apn, GF(
"\",\""), user, GF(
"\",\""), pwd, GF(
"\""));
561 if (waitResponse(60000L) != 1) {
566 sendAT(GF(
"+CIICR"));
567 if (waitResponse(60000L) != 1) {
572 sendAT(GF(
"+CIFSR;E0"));
573 if (waitResponse(10000L) != 1) {
578 sendAT(GF(
"+CDNSCFG=\"8.8.8.8\",\"8.8.4.4\""));
579 if (waitResponse() != 1) {
586 bool gprsDisconnect()
589 sendAT(GF(
"+CIPSHUT"));
590 if (waitResponse(60000L) != 1) {
594 sendAT(GF(
"+CGATT=0"));
595 if (waitResponse(60000L) != 1) {
602 bool isGprsConnected()
604 sendAT(GF(
"+CGATT?"));
605 if (waitResponse(GF(GSM_NL
"+CGATT:")) != 1) {
608 int res = stream.readStringUntil(
'\n').toInt();
614 sendAT(GF(
"+CIFSR;E0"));
615 if (waitResponse() != 1) {
624 sendAT(GF(
"+CIFSR;E0"));
626 if (waitResponse(10000L, res) != 1) {
629 res.replace(GSM_NL
"OK" GSM_NL,
"");
630 res.replace(GSM_NL,
"");
637 return TinyGsmIpFromString(getLocalIP());
644 bool setGsmBusy(
bool busy =
true)
646 sendAT(GF(
"+GSMBUSY="), busy ? 1 : 0);
647 return waitResponse() == 1;
653 return waitResponse() == 1;
657 bool callNumber(
const String& number)
659 if (number == GF(
"last")) {
662 sendAT(GF(
"D"), number,
";");
664 int status = waitResponse(60000L,
667 GF(
"NO ANSWER" GSM_NL),
668 GF(
"NO CARRIER" GSM_NL));
683 return waitResponse() == 1;
687 bool dtmfSend(
char cmd,
int duration_ms = 100)
689 duration_ms = constrain(duration_ms, 100, 1000);
691 sendAT(GF(
"+VTD="), duration_ms / 100);
694 sendAT(GF(
"+VTS="), cmd);
695 return waitResponse(10000L) == 1;
702 String sendUSSD(
const String& code)
704 sendAT(GF(
"+CMGF=1"));
706 sendAT(GF(
"+CSCS=\"HEX\""));
708 sendAT(GF(
"+CUSD=1,\""), code, GF(
"\""));
709 if (waitResponse() != 1) {
712 if (waitResponse(10000L, GF(GSM_NL
"+CUSD:")) != 1) {
715 stream.readStringUntil(
'"');
716 String hex = stream.readStringUntil(
'"');
717 stream.readStringUntil(
',');
718 int dcs = stream.readStringUntil(
'\n').toInt();
721 return TinyGsmDecodeHex8bit(hex);
722 }
else if (dcs == 72) {
723 return TinyGsmDecodeHex16bit(hex);
729 bool sendSMS(
const String& number,
const String& text)
731 sendAT(GF(
"+CMGF=1"));
734 sendAT(GF(
"+CSCS=\"GSM\""));
736 sendAT(GF(
"+CMGS=\""), number, GF(
"\""));
737 if (waitResponse(GF(
">")) != 1) {
741 stream.write((
char)0x1A);
743 return waitResponse(60000L) == 1;
746 bool sendSMS_UTF16(
const String& number,
const void* text,
size_t len)
748 sendAT(GF(
"+CMGF=1"));
750 sendAT(GF(
"+CSCS=\"HEX\""));
752 sendAT(GF(
"+CSMP=17,167,0,8"));
755 sendAT(GF(
"+CMGS=\""), number, GF(
"\""));
756 if (waitResponse(GF(
">")) != 1) {
760 uint16_t* t = (uint16_t*)text;
761 for (
size_t i=0; i<len; i++) {
762 uint8_t c = t[i] >> 8;
766 stream.print(c, HEX);
771 stream.print(c, HEX);
773 stream.write((
char)0x1A);
775 return waitResponse(60000L) == 1;
783 String getGsmLocation()
785 sendAT(GF(
"+CIPGSMLOC=1,1"));
786 if (waitResponse(10000L, GF(GSM_NL
"+CIPGSMLOC:")) != 1) {
789 String res = stream.readStringUntil(
'\n');
799 uint16_t getBattVoltage()
802 if (waitResponse(GF(GSM_NL
"+CBC:")) != 1) {
805 streamSkipUntil(
',');
806 streamSkipUntil(
',');
808 uint16_t res = stream.readStringUntil(
',').toInt();
816 if (waitResponse(GF(GSM_NL
"+CBC:")) != 1) {
819 stream.readStringUntil(
',');
820 int res = stream.readStringUntil(
',').toInt();
827 bool modemConnect(
const char* host, uint16_t port, uint8_t mux,
bool ssl =
false)
829 #if !defined(TINY_GSM_MODEM_SIM900)
830 sendAT(GF(
"+CIPSSL="), ssl);
831 int rsp = waitResponse();
832 if (ssl && rsp != 1) {
836 sendAT(GF(
"+CIPSTART="), mux,
',', GF(
"\"TCP"), GF(
"\",\""), host, GF(
"\","), port);
837 rsp = waitResponse(75000L,
838 GF(
"CONNECT OK" GSM_NL),
839 GF(
"CONNECT FAIL" GSM_NL),
840 GF(
"ALREADY CONNECT" GSM_NL),
842 GF(
"CLOSE OK" GSM_NL)
847 int modemSend(
const void* buff,
size_t len, uint8_t mux)
849 sendAT(GF(
"+CIPSEND="), mux,
',', len);
850 if (waitResponse(GF(
">")) != 1) {
853 stream.write((uint8_t*)buff, len);
855 if (waitResponse(GF(GSM_NL
"DATA ACCEPT:")) != 1) {
858 streamSkipUntil(
',');
859 return stream.readStringUntil(
'\n').toInt();
862 size_t modemRead(
size_t size, uint8_t mux)
864 #ifdef TINY_GSM_USE_HEX
865 sendAT(GF(
"+CIPRXGET=3,"), mux,
',', size);
866 if (waitResponse(GF(
"+CIPRXGET:")) != 1) {
870 sendAT(GF(
"+CIPRXGET=2,"), mux,
',', size);
871 if (waitResponse(GF(
"+CIPRXGET:")) != 1) {
875 streamSkipUntil(
',');
876 streamSkipUntil(
',');
877 size_t len = stream.readStringUntil(
',').toInt();
878 sockets[mux]->sock_available = stream.readStringUntil(
'\n').toInt();
880 for (
size_t i=0; i<len; i++) {
881 #ifdef TINY_GSM_USE_HEX
882 while (stream.available() < 2) {
885 char buf[4] = { 0, };
886 buf[0] = stream.read();
887 buf[1] = stream.read();
888 char c = strtol(buf, NULL, 16);
890 while (!stream.available()) {
893 char c = stream.read();
895 sockets[mux]->rx.put(c);
901 size_t modemGetAvailable(uint8_t mux)
903 sendAT(GF(
"+CIPRXGET=4,"), mux);
905 if (waitResponse(GF(
"+CIPRXGET:")) == 1) {
906 streamSkipUntil(
',');
907 streamSkipUntil(
',');
908 result = stream.readStringUntil(
'\n').toInt();
912 sockets[mux]->sock_connected = modemGetConnected(mux);
917 bool modemGetConnected(uint8_t mux)
919 sendAT(GF(
"+CIPSTATUS="), mux);
920 int res = waitResponse(GF(
",\"CONNECTED\""), GF(
",\"CLOSED\""), GF(
",\"CLOSING\""),
931 void streamWrite(T
last)
936 template<
typename T,
typename... Args>
937 void streamWrite(T head, Args... tail)
940 streamWrite(tail...);
943 bool streamSkipUntil(
char c)
946 while (!stream.available()) {
949 if (stream.read() == c) {
956 template<
typename... Args>
957 void sendAT(Args... cmd)
959 streamWrite(
"AT", cmd..., GSM_NL);
966 uint8_t waitResponse(uint32_t timeout, String&
data,
967 GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
968 GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
978 unsigned long startMillis = millis();
981 while (stream.available() > 0) {
982 int a = stream.read();
987 if (r1 &&
data.endsWith(r1)) {
990 }
else if (r2 &&
data.endsWith(r2)) {
993 }
else if (r3 &&
data.endsWith(r3)) {
996 }
else if (r4 &&
data.endsWith(r4)) {
999 }
else if (r5 &&
data.endsWith(r5)) {
1002 }
else if (
data.endsWith(GF(GSM_NL
"+CIPRXGET:"))) {
1003 String mode = stream.readStringUntil(
',');
1004 if (mode.toInt() == 1) {
1005 int mux = stream.readStringUntil(
'\n').toInt();
1006 if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
1007 sockets[mux]->got_data =
true;
1013 }
else if (
data.endsWith(GF(
"CLOSED" GSM_NL))) {
1014 int nl =
data.lastIndexOf(GSM_NL,
data.length()-8);
1015 int coma =
data.indexOf(
',', nl+2);
1016 int mux =
data.substring(nl+2, coma).toInt();
1017 if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
1018 sockets[mux]->sock_connected =
false;
1021 DBG(
"### Closed: ", mux);
1024 }
while (millis() - startMillis < timeout);
1028 if (
data.length()) {
1029 DBG(
"### Unhandled:",
data);
1036 uint8_t waitResponse(uint32_t timeout,
1037 GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
1038 GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
1041 return waitResponse(timeout,
data, r1, r2, r3, r4, r5);
1044 uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
1045 GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
1047 return waitResponse(1000, r1, r2, r3, r4, r5);
1054 GsmClient* sockets[TINY_GSM_MUX_COUNT];