From fae6d3fc9e40453fc97c62287f1c9c12946f8dff Mon Sep 17 00:00:00 2001 From: tryhus Date: Sun, 16 Dec 2018 11:48:31 +0100 Subject: [PATCH 1/2] Add TCP write in binary mode --- src/GSMClient.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++- src/GSMClient.h | 3 +++ src/Modem.cpp | 32 ++++++++++++++++++++++++++++++- src/Modem.h | 2 +- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/GSMClient.cpp b/src/GSMClient.cpp index ddaa19a..ca07ef7 100644 --- a/src/GSMClient.cpp +++ b/src/GSMClient.cpp @@ -51,7 +51,8 @@ GSMClient::GSMClient(int socket, bool synch) : _host(NULL), _port(0), _ssl(false), - _writeSync(true) + _writeSync(true), + _bytesWritten(0) { MODEM.addUrcHandler(this); } @@ -325,6 +326,45 @@ size_t GSMClient::write(const uint8_t* buf, size_t size) return written; } +size_t GSMClient::send(const void* buf, size_t size, uint32_t timeout) +{ + uint32_t start = millis(); + if (_writeSync) { + while (ready() == 0); + } + else if (ready() == 0) { + return 0; + } + + if (_socket == -1) { + return 0; + } + String command; + + command += "AT+USOWR="; + command += _socket; + command += ","; + command += size; + + MODEM.send(command); + + String response; + if ((MODEM.waitForResponse(10000, &response) == 1) && + (response == "@")){ + MODEM.send((uint8_t*)buf, size); + }else{ + return 0; + } + + _bytesWritten = 0; + + while (((millis() - start) < timeout) && (_bytesWritten < size)) { + MODEM.ready(); + } + + return _bytesWritten; +} + void GSMClient::endWrite(bool /*sync*/) { _writeSync = true; @@ -437,6 +477,12 @@ void GSMClient::stop() void GSMClient::handleUrc(const String& urc) { + if (urc.startsWith("+USOWR: ")){ + int i = urc.indexOf(','); + if (i > 0){ + _bytesWritten = urc.substring(i + 1).toInt(); + } + } if (urc.startsWith("+UUSORD: ")) { int socket = urc.charAt(9) - '0'; diff --git a/src/GSMClient.h b/src/GSMClient.h index 1455d58..3e65f95 100644 --- a/src/GSMClient.h +++ b/src/GSMClient.h @@ -86,6 +86,8 @@ class GSMClient : public Client, public ModemUrcHandler { */ size_t write(const uint8_t*, size_t); + size_t send(const void*, size_t, uint32_t timeout); + /** Finish write request @param sync Sync mode */ @@ -145,6 +147,7 @@ class GSMClient : public Client, public ModemUrcHandler { bool _writeSync; String _response; + uint32_t _bytesWritten; }; #endif diff --git a/src/Modem.cpp b/src/Modem.cpp index 2e73cd1..fd3b8f5 100644 --- a/src/Modem.cpp +++ b/src/Modem.cpp @@ -172,6 +172,26 @@ size_t ModemClass::write(const uint8_t* buf, size_t size) return _uart->write(buf, size); } +void ModemClass::send(const uint8_t* buf, size_t size) +{ + if (_lowPowerMode) { + digitalWrite(_dtrPin, LOW); + delay(5); + } + + // compare the time of the last response or URC and ensure + // at least 20ms have passed before sending a new command + unsigned long delta = millis() - _lastResponseOrUrcMillis; + if (delta < MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS) { + delay(MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS - delta); + } + + _uart->write(buf, size); + _uart->flush(); + _atCommandState = AT_COMMAND_IDLE; + _ready = 0; +} + void ModemClass::send(const char* command) { if (_lowPowerMode) { @@ -279,7 +299,17 @@ void ModemClass::poll() } case AT_RECEIVING_RESPONSE: { - if (c == '\n') { + if (c == '@'){ + _lastResponseOrUrcMillis = millis(); + _ready = 1; + if (_responseDataStorage != NULL){ + *_responseDataStorage = _buffer; + _responseDataStorage = NULL; + } + _atCommandState = AT_COMMAND_IDLE; + _buffer = ""; + return; + } else if (c == '\n') { _lastResponseOrUrcMillis = millis(); int responseResultIndex = _buffer.lastIndexOf("OK\r\n"); diff --git a/src/Modem.h b/src/Modem.h index 57e6152..14f9941 100644 --- a/src/Modem.h +++ b/src/Modem.h @@ -50,7 +50,7 @@ class ModemClass { size_t write(uint8_t c); size_t write(const uint8_t*, size_t); - + void send(const uint8_t*, size_t); void send(const char* command); void send(const String& command) { send(command.c_str()); } void sendf(const char *fmt, ...); From d322e46d3c22b31d4780af848589b18381cde96b Mon Sep 17 00:00:00 2001 From: tryhus Date: Fri, 21 Dec 2018 23:35:49 +0100 Subject: [PATCH 2/2] delete send function of ModemClass, add a function to wait TCP acknoledgedment --- src/GSMClient.cpp | 34 +++++++++++++++++++++++++++++++--- src/GSMClient.h | 21 ++++++++++++++++++++- src/Modem.cpp | 20 -------------------- src/Modem.h | 1 - 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/GSMClient.cpp b/src/GSMClient.cpp index ca07ef7..9da359c 100644 --- a/src/GSMClient.cpp +++ b/src/GSMClient.cpp @@ -329,6 +329,7 @@ size_t GSMClient::write(const uint8_t* buf, size_t size) size_t GSMClient::send(const void* buf, size_t size, uint32_t timeout) { uint32_t start = millis(); + if (_writeSync) { while (ready() == 0); } @@ -350,9 +351,12 @@ size_t GSMClient::send(const void* buf, size_t size, uint32_t timeout) String response; if ((MODEM.waitForResponse(10000, &response) == 1) && - (response == "@")){ - MODEM.send((uint8_t*)buf, size); - }else{ + (response == "@")) { + //After the @ prompt reception, wait for a minimum of 50ms before sending data. + delay(50); + MODEM.write((uint8_t*)buf, size); + } + else { return 0; } @@ -365,6 +369,30 @@ size_t GSMClient::send(const void* buf, size_t size, uint32_t timeout) return _bytesWritten; } +size_t GSMClient::unacknoledgedBytes(uint32_t timeout) +{ + uint32_t start = millis(); + uint32_t unacknoledgedBytes = 0; + + do { + String response; + MODEM.send("AT+USOCTL=0,11"); + if (MODEM.waitForResponse(100, &response) == 1) { + if (response.startsWith("+USOCTL: ")) { + int i = response.lastIndexOf(','); + if (i > 0) { + unacknoledgedBytes = response.substring(i + 1).toInt(); + if (unacknoledgedBytes == 0) { + break; + } + } + } + } + } while ((millis() - start) < timeout); + + return unacknoledgedBytes; +} + void GSMClient::endWrite(bool /*sync*/) { _writeSync = true; diff --git a/src/GSMClient.h b/src/GSMClient.h index 3e65f95..5930c9d 100644 --- a/src/GSMClient.h +++ b/src/GSMClient.h @@ -86,7 +86,26 @@ class GSMClient : public Client, public ModemUrcHandler { */ size_t write(const uint8_t*, size_t); - size_t send(const void*, size_t, uint32_t timeout); + /** Write a buffer with size in request in binary mode + @param (uint8_t*) Buffer + @param (size_t) Buffer size + @param (uint32_t) Timeout + @return data bytes sent to lower level of protocol stack. + + @brief Write data bytes. + The returned value is not a notification of an acknowledgment + received from the remote host. + */ + size_t send(const void*, size_t, uint32_t); + + /** Waiting data acknowledgement + @param (uint32_t) Timeout + @return data bytes unacknoledged. + + @brief This function ensures that all data sent + are received from the remote host. +*/ + size_t unacknoledgedBytes(uint32_t timeout=5000); /** Finish write request @param sync Sync mode diff --git a/src/Modem.cpp b/src/Modem.cpp index fd3b8f5..1e14ad0 100644 --- a/src/Modem.cpp +++ b/src/Modem.cpp @@ -172,26 +172,6 @@ size_t ModemClass::write(const uint8_t* buf, size_t size) return _uart->write(buf, size); } -void ModemClass::send(const uint8_t* buf, size_t size) -{ - if (_lowPowerMode) { - digitalWrite(_dtrPin, LOW); - delay(5); - } - - // compare the time of the last response or URC and ensure - // at least 20ms have passed before sending a new command - unsigned long delta = millis() - _lastResponseOrUrcMillis; - if (delta < MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS) { - delay(MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS - delta); - } - - _uart->write(buf, size); - _uart->flush(); - _atCommandState = AT_COMMAND_IDLE; - _ready = 0; -} - void ModemClass::send(const char* command) { if (_lowPowerMode) { diff --git a/src/Modem.h b/src/Modem.h index 14f9941..7d47cc2 100644 --- a/src/Modem.h +++ b/src/Modem.h @@ -50,7 +50,6 @@ class ModemClass { size_t write(uint8_t c); size_t write(const uint8_t*, size_t); - void send(const uint8_t*, size_t); void send(const char* command); void send(const String& command) { send(command.c_str()); } void sendf(const char *fmt, ...);