Moved bulk of WaitResponse to modem template and gave modems handleURCs fxn

Signed-off-by: Sara Damiano <sdamiano@stroudcenter.org>
This commit is contained in:
Sara Damiano
2024-04-11 16:16:25 -04:00
parent 56305cb1a4
commit f1f924fef1
20 changed files with 714 additions and 1833 deletions

1
.gitignore vendored
View File

@@ -47,3 +47,4 @@ extras/At Command Manuals - Unsupported/*
filters/*
platformio_extra_envs.ini
*.tar.gz
pioScripts/generate_compile_commands.py

View File

@@ -451,115 +451,37 @@ class TinyGsmA6 : public TinyGsmModem<TinyGsmA6>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+CIPRCV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore(',');
int16_t len_orig = len;
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
} else {
DBG("### Got: ", len, "->", sockets[mux]->rx.free());
}
while (len--) { moveCharFromStreamToFifo(mux); }
// TODO(?) Deal with missing characters
if (len_orig > sockets[mux]->available()) {
DBG("### Fewer characters received than expected: ",
sockets[mux]->available(), " vs ", len_orig);
}
}
data = "";
} else if (data.endsWith(GF("+TCPCLOSED:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
bool handleURCs(String& data) {
if (data.endsWith(GF("+CIPRCV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore(',');
int16_t len_orig = len;
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
// reset the len to read to the amount free
len = sockets[mux]->rx.free();
}
while (len--) { moveCharFromStreamToFifo(mux); }
// TODO(?) Deal with missing characters
if (len_orig != sockets[mux]->available()) {
DBG("### Different number of characters received than expected: ",
sockets[mux]->available(), " vs ", len_orig);
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
DBG("### Got Data: ", len_orig, "on", mux);
return true;
} else if (data.endsWith(GF("+TCPCLOSED:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -603,110 +603,30 @@ class TinyGsmBG96 : public TinyGsmModem<TinyGsmBG96>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+QIURC:"))) {
streamSkipUntil('\"');
String urc = stream.readStringUntil('\"');
streamSkipUntil(',');
if (urc == "recv") {
int8_t mux = streamGetIntBefore('\n');
DBG("### URC RECV:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
} else if (urc == "closed") {
int8_t mux = streamGetIntBefore('\n');
DBG("### URC CLOSE:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
} else {
streamSkipUntil('\n');
}
data = "";
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+QIURC:"))) {
streamSkipUntil('\"');
String urc = stream.readStringUntil('\"');
streamSkipUntil(',');
if (urc == "recv") {
int8_t mux = streamGetIntBefore('\n');
DBG("### URC RECV:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
} else if (urc == "closed") {
int8_t mux = streamGetIntBefore('\n');
DBG("### URC CLOSE:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
} else {
streamSkipUntil('\n');
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -24,16 +24,20 @@
static uint8_t TINY_GSM_TCP_KEEP_ALIVE = 120;
// <stat> status of ESP8266 station interface
// 0: ESP8266 station is not initialized.
// 1: ESP8266 station is initialized, but not started a Wi-Fi connection yet.
// 2 : ESP8266 station connected to an AP and has obtained IP
// 3 : ESP8266 station created a TCP or UDP transmission
// 4 : the TCP or UDP transmission of ESP8266 station disconnected
// 5 : ESP8266 station did NOT connect to an AP
enum RegStatus {
REG_OK_IP = 2,
REG_OK_TCP = 3,
REG_OK_NO_TCP = 4,
REG_DENIED = 5,
REG_UNKNOWN = 6,
REG_UNINITIALIZED = 0,
REG_UNREGISTERED = 1,
REG_OK_IP = 2,
REG_OK_TCP = 3,
REG_OK_NO_TCP = 4,
REG_DENIED = 5,
REG_UNKNOWN = 6,
};
class TinyGsmESP8266 : public TinyGsmModem<TinyGsmESP8266>,
@@ -221,9 +225,14 @@ class TinyGsmESP8266 : public TinyGsmModem<TinyGsmESP8266>,
RegStatus getRegistrationStatus() {
sendAT(GF("+CIPSTATUS"));
if (waitResponse(3000, GF("STATUS:")) != 1) return REG_UNKNOWN;
int8_t status = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"),
GF("5"));
waitResponse(); // Returns an OK after the status
// after "STATUS:" it should return the status number (0,1,2,3,4,5),
// followed by an OK
// Since there are more possible status number codes than the arguments for
// waitResponse, we'll capture the response in a string and then parse it.
String res;
if (waitResponse(3000L, res) != 1) { return REG_UNKNOWN; }
res.trim();
int8_t status = res.toInt();
return (RegStatus)status;
}
@@ -342,11 +351,12 @@ class TinyGsmESP8266 : public TinyGsmModem<TinyGsmESP8266>,
bool modemGetConnected(uint8_t mux) {
sendAT(GF("+CIPSTATUS"));
if (waitResponse(3000, GF("STATUS:")) != 1) { return false; }
int8_t status = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"),
GF("5"));
if (status != 3) {
// if the status is anything but 3, there are no connections open
waitResponse(); // Returns an OK after the status
// after "STATUS:" it should return the status number (0,1,2,3,4,5),
// followed by an OK
// Hopefully we'll catch the "3" here, but fall back to the OK or Error
int8_t status = waitResponse(GF("3"), GFP(GSM_OK), GFP(GSM_ERROR));
// if the status is anything but 3, there are no connections open
if (status != 1) {
for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) {
if (sockets[muxNo]) { sockets[muxNo]->sock_connected = false; }
}
@@ -380,96 +390,40 @@ class TinyGsmESP8266 : public TinyGsmModem<TinyGsmESP8266>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR), GsmConstStr r3 = NULL,
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+IPD,"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore(':');
int16_t len_orig = len;
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "received vs",
sockets[mux]->rx.free(), "available");
} else {
// DBG("### Got Data: ", len, "on", mux);
}
while (len--) { moveCharFromStreamToFifo(mux); }
// TODO(SRGDamia1): deal with buffer overflow/missed characters
if (len_orig > sockets[mux]->available()) {
DBG("### Fewer characters received than expected: ",
sockets[mux]->available(), " vs ", len_orig);
}
}
data = "";
} else if (data.endsWith(GF("CLOSED"))) {
int8_t muxStart =
TinyGsmMax(0, data.lastIndexOf(GSM_NL, data.length() - 8));
int8_t coma = data.indexOf(',', muxStart);
int8_t mux = data.substring(muxStart, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
bool handleURCs(String& data) {
if (data.endsWith(GF("+IPD,"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore(':');
int16_t len_orig = len;
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
// reset the len to read to the amount free
len = sockets[mux]->rx.free();
}
while (len--) { moveCharFromStreamToFifo(mux); }
// TODO(SRGDamia1): deal with buffer overflow/missed characters
if (len_orig != sockets[mux]->available()) {
DBG("### Different number of characters received than expected: ",
sockets[mux]->available(), " vs ", len_orig);
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
DBG("### Got Data: ", len_orig, "on", mux);
return true;
} else if (data.endsWith(GF("CLOSED"))) {
int8_t muxStart = TinyGsmMax(0,
data.lastIndexOf(GSM_NL, data.length() - 8));
int8_t coma = data.indexOf(',', muxStart);
int8_t mux = data.substring(muxStart, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR), GsmConstStr r3 = NULL,
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR), GsmConstStr r3 = NULL,
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -343,116 +343,38 @@ class TinyGsmM590 : public TinyGsmModem<TinyGsmM590>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+TCPRECV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore(',');
int16_t len_orig = len;
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
} else {
DBG("### Got: ", len, "->", sockets[mux]->rx.free());
}
while (len--) { moveCharFromStreamToFifo(mux); }
// TODO(?): Handle lost characters
if (len_orig > sockets[mux]->available()) {
DBG("### Fewer characters received than expected: ",
sockets[mux]->available(), " vs ", len_orig);
}
}
data = "";
} else if (data.endsWith(GF("+TCPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
bool handleURCs(String& data) {
if (data.endsWith(GF("+TCPRECV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore(',');
int16_t len_orig = len;
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
// reset the len to read to the amount free
len = sockets[mux]->rx.free();
}
while (len--) { moveCharFromStreamToFifo(mux); }
// TODO(?): Handle lost characters
if (len_orig != sockets[mux]->available()) {
DBG("### Different number of characters received than expected: ",
sockets[mux]->available(), " vs ", len_orig);
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
DBG("### Got Data: ", len_orig, "on", mux);
return true;
} else if (data.endsWith(GF("+TCPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -508,114 +508,36 @@ class TinyGsmM95 : public TinyGsmModem<TinyGsmM95>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+QIRDI:"))) {
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
int8_t mux = streamGetIntBefore('\n');
// DBG("### Got Data:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
// We have no way of knowing how much data actually came in, so
// we set the value to 1500, the maximum possible size.
sockets[mux]->sock_available = 1500;
}
data = "";
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
} else if (data.endsWith(GF("+QNITZ:"))) {
streamSkipUntil('\n'); // URC for time sync
data = "";
DBG("### Network time updated.");
}
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+QIRDI:"))) {
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
int8_t mux = streamGetIntBefore('\n');
// DBG("### Got Data:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
// We have no way of knowing how much data actually came in, so
// we set the value to 1500, the maximum possible size.
sockets[mux]->sock_available = 1500;
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
return true;
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
} else if (data.endsWith(GF("+QNITZ:"))) {
streamSkipUntil('\n'); // URC for time sync
data = "";
DBG("### Network time updated.");
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -481,127 +481,43 @@ class TinyGsmMC60 : public TinyGsmModem<TinyGsmMC60>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
String r6s(r6); r6s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s, ",", r6s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (r6 && data.endsWith(r6)) {
index = 6;
goto finish;
} else if (data.endsWith(
GF(GSM_NL "+QIRDI:"))) { // TODO(?): QIRD? or QIRDI?
// +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
// read the connection id
int8_t mux = streamGetIntBefore(',');
// read the number of packets in the buffer
int8_t num_packets = streamGetIntBefore(',');
// read the length of the current packet
streamSkipUntil(
','); // Skip the length of the current package in the buffer
int16_t len_total =
streamGetIntBefore('\n'); // Total length of all packages
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux] &&
num_packets >= 0 && len_total >= 0) {
sockets[mux]->sock_available = len_total;
}
data = "";
// DBG("### Got Data:", len_total, "on", mux);
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
} else if (data.endsWith(GF("+QNITZ:"))) {
streamSkipUntil('\n'); // URC for time sync
DBG("### Network time updated.");
data = "";
}
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+QIRDI:"))) { // TODO(?): QIRD? or QIRDI?
// +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
// read the connection id
int8_t mux = streamGetIntBefore(',');
// read the number of packets in the buffer
int8_t num_packets = streamGetIntBefore(',');
// read the length of the current packet
streamSkipUntil(
','); // Skip the length of the current package in the buffer
int16_t len_total =
streamGetIntBefore('\n'); // Total length of all packages
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux] &&
num_packets >= 0 && len_total >= 0) {
sockets[mux]->sock_available = len_total;
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
// DBG("### Got Data:", len_total, "on", mux);
return true;
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
} else if (data.endsWith(GF("+QNITZ:"))) {
streamSkipUntil('\n'); // URC for time sync
DBG("### Network time updated.");
data = "";
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5, r6);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5, r6);
return false;
}
public:

View File

@@ -602,125 +602,49 @@ class TinyGsmSim5360 : public TinyGsmModem<TinyGsmSim5360>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
} else {
data += mode;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
// DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("+IPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n'); // Skip the reason code
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
} else if (data.endsWith(GF("+CIPEVENT:"))) {
// Need to close all open sockets and release the network library.
// User will then need to reconnect.
DBG("### Network error!");
if (!isGprsConnected()) { gprsDisconnect(); }
data = "";
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
return true;
} else {
data += mode;
return false;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
// DBG("### Got Data:", len, "on", mux);
return true;
} else if (data.endsWith(GF("+IPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n'); // Skip the reason code
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
} else if (data.endsWith(GF("+CIPEVENT:"))) {
// Need to close all open sockets and release the network library.
// User will then need to reconnect.
DBG("### Network error!");
if (!isGprsConnected()) { gprsDisconnect(); }
data = "";
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -390,141 +390,68 @@ class TinyGsmSim7000 : public TinyGsmSim70xx<TinyGsmSim7000>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
} else {
data += mode;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
// DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
} else if (data.endsWith(GF("DST: "))) {
streamSkipUntil(
'\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
} else if (data.endsWith(GF(GSM_NL "SMS Ready" GSM_NL))) {
data = "";
DBG("### Unexpected module reset!");
init();
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
return true;
} else {
data += mode;
return false;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
// DBG("### Got Data:", len, "on", mux);
return true;
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
return true;
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
return true;
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
return true;
} else if (data.endsWith(GF("DST: "))) {
streamSkipUntil('\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
return true;
} else if (data.endsWith(GF(GSM_NL "SMS Ready" GSM_NL))) {
data = "";
DBG("### Unexpected module reset!");
init();
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
protected:

View File

@@ -588,138 +588,64 @@ class TinyGsmSim7000SSL
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+CARECV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("+CADATAIND:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
DBG("### Got Data:", mux);
} else if (data.endsWith(GF("+CASTATE:"))) {
int8_t mux = streamGetIntBefore(',');
int8_t state = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (state != 1) {
sockets[mux]->sock_connected = false;
DBG("### Closed: ", mux);
}
}
data = "";
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
} else if (data.endsWith(GF("DST: "))) {
streamSkipUntil(
'\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
} else if (data.endsWith(GF(GSM_NL "SMS Ready" GSM_NL))) {
data = "";
DBG("### Unexpected module reset!");
init();
data = "";
bool handleURCs(String& data) {
if (data.endsWith(GF("+CARECV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
DBG("### Got Data:", len, "on", mux);
return true;
} else if (data.endsWith(GF("+CADATAIND:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
DBG("### Got Data:", mux);
return true;
} else if (data.endsWith(GF("+CASTATE:"))) {
int8_t mux = streamGetIntBefore(',');
int8_t state = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (state != 1) {
sockets[mux]->sock_connected = false;
DBG("### Closed: ", mux);
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
return true;
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
return true;
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
return true;
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
return true;
} else if (data.endsWith(GF("DST: "))) {
streamSkipUntil('\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
return true;
} else if (data.endsWith(GF(GSM_NL "SMS Ready" GSM_NL))) {
data = "";
DBG("### Unexpected module reset!");
init();
data = "";
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
protected:

View File

@@ -587,138 +587,64 @@ class TinyGsmSim7080 : public TinyGsmSim70xx<TinyGsmSim7080>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+CARECV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("+CADATAIND:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
DBG("### Got Data:", mux);
} else if (data.endsWith(GF("+CASTATE:"))) {
int8_t mux = streamGetIntBefore(',');
int8_t state = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (state != 1) {
sockets[mux]->sock_connected = false;
DBG("### Closed: ", mux);
}
}
data = "";
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
} else if (data.endsWith(GF("DST: "))) {
streamSkipUntil(
'\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
} else if (data.endsWith(GF(GSM_NL "SMS Ready" GSM_NL))) {
data = "";
DBG("### Unexpected module reset!");
init();
data = "";
bool handleURCs(String& data) {
if (data.endsWith(GF("+CARECV:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
DBG("### Got Data:", len, "on", mux);
return true;
} else if (data.endsWith(GF("+CADATAIND:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
DBG("### Got Data:", mux);
return true;
} else if (data.endsWith(GF("+CASTATE:"))) {
int8_t mux = streamGetIntBefore(',');
int8_t state = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
if (state != 1) {
sockets[mux]->sock_connected = false;
DBG("### Closed: ", mux);
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
return true;
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
return true;
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
return true;
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
return true;
} else if (data.endsWith(GF("DST: "))) {
streamSkipUntil('\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
return true;
} else if (data.endsWith(GF(GSM_NL "SMS Ready" GSM_NL))) {
data = "";
DBG("### Unexpected module reset!");
init();
data = "";
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
protected:

View File

@@ -398,48 +398,8 @@ class TinyGsmSim70xx : public TinyGsmModem<TinyGsmSim70xx<modemType>>,
* Client related functions
*/
// should implement in sub-classes
/*
* Utilities
*/
public:
// should implement in sub-classes
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return thisModem().waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return thisModem().waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return thisModem().waitResponse(1000, r1, r2, r3, r4, r5);
bool handleURCs(String& data) {
return thisModem().handleURCs(data);
}
public:

