From 4ba8306880ba5da727d69581ce60339030349524 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Mon, 20 May 2019 09:21:08 -0400 Subject: [PATCH] Implement connect with timeout, XBee improvements --- .travis.yml | 40 ++--- src/TinyGsmClientA6.h | 15 +- src/TinyGsmClientBG96.h | 16 +- src/TinyGsmClientESP8266.h | 19 ++- src/TinyGsmClientM590.h | 10 +- src/TinyGsmClientM95.h | 16 +- src/TinyGsmClientMC60.h | 16 +- src/TinyGsmClientSIM7000.h | 16 +- src/TinyGsmClientSIM800.h | 16 +- src/TinyGsmClientSaraR4.h | 16 +- src/TinyGsmClientSequansMonarch.h | 28 ++- src/TinyGsmClientUBLOX.h | 16 +- src/TinyGsmClientXBee.h | 275 +++++++++++++++++------------- src/TinyGsmCommon.h | 12 +- 14 files changed, 275 insertions(+), 236 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4399f45..4e2ef4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,33 +18,19 @@ env: - PLATFORMIO_CI_SRC=tools/FactoryReset # Arduino test - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M95' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_MC60' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM808' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7000' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SARAR4' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - # - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SEQUANS_MONARCH' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" - - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M95' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_MC60' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM808' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7000' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SARAR4' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" - - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SEQUANS_MONARCH' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M95' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_MC60' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM808' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7000' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SARAR4' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" + - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SEQUANS_MONARCH' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev" # Energia test - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=energia' --board=lplm4f120h5qr" diff --git a/src/TinyGsmClientA6.h b/src/TinyGsmClientA6.h index 42f5265..1883145 100644 --- a/src/TinyGsmClientA6.h +++ b/src/TinyGsmClientA6.h @@ -66,12 +66,12 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); uint8_t newMux = -1; - sock_connected = at->modemConnect(host, port, &newMux); + sock_connected = at->modemConnect(host, port, &newMux, timeout) if (sock_connected) { mux = newMux; at->sockets[mux] = this; @@ -79,7 +79,7 @@ public: return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -504,15 +504,16 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t* mux) { - sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port); + bool modemConnect(const char* host, uint16_t port, uint8_t* mux, int timeout = 75000L) { + unsigned long startMillis = millis(); - if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { + sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port); + if (waitResponse(timeout, GF(GSM_NL "+CIPNUM:")) != 1) { return false; } int newMux = stream.readStringUntil('\n').toInt(); - int rsp = waitResponse(75000L, + int rsp = waitResponse((timeout - (millis() - startMillis)), GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL), GF("ALREADY CONNECT" GSM_NL)); diff --git a/src/TinyGsmClientBG96.h b/src/TinyGsmClientBG96.h index 49e4427..00c7543 100644 --- a/src/TinyGsmClientBG96.h +++ b/src/TinyGsmClientBG96.h @@ -71,15 +71,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -134,11 +134,11 @@ private: // {} // // public: -// virtual int connect(const char *host, uint16_t port) { +// virtual int connect(const char *host, uint16_t port, int timeout) { // stop(); // TINY_GSM_YIELD(); // rx.clear(); -// sock_connected = at->modemConnect(host, port, mux, true); +// sock_connected = at->modemConnect(host, port, mux, true, timeout); // return sock_connected; // } // }; @@ -470,14 +470,16 @@ TINY_GSP_MODEM_GET_GPRS_IP_CONNECTED() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 20000L) + { int rsp; // (1-16), (0-11),"TCP/UDP/TCP LISTENER/UDP SERVICE", // "/",,,(0-2 0=buffer) sendAT(GF("+QIOPEN=1,"), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",0,0")); rsp = waitResponse(); - if (waitResponse(20000L, GF(GSM_NL "+QIOPEN:")) != 1) { + if (waitResponse(timeout, GF(GSM_NL "+QIOPEN:")) != 1) { return false; } diff --git a/src/TinyGsmClientESP8266.h b/src/TinyGsmClientESP8266.h index 685493d..77737fc 100644 --- a/src/TinyGsmClientESP8266.h +++ b/src/TinyGsmClientESP8266.h @@ -68,15 +68,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -118,11 +118,11 @@ public: {} public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux, true); + sock_connected = at->modemConnect(host, port, mux, true, timeout); return sock_connected; } }; @@ -331,14 +331,17 @@ TINY_GSM_MODEM_MAINTAIN_LISTEN() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 75000L) + { if (ssl) { sendAT(GF("+CIPSSLSIZE=4096")); waitResponse(); } - sendAT(GF("+CIPSTART="), mux, ',', ssl ? GF("\"SSL") : GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE); + sendAT(GF("+CIPSTART="), mux, ',', ssl ? GF("\"SSL") : GF("\"TCP"), + GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE); // TODO: Check mux - int rsp = waitResponse(75000L, + int rsp = waitResponse(timeout, GFP(GSM_OK), GFP(GSM_ERROR), GF("ALREADY CONNECT")); diff --git a/src/TinyGsmClientM590.h b/src/TinyGsmClientM590.h index 2530525..941c462 100644 --- a/src/TinyGsmClientM590.h +++ b/src/TinyGsmClientM590.h @@ -68,16 +68,16 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -413,12 +413,12 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, int timeout = 75000L) { for (int i=0; i<3; i++) { // TODO: no need for loop? String ip = dnsIpQuery(host); sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); - int rsp = waitResponse(75000L, + int rsp = waitResponse(timeout, GF(",OK" GSM_NL), GF(",FAIL" GSM_NL), GF("+TCPSETUP:Error" GSM_NL)); diff --git a/src/TinyGsmClientM95.h b/src/TinyGsmClientM95.h index 87dc3e0..e45bc46 100644 --- a/src/TinyGsmClientM95.h +++ b/src/TinyGsmClientM95.h @@ -71,15 +71,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -134,11 +134,11 @@ private: // {} // // public: -// virtual int connect(const char *host, uint16_t port) { +// virtual int connect(const char *host, uint16_t port, int timeout) { // stop(); // TINY_GSM_YIELD(); // rx.clear(); -// sock_connected = at->modemConnect(host, port, mux, true); +// sock_connected = at->modemConnect(host, port, mux, true, timeout); // return sock_connected; // } // }; @@ -518,9 +518,11 @@ TINY_GSP_MODEM_GET_GPRS_IP_CONNECTED() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 75000L) + { sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port); - int rsp = waitResponse(75000L, + int rsp = waitResponse(timeout, GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL), GF("ALREADY CONNECT" GSM_NL)); diff --git a/src/TinyGsmClientMC60.h b/src/TinyGsmClientMC60.h index 0157f53..0135942 100644 --- a/src/TinyGsmClientMC60.h +++ b/src/TinyGsmClientMC60.h @@ -75,15 +75,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -138,11 +138,11 @@ private: // {} // // public: -// virtual int connect(const char *host, uint16_t port) { +// virtual int connect(const char *host, uint16_t port, int timeout) { // stop(); // TINY_GSM_YIELD(); // rx.clear(); -// sock_connected = at->modemConnect(host, port, mux, true); +// sock_connected = at->modemConnect(host, port, mux, true, timeout); // return sock_connected; // } // }; @@ -537,9 +537,11 @@ TINY_GSP_MODEM_GET_GPRS_IP_CONNECTED() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 75000L) + { sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port); - int rsp = waitResponse(75000L, + int rsp = waitResponse(timeout, GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL), GF("ALREADY CONNECT" GSM_NL)); diff --git a/src/TinyGsmClientSIM7000.h b/src/TinyGsmClientSIM7000.h index 3abeae3..322ce4a 100644 --- a/src/TinyGsmClientSIM7000.h +++ b/src/TinyGsmClientSIM7000.h @@ -76,15 +76,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -140,11 +140,11 @@ public: {} public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux, true); + sock_connected = at->modemConnect(host, port, mux, true, timeout); return sock_connected; } }; @@ -760,10 +760,12 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 75000L) + { int rsp; sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - rsp = waitResponse(75000L, + rsp = waitResponse(timeout, GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL), GF("ALREADY CONNECT" GSM_NL), diff --git a/src/TinyGsmClientSIM800.h b/src/TinyGsmClientSIM800.h index 6a6fd51..e366d86 100644 --- a/src/TinyGsmClientSIM800.h +++ b/src/TinyGsmClientSIM800.h @@ -77,15 +77,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -141,11 +141,11 @@ public: {} public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux, true); + sock_connected = at->modemConnect(host, port, mux, true, timeout); return sock_connected; } }; @@ -681,7 +681,9 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 75000L) + { int rsp; #if !defined(TINY_GSM_MODEM_SIM900) sendAT(GF("+CIPSSL="), ssl); @@ -691,7 +693,7 @@ protected: } #endif sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - rsp = waitResponse(75000L, + rsp = waitResponse(timeout, GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL), GF("ALREADY CONNECT" GSM_NL), diff --git a/src/TinyGsmClientSaraR4.h b/src/TinyGsmClientSaraR4.h index 8f628fc..00b6ffc 100644 --- a/src/TinyGsmClientSaraR4.h +++ b/src/TinyGsmClientSaraR4.h @@ -72,7 +72,7 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); // If we're creating a new connection on the same client, we need to wait // until the async close has finished on Cat-M modems. @@ -94,7 +94,7 @@ public: rx.clear(); uint8_t oldMux = mux; - sock_connected = at->modemConnect(host, port, &mux); + sock_connected = at->modemConnect(host, port, &mux, timeout); if (mux != oldMux) { DBG("WARNING: Mux number changed from", oldMux, "to", mux); at->sockets[oldMux] = NULL; @@ -105,7 +105,7 @@ public: return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -159,12 +159,12 @@ public: {} public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); uint8_t oldMux = mux; - sock_connected = at->modemConnect(host, port, &mux, true); + sock_connected = at->modemConnect(host, port, &mux, true, timeout); if (mux != oldMux) { DBG("WARNING: Mux number changed from", oldMux, "to", mux); at->sockets[oldMux] = NULL; @@ -528,7 +528,9 @@ TINY_GSP_MODEM_GET_GPRS_IP_CONNECTED() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t* mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t* mux, + bool ssl = false, int timeout = 120000L) + { sendAT(GF("+USOCR=6")); // create a socket if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { // reply is +USOCR: ## of socket created return false; @@ -553,7 +555,7 @@ protected: // TODO: Use faster "asynchronous" connection? // We would have to wait for the +UUSOCO URC to verify connection sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port); - int rsp = waitResponse(120000L); + int rsp = waitResponse(timeout); return (1 == rsp); } diff --git a/src/TinyGsmClientSequansMonarch.h b/src/TinyGsmClientSequansMonarch.h index 720653a..c84c081 100644 --- a/src/TinyGsmClientSequansMonarch.h +++ b/src/TinyGsmClientSequansMonarch.h @@ -83,15 +83,15 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { if (sock_connected) stop(); TINY_GSM_YIELD(); rx.clear(); - sock_connected = at->modemConnect(host, port, mux); + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -150,7 +150,7 @@ protected: bool strictSSL = false; public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); @@ -172,7 +172,7 @@ public: return false; } - sock_connected = at->modemConnect(host, port, mux, true); + sock_connected = at->modemConnect(host, port, mux, true, timeout); return sock_connected; } @@ -477,8 +477,11 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, + bool ssl = false, int timeout = 75000L) + { int rsp; + unsigned long startMillis = millis(); if (ssl) { // enable SSl and use security profile 1 @@ -496,7 +499,7 @@ protected: waitResponse(); sendAT(GF("+SQNSD="), mux, ",0,", port, ',', GF("\""), host, GF("\""), ",0,0,1"); - rsp = waitResponse(75000L, + rsp = waitResponse((timeout - (millis() - startMillis)), GF("OK" GSM_NL), GF("NO CARRIER" GSM_NL) ); @@ -505,19 +508,10 @@ protected: if (rsp != 1) return rsp; // wait until we get a good status - unsigned long timeout = 5000; - unsigned long startMillis = millis(); bool connected = false; - while (!connected) { + while (!connected && ((millis() - startMillis) < timeout)) { connected = modemGetConnected(mux); - if (connected) { - delay(50); - break; - } delay(100); // socket may be in opening state - if (millis() - startMillis < timeout) { - break; - } } return connected; } diff --git a/src/TinyGsmClientUBLOX.h b/src/TinyGsmClientUBLOX.h index 74c0206..e4235e8 100644 --- a/src/TinyGsmClientUBLOX.h +++ b/src/TinyGsmClientUBLOX.h @@ -72,13 +72,13 @@ public: } public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); uint8_t oldMux = mux; - sock_connected = at->modemConnect(host, port, &mux); + sock_connected = at->modemConnect(host, port, &mux, timeout); if (mux != oldMux) { DBG("WARNING: Mux number changed from", oldMux, "to", mux); at->sockets[oldMux] = NULL; @@ -89,7 +89,7 @@ public: return sock_connected; } -TINY_GSM_CLIENT_CONNECT_TO_IP() +TINY_GSM_CLIENT_CONNECT_OVERLOADS() virtual void stop() { TINY_GSM_YIELD(); @@ -143,12 +143,12 @@ public: {} public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { stop(); TINY_GSM_YIELD(); rx.clear(); uint8_t oldMux = mux; - sock_connected = at->modemConnect(host, port, &mux, true); + sock_connected = at->modemConnect(host, port, &mux, true, timeout); if (mux != oldMux) { DBG("WARNING: Mux number changed from", oldMux, "to", mux); at->sockets[oldMux] = NULL; @@ -511,7 +511,9 @@ TINY_GSP_MODEM_GET_GPRS_IP_CONNECTED() protected: - bool modemConnect(const char* host, uint16_t port, uint8_t* mux, bool ssl = false) { + bool modemConnect(const char* host, uint16_t port, uint8_t* mux, + bool ssl = false, int timeout = 120000L) + { sendAT(GF("+USOCR=6")); // create a socket if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { // reply is +USOCR: ## of socket created return false; @@ -536,7 +538,7 @@ protected: // TODO: Use faster "asynchronous" connection? // We would have to wait for the +UUSOCO URC to verify connection sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port); - int rsp = waitResponse(120000L); + int rsp = waitResponse(timeout); return (1 == rsp); } diff --git a/src/TinyGsmClientXBee.h b/src/TinyGsmClientXBee.h index 63a8003..7e8b19f 100644 --- a/src/TinyGsmClientXBee.h +++ b/src/TinyGsmClientXBee.h @@ -24,6 +24,20 @@ static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; +// Use this to avoid too many entrances and exits from command mode. +// The cellular Bee's often freeze up and won't respond when attempting +// to enter command mode too many times. +#define XBEE_COMMAND_START_DECORATOR(nAttempts, failureReturn) \ + bool wasInCommandMode = inCommandMode; \ + if (!wasInCommandMode) { /* don't re-enter command mode if already in it */ \ + if (!commandMode(nAttempts)) return failureReturn; /* Return immediately if fails */ \ + } +#define XBEE_COMMAND_END_DECORATOR \ + if (!wasInCommandMode) { /* only exit if we weren't in command mode */ \ + exitCommand(); \ + } + + enum SimStatus { SIM_ERROR = 0, SIM_READY = 1, @@ -77,31 +91,30 @@ public: } public: - // NOTE: The XBee saves all paramter information in flash. When you turn it - // on it immediately prepares to re-connect to whatever was last connected to. - // All the modemConnect() function does is tell it the paramters to put into - // flash. The connection itself is not opened until you attempt to send data. + // NOTE: The XBee saves all connection information (ssid/pwd or apn AND last used IP address) + // in flash (NVM). When you turn it on it immediately prepares to re-connect to whatever was + // last set. The TCP connection itself is not opened until you attempt to send data. // Because all settings are saved to flash, it is possible (or likely) that - // you could send out data even if you haven't "made" any connection. - virtual int connect(const char *host, uint16_t port) { + // you could send data even if you haven't "made" any connection. + virtual int connect(const char *host, uint16_t port, int timeout) { + // NOTE: Not caling stop() or yeild() here at->streamClear(); // Empty anything in the buffer before starting - if (at->commandMode()) { // Don't try if we didn't successfully get into command mode - sock_connected = at->modemConnect(host, port, mux, false); - at->writeChanges(); - at->exitCommand(); - } + sock_connected = at->modemConnect(host, port, mux, timeout); return sock_connected; } + virtual int connect(const char *host, uint16_t port) { + return connect(host, port, 75000L); + } - virtual int connect(IPAddress ip, uint16_t port) { + virtual int connect(IPAddress ip, uint16_t port, int timeout) { + // NOTE: Not caling stop() or yeild() here at->streamClear(); // Empty anything in the buffer before starting - if (at->commandMode()) { // Don't try if we didn't successfully get into command mode - sock_connected = at->modemConnect(ip, port, mux, false); - at->writeChanges(); - at->exitCommand(); - } + sock_connected = at->modemConnect(ip, port, mux, timeout); return sock_connected; } + virtual int connect(IPAddress ip, uint16_t port) { + return connect(ip, port, 75000L); + } virtual void stop() { at->streamClear(); // Empty anything in the buffer @@ -196,12 +209,6 @@ public: if (available()) { return true; } - // Double check that we don't know it's closed - // NOTE: modemGetConnected() is likely to return a "false" true because - // it will return unknown until after data is sent over the connection. - // If the socket is definitely closed, modemGetConnected() will set - // sock_connected to false; - at->modemGetConnected(); return sock_connected; } virtual operator bool() { return connected(); } @@ -230,23 +237,17 @@ public: {} public: - virtual int connect(const char *host, uint16_t port) { + virtual int connect(const char *host, uint16_t port, int timeout) { + // NOTE: Not caling stop() or yeild() here at->streamClear(); // Empty anything in the buffer before starting - if (at->commandMode()) { // Don't try if we didn't successfully get into command mode - sock_connected = at->modemConnect(host, port, mux, true); - at->writeChanges(); - at->exitCommand(); - } + sock_connected = at->modemConnect(host, port, mux, true, timeout); return sock_connected; } - virtual int connect(IPAddress ip, uint16_t port) { + virtual int connect(IPAddress ip, uint16_t port, int timeout) { + // NOTE: Not caling stop() or yeild() here at->streamClear(); // Empty anything in the buffer before starting - if (at->commandMode()) { // Don't try if we didn't successfully get into command mode - sock_connected = at->modemConnect(ip, port, mux, false); - at->writeChanges(); - at->exitCommand(); - } + sock_connected = at->modemConnect(ip, port, mux, timeout); return sock_connected; } }; @@ -294,20 +295,26 @@ public: digitalWrite(resetPin, HIGH); } - if (!commandMode(10)) return false; // Try up to 10 times for the init + XBEE_COMMAND_START_DECORATOR(10, false) sendAT(GF("AP0")); // Put in transparent mode bool ret_val = waitResponse() == 1; - ret_val &= writeChanges(); sendAT(GF("GT64")); // shorten the guard time to 100ms - ret_val &= waitResponse(); - ret_val &= writeChanges(); + ret_val &= waitResponse() == 1; if (ret_val) guardTime = 110; + // Make sure the command mode drop-out time is long enough that we won't fall + // out of command mode without intentionally leaving it. This is the default + // drop out time of 0x64 x 100ms (10 seconds) + sendAT(GF("CT64")); + ret_val &= waitResponse() == 1; + ret_val &= writeChanges(); + getSeries(); // Get the "Hardware Series"; - exitCommand(); + XBEE_COMMAND_END_DECORATOR + return ret_val; } @@ -316,7 +323,7 @@ public: } void setBaud(unsigned long baud) { - if (!commandMode()) return; + XBEE_COMMAND_START_DECORATOR(5, ) switch(baud) { case 2400: sendAT(GF("BD1")); break; @@ -337,7 +344,7 @@ public: } waitResponse(); writeChanges(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR } bool testAT(unsigned long timeout = 10000L) { @@ -352,9 +359,8 @@ public: sendAT(); if (waitResponse(200) == 1) { success = true; - exitCommand(); } - // if we didn't respond to the AT, must not be in command mode + // if we didn't respond to the AT, assume we're not in command mode else inCommandMode = false; } delay(250); @@ -375,11 +381,11 @@ public: } bool factoryDefault() { - if (!commandMode()) return false; // Return immediately + XBEE_COMMAND_START_DECORATOR(5, false) sendAT(GF("RE")); bool ret_val = waitResponse() == 1; ret_val &= writeChanges(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR // Make sure the guard time for the modem object is set back to default // otherwise communication would fail after the reset guardTime = 1010; @@ -387,14 +393,7 @@ public: } String getModemInfo() { - String modemInf = ""; - if (!commandMode()) return modemInf; // Try up to 10 times for the init - - sendAT(GF("HS")); // Get the "Hardware Series" - modemInf += readResponseString(); - - exitCommand(); - return modemInf; + return sendATGetString(GF("HS")); } bool hasSSL() { @@ -443,7 +442,9 @@ public: } bool restart() { + if (!commandMode()) return false; // Return immediately + if (beeType == XBEE_UNKNOWN) getSeries(); // how we restart depends on this if (beeType != XBEE_S6B_WIFI) { @@ -455,9 +456,10 @@ public: sendAT(GF("FR")); if (waitResponse() != 1) return exitAndFail(); + else inCommandMode = false; // Reset effectively exits command mode if (beeType == XBEE_S6B_WIFI) delay(2000); // Wifi module actually resets about 2 seconds later - else delay(100); // cellular modules wait 100ms before reset happes + else delay(100); // cellular modules wait 100ms before reset happens // Wait until reboot complete and responds to command mode call again for (unsigned long start = millis(); millis() - start < 60000L; ) { @@ -477,7 +479,7 @@ public: } void setupPinSleep(bool maintainAssociation = false) { - if (!commandMode()) return; // Return immediately + XBEE_COMMAND_START_DECORATOR(5, ) if (beeType == XBEE_UNKNOWN) getSeries(); // Command depends on series @@ -496,7 +498,7 @@ public: } writeChanges(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR } bool poweroff() { // Not supported @@ -516,19 +518,11 @@ public: } String getSimCCID() { - if (!commandMode()) return ""; // Return immediately - sendAT(GF("S#")); - String res = readResponseString(); - exitCommand(); - return res; + return sendATGetString(GF("S#")); } String getIMEI() { - if (!commandMode()) return ""; // Return immediately - sendAT(GF("IM")); - String res = readResponseString(); - exitCommand(); - return res; + return sendATGetString(GF("IM")); } SimStatus getSimStatus(unsigned long timeout = 10000L) { @@ -537,10 +531,7 @@ public: RegStatus getRegistrationStatus() { - bool wasInCommandMode = inCommandMode; - if (!wasInCommandMode) { // don't re-enter command mode if already in it - commandMode(); - } + XBEE_COMMAND_START_DECORATOR(5, REG_UNKNOWN) if (!inCommandMode) return REG_UNKNOWN; // Return immediately @@ -619,18 +610,12 @@ public: } } - if (!wasInCommandMode) { // only exit if we weren't in command mode - exitCommand(); - } + XBEE_COMMAND_END_DECORATOR return stat; } String getOperator() { - if (!commandMode()) return ""; // Return immediately - sendAT(GF("MN")); - String res = readResponseString(); - exitCommand(); - return res; + return sendATGetString(GF("MN")); } /* @@ -638,12 +623,17 @@ public: */ int16_t getSignalQuality() { - if (!commandMode()) return 0; // Return immediately + + XBEE_COMMAND_START_DECORATOR(5, 0); + if (beeType == XBEE_UNKNOWN) getSeries(); // Need to know what type of bee so we know how to ask + if (beeType == XBEE_S6B_WIFI) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity else sendAT(GF("DB")); // ask for the cell strength in dBm int16_t intRes = readResponseInt(); - exitCommand(); + + XBEE_COMMAND_END_DECORATOR + if (beeType == XBEE3_LTEM_ATT && intRes == 105) intRes = 0; // tends to reply with "69" when signal is unknown if (beeType == XBEE_S6B_WIFI) return -93 + intRes; // the maximum sensitivity is -93dBm else return -1*intRes; // need to convert to negative number @@ -655,17 +645,14 @@ public: } bool waitForNetwork(unsigned long timeout = 60000L) { - // Enter command mode at the start so we don't have to go in and out of it - // The cellular Bee's often freeze up and won't respond when attempting - // to enter command mode too many times. - commandMode(); + XBEE_COMMAND_START_DECORATOR(5, false) for (unsigned long start = millis(); millis() - start < timeout; ) { if (isNetworkConnected()) { return true; } delay(250); // per Neil H. - more stable with delay } - exitCommand(); + XBEE_COMMAND_END_DECORATOR return false; } @@ -675,7 +662,8 @@ public: bool networkConnect(const char* ssid, const char* pwd) { - if (!commandMode()) return false; // return immediately + XBEE_COMMAND_START_DECORATOR(5, false) + //nh For no pwd don't set setscurity or pwd if (NULL == ssid ) return exitAndFail(); @@ -693,19 +681,19 @@ public: if (waitResponse() != 1) return exitAndFail(); if (!writeChanges()) return exitAndFail(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR return true; } bool networkDisconnect() { - if (!commandMode()) return false; // return immediately + XBEE_COMMAND_START_DECORATOR(5, false) sendAT(GF("NR0")); // Do a network reset in order to disconnect - // NOTE: On wifi modules, using a network reset will not + // WARNING: On wifi modules, using a network reset will not // allow the same ssid to re-join without rebooting the module. int8_t res = (1 == waitResponse(5000)); writeChanges(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR return res; } @@ -714,12 +702,12 @@ public: */ String getLocalIP() { - if (!commandMode()) return ""; // Return immediately + XBEE_COMMAND_START_DECORATOR(5, "") sendAT(GF("MY")); String IPaddr; IPaddr.reserve(16); // wait for the response - this response can be very slow IPaddr = readResponseString(30000); - exitCommand(); + XBEE_COMMAND_END_DECORATOR IPaddr.trim(); return IPaddr; } @@ -733,23 +721,23 @@ public: */ bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { - if (!commandMode()) return false; // Return immediately + XBEE_COMMAND_START_DECORATOR(5, false) sendAT(GF("AN"), apn); // Set the APN - waitResponse(); + bool success = waitResponse() == 1; writeChanges(); - exitCommand(); - return true; + XBEE_COMMAND_END_DECORATOR + return success; } bool gprsDisconnect() { - if (!commandMode()) return false; // return immediately + XBEE_COMMAND_START_DECORATOR(5, false) sendAT(GF("AM1")); // Cheating and disconnecting by turning on airplane mode int8_t res = (1 == waitResponse(5000)); writeChanges(); sendAT(GF("AM0")); // Airplane mode off waitResponse(5000); writeChanges(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR return res; } @@ -772,11 +760,14 @@ public: if (waitResponse() !=1) return exitAndFail(); sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriage return) if (waitResponse() !=1) return exitAndFail(); - if (!writeChanges()) return exitAndFail(); + if (!writeChanges()) return exitAndFail(); + // Get out of command mode to actually send the text exitCommand(); + streamWrite(text); stream.write((char)0x0D); // close off with the carriage return + return true; } @@ -800,16 +791,17 @@ public: protected: - IPAddress getHostIP(const char* host) { + IPAddress getHostIP(const char* host, int timeout = 45000L) { String strIP; strIP.reserve(16); unsigned long startMillis = millis(); bool gotIP = false; + XBEE_COMMAND_START_DECORATOR(5, IPAddress(0,0,0,0)) // XBee's require a numeric IP address for connection, but do provide the // functionality to look up the IP address from a fully qualified domain name - while (millis() - startMillis < 45000L) // the lookup can take a while + while (millis() - startMillis < timeout) // the lookup can take a while { sendAT(GF("LA"), host); - while (stream.available() < 4 && (millis() - startMillis < 45000L)) {}; // wait for any response + while (stream.available() < 4 && (millis() - startMillis < timeout)) {}; // wait for any response strIP = stream.readStringUntil('\r'); // read result strIP.trim(); if (!strIP.endsWith(GF("ERROR"))) { @@ -818,33 +810,44 @@ protected: } delay(2500); // wait a bit before trying again } - if (gotIP) { // No reason to continue if we don't know the IP address + + XBEE_COMMAND_END_DECORATOR + + if (gotIP) { return TinyGsmIpFromString(strIP); } else return IPAddress(0,0,0,0); } - bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) { - // If requested host is the same as the previous one and we already - // have a valid IP address, we don't have to do anything. - if (this->savedHost == String(host) && savedIP != IPAddress(0,0,0,0)) { - return true; + bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, + bool ssl = false, int timeout = 75000L) + { + unsigned long startMillis = millis(); + bool retVal = false; + XBEE_COMMAND_START_DECORATOR(5, false) + + // If it's a new host or we dont' have a good IP, we need to do a DNS + // search for the IP to connect to + if (this->savedHost != String(host) || savedIP == IPAddress(0,0,0,0)) { + this->savedHost = String(host); + savedIP = getHostIP(host, timeout); // This will return 0.0.0.0 if lookup fails } - // Otherwise, set the new host and mark the IP as invalid - this->savedHost = String(host); - savedIP = getHostIP(host); // This will return 0.0.0.0 if lookup fails - // If we now have a valid IP address, use it to connect if (savedIP != IPAddress(0,0,0,0)) { // Only re-set connection information if we have an IP address - return modemConnect(savedIP, port, mux, ssl); + retVal = modemConnect(savedIP, port, mux, ssl, timeout - (millis() - startMillis)); } - else return false; + + XBEE_COMMAND_END_DECORATOR + + return retVal; } - bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) { + bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false, int timeout = 75000L) { + savedIP = ip; // Set the newly requested IP address bool success = true; + XBEE_COMMAND_START_DECORATOR(5, false) String host; host.reserve(16); host += ip[0]; host += "."; @@ -853,6 +856,7 @@ protected: host += ip[2]; host += "."; host += ip[3]; + if (ssl) { sendAT(GF("IP"), 4); // Put in SSL over TCP communication mode success &= (1 == waitResponse()); @@ -860,10 +864,21 @@ protected: sendAT(GF("IP"), 1); // Put in TCP mode success &= (1 == waitResponse()); } + sendAT(GF("DL"), host); // Set the "Destination Address Low" success &= (1 == waitResponse()); sendAT(GF("DE"), String(port, HEX)); // Set the destination port success &= (1 == waitResponse()); + + for (unsigned long start = millis(); millis() - start < timeout; ) { + if (modemGetConnected()) { + sockets[mux]->sock_connected = true; + break; + } + } + + XBEE_COMMAND_END_DECORATOR + return success; } @@ -879,7 +894,7 @@ protected: // as true so there's a possibility it's wrong. bool modemGetConnected() { - if (!commandMode()) return false; // Return immediately + XBEE_COMMAND_START_DECORATOR(5, false) // If the IP address is 0, it's not valid so we can't be connected if (savedIP == IPAddress(0,0,0,0)) return false; @@ -898,14 +913,14 @@ protected: case XBEE_S6B_WIFI: { RegStatus s = getRegistrationStatus(); if (s != REG_OK) { - sockets[0]->sock_connected = false; + sockets[0]->sock_connected = false; // no multiplex } return (s == REG_OK); // if it's connected, we hope the sockets are too } default: { // Cellular XBee's sendAT(GF("CI")); int16_t intRes = readResponseInt(); - exitCommand(); + XBEE_COMMAND_END_DECORATOR switch(intRes) { case 0x00: // 0x00 = The socket is definitely open case 0xFF: // 0xFF = No known status - this is always returned prior to sending data @@ -1014,10 +1029,15 @@ finish: } bool commandMode(uint8_t retries = 5) { + + // If we're already in command mode, move on + if (inCommandMode && (millis() - lastCommandModeMillis) < 10000L) return true; + uint8_t triesMade = 0; uint8_t triesUntilReset = 4; // only reset after 4 failures bool success = false; streamClear(); // Empty everything in the buffer before starting + while (!success and triesMade < retries) { // Cannot send anything for 1 "guard time" before entering command mode // Default guard time is 1s, but the init fxn decreases it to 100 ms @@ -1036,7 +1056,11 @@ finish: } triesMade ++; } - if (success) inCommandMode = true; + + if (success) { + inCommandMode = true; + lastCommandModeMillis = millis(); + } return success; } @@ -1049,6 +1073,8 @@ finish: } void exitCommand(void) { + // NOTE: Here we explicitely try to exit command mode + // even if the internal flag inCommandMode was already false sendAT(GF("CN")); // Exit command mode waitResponse(); inCommandMode = false; @@ -1083,6 +1109,14 @@ finish: return intRes; } + String sendATGetString(GsmConstStr cmd) { + XBEE_COMMAND_START_DECORATOR(5, "") + sendAT(cmd); + String res = readResponseString(); + XBEE_COMMAND_END_DECORATOR + return res; + } + bool gotIPforSavedHost() { if (savedHost != "" && savedIP != IPAddress(0,0,0,0)) return true; else return false; @@ -1098,6 +1132,7 @@ protected: IPAddress savedIP; String savedHost; bool inCommandMode; + uint32_t lastCommandModeMillis; GsmClient* sockets[TINY_GSM_MUX_COUNT]; }; diff --git a/src/TinyGsmCommon.h b/src/TinyGsmCommon.h index 70667e5..29dd28c 100644 --- a/src/TinyGsmCommon.h +++ b/src/TinyGsmCommon.h @@ -201,8 +201,8 @@ String TinyGsmDecodeHex16bit(String &instr) { // Connect to a IP address given as an IPAddress object by // converting said IP address to text -#define TINY_GSM_CLIENT_CONNECT_TO_IP() \ - virtual int connect(IPAddress ip, uint16_t port) { \ +#define TINY_GSM_CLIENT_CONNECT_OVERLOADS() \ + virtual int connect(IPAddress ip, uint16_t port, int timeout) { \ String host; host.reserve(16); \ host += ip[0]; \ host += "."; \ @@ -211,7 +211,13 @@ String TinyGsmDecodeHex16bit(String &instr) { host += ip[2]; \ host += "."; \ host += ip[3]; \ - return connect(host.c_str(), port); \ + return connect(host.c_str(), port, timeout); \ + } \ + virtual int connect(const char *host, uint16_t port) \ + return connect(host, port, 75000L); \ + } \ + virtual int connect(IPAddress ip, uint16_t port) \ + return connect(ip, port, 75000L); \ }