9 #ifndef TinyGsmClientESP8266_h
10 #define TinyGsmClientESP8266_h
14 #if !defined(TINY_GSM_RX_BUFFER)
15 #define TINY_GSM_RX_BUFFER 512
18 #define TINY_GSM_MUX_COUNT 5
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;
25 static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120;
32 class GsmClient :
public Client
40 GsmClient(
TinyGsm& modem, uint8_t mux = 1)
45 bool init(
TinyGsm* modem, uint8_t mux = 1)
49 sock_connected =
false;
51 at->sockets[mux] =
this;
57 virtual int connect(
const char *host, uint16_t port)
62 sock_connected = at->modemConnect(host, port, mux);
63 return sock_connected;
66 virtual int connect(
IPAddress ip, uint16_t port)
77 return connect(host.c_str(), port);
83 at->sendAT(GF(
"+CIPCLOSE="), mux);
84 sock_connected =
false;
89 virtual size_t write(
const uint8_t *buf,
size_t size)
93 return at->modemSend(buf, size, mux);
96 virtual size_t write(uint8_t c)
101 virtual int available()
104 if (!rx.size() && sock_connected) {
110 virtual int read(uint8_t *buf,
size_t size)
115 size_t chunk = TinyGsmMin(size-cnt, rx.size());
123 if (!rx.size() && sock_connected) {
134 if (read(&c, 1) == 1) {
149 virtual uint8_t connected()
154 return sock_connected;
156 virtual operator bool()
165 String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
184 virtual int connect(
const char *host, uint16_t port)
189 sock_connected = at->modemConnect(host, port, mux,
true);
190 return sock_connected;
196 explicit TinyGsm(Stream& stream)
199 memset(sockets, 0,
sizeof(sockets));
216 if (waitResponse() != 1) {
222 void setBaud(
unsigned long baud)
224 sendAT(GF(
"+IPR="), baud);
227 bool testAT(
unsigned long timeout = 10000L)
229 for (
unsigned long start = millis(); millis() - start < timeout; ) {
231 if (waitResponse(200) == 1) {
242 waitResponse(10, NULL, NULL);
245 bool factoryDefault()
247 sendAT(GF(
"+RESTORE"));
248 return waitResponse() == 1;
251 String getModemInfo()
255 if (waitResponse(1000L, res) != 1) {
258 res.replace(GSM_NL
"OK" GSM_NL,
"");
259 res.replace(GSM_NL,
" ");
279 if (waitResponse(10000L) != 1) {
282 if (waitResponse(10000L, GF(GSM_NL
"ready" GSM_NL)) != 1) {
294 int getSignalQuality()
296 sendAT(GF(
"+CWJAP_CUR?"));
297 int res1 = waitResponse(GF(
"No AP"), GF(
"+CWJAP_CUR:"));
302 streamSkipUntil(
',');
303 streamSkipUntil(
',');
304 streamSkipUntil(
',');
305 int res2 = stream.parseInt();
310 bool isNetworkConnected()
312 sendAT(GF(
"+CIPSTATUS"));
313 int res1 = waitResponse(3000, GF(
"STATUS:"));
316 res2 = waitResponse(GFP(GSM_ERROR), GF(
"2"), GF(
"3"), GF(
"4"), GF(
"5"));
324 if (res2 == 2 || res2 == 3 || res2 == 4) {
331 bool waitForNetwork(
unsigned long timeout = 60000L)
333 for (
unsigned long start = millis(); millis() - start < timeout; ) {
334 sendAT(GF(
"+CIPSTATUS"));
335 int res1 = waitResponse(3000, GF(
"busy p..."), GF(
"STATUS:"));
337 int res2 = waitResponse(GFP(GSM_ERROR), GF(
"2"), GF(
"3"), GF(
"4"), GF(
"5"));
338 if (res2 == 2 || res2 == 3 || res2 == 4) {
351 bool networkConnect(
const char* ssid,
const char* pwd)
354 sendAT(GF(
"+CIPMUX=1"));
355 if (waitResponse() != 1) {
359 sendAT(GF(
"+CWMODE_CUR=1"));
360 if (waitResponse() != 1) {
364 sendAT(GF(
"+CWJAP_CUR=\""), ssid, GF(
"\",\""), pwd, GF(
"\""));
365 if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL
"FAIL" GSM_NL)) != 1) {
372 bool networkDisconnect()
374 sendAT(GF(
"+CWQAP"));
375 bool retVal = waitResponse(10000L) == 1;
376 waitResponse(GF(
"WIFI DISCONNECT"));
382 sendAT(GF(
"+CIPSTA_CUR??"));
383 int res1 = waitResponse(GF(
"ERROR"), GF(
"+CWJAP_CUR:"));
387 String res2 = stream.readStringUntil(
'"');
394 return TinyGsmIpFromString(getLocalIP());
399 bool modemConnect(
const char* host, uint16_t port, uint8_t mux,
bool ssl =
false)
402 sendAT(GF(
"+CIPSSLSIZE=4096"));
405 sendAT(GF(
"+CIPSTART="), mux,
',', ssl ? GF(
"\"SSL") : GF(
"\"TCP"), GF(
"\",\""), host, GF(
"\","),
406 port, GF(
","), TINY_GSM_TCP_KEEP_ALIVE);
408 int rsp = waitResponse(75000L,
411 GF(
"ALREADY CONNECT"));
416 int modemSend(
const void* buff,
size_t len, uint8_t mux)
418 sendAT(GF(
"+CIPSEND="), mux,
',', len);
419 if (waitResponse(GF(
">")) != 1) {
422 stream.write((uint8_t*)buff, len);
424 if (waitResponse(10000L, GF(GSM_NL
"SEND OK" GSM_NL)) != 1) {
430 bool modemGetConnected(uint8_t mux)
433 sendAT(GF(
"+CIPSTATUS="), mux);
434 int res1 = waitResponse(3000, GF(
"STATUS:"));
437 res2 = waitResponse(GFP(GSM_ERROR), GF(
"2"), GF(
"3"), GF(
"4"), GF(
"5"));
445 if (res2 == 2 || res2 == 3 || res2 == 4) {
457 void streamWrite(T
last)
462 template<
typename T,
typename... Args>
463 void streamWrite(T head, Args... tail)
466 streamWrite(tail...);
469 bool streamSkipUntil(
char c)
472 while (!stream.available()) {
475 if (stream.read() == c) {
482 template<
typename... Args>
483 void sendAT(Args... cmd)
485 streamWrite(
"AT", cmd..., GSM_NL);
492 uint8_t waitResponse(uint32_t timeout, String&
data,
493 GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
494 GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
504 unsigned long startMillis = millis();
507 while (stream.available() > 0) {
508 int a = stream.read();
513 if (r1 &&
data.endsWith(r1)) {
516 }
else if (r2 &&
data.endsWith(r2)) {
519 }
else if (r3 &&
data.endsWith(r3)) {
522 }
else if (r4 &&
data.endsWith(r4)) {
525 }
else if (r5 &&
data.endsWith(r5)) {
528 }
else if (
data.endsWith(GF(GSM_NL
"+IPD,"))) {
529 int mux = stream.readStringUntil(
',').toInt();
530 int len = stream.readStringUntil(
':').toInt();
532 if (len > sockets[mux]->rx.free()) {
533 DBG(
"### Buffer overflow: ", len,
"->", sockets[mux]->rx.free());
535 DBG(
"### Got: ", len,
"->", sockets[mux]->rx.free());
538 while (!stream.available()) {
541 sockets[mux]->rx.put(stream.read());
543 if (len_orig > sockets[mux]->available()) {
544 DBG(
"### Fewer characters received than expected: ", sockets[mux]->available(),
" vs ", len_orig);
547 }
else if (
data.endsWith(GF(
"CLOSED"))) {
548 int muxStart =
max(0,
data.lastIndexOf(GSM_NL,
data.length()-8));
549 int coma =
data.indexOf(
',', muxStart);
550 int mux =
data.substring(muxStart, coma).toInt();
551 if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
552 sockets[mux]->sock_connected =
false;
555 DBG(
"### Closed: ", mux);
558 }
while (millis() - startMillis < timeout);
563 DBG(
"### Unhandled:",
data);
570 uint8_t waitResponse(uint32_t timeout,
571 GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
572 GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
575 return waitResponse(timeout,
data, r1, r2, r3, r4, r5);
578 uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
579 GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
581 return waitResponse(1000, r1, r2, r3, r4, r5);
588 GsmClient* sockets[TINY_GSM_MUX_COUNT];