View File

@@ -727,125 +727,49 @@ class TinyGsmSim7600 : public TinyGsmModem<TinyGsmSim7600>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
} else {
data += mode;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
// DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("+IPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n'); // Skip the reason code
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
} else if (data.endsWith(GF("+CIPEVENT:"))) {
// Need to close all open sockets and release the network library.
// User will then need to reconnect.
DBG("### Network error!");
if (!isGprsConnected()) { gprsDisconnect(); }
data = "";
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
return true;
} else {
data += mode;
return false;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
// DBG("### Got Data:", len, "on", mux);
return true;
} else if (data.endsWith(GF("+IPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n'); // Skip the reason code
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
} else if (data.endsWith(GF("+CIPEVENT:"))) {
// Need to close all open sockets and release the network library.
// User will then need to reconnect.
DBG("### Network error!");
if (!isGprsConnected()) { gprsDisconnect(); }
data = "";
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -620,137 +620,63 @@ class TinyGsmSim800 : public TinyGsmModem<TinyGsmSim800>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
} else {
data += mode;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
// DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
} else if (data.endsWith(GF("DST:"))) {
streamSkipUntil(
'\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
return true;
} else {
data += mode;
return false;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
// DBG("### Got Data:", len, "on", mux);
return true;
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
int8_t coma = data.indexOf(',', nl + 2);
int8_t mux = data.substring(nl + 2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
return true;
} else if (data.endsWith(GF("*PSNWID:"))) {
streamSkipUntil('\n'); // Refresh network name by network
data = "";
DBG("### Network name updated.");
return true;
} else if (data.endsWith(GF("*PSUTTZ:"))) {
streamSkipUntil('\n'); // Refresh time and time zone by network
data = "";
DBG("### Network time and time zone updated.");
return true;
} else if (data.endsWith(GF("+CTZV:"))) {
streamSkipUntil('\n'); // Refresh network time zone by network
data = "";
DBG("### Network time zone updated.");
return true;
} else if (data.endsWith(GF("DST:"))) {
streamSkipUntil('\n'); // Refresh Network Daylight Saving Time by network
data = "";
DBG("### Daylight savings time state updated.");
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -768,116 +768,38 @@ class TinyGsmSaraR4 : public TinyGsmModem<TinyGsmSaraR4>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+UUSORD:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
// max size is 1024
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
DBG("### URC Data Received:", len, "on", mux);
} else if (data.endsWith(GF("+UUSOCL:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### URC Sock Closed: ", mux);
} else if (data.endsWith(GF("+UUSOCO:"))) {
int8_t mux = streamGetIntBefore('\n');
int8_t socket_error = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux] &&
socket_error == 0) {
sockets[mux]->sock_connected = true;
}
data = "";
DBG("### URC Sock Opened: ", mux);
}
bool handleURCs(String& data) {
if (data.endsWith(GF("+UUSORD:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
// max size is 1024
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
DBG("### URC Data Received:", len, "on", mux);
return true;
} else if (data.endsWith(GF("+UUSOCL:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### URC Sock Closed: ", mux);
return true;
} else if (data.endsWith(GF("+UUSOCO:"))) {
int8_t mux = streamGetIntBefore('\n');
int8_t socket_error = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux] &&
socket_error == 0) {
sockets[mux]->sock_connected = true;
}
data = "";
DBG("### URC Sock Opened: ", mux);
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -503,9 +503,10 @@ class TinyGsmSequansMonarch
waitResponse(10000L, GF(GSM_NL "> "));
// Translate bytes into char to be able to send them as an hex string
char char_command[2];
for (size_t i=0; i<len; i++) {
for (size_t i = 0; i < len; i++) {
memset(&char_command, 0, sizeof(char_command));
sprintf(&char_command[0], "%02X", reinterpret_cast<const uint8_t*>(buff)[i]);
sprintf(&char_command[0], "%02X",
reinterpret_cast<const uint8_t*>(buff)[i]);
stream.write(char_command, sizeof(char_command));
}
stream.flush();
@@ -610,108 +611,29 @@ class TinyGsmSequansMonarch
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+SQNSRING:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT &&
sockets[mux % TINY_GSM_MUX_COUNT]) {
sockets[mux % TINY_GSM_MUX_COUNT]->got_data = true;
sockets[mux % TINY_GSM_MUX_COUNT]->sock_available = len;
}
data = "";
DBG("### URC Data Received:", len, "on", mux);
} else if (data.endsWith(GF("SQNSH: "))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT &&
sockets[mux % TINY_GSM_MUX_COUNT]) {
sockets[mux % TINY_GSM_MUX_COUNT]->sock_connected = false;
}
data = "";
DBG("### URC Sock Closed: ", mux);
}
bool handleURCs(String& data) {
if (data.endsWith(GF(GSM_NL "+SQNSRING:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT &&
sockets[mux % TINY_GSM_MUX_COUNT]) {
sockets[mux % TINY_GSM_MUX_COUNT]->got_data = true;
sockets[mux % TINY_GSM_MUX_COUNT]->sock_available = len;
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
DBG("### URC Data Received:", len, "on", mux);
return true;
} else if (data.endsWith(GF("SQNSH: "))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT &&
sockets[mux % TINY_GSM_MUX_COUNT]) {
sockets[mux % TINY_GSM_MUX_COUNT]->sock_connected = false;
}
data = "";
DBG("### URC Sock Closed: ", mux);
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -733,107 +733,28 @@ class TinyGsmUBLOX : public TinyGsmModem<TinyGsmUBLOX>,
* Utilities
*/
public:
// TODO(vshymanskyy): Optimize this!
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF("+UUSORD:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
// max size is 1024
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
data = "";
// DBG("### URC Data Received:", len, "on", mux);
} else if (data.endsWith(GF("+UUSOCL:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### URC Sock Closed: ", mux);
}
bool handleURCs(String& data) {
if (data.endsWith(GF("+UUSORD:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
// max size is 1024
if (len >= 0 && len <= 1024) { sockets[mux]->sock_available = len; }
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
// DBG("### URC Data Received:", len, "on", mux);
return true;
} else if (data.endsWith(GF("+UUSOCL:"))) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### URC Sock Closed: ", mux);
return true;
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
return false;
}
public:

View File

@@ -828,7 +828,8 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
changesMade = true;
}
} else {
changesMade |= changeSettingIfNeeded(GF("EE"), 0x0); // Set No security
changesMade |= changeSettingIfNeeded(GF("EE"),
0x0); // Set No security
}
if (changesMade) { retVal &= writeChanges(); }
@@ -878,7 +879,8 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
changesMade = true;
}
}
changesMade |= changeSettingIfNeeded(GF("AN"), String(apn)); // Set the APN
changesMade |= changeSettingIfNeeded(GF("AN"),
String(apn)); // Set the APN
changesMade |= changeSettingIfNeeded(GF("AM"), 0x0,
5000L); // Airplane mode off
@@ -1029,9 +1031,9 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
0,
};
res.toCharArray(buf, 5);
int8_t intRes = (int8_t)strtol(
buf, 0,
16); // degrees Celsius displayed in 8-bit two's complement format.
int8_t intRes = (int8_t)strtol(buf, 0,
16); // degrees Celsius displayed in
// 8-bit two's complement format.
XBEE_COMMAND_END_DECORATOR
return static_cast<float>(intRes);
}
@@ -1072,9 +1074,9 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
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
// 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
// NOTE: the lookup can take a while
while ((millis() - startMillis) < timeout_ms) {
sendAT(GF("LA"), host);
@@ -1104,8 +1106,8 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
bool retVal = false;
XBEE_COMMAND_START_DECORATOR(5, false)
// If this is a new host name, replace the saved host and wipe out the saved
// host IP
// If this is a new host name, replace the saved host and wipe out the
// saved host IP
if (this->savedHost != String(host)) {
this->savedHost = String(host);
savedHostIP = IPAddress(0, 0, 0, 0);
@@ -1175,7 +1177,8 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
if (changesMade) { success &= writeChanges(); }
}
// confirm the XBee type if needed so we know if we can know if connected
// confirm the XBee type if needed so we know if we can know if
// connected
if (beeType == XBEE_UNKNOWN) { getSeries(); }
// we'll accept either unknown or connected
if (beeType != XBEE_S6B_WIFI) {
@@ -1205,9 +1208,10 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
sendAT(GF("TM"));
String timeoutUsed = readResponseString(5000L);
// For cellular models, per documentation: If you write the TM (socket
// timeout) value while in Transparent Mode, the current connection is
// immediately closed - this works even if the TM values is unchanged
// For cellular models, per documentation: If you write the TM
// (socket timeout) value while in Transparent Mode, the current
// connection is immediately closed - this works even if the TM
// values is unchanged
sendAT(GF("TM"), timeoutUsed); // Re-set socket timeout
waitResponse(maxWaitMs); // This response can be slow
}
@@ -1229,7 +1233,8 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
modemGetConnected(0);
} else if (len > 5) {
// After sending several characters, also re-check
// NOTE: I'm intentionally not checking after every single character!
// NOTE: I'm intentionally not checking after every single
// character!
modemGetConnected(0);
}
}
@@ -1237,10 +1242,11 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
return len;
}
// NOTE: The CI command returns the status of the TCP connection as open only
// after data has been sent on the socket. If it returns 0xFF the socket may
// really be open, but no data has yet been sent. We return this unknown
// value as true so there's a possibility it's wrong.
// NOTE: The CI command returns the status of the TCP connection as
// open only after data has been sent on the socket. If it returns 0xFF
// the socket may really be open, but no data has yet been sent. We
// return this unknown value as true so there's a possibility it's
// wrong.
bool modemGetConnected(uint8_t) {
// 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; }
@@ -1281,11 +1287,12 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
}
// 0x28 = "Unknown."
// 0xFF = No known status - always returned prior to sending data
// 0xFF = No known status - always returned prior to sending
// data
case 0x28:
case 0xFF: {
// If we previously had an operating destination and we no longer
// do, the socket must have closed
// If we previously had an operating destination and we no
// longer do, the socket must have closed
if (od == IPAddress(0, 0, 0, 0) &&
savedOperatingIP != IPAddress(0, 0, 0, 0)) {
savedOperatingIP = od;
@@ -1297,13 +1304,14 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
sockets[0]->stop();
return false;
} else if (od != IPAddress(0, 0, 0, 0) && od == savedIP) {
// else if the operating destination exists and matches, we're
// good to go
// else if the operating destination exists and matches,
// we're good to go
savedOperatingIP = od;
return true;
} else {
// If we never had an operating destination, then sock may be open
// but data never sent - this is the dreaded "we don't know"
// If we never had an operating destination, then sock may
// be open but data never sent - this is the dreaded "we
// don't know"
savedOperatingIP = od;
return true;
}
@@ -1347,8 +1355,8 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
// 0x02 = Invalid parameters (bad IP/host)
// 0x12 = DNS query lookup failure
// 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!)
// fall through
// 0x25 = Unknown server - DNS lookup failed (0x22 for UDP
// socket!) fall through
case 0x02:
case 0x12:
case 0x25: {
@@ -1378,80 +1386,9 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
TINY_GSM_YIELD();
}
}
// TODO(vshymanskyy): Optimize this!
// NOTE: This function is used while INSIDE command mode, so we're only
// waiting for requested responses. The XBee has no unsoliliced responses
// (URC's) when in command mode.
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR), GsmConstStr r3 = NULL,
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(16); // Should never be getting much here for the XBee
int8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
data.replace(GSM_NL GSM_NL, GSM_NL);
data.replace(GSM_NL, "\r\n ");
if (data.length()) {
DBG("### Unhandled:", data, "\r\n");
} else {
DBG("### NO RESPONSE FROM MODEM!\r\n");
}
} else {
data.trim();
data.replace(GSM_NL GSM_NL, GSM_NL);
data.replace(GSM_NL, "\r\n ");
}
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR), GsmConstStr r3 = NULL,
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR), GsmConstStr r3 = NULL,
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
// The XBee has no unsoliliced responses (URC's) when in command mode.
bool handleURCs(String& data) {
return true;
}
bool commandMode(uint8_t retries = 5) {
@@ -1467,8 +1404,9 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>,
streamClear(); // Empty everything in the buffer before starting
while (!success && 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
// 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
delay(guardTime + 10);
streamWrite(GF("+++")); // enter command mode

View File

@@ -48,6 +48,48 @@ class TinyGsmModem {
bool testAT(uint32_t timeout_ms = 10000L) {
return thisModem().testATImpl(timeout_ms);
}
// Listen for responses to commands and handle URCs
int8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL,
GsmConstStr r7 = NULL) {
return thisModem().waitResponseImpl(timeout_ms, data, r1, r2, r3, r4, r5,
r6, r7);
}
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL,
GsmConstStr r7 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5, r6, r7);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL,
GsmConstStr r7 = NULL) {
return waitResponse(1000L, r1, r2, r3, r4, r5, r6, r7);
}
// Asks for modem information via the V.25TER standard ATI command
// NOTE: The actual value and style of the response is quite varied
@@ -132,6 +174,72 @@ class TinyGsmModem {
return false;
}
// TODO(vshymanskyy): Optimize this!
int8_t waitResponseImpl(uint32_t timeout_ms, String& data,
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
#if defined TINY_GSM_DEBUG
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
#else
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
#endif
GsmConstStr r5 = NULL, GsmConstStr r6 = NULL,
GsmConstStr r7 = NULL) {
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (thisModem().stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = thisModem().stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
#if defined TINY_GSM_DEBUG
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
#endif
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (r6 && data.endsWith(r6)) {
index = 6;
goto finish;
} else if (r7 && data.endsWith(r7)) {
index = 7;
goto finish;
} else if (thisModem().handleURCs(data)) {
data = "";
}
}
} while (millis() - startMillis < timeout_ms);
finish:
if (!index) {
data.trim();
if (data.length()) { DBG("### Unhandled:", data); }
data = "";
}
// data.replace(AT_NL, "/");
// DBG('<', index, '>', data);
return index;
}
String getModemInfoImpl() {
thisModem().sendAT(GF("I"));
String res;

View File

@@ -241,9 +241,9 @@ class TinyGsmTCP {
return -1;
}
int peek() override {
return (uint8_t)rx.peek();
}
int peek() override {
return (uint8_t)rx.peek();
}
void flush() override {
at->stream.flush();
@@ -345,7 +345,7 @@ class TinyGsmTCP {
// Yields up to a time-out period and then reads a character from the stream
// into the mux FIFO
// TODO(SRGDamia1): Do we need to wait two _timeout periods for no
// TODO(SRGDamia1): Do we really need to wait _two_ timeout periods for no
// character return? Will wait once in the first "while
// !stream.available()" and then will wait again in the stream.read()
// function.