From c0214de24bbdc0a92999fddff92d212bc4dc0175 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Wed, 13 Dec 2023 13:01:39 -0700 Subject: [PATCH 1/8] Run library source through formatter Clang formatter in VS Code set to Microsoft style --- ...SparkFun_u-blox_Cellular_Arduino_Library.h | 4 +- src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 48 +- src/sfe_lara_r6.h | 21 +- src/sfe_sara_r5.cpp | 581 +- src/sfe_sara_r5.h | 85 +- src/sfe_ublox_cellular.cpp | 10697 ++++++++-------- src/sfe_ublox_cellular.h | 1677 +-- src/sfe_ublox_cellular_voice.h | 299 +- 8 files changed, 6725 insertions(+), 6687 deletions(-) diff --git a/src/SparkFun_u-blox_Cellular_Arduino_Library.h b/src/SparkFun_u-blox_Cellular_Arduino_Library.h index 96e8cd8..b69171c 100644 --- a/src/SparkFun_u-blox_Cellular_Arduino_Library.h +++ b/src/SparkFun_u-blox_Cellular_Arduino_Library.h @@ -1,4 +1,4 @@ +#include "sfe_lara_r6.h" +#include "sfe_sara_r5.h" #include "sfe_ublox_cellular.h" #include "sfe_ublox_cellular_voice.h" -#include "sfe_sara_r5.h" -#include "sfe_lara_r6.h" diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index eb9a620..a5fff86 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -2,9 +2,8 @@ // RegEx Replace: \#define\sSARA\_R5\_([A-Z0-9_]+).* \#define SARA\_R5\_$+ UBLOX\_AT\_$+ /* - Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod Asset Tracker - By: Paul Clark - October 19th 2020 + Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod + Asset Tracker By: Paul Clark October 19th 2020 Based extensively on the: Arduino Library for the SparkFun LTE CAT M1/NB-IoT Shield - SARA-R4 @@ -34,8 +33,9 @@ #define SARA_R5_3_MIN_TIMEOUT 180000 #define SARA_R5_SET_BAUD_TIMEOUT 500 #define SARA_R5_POWER_OFF_PULSE_PERIOD 3200 // Hold PWR_ON low for this long to power the module off -#define SARA_R5_POWER_ON_PULSE_PERIOD 100 // Hold PWR_ON low for this long to power the module on (SARA-R510M8S) -#define SARA_R5_RESET_PULSE_PERIOD 23000 // Used to perform an abrupt emergency hardware shutdown. 23 seconds... (Yes, really!) +#define SARA_R5_POWER_ON_PULSE_PERIOD 100 // Hold PWR_ON low for this long to power the module on (SARA-R510M8S) +#define SARA_R5_RESET_PULSE_PERIOD \ + 23000 // Used to perform an abrupt emergency hardware shutdown. 23 seconds... (Yes, really!) #define SARA_R5_POWER_OFF_TIMEOUT 40000 // Datasheet says 40 seconds... #define SARA_R5_IP_CONNECT_TIMEOUT 130000 #define SARA_R5_POLL_DELAY 1 @@ -141,7 +141,6 @@ #define SARA_R5_SEC_PROFILE UBX_CELL_SEC_PROFILE #define SARA_R5_SEC_MANAGER UBX_CELL_SEC_MANAGER - // ### URC strings #define SARA_R5_READ_SOCKET_URC UBX_CELL_READ_SOCKET_URC #define SARA_R5_READ_UDP_SOCKET_URC UBX_CELL_READ_UDP_SOCKET_URC @@ -167,14 +166,7 @@ #define SARA_R5_NUM_SOCKETS 6 #define SARA_R5_NUM_SUPPORTED_BAUD 6 -const unsigned long SARA_R5_SUPPORTED_BAUD[SARA_R5_NUM_SUPPORTED_BAUD] = - { - 115200, - 9600, - 19200, - 38400, - 57600, - 230400}; +const unsigned long SARA_R5_SUPPORTED_BAUD[SARA_R5_NUM_SUPPORTED_BAUD] = {115200, 9600, 19200, 38400, 57600, 230400}; #define SARA_R5_DEFAULT_BAUD_RATE 115200 // Flow control definitions for AT&K @@ -244,13 +236,13 @@ const unsigned long SARA_R5_SUPPORTED_BAUD[SARA_R5_NUM_SUPPORTED_BAUD] = #define SARA_R5_SIM_NOT_OPERATIONAL UBX_CELL_SIM_NOT_OPERATIONAL #define SARA_R5_SIM_RESTRICTED UBX_CELL_SIM_RESTRICTED #define SARA_R5_SIM_OPERATIONAL UBX_CELL_SIM_OPERATIONAL -//SARA_R5_SIM_PHONEBOOK_READY, // Not reported by SARA-R5 -//SARA_R5_SIM_USIM_PHONEBOOK_READY, // Not reported by SARA-R5 -//SARA_R5_SIM_TOOLKIT_REFRESH_SUCCESSFUL, // Not reported by SARA-R5 -//SARA_R5_SIM_TOOLKIT_REFRESH_UNSUCCESSFUL, // Not reported by SARA-R5 -//SARA_R5_SIM_PPP_CONNECTION_ACTIVE, // Not reported by SARA-R5 -//SARA_R5_SIM_VOICE_CALL_ACTIVE, // Not reported by SARA-R5 -//SARA_R5_SIM_CSD_CALL_ACTIVE // Not reported by SARA-R5 +// SARA_R5_SIM_PHONEBOOK_READY, // Not reported by SARA-R5 +// SARA_R5_SIM_USIM_PHONEBOOK_READY, // Not reported by SARA-R5 +// SARA_R5_SIM_TOOLKIT_REFRESH_SUCCESSFUL, // Not reported by SARA-R5 +// SARA_R5_SIM_TOOLKIT_REFRESH_UNSUCCESSFUL, // Not reported by SARA-R5 +// SARA_R5_SIM_PPP_CONNECTION_ACTIVE, // Not reported by SARA-R5 +// SARA_R5_SIM_VOICE_CALL_ACTIVE, // Not reported by SARA-R5 +// SARA_R5_SIM_CSD_CALL_ACTIVE // Not reported by SARA-R5 #define SARA_R5_NUM_PSD_PROFILES 6 // Number of supported PSD profiles #define SARA_R5_NUM_PDP_CONTEXT_IDENTIFIERS 11 // Number of supported PDP context identifiers @@ -335,14 +327,14 @@ const unsigned long SARA_R5_SUPPORTED_BAUD[SARA_R5_NUM_SUPPORTED_BAUD] = #define SARA_R5_PSD_CONFIG_PARAM_PROTOCOL UBX_CELL_PSD_CONFIG_PARAM_PROTOCOL #define SARA_R5_PSD_CONFIG_PARAM_APN UBX_CELL_PSD_CONFIG_PARAM_APN -//SARA_R5_PSD_CONFIG_PARAM_USERNAME, // Not allowed on SARA-R5 -//SARA_R5_PSD_CONFIG_PARAM_PASSWORD, // Not allowed on SARA-R5 +// SARA_R5_PSD_CONFIG_PARAM_USERNAME, // Not allowed on SARA-R5 +// SARA_R5_PSD_CONFIG_PARAM_PASSWORD, // Not allowed on SARA-R5 #define SARA_R5_PSD_CONFIG_PARAM_DNS1 UBX_CELL_PSD_CONFIG_PARAM_DNS1 #define SARA_R5_PSD_CONFIG_PARAM_DNS2 UBX_CELL_PSD_CONFIG_PARAM_DNS2 -//SARA_R5_PSD_CONFIG_PARAM_AUTHENTICATION, // Not allowed on SARA-R5 -//SARA_R5_PSD_CONFIG_PARAM_IP_ADDRESS, // Not allowed on SARA-R5 -//SARA_R5_PSD_CONFIG_PARAM_DATA_COMPRESSION, // Not allowed on SARA-R5 -//SARA_R5_PSD_CONFIG_PARAM_HEADER_COMPRESSION, // Not allowed on SARA-R5 +// SARA_R5_PSD_CONFIG_PARAM_AUTHENTICATION, // Not allowed on SARA-R5 +// SARA_R5_PSD_CONFIG_PARAM_IP_ADDRESS, // Not allowed on SARA-R5 +// SARA_R5_PSD_CONFIG_PARAM_DATA_COMPRESSION, // Not allowed on SARA-R5 +// SARA_R5_PSD_CONFIG_PARAM_HEADER_COMPRESSION, // Not allowed on SARA-R5 #define SARA_R5_PSD_CONFIG_PARAM_MAP_TO_CID UBX_CELL_PSD_CONFIG_PARAM_MAP_TO_CID #define SARA_R5_PSD_PROTOCOL_IPV4 UBX_CELL_PSD_PROTOCOL_IPV4 @@ -388,4 +380,4 @@ const unsigned long SARA_R5_SUPPORTED_BAUD[SARA_R5_NUM_SUPPORTED_BAUD] = #define SARA_R5_SEC_MANAGER_CLIENT_KEY UBX_CELL_SEC_MANAGER_CLIENT_KEY #define SARA_R5_SEC_MANAGER_SERVER_CERT UBX_CELL_SEC_MANAGER_SERVER_CERT -#endif //SPARKFUN_SARA_R5_ARDUINO_LIBRARY_H +#endif // SPARKFUN_SARA_R5_ARDUINO_LIBRARY_H diff --git a/src/sfe_lara_r6.h b/src/sfe_lara_r6.h index 08e9736..40fc862 100644 --- a/src/sfe_lara_r6.h +++ b/src/sfe_lara_r6.h @@ -5,39 +5,32 @@ #include "sfe_ublox_cellular_voice.h" // Base LARA-R6 class -class LARA_R6: public UBX_CELL +class LARA_R6 : public UBX_CELL { - }; -class LARA_R6001: public LARA_R6, public UBX_CELL_VOICE +class LARA_R6001 : public LARA_R6, public UBX_CELL_VOICE { - }; -class LARA_R6001D: public LARA_R6 +class LARA_R6001D : public LARA_R6 { - }; -class LARA_R6401: public LARA_R6, public UBX_CELL_VOICE +class LARA_R6401 : public LARA_R6, public UBX_CELL_VOICE { - }; -class LARA_R6401D: public LARA_R6 +class LARA_R6401D : public LARA_R6 { - }; -class LARA_R6801_00B: public LARA_R6, public UBX_CELL_VOICE +class LARA_R6801_00B : public LARA_R6, public UBX_CELL_VOICE { - }; -class LARA_R6801D: public LARA_R6 +class LARA_R6801D : public LARA_R6 { - }; #endif \ No newline at end of file diff --git a/src/sfe_sara_r5.cpp b/src/sfe_sara_r5.cpp index 2478862..34a4992 100644 --- a/src/sfe_sara_r5.cpp +++ b/src/sfe_sara_r5.cpp @@ -2,402 +2,397 @@ SARA_R5::SARA_R5() { - addURCHandler(UBX_CELL_MESSAGE_PDP_ACTION_URC, [this](const char* event){return this->urcHandlerPDPAction(event);}); + addURCHandler(UBX_CELL_MESSAGE_PDP_ACTION_URC, + [this](const char *event) { return this->urcHandlerPDPAction(event); }); } UBX_CELL_error_t SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utime_sensor_t sensor) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_TIME) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (mode == UBX_CELL_UTIME_MODE_STOP) // stop UTIME does not require a sensor - sprintf(command, "%s=%d", UBX_CELL_GNSS_REQUEST_TIME, mode); - else - sprintf(command, "%s=%d,%d", UBX_CELL_GNSS_REQUEST_TIME, mode, sensor); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_10_SEC_TIMEOUT); - free(command); - return err; + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_TIME) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (mode == UBX_CELL_UTIME_MODE_STOP) // stop UTIME does not require a sensor + sprintf(command, "%s=%d", UBX_CELL_GNSS_REQUEST_TIME, mode); + else + sprintf(command, "%s=%d,%d", UBX_CELL_GNSS_REQUEST_TIME, mode, sensor); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); + free(command); + return err; } UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_utime_sensor_t *sensor) { - UBX_CELL_error_t err; - char *command; - char *response; + UBX_CELL_error_t err; + char *command; + char *response; - UBX_CELL_utime_mode_t m; - UBX_CELL_utime_sensor_t s; + UBX_CELL_utime_mode_t m; + UBX_CELL_utime_sensor_t s; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_TIME) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_REQUEST_TIME); + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_TIME) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_GNSS_REQUEST_TIME); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_10_SEC_TIMEOUT); - - // Response format: \r\n+UTIME: [,]\r\n\r\nOK\r\n - if (err == UBX_CELL_ERROR_SUCCESS) - { - int mStore, sStore, scanned = 0; - char *searchPtr = strstr(response, "+UTIME:"); - if (searchPtr != nullptr) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - searchPtr += strlen("+UTIME:"); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,%d\r\n", &mStore, &sStore); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - m = (UBX_CELL_utime_mode_t)mStore; - s = (UBX_CELL_utime_sensor_t)sStore; - if (scanned == 2) - { - *mode = m; - *sensor = s; - } - else if (scanned == 1) + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); + + // Response format: \r\n+UTIME: [,]\r\n\r\nOK\r\n + if (err == UBX_CELL_ERROR_SUCCESS) { - *mode = m; - *sensor = UBX_CELL_UTIME_SENSOR_NONE; + int mStore, sStore, scanned = 0; + char *searchPtr = strstr(response, "+UTIME:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UTIME:"); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,%d\r\n", &mStore, &sStore); + } + m = (UBX_CELL_utime_mode_t)mStore; + s = (UBX_CELL_utime_sensor_t)sStore; + if (scanned == 2) + { + *mode = m; + *sensor = s; + } + else if (scanned == 1) + { + *mode = m; + *sensor = UBX_CELL_UTIME_SENSOR_NONE; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - free(command); - free(response); - return err; + free(command); + free(response); + return err; } UBX_CELL_error_t SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t config) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_INDICATION) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_GNSS_TIME_INDICATION, config); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_INDICATION) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_GNSS_TIME_INDICATION, config); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t *config) { - UBX_CELL_error_t err; - char *command; - char *response; + UBX_CELL_error_t err; + char *command; + char *response; - UBX_CELL_utime_urc_configuration_t c; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_INDICATION) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_TIME_INDICATION); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + UBX_CELL_utime_urc_configuration_t c; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_INDICATION) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_GNSS_TIME_INDICATION); - // Response format: \r\n+UTIMEIND: \r\n\r\nOK\r\n - if (err == UBX_CELL_ERROR_SUCCESS) - { - int cStore, scanned = 0; - char *searchPtr = strstr(response, "+UTIMEIND:"); - if (searchPtr != nullptr) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - searchPtr += strlen("+UTIMEIND:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d\r\n", &cStore); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - c = (UBX_CELL_utime_urc_configuration_t)cStore; - if (scanned == 1) + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + // Response format: \r\n+UTIMEIND: \r\n\r\nOK\r\n + if (err == UBX_CELL_ERROR_SUCCESS) { - *config = c; + int cStore, scanned = 0; + char *searchPtr = strstr(response, "+UTIMEIND:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UTIMEIND:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d\r\n", &cStore); + } + c = (UBX_CELL_utime_urc_configuration_t)cStore; + if (scanned == 1) + { + *config = c; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - free(command); - free(response); - return err; + free(command); + free(response); + return err; } UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32_t offsetSeconds) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 48); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 48); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - sprintf(command, "%s=%d,%d", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); + sprintf(command, "%s=%d,%d", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); #else - sprintf(command, "%s=%ld,%ld", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); + sprintf(command, "%s=%ld,%ld", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); #endif - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds) { - UBX_CELL_error_t err; - char *command; - char *response; + UBX_CELL_error_t err; + char *command; + char *response; - int32_t ons; - int32_t os; + int32_t ons; + int32_t os; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_TIME_CONFIGURATION); + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_GNSS_TIME_CONFIGURATION); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - // Response format: \r\n+UTIMECFG: ,\r\n\r\nOK\r\n - if (err == UBX_CELL_ERROR_SUCCESS) - { - int scanned = 0; - char *searchPtr = strstr(response, "+UTIMECFG:"); - if (searchPtr != nullptr) + // Response format: \r\n+UTIMECFG: ,\r\n\r\nOK\r\n + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("+UTIMECFG:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces + int scanned = 0; + char *searchPtr = strstr(response, "+UTIMECFG:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UTIMECFG:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - scanned = sscanf(searchPtr, "%d,%d\r\n", &ons, &os); + scanned = sscanf(searchPtr, "%d,%d\r\n", &ons, &os); #else - scanned = sscanf(searchPtr, "%ld,%ld\r\n", &ons, &os); + scanned = sscanf(searchPtr, "%ld,%ld\r\n", &ons, &os); #endif + } + if (scanned == 2) + { + *offsetNanoseconds = ons; + *offsetSeconds = os; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - if (scanned == 2) - { - *offsetNanoseconds = ons; - *offsetSeconds = os; - } - else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - free(command); - free(response); - return err; + free(command); + free(response); + return err; } UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, int value) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - if (profile >= UBX_CELL_NUM_PSD_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (profile >= UBX_CELL_NUM_PSD_PROFILES) + return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 24); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, - value); + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 24); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, UBX_CELL_pdp_protocol_type_t value) +UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + UBX_CELL_pdp_protocol_type_t value) { - return (setPDPconfiguration(profile, parameter, (int)value)); + return (setPDPconfiguration(profile, parameter, (int)value)); } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, String value) +UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + String value) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - if (profile >= UBX_CELL_NUM_PSD_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (profile >= UBX_CELL_NUM_PSD_PROFILES) + return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, - value.c_str()); + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, IPAddress value) +UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + IPAddress value) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - if (profile >= UBX_CELL_NUM_PSD_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (profile >= UBX_CELL_NUM_PSD_PROFILES) + return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, - value[0], value[1], value[2], value[3]); + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value[0], value[1], + value[2], value[3]); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } UBX_CELL_error_t SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t action) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - if (profile >= UBX_CELL_NUM_PSD_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (profile >= UBX_CELL_NUM_PSD_PROFILES) + return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_ACTION) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_ACTION, profile, action); + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_ACTION) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_ACTION, profile, action); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *address) { - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int profileStore = 0; - int paramTag = 0; // 0: IP address: dynamic IP address assigned during PDP context activation - int paramVals[4]; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_NETWORK_ASSIGNED_DATA) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d", UBX_CELL_NETWORK_ASSIGNED_DATA, profile, paramTag); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+UPSND:"); - if (searchPtr != nullptr) + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int profileStore = 0; + int paramTag = 0; // 0: IP address: dynamic IP address assigned during PDP context activation + int paramVals[4]; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_NETWORK_ASSIGNED_DATA) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d", UBX_CELL_NETWORK_ASSIGNED_DATA, profile, paramTag); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - searchPtr += strlen("+UPSND:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d,\"%d.%d.%d.%d\"", - &profileStore, ¶mTag, - ¶mVals[0], ¶mVals[1], ¶mVals[2], ¶mVals[3]); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - if (scanNum != 6) + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) { - if (_printDebug == true) - { - _debugPort->print(F("getNetworkAssignedIPAddress: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + char *searchPtr = strstr(response, "+UPSND:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UPSND:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,%d,\"%d.%d.%d.%d\"", &profileStore, ¶mTag, ¶mVals[0], ¶mVals[1], + ¶mVals[2], ¶mVals[3]); + } + if (scanNum != 6) + { + if (_printDebug == true) + { + _debugPort->print(F("getNetworkAssignedIPAddress: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + IPAddress tempAddress = {(uint8_t)paramVals[0], (uint8_t)paramVals[1], (uint8_t)paramVals[2], + (uint8_t)paramVals[3]}; + *address = tempAddress; } - IPAddress tempAddress = { (uint8_t)paramVals[0], (uint8_t)paramVals[1], - (uint8_t)paramVals[2], (uint8_t)paramVals[3] }; - *address = tempAddress; - } - - free(command); - free(response); + free(command); + free(response); - return err; + return err; } -bool SARA_R5::urcHandlerPDPAction(const char* event) +bool SARA_R5::urcHandlerPDPAction(const char *event) { - // URC: +UUPSDA (Packet Switched Data Action) - int result; - IPAddress remoteIP = {0, 0, 0, 0}; - int scanNum; - int remoteIPstore[4]; - - char *searchPtr = strstr(event, UBX_CELL_MESSAGE_PDP_ACTION_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_MESSAGE_PDP_ACTION_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,\"%d.%d.%d.%d\"", - &result, &remoteIPstore[0], &remoteIPstore[1], &remoteIPstore[2], &remoteIPstore[3]); - - if (scanNum == 5) - { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: packet switched data action")); - - for (int i = 0; i <= 3; i++) - { - remoteIP[i] = (uint8_t)remoteIPstore[i]; - } + // URC: +UUPSDA (Packet Switched Data Action) + int result; + IPAddress remoteIP = {0, 0, 0, 0}; + int scanNum; + int remoteIPstore[4]; - if (_psdActionRequestCallback != nullptr) - { - _psdActionRequestCallback(result, remoteIP); - } - - return true; + char *searchPtr = strstr(event, UBX_CELL_MESSAGE_PDP_ACTION_URC); + if (searchPtr != nullptr) + { + searchPtr += strlen(UBX_CELL_MESSAGE_PDP_ACTION_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,\"%d.%d.%d.%d\"", &result, &remoteIPstore[0], &remoteIPstore[1], + &remoteIPstore[2], &remoteIPstore[3]); + + if (scanNum == 5) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: packet switched data action")); + + for (int i = 0; i <= 3; i++) + { + remoteIP[i] = (uint8_t)remoteIPstore[i]; + } + + if (_psdActionRequestCallback != nullptr) + { + _psdActionRequestCallback(result, remoteIP); + } + + return true; + } } - } - return false; + return false; } diff --git a/src/sfe_sara_r5.h b/src/sfe_sara_r5.h index ffa060c..a8189c7 100644 --- a/src/sfe_sara_r5.h +++ b/src/sfe_sara_r5.h @@ -3,64 +3,71 @@ #include "sfe_ublox_cellular.h" -const char* const UBX_CELL_MESSAGE_PDP_CONFIG = "+UPSD"; // Packet switched Data Profile configuration -const char* const UBX_CELL_MESSAGE_PDP_ACTION = "+UPSDA"; // Perform the action for the specified PSD profile -const char* const UBX_CELL_NETWORK_ASSIGNED_DATA = "+UPSND"; // Packet switched network-assigned data -const char* const UBX_CELL_GNSS_REQUEST_TIME = "+UTIME"; // Ask for time information from cellular modem (CellTime) -const char* const UBX_CELL_GNSS_TIME_INDICATION = "+UTIMEIND"; // Time information request status unsolicited indication -const char* const UBX_CELL_GNSS_TIME_CONFIGURATION = "+UTIMECFG"; // Sets time configuration +const char *const UBX_CELL_MESSAGE_PDP_CONFIG = "+UPSD"; // Packet switched Data Profile configuration +const char *const UBX_CELL_MESSAGE_PDP_ACTION = "+UPSDA"; // Perform the action for the specified PSD profile +const char *const UBX_CELL_NETWORK_ASSIGNED_DATA = "+UPSND"; // Packet switched network-assigned data +const char *const UBX_CELL_GNSS_REQUEST_TIME = "+UTIME"; // Ask for time information from cellular modem (CellTime) +const char *const UBX_CELL_GNSS_TIME_INDICATION = "+UTIMEIND"; // Time information request status unsolicited indication +const char *const UBX_CELL_GNSS_TIME_CONFIGURATION = "+UTIMECFG"; // Sets time configuration -const char* const UBX_CELL_MESSAGE_PDP_ACTION_URC = "+UUPSDA:"; +const char *const UBX_CELL_MESSAGE_PDP_ACTION_URC = "+UUPSDA:"; // Base SARA-R5 class -class SARA_R5: public UBX_CELL +class SARA_R5 : public UBX_CELL { -public: - SARA_R5(); - - UBX_CELL_error_t setUtimeMode(UBX_CELL_utime_mode_t mode = UBX_CELL_UTIME_MODE_PPS, UBX_CELL_utime_sensor_t sensor = UBX_CELL_UTIME_SENSOR_GNSS_LTE); // Time mode, source etc. (+UTIME) - UBX_CELL_error_t getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_utime_sensor_t *sensor); - UBX_CELL_error_t setUtimeIndication(UBX_CELL_utime_urc_configuration_t config = UBX_CELL_UTIME_URC_CONFIGURATION_ENABLED); // +UTIMEIND - UBX_CELL_error_t getUtimeIndication(UBX_CELL_utime_urc_configuration_t *config); - UBX_CELL_error_t setUtimeConfiguration(int32_t offsetNanoseconds = 0, int32_t offsetSeconds = 0); // +UTIMECFG - UBX_CELL_error_t getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds); - - // Packet Switched Data - // Configure the PDP using +UPSD. See UBX_CELL_pdp_configuration_parameter_t for the list of parameters: protocol, APN, username, DNS, etc. - UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, int value); // Set parameters in the chosen PSD profile - UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, UBX_CELL_pdp_protocol_type_t value); // Set parameters in the chosen PSD profile - UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, String value); // Set parameters in the chosen PSD profile - UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, IPAddress value); // Set parameters in the chosen PSD profile - UBX_CELL_error_t performPDPaction(int profile, UBX_CELL_pdp_actions_t action); // Performs the requested action for the specified PSD profile: reset, store, load, activate, deactivate - UBX_CELL_error_t getNetworkAssignedIPAddress(int profile, IPAddress *address); // Get the dynamic IP address assigned during PDP context activation - -protected: - bool urcHandlerPDPAction(const char* event); + public: + SARA_R5(); + + UBX_CELL_error_t setUtimeMode( + UBX_CELL_utime_mode_t mode = UBX_CELL_UTIME_MODE_PPS, + UBX_CELL_utime_sensor_t sensor = UBX_CELL_UTIME_SENSOR_GNSS_LTE); // Time mode, source etc. (+UTIME) + UBX_CELL_error_t getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_utime_sensor_t *sensor); + UBX_CELL_error_t setUtimeIndication( + UBX_CELL_utime_urc_configuration_t config = UBX_CELL_UTIME_URC_CONFIGURATION_ENABLED); // +UTIMEIND + UBX_CELL_error_t getUtimeIndication(UBX_CELL_utime_urc_configuration_t *config); + UBX_CELL_error_t setUtimeConfiguration(int32_t offsetNanoseconds = 0, int32_t offsetSeconds = 0); // +UTIMECFG + UBX_CELL_error_t getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds); + + // Packet Switched Data + // Configure the PDP using +UPSD. See UBX_CELL_pdp_configuration_parameter_t for the list of parameters: protocol, + // APN, username, DNS, etc. + UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + int value); // Set parameters in the chosen PSD profile + UBX_CELL_error_t setPDPconfiguration( + int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + UBX_CELL_pdp_protocol_type_t value); // Set parameters in the chosen PSD profile + UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + String value); // Set parameters in the chosen PSD profile + UBX_CELL_error_t setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, + IPAddress value); // Set parameters in the chosen PSD profile + UBX_CELL_error_t performPDPaction( + int profile, UBX_CELL_pdp_actions_t action); // Performs the requested action for the specified PSD profile: + // reset, store, load, activate, deactivate + UBX_CELL_error_t getNetworkAssignedIPAddress( + int profile, IPAddress *address); // Get the dynamic IP address assigned during PDP context activation + + protected: + bool urcHandlerPDPAction(const char *event); }; -class SARA_R500S: public SARA_R5 +class SARA_R500S : public SARA_R5 { - }; -class SARA_R500S_01B: public SARA_R5 +class SARA_R500S_01B : public SARA_R5 { - }; -class SARA_R500S_61B: public SARA_R5 +class SARA_R500S_61B : public SARA_R5 { - }; -class SARA_R510M8S_61B: public SARA_R5 +class SARA_R510M8S_61B : public SARA_R5 { - }; -class SARA_R510S: public SARA_R5 +class SARA_R510S : public SARA_R5 { - }; #endif \ No newline at end of file diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index 9a9ae0a..e7fbe8f 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -1,7 +1,6 @@ /* - Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod Asset Tracker - By: Paul Clark - October 19th 2020 + Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod + Asset Tracker By: Paul Clark October 19th 2020 Based extensively on the: Arduino Library for the SparkFun LTE CAT M1/NB-IoT Shield - SARA-R4 @@ -19,187 +18,196 @@ UBX_CELL::UBX_CELL(int powerPin, int resetPin, uint8_t maxInitTries) { #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - _softSerial = nullptr; + _softSerial = nullptr; #endif - _hardSerial = nullptr; - _baud = 0; - _resetPin = resetPin; - _powerPin = powerPin; - _invertPowerPin = false; - _maxInitTries = maxInitTries; - _socketListenCallback = nullptr; - _socketReadCallback = nullptr; - _socketReadCallbackPlus = nullptr; - _socketCloseCallback = nullptr; - _gpsRequestCallback = nullptr; - _simStateReportCallback = nullptr; - _psdActionRequestCallback = nullptr; - _pingRequestCallback = nullptr; - _httpCommandRequestCallback = nullptr; - _mqttCommandRequestCallback = nullptr; - _registrationCallback = nullptr; - _epsRegistrationCallback = nullptr; - _debugAtPort = nullptr; - _debugPort = nullptr; - _printDebug = false; - _lastRemoteIP = {0, 0, 0, 0}; - _lastLocalIP = {0, 0, 0, 0}; - for (int i = 0; i < UBX_CELL_NUM_SOCKETS; i++) - _lastSocketProtocol[i] = 0; // Set to zero initially. Will be set to TCP/UDP by socketOpen etc. - _autoTimeZoneForBegin = true; - _bufferedPollReentrant = false; - _pollReentrant = false; - _saraResponseBacklogLength = 0; - _saraRXBuffer = nullptr; - _pruneBuffer = nullptr; - _saraResponseBacklog = nullptr; - - // Add base URC handlers - addURCHandler(UBX_CELL_READ_SOCKET_URC, [this](const char* event){return this->urcHandlerReadSocket(event);}); - addURCHandler(UBX_CELL_READ_UDP_SOCKET_URC, [this](const char* event){return this->urcHandlerReadUDPSocket(event);}); - addURCHandler(UBX_CELL_LISTEN_SOCKET_URC, [this](const char* event){return this->urcHandlerListeningSocket(event);}); - addURCHandler(UBX_CELL_CLOSE_SOCKET_URC, [this](const char* event){return this->urcHandlerCloseSocket(event);}); - addURCHandler(UBX_CELL_GNSS_REQUEST_LOCATION_URC, [this](const char* event){return this->urcHandlerGNSSRequestLocation(event);}); - addURCHandler(UBX_CELL_SIM_STATE_URC, [this](const char* event){return this->urcHandlerSIMState(event);}); - addURCHandler(UBX_CELL_HTTP_COMMAND_URC, [this](const char* event){return this->urcHandlerHTTPCommand(event);}); - addURCHandler(UBX_CELL_MQTT_COMMAND_URC, [this](const char* event){return this->urcHandlerMQTTCommand(event);}); - addURCHandler(UBX_CELL_PING_COMMAND_URC, [this](const char* event){return this->urcHandlerPingCommand(event);}); - addURCHandler(UBX_CELL_FTP_COMMAND_URC, [this](const char* event){return this->urcHandlerFTPCommand(event);}); - addURCHandler(UBX_CELL_REGISTRATION_STATUS_URC, [this](const char* event){return this->urcHandlerRegistrationStatus(event);}); - addURCHandler(UBX_CELL_EPSREGISTRATION_STATUS_URC, [this](const char* event){return this->urcHandlerEPSRegistrationStatus(event);}); -} - -UBX_CELL::~UBX_CELL(void) { - if (nullptr != _saraRXBuffer) { - delete[] _saraRXBuffer; + _hardSerial = nullptr; + _baud = 0; + _resetPin = resetPin; + _powerPin = powerPin; + _invertPowerPin = false; + _maxInitTries = maxInitTries; + _socketListenCallback = nullptr; + _socketReadCallback = nullptr; + _socketReadCallbackPlus = nullptr; + _socketCloseCallback = nullptr; + _gpsRequestCallback = nullptr; + _simStateReportCallback = nullptr; + _psdActionRequestCallback = nullptr; + _pingRequestCallback = nullptr; + _httpCommandRequestCallback = nullptr; + _mqttCommandRequestCallback = nullptr; + _registrationCallback = nullptr; + _epsRegistrationCallback = nullptr; + _debugAtPort = nullptr; + _debugPort = nullptr; + _printDebug = false; + _lastRemoteIP = {0, 0, 0, 0}; + _lastLocalIP = {0, 0, 0, 0}; + for (int i = 0; i < UBX_CELL_NUM_SOCKETS; i++) + _lastSocketProtocol[i] = 0; // Set to zero initially. Will be set to TCP/UDP by socketOpen etc. + _autoTimeZoneForBegin = true; + _bufferedPollReentrant = false; + _pollReentrant = false; + _saraResponseBacklogLength = 0; _saraRXBuffer = nullptr; - } - if (nullptr != _pruneBuffer) { - delete[] _pruneBuffer; _pruneBuffer = nullptr; - } - if (nullptr != _saraResponseBacklog) { - delete[] _saraResponseBacklog; _saraResponseBacklog = nullptr; - } + + // Add base URC handlers + addURCHandler(UBX_CELL_READ_SOCKET_URC, [this](const char *event) { return this->urcHandlerReadSocket(event); }); + addURCHandler(UBX_CELL_READ_UDP_SOCKET_URC, + [this](const char *event) { return this->urcHandlerReadUDPSocket(event); }); + addURCHandler(UBX_CELL_LISTEN_SOCKET_URC, + [this](const char *event) { return this->urcHandlerListeningSocket(event); }); + addURCHandler(UBX_CELL_CLOSE_SOCKET_URC, [this](const char *event) { return this->urcHandlerCloseSocket(event); }); + addURCHandler(UBX_CELL_GNSS_REQUEST_LOCATION_URC, + [this](const char *event) { return this->urcHandlerGNSSRequestLocation(event); }); + addURCHandler(UBX_CELL_SIM_STATE_URC, [this](const char *event) { return this->urcHandlerSIMState(event); }); + addURCHandler(UBX_CELL_HTTP_COMMAND_URC, [this](const char *event) { return this->urcHandlerHTTPCommand(event); }); + addURCHandler(UBX_CELL_MQTT_COMMAND_URC, [this](const char *event) { return this->urcHandlerMQTTCommand(event); }); + addURCHandler(UBX_CELL_PING_COMMAND_URC, [this](const char *event) { return this->urcHandlerPingCommand(event); }); + addURCHandler(UBX_CELL_FTP_COMMAND_URC, [this](const char *event) { return this->urcHandlerFTPCommand(event); }); + addURCHandler(UBX_CELL_REGISTRATION_STATUS_URC, + [this](const char *event) { return this->urcHandlerRegistrationStatus(event); }); + addURCHandler(UBX_CELL_EPSREGISTRATION_STATUS_URC, + [this](const char *event) { return this->urcHandlerEPSRegistrationStatus(event); }); +} + +UBX_CELL::~UBX_CELL(void) +{ + if (nullptr != _saraRXBuffer) + { + delete[] _saraRXBuffer; + _saraRXBuffer = nullptr; + } + if (nullptr != _pruneBuffer) + { + delete[] _pruneBuffer; + _pruneBuffer = nullptr; + } + if (nullptr != _saraResponseBacklog) + { + delete[] _saraResponseBacklog; + _saraResponseBacklog = nullptr; + } } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED bool UBX_CELL::begin(SoftwareSerial &softSerial, unsigned long baud) { - if (nullptr == _saraRXBuffer) - { - _saraRXBuffer = new char[_RXBuffSize]; if (nullptr == _saraRXBuffer) { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _saraRXBuffer!")); - return false; + _saraRXBuffer = new char[_RXBuffSize]; + if (nullptr == _saraRXBuffer) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _saraRXBuffer!")); + return false; + } } - } - memset(_saraRXBuffer, 0, _RXBuffSize); + memset(_saraRXBuffer, 0, _RXBuffSize); - if (nullptr == _pruneBuffer) - { - _pruneBuffer = new char[_RXBuffSize]; if (nullptr == _pruneBuffer) { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _pruneBuffer!")); - return false; + _pruneBuffer = new char[_RXBuffSize]; + if (nullptr == _pruneBuffer) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _pruneBuffer!")); + return false; + } } - } - memset(_pruneBuffer, 0, _RXBuffSize); + memset(_pruneBuffer, 0, _RXBuffSize); - if (nullptr == _saraResponseBacklog) - { - _saraResponseBacklog = new char[_RXBuffSize]; if (nullptr == _saraResponseBacklog) { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _saraResponseBacklog!")); - return false; + _saraResponseBacklog = new char[_RXBuffSize]; + if (nullptr == _saraResponseBacklog) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _saraResponseBacklog!")); + return false; + } } - } - memset(_saraResponseBacklog, 0, _RXBuffSize); + memset(_saraResponseBacklog, 0, _RXBuffSize); - UBX_CELL_error_t err; + UBX_CELL_error_t err; - _softSerial = &softSerial; + _softSerial = &softSerial; - err = init(baud); - if (err == UBX_CELL_ERROR_SUCCESS) - { - return true; - } - return false; + err = init(baud); + if (err == UBX_CELL_ERROR_SUCCESS) + { + return true; + } + return false; } #endif bool UBX_CELL::begin(HardwareSerial &hardSerial, unsigned long baud) { - if (nullptr == _saraRXBuffer) - { - _saraRXBuffer = new char[_RXBuffSize]; if (nullptr == _saraRXBuffer) { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _saraRXBuffer!")); - return false; + _saraRXBuffer = new char[_RXBuffSize]; + if (nullptr == _saraRXBuffer) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _saraRXBuffer!")); + return false; + } } - } - memset(_saraRXBuffer, 0, _RXBuffSize); + memset(_saraRXBuffer, 0, _RXBuffSize); - if (nullptr == _pruneBuffer) - { - _pruneBuffer = new char[_RXBuffSize]; if (nullptr == _pruneBuffer) { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _pruneBuffer!")); - return false; + _pruneBuffer = new char[_RXBuffSize]; + if (nullptr == _pruneBuffer) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _pruneBuffer!")); + return false; + } } - } - memset(_pruneBuffer, 0, _RXBuffSize); + memset(_pruneBuffer, 0, _RXBuffSize); - if (nullptr == _saraResponseBacklog) - { - _saraResponseBacklog = new char[_RXBuffSize]; if (nullptr == _saraResponseBacklog) { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _saraResponseBacklog!")); - return false; + _saraResponseBacklog = new char[_RXBuffSize]; + if (nullptr == _saraResponseBacklog) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _saraResponseBacklog!")); + return false; + } } - } - memset(_saraResponseBacklog, 0, _RXBuffSize); + memset(_saraResponseBacklog, 0, _RXBuffSize); - UBX_CELL_error_t err; + UBX_CELL_error_t err; - _hardSerial = &hardSerial; + _hardSerial = &hardSerial; - err = init(baud); - if (err == UBX_CELL_ERROR_SUCCESS) - { - return true; - } - return false; + err = init(baud); + if (err == UBX_CELL_ERROR_SUCCESS) + { + return true; + } + return false; } -//Calling this function with nothing sets the debug port to Serial -//You can also call it with other streams like Serial1, SerialUSB, etc. +// Calling this function with nothing sets the debug port to Serial +// You can also call it with other streams like Serial1, SerialUSB, etc. void UBX_CELL::enableDebugging(Print &debugPort) { - _debugPort = &debugPort; - _printDebug = true; + _debugPort = &debugPort; + _printDebug = true; } -//Calling this function with nothing sets the debug port to Serial -//You can also call it with other streams like Serial1, SerialUSB, etc. +// Calling this function with nothing sets the debug port to Serial +// You can also call it with other streams like Serial1, SerialUSB, etc. void UBX_CELL::enableAtDebugging(Print &debugPort) { - _debugAtPort = &debugPort; - _printAtDebug = true; + _debugAtPort = &debugPort; + _printAtDebug = true; } // This function was originally written by Matthew Menze for the LTE Shield (SARA-R4) library @@ -208,625 +216,637 @@ void UBX_CELL::enableAtDebugging(Print &debugPort) // It also has a built-in timeout - which ::poll does not bool UBX_CELL::bufferedPoll(void) { - if (_bufferedPollReentrant == true) // Check for reentry (i.e. bufferedPoll has been called from inside a callback) - return false; + if (_bufferedPollReentrant == true) // Check for reentry (i.e. bufferedPoll has been called from inside a callback) + return false; - _bufferedPollReentrant = true; + _bufferedPollReentrant = true; - int avail = 0; - char c = 0; - bool handled = false; - unsigned long timeIn = millis(); - char *event; - int backlogLen = _saraResponseBacklogLength; + int avail = 0; + char c = 0; + bool handled = false; + unsigned long timeIn = millis(); + char *event; + int backlogLen = _saraResponseBacklogLength; - memset(_saraRXBuffer, 0, _RXBuffSize); // Clear _saraRXBuffer + memset(_saraRXBuffer, 0, _RXBuffSize); // Clear _saraRXBuffer - // Does the backlog contain any data? If it does, copy it into _saraRXBuffer and then clear the backlog - if (_saraResponseBacklogLength > 0) - { - //The backlog also logs reads from other tasks like transmitting. - if (_printDebug == true) + // Does the backlog contain any data? If it does, copy it into _saraRXBuffer and then clear the backlog + if (_saraResponseBacklogLength > 0) { - _debugPort->print(F("bufferedPoll: backlog found! backlogLen is ")); - _debugPort->println(_saraResponseBacklogLength); - } - memcpy(_saraRXBuffer + avail, _saraResponseBacklog, _saraResponseBacklogLength); - avail += _saraResponseBacklogLength; - memset(_saraResponseBacklog, 0, _RXBuffSize); // Clear the backlog making sure it is NULL-terminated - _saraResponseBacklogLength = 0; - } - - if ((hwAvailable() > 0) || (backlogLen > 0)) // If either new data is available, or backlog had data. - { - //Check for incoming serial data. Copy it into the backlog - - // Important note: - // On ESP32, Serial.available only provides an update every ~120 bytes during the reception of long messages: - // https://gitter.im/espressif/arduino-esp32?at=5e25d6370a1cf54144909c85 - // Be aware that if a long message is being received, the code below will timeout after _rxWindowMillis = 2 millis. - // At 115200 baud, hwAvailable takes ~120 * 10 / 115200 = 10.4 millis before it indicates that data is being received. - - while (((millis() - timeIn) < _rxWindowMillis) && (avail < _RXBuffSize)) - { - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is NULL - { - c = readChar(); - // bufferedPoll is only interested in the URCs. - // The URCs are all readable. - // strtok does not like NULL characters. - // So we need to make sure no NULL characters are added to _saraRXBuffer - if (c == '\0') - c = '0'; // Convert any NULLs to ASCII Zeros - _saraRXBuffer[avail++] = c; - timeIn = millis(); - } else { - yield(); - } - } - - // _saraRXBuffer now contains the backlog (if any) and the new serial data (if any) - - // A health warning about strtok: - // strtok will convert any delimiters it finds ("\r\n" in our case) into NULL characters. - // Also, be very careful that you do not use strtok within an strtok while loop. - // The next call of strtok(NULL, ...) in the outer loop will use the pointer saved from the inner loop! - // In our case, strtok is also used in pruneBacklog, which is called by waitForRespone or sendCommandWithResponse, - // which is called by the parse functions called by processURCEvent... - // The solution is to use strtok_r - the reentrant version of strtok - - char *preservedEvent; - event = strtok_r(_saraRXBuffer, "\r\n", &preservedEvent); // Look for an 'event' (_saraRXBuffer contains something ending in \r\n) - - if (event != nullptr) - if (_printDebug == true) - _debugPort->println(F("bufferedPoll: event(s) found! ===>")); - - while (event != nullptr) // Keep going until all events have been processed - { - if (_printDebug == true) - { - _debugPort->print(F("bufferedPoll: start of event: ")); - _debugPort->println(event); - } - - //Process the event - bool latestHandled = processURCEvent((const char *)event); - if (latestHandled) { - if ((true == _printAtDebug) && (nullptr != event)) { - _debugAtPort->print(event); - } - handled = true; // handled will be true if latestHandled has ever been true - } - if ((_saraResponseBacklogLength > 0) && ((avail + _saraResponseBacklogLength) < _RXBuffSize)) // Has any new data been added to the backlog? - { + // The backlog also logs reads from other tasks like transmitting. if (_printDebug == true) { - _debugPort->println(F("bufferedPoll: new backlog added!")); + _debugPort->print(F("bufferedPoll: backlog found! backlogLen is ")); + _debugPort->println(_saraResponseBacklogLength); } memcpy(_saraRXBuffer + avail, _saraResponseBacklog, _saraResponseBacklogLength); avail += _saraResponseBacklogLength; - memset(_saraResponseBacklog, 0, _RXBuffSize); //Clear out the backlog buffer again. + memset(_saraResponseBacklog, 0, _RXBuffSize); // Clear the backlog making sure it is NULL-terminated _saraResponseBacklogLength = 0; - } + } - //Walk through any remaining events - event = strtok_r(nullptr, "\r\n", &preservedEvent); + if ((hwAvailable() > 0) || (backlogLen > 0)) // If either new data is available, or backlog had data. + { + // Check for incoming serial data. Copy it into the backlog - if (_printDebug == true) - _debugPort->println(F("bufferedPoll: end of event")); //Just to denote end of processing event. + // Important note: + // On ESP32, Serial.available only provides an update every ~120 bytes during the reception of long messages: + // https://gitter.im/espressif/arduino-esp32?at=5e25d6370a1cf54144909c85 + // Be aware that if a long message is being received, the code below will timeout after _rxWindowMillis = 2 + // millis. At 115200 baud, hwAvailable takes ~120 * 10 / 115200 = 10.4 millis before it indicates that data is + // being received. - if (event == nullptr) - if (_printDebug == true) - _debugPort->println(F("bufferedPoll: <=== end of event(s)!")); + while (((millis() - timeIn) < _rxWindowMillis) && (avail < _RXBuffSize)) + { + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is NULL + { + c = readChar(); + // bufferedPoll is only interested in the URCs. + // The URCs are all readable. + // strtok does not like NULL characters. + // So we need to make sure no NULL characters are added to _saraRXBuffer + if (c == '\0') + c = '0'; // Convert any NULLs to ASCII Zeros + _saraRXBuffer[avail++] = c; + timeIn = millis(); + } + else + { + yield(); + } + } + + // _saraRXBuffer now contains the backlog (if any) and the new serial data (if any) + + // A health warning about strtok: + // strtok will convert any delimiters it finds ("\r\n" in our case) into NULL characters. + // Also, be very careful that you do not use strtok within an strtok while loop. + // The next call of strtok(NULL, ...) in the outer loop will use the pointer saved from the inner loop! + // In our case, strtok is also used in pruneBacklog, which is called by waitForRespone or + // sendCommandWithResponse, which is called by the parse functions called by processURCEvent... The solution is + // to use strtok_r - the reentrant version of strtok + + char *preservedEvent; + event = strtok_r(_saraRXBuffer, "\r\n", + &preservedEvent); // Look for an 'event' (_saraRXBuffer contains something ending in \r\n) + + if (event != nullptr) + if (_printDebug == true) + _debugPort->println(F("bufferedPoll: event(s) found! ===>")); + + while (event != nullptr) // Keep going until all events have been processed + { + if (_printDebug == true) + { + _debugPort->print(F("bufferedPoll: start of event: ")); + _debugPort->println(event); + } + + // Process the event + bool latestHandled = processURCEvent((const char *)event); + if (latestHandled) + { + if ((true == _printAtDebug) && (nullptr != event)) + { + _debugAtPort->print(event); + } + handled = true; // handled will be true if latestHandled has ever been true + } + if ((_saraResponseBacklogLength > 0) && + ((avail + _saraResponseBacklogLength) < _RXBuffSize)) // Has any new data been added to the backlog? + { + if (_printDebug == true) + { + _debugPort->println(F("bufferedPoll: new backlog added!")); + } + memcpy(_saraRXBuffer + avail, _saraResponseBacklog, _saraResponseBacklogLength); + avail += _saraResponseBacklogLength; + memset(_saraResponseBacklog, 0, _RXBuffSize); // Clear out the backlog buffer again. + _saraResponseBacklogLength = 0; + } + + // Walk through any remaining events + event = strtok_r(nullptr, "\r\n", &preservedEvent); + + if (_printDebug == true) + _debugPort->println(F("bufferedPoll: end of event")); // Just to denote end of processing event. + + if (event == nullptr) + if (_printDebug == true) + _debugPort->println(F("bufferedPoll: <=== end of event(s)!")); + } } - } - _bufferedPollReentrant = false; + _bufferedPollReentrant = false; - return handled; + return handled; } // /bufferedPoll -bool UBX_CELL::urcHandlerReadSocket(const char* event) -{ - // URC: +UUSORD (Read Socket Data) - int socket, length; - char *searchPtr = strstr(event, UBX_CELL_READ_SOCKET_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_READ_SOCKET_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // Skip spaces - int ret = sscanf(searchPtr, "%d,%d", &socket, &length); - if (ret == 2) - { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: read socket data")); - // From the UBX_CELL AT Commands Manual: - // "For the UDP socket type the URC +UUSORD: , notifies that a UDP packet has been received, - // either when buffer is empty or after a UDP packet has been read and one or more packets are stored in the - // buffer." - // So we need to check if this is a TCP socket or a UDP socket: - // If UDP, we call parseSocketReadIndicationUDP. - // Otherwise, we call parseSocketReadIndication. - if (_lastSocketProtocol[socket] == UBX_CELL_UDP) - { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: received +UUSORD but socket is UDP. Calling parseSocketReadIndicationUDP")); - parseSocketReadIndicationUDP(socket, length); - } - else - parseSocketReadIndication(socket, length); - return true; +bool UBX_CELL::urcHandlerReadSocket(const char *event) +{ + // URC: +UUSORD (Read Socket Data) + int socket, length; + char *searchPtr = strstr(event, UBX_CELL_READ_SOCKET_URC); + if (searchPtr != nullptr) + { + searchPtr += strlen(UBX_CELL_READ_SOCKET_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // Skip spaces + int ret = sscanf(searchPtr, "%d,%d", &socket, &length); + if (ret == 2) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: read socket data")); + // From the UBX_CELL AT Commands Manual: + // "For the UDP socket type the URC +UUSORD: , notifies that a UDP packet has been received, + // either when buffer is empty or after a UDP packet has been read and one or more packets are stored in + // the buffer." + // So we need to check if this is a TCP socket or a UDP socket: + // If UDP, we call parseSocketReadIndicationUDP. + // Otherwise, we call parseSocketReadIndication. + if (_lastSocketProtocol[socket] == UBX_CELL_UDP) + { + if (_printDebug == true) + _debugPort->println(F( + "processReadEvent: received +UUSORD but socket is UDP. Calling parseSocketReadIndicationUDP")); + parseSocketReadIndicationUDP(socket, length); + } + else + parseSocketReadIndication(socket, length); + return true; + } + } + + return false; +} + +bool UBX_CELL::urcHandlerReadUDPSocket(const char *event) +{ + // URC: +UUSORF (Receive From command (UDP only)) + int socket, length; + char *searchPtr = strstr(event, UBX_CELL_READ_UDP_SOCKET_URC); + if (searchPtr != nullptr) + { + searchPtr += strlen(UBX_CELL_READ_UDP_SOCKET_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + int ret = sscanf(searchPtr, "%d,%d", &socket, &length); + if (ret == 2) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: UDP receive")); + parseSocketReadIndicationUDP(socket, length); + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerReadUDPSocket(const char* event) +bool UBX_CELL::urcHandlerListeningSocket(const char *event) { - // URC: +UUSORF (Receive From command (UDP only)) - int socket, length; - char *searchPtr = strstr(event, UBX_CELL_READ_UDP_SOCKET_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_READ_UDP_SOCKET_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - int ret = sscanf(searchPtr, "%d,%d", &socket, &length); - if (ret == 2) - { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: UDP receive")); - parseSocketReadIndicationUDP(socket, length); - return true; - } - } - - return false; -} - -bool UBX_CELL::urcHandlerListeningSocket(const char* event) -{ - // URC: +UUSOLI (Set Listening Socket) - int socket = 0; - int listenSocket = 0; - unsigned int port = 0; - unsigned int listenPort = 0; - IPAddress remoteIP = {0,0,0,0}; - IPAddress localIP = {0,0,0,0}; - int remoteIPstore[4] = {0,0,0,0}; - int localIPstore[4] = {0,0,0,0}; - - char *searchPtr = strstr(event, UBX_CELL_LISTEN_SOCKET_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_LISTEN_SOCKET_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - int ret = sscanf(searchPtr, - "%d,\"%d.%d.%d.%d\",%u,%d,\"%d.%d.%d.%d\",%u", - &socket, - &remoteIPstore[0], &remoteIPstore[1], &remoteIPstore[2], &remoteIPstore[3], - &port, &listenSocket, - &localIPstore[0], &localIPstore[1], &localIPstore[2], &localIPstore[3], - &listenPort); - for (int i = 0; i <= 3; i++) - { - if (ret >= 5) - remoteIP[i] = (uint8_t)remoteIPstore[i]; - if (ret >= 11) - localIP[i] = (uint8_t)localIPstore[i]; - } - if (ret >= 5) - { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: socket listen")); - parseSocketListenIndication(listenSocket, localIP, listenPort, socket, remoteIP, port); - return true; - } - } - - return false; -} - -bool UBX_CELL::urcHandlerCloseSocket(const char* event) -{ - // URC: +UUSOCL (Close Socket) - int socket; - char *searchPtr = strstr(event, UBX_CELL_CLOSE_SOCKET_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_CLOSE_SOCKET_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - int ret = sscanf(searchPtr, "%d", &socket); - if (ret == 1) - { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: socket close")); - if ((socket >= 0) && (socket <= 6)) - { - if (_socketCloseCallback != nullptr) - { - _socketCloseCallback(socket); - } - } - return true; - } - } - - return false; -} - -bool UBX_CELL::urcHandlerGNSSRequestLocation(const char* event) -{ - // URC: +UULOC (Localization information - CellLocate and hybrid positioning) - ClockData clck; - PositionData gps; - SpeedData spd; - unsigned long uncertainty; - int scanNum; - int latH, lonH, alt; - unsigned int speedU, cogU; - char latL[10], lonL[10]; - int dateStore[5]; - - // Maybe we should also scan for +UUGIND and extract the activated gnss system? - - // This assumes the ULOC response type is "0" or "1" - as selected by gpsRequest detailed - char *searchPtr = strstr(event, UBX_CELL_GNSS_REQUEST_LOCATION_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_GNSS_REQUEST_LOCATION_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, - "%d/%d/%d,%d:%d:%d.%d,%d.%[^,],%d.%[^,],%d,%lu,%u,%u,%*s", - &dateStore[0], &dateStore[1], &clck.date.year, - &dateStore[2], &dateStore[3], &dateStore[4], &clck.time.ms, - &latH, latL, &lonH, lonL, &alt, &uncertainty, - &speedU, &cogU); - clck.date.day = dateStore[0]; - clck.date.month = dateStore[1]; - clck.time.hour = dateStore[2]; - clck.time.minute = dateStore[3]; - clck.time.second = dateStore[4]; - - if (scanNum >= 13) - { - // Found a Location string! - if (_printDebug == true) - { - _debugPort->println(F("processReadEvent: location")); - } - - if (latH >= 0) - gps.lat = (float)latH + ((float)atol(latL) / pow(10, strlen(latL))); - else - gps.lat = (float)latH - ((float)atol(latL) / pow(10, strlen(latL))); - if (lonH >= 0) - gps.lon = (float)lonH + ((float)atol(lonL) / pow(10, strlen(lonL))); - else - gps.lon = (float)lonH - ((float)atol(lonL) / pow(10, strlen(lonL))); - gps.alt = (float)alt; - if (scanNum >= 15) // If detailed response, get speed data - { - spd.speed = (float)speedU; - spd.cog = (float)cogU; - } + // URC: +UUSOLI (Set Listening Socket) + int socket = 0; + int listenSocket = 0; + unsigned int port = 0; + unsigned int listenPort = 0; + IPAddress remoteIP = {0, 0, 0, 0}; + IPAddress localIP = {0, 0, 0, 0}; + int remoteIPstore[4] = {0, 0, 0, 0}; + int localIPstore[4] = {0, 0, 0, 0}; - // if (_printDebug == true) - // { - // _debugPort->print(F("processReadEvent: location: lat: ")); - // _debugPort->print(gps.lat, 7); - // _debugPort->print(F(" lon: ")); - // _debugPort->print(gps.lon, 7); - // _debugPort->print(F(" alt: ")); - // _debugPort->print(gps.alt, 2); - // _debugPort->print(F(" speed: ")); - // _debugPort->print(spd.speed, 2); - // _debugPort->print(F(" cog: ")); - // _debugPort->println(spd.cog, 2); - // } + char *searchPtr = strstr(event, UBX_CELL_LISTEN_SOCKET_URC); + if (searchPtr != nullptr) + { + searchPtr += strlen(UBX_CELL_LISTEN_SOCKET_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + int ret = sscanf(searchPtr, "%d,\"%d.%d.%d.%d\",%u,%d,\"%d.%d.%d.%d\",%u", &socket, &remoteIPstore[0], + &remoteIPstore[1], &remoteIPstore[2], &remoteIPstore[3], &port, &listenSocket, + &localIPstore[0], &localIPstore[1], &localIPstore[2], &localIPstore[3], &listenPort); + for (int i = 0; i <= 3; i++) + { + if (ret >= 5) + remoteIP[i] = (uint8_t)remoteIPstore[i]; + if (ret >= 11) + localIP[i] = (uint8_t)localIPstore[i]; + } + if (ret >= 5) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: socket listen")); + parseSocketListenIndication(listenSocket, localIP, listenPort, socket, remoteIP, port); + return true; + } + } - if (_gpsRequestCallback != nullptr) - { - _gpsRequestCallback(clck, gps, spd, uncertainty); - } + return false; +} - return true; +bool UBX_CELL::urcHandlerCloseSocket(const char *event) +{ + // URC: +UUSOCL (Close Socket) + int socket; + char *searchPtr = strstr(event, UBX_CELL_CLOSE_SOCKET_URC); + if (searchPtr != nullptr) + { + searchPtr += strlen(UBX_CELL_CLOSE_SOCKET_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + int ret = sscanf(searchPtr, "%d", &socket); + if (ret == 1) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: socket close")); + if ((socket >= 0) && (socket <= 6)) + { + if (_socketCloseCallback != nullptr) + { + _socketCloseCallback(socket); + } + } + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerSIMState(const char* event) +bool UBX_CELL::urcHandlerGNSSRequestLocation(const char *event) { - // URC: +UUSIMSTAT (SIM Status) - UBX_CELL_sim_states_t state; - int scanNum; - int stateStore; + // URC: +UULOC (Localization information - CellLocate and hybrid positioning) + ClockData clck; + PositionData gps; + SpeedData spd; + unsigned long uncertainty; + int scanNum; + int latH, lonH, alt; + unsigned int speedU, cogU; + char latL[10], lonL[10]; + int dateStore[5]; - char *searchPtr = strstr(event, UBX_CELL_SIM_STATE_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_SIM_STATE_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d", &stateStore); + // Maybe we should also scan for +UUGIND and extract the activated gnss system? - if (scanNum == 1) + // This assumes the ULOC response type is "0" or "1" - as selected by gpsRequest detailed + char *searchPtr = strstr(event, UBX_CELL_GNSS_REQUEST_LOCATION_URC); + if (searchPtr != nullptr) { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: SIM status")); + searchPtr += strlen(UBX_CELL_GNSS_REQUEST_LOCATION_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d/%d/%d,%d:%d:%d.%d,%d.%[^,],%d.%[^,],%d,%lu,%u,%u,%*s", &dateStore[0], + &dateStore[1], &clck.date.year, &dateStore[2], &dateStore[3], &dateStore[4], &clck.time.ms, + &latH, latL, &lonH, lonL, &alt, &uncertainty, &speedU, &cogU); + clck.date.day = dateStore[0]; + clck.date.month = dateStore[1]; + clck.time.hour = dateStore[2]; + clck.time.minute = dateStore[3]; + clck.time.second = dateStore[4]; + + if (scanNum >= 13) + { + // Found a Location string! + if (_printDebug == true) + { + _debugPort->println(F("processReadEvent: location")); + } - state = (UBX_CELL_sim_states_t)stateStore; + if (latH >= 0) + gps.lat = (float)latH + ((float)atol(latL) / pow(10, strlen(latL))); + else + gps.lat = (float)latH - ((float)atol(latL) / pow(10, strlen(latL))); + if (lonH >= 0) + gps.lon = (float)lonH + ((float)atol(lonL) / pow(10, strlen(lonL))); + else + gps.lon = (float)lonH - ((float)atol(lonL) / pow(10, strlen(lonL))); + gps.alt = (float)alt; + if (scanNum >= 15) // If detailed response, get speed data + { + spd.speed = (float)speedU; + spd.cog = (float)cogU; + } - if (_simStateReportCallback != nullptr) - { - _simStateReportCallback(state); - } + // if (_printDebug == true) + // { + // _debugPort->print(F("processReadEvent: location: lat: ")); + // _debugPort->print(gps.lat, 7); + // _debugPort->print(F(" lon: ")); + // _debugPort->print(gps.lon, 7); + // _debugPort->print(F(" alt: ")); + // _debugPort->print(gps.alt, 2); + // _debugPort->print(F(" speed: ")); + // _debugPort->print(spd.speed, 2); + // _debugPort->print(F(" cog: ")); + // _debugPort->println(spd.cog, 2); + // } + + if (_gpsRequestCallback != nullptr) + { + _gpsRequestCallback(clck, gps, spd, uncertainty); + } - return true; + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerHTTPCommand(const char* event) +bool UBX_CELL::urcHandlerSIMState(const char *event) { - // URC: +UUHTTPCR (HTTP Command Result) - int profile, command, result; - int scanNum; + // URC: +UUSIMSTAT (SIM Status) + UBX_CELL_sim_states_t state; + int scanNum; + int stateStore; - char *searchPtr = strstr(event, UBX_CELL_HTTP_COMMAND_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_HTTP_COMMAND_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d,%d", &profile, &command, &result); - - if (scanNum == 3) + char *searchPtr = strstr(event, UBX_CELL_SIM_STATE_URC); + if (searchPtr != nullptr) { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: HTTP command result")); + searchPtr += strlen(UBX_CELL_SIM_STATE_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d", &stateStore); - if ((profile >= 0) && (profile < UBX_CELL_NUM_HTTP_PROFILES)) - { - if (_httpCommandRequestCallback != nullptr) + if (scanNum == 1) { - _httpCommandRequestCallback(profile, command, result); - } - } + if (_printDebug == true) + _debugPort->println(F("processReadEvent: SIM status")); + + state = (UBX_CELL_sim_states_t)stateStore; - return true; + if (_simStateReportCallback != nullptr) + { + _simStateReportCallback(state); + } + + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerMQTTCommand(const char* event) +bool UBX_CELL::urcHandlerHTTPCommand(const char *event) { - // URC: +UUMQTTC (MQTT Command Result) - int command, result; - int scanNum; - int qos = -1; - String topic; + // URC: +UUHTTPCR (HTTP Command Result) + int profile, command, result; + int scanNum; - char *searchPtr = strstr(event, UBX_CELL_MQTT_COMMAND_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_MQTT_COMMAND_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') + char *searchPtr = strstr(event, UBX_CELL_HTTP_COMMAND_URC); + if (searchPtr != nullptr) { - searchPtr++; // skip spaces - } + searchPtr += strlen(UBX_CELL_HTTP_COMMAND_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,%d,%d", &profile, &command, &result); - scanNum = sscanf(searchPtr, "%d,%d", &command, &result); - if ((scanNum == 2) && (command == UBX_CELL_MQTT_COMMAND_SUBSCRIBE)) - { - char topicC[100] = ""; - scanNum = sscanf(searchPtr, "%*d,%*d,%d,\"%[^\"]\"", &qos, topicC); - topic = topicC; - } - if ((scanNum == 2) || (scanNum == 4)) - { - if (_printDebug == true) - { - _debugPort->println(F("processReadEvent: MQTT command result")); - } + if (scanNum == 3) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: HTTP command result")); - if (_mqttCommandRequestCallback != nullptr) - { - _mqttCommandRequestCallback(command, result); - } + if ((profile >= 0) && (profile < UBX_CELL_NUM_HTTP_PROFILES)) + { + if (_httpCommandRequestCallback != nullptr) + { + _httpCommandRequestCallback(profile, command, result); + } + } - return true; + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerPingCommand(const char* event) +bool UBX_CELL::urcHandlerMQTTCommand(const char *event) { - // URC: +UUPING (Ping Result) - int retry = 0; - int p_size = 0; - int ttl = 0; - String remote_host = ""; - IPAddress remoteIP = {0, 0, 0, 0}; - long rtt = 0; - int scanNum; - - // Try to extract the UUPING retries and payload size - char *searchPtr = strstr(event, UBX_CELL_PING_COMMAND_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_PING_COMMAND_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d,", &retry, &p_size); + // URC: +UUMQTTC (MQTT Command Result) + int command, result; + int scanNum; + int qos = -1; + String topic; - if (scanNum == 2) + char *searchPtr = strstr(event, UBX_CELL_MQTT_COMMAND_URC); + if (searchPtr != nullptr) { - if (_printDebug == true) - { - _debugPort->println(F("processReadEvent: ping")); - } + searchPtr += strlen(UBX_CELL_MQTT_COMMAND_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + { + searchPtr++; // skip spaces + } - searchPtr = strchr(++searchPtr, '\"'); // Search to the first quote + scanNum = sscanf(searchPtr, "%d,%d", &command, &result); + if ((scanNum == 2) && (command == UBX_CELL_MQTT_COMMAND_SUBSCRIBE)) + { + char topicC[100] = ""; + scanNum = sscanf(searchPtr, "%*d,%*d,%d,\"%[^\"]\"", &qos, topicC); + topic = topicC; + } + if ((scanNum == 2) || (scanNum == 4)) + { + if (_printDebug == true) + { + _debugPort->println(F("processReadEvent: MQTT command result")); + } - // Extract the remote host name, stop at the next quote - while ((*(++searchPtr) != '\"') && (*searchPtr != '\0')) - { - remote_host.concat(*(searchPtr)); - } + if (_mqttCommandRequestCallback != nullptr) + { + _mqttCommandRequestCallback(command, result); + } - if (*searchPtr != '\0') // Make sure we found a quote - { - // Extract IP address - int remoteIPstore[4]; - scanNum = sscanf(searchPtr, "\",\"%d.%d.%d.%d", - &remoteIPstore[0], &remoteIPstore[1], &remoteIPstore[2], &remoteIPstore[3]); - for (int i = 0; i <= 3; i++) - { - remoteIP[i] = (uint8_t)remoteIPstore[i]; + return true; } + } + + return false; +} + +bool UBX_CELL::urcHandlerPingCommand(const char *event) +{ + // URC: +UUPING (Ping Result) + int retry = 0; + int p_size = 0; + int ttl = 0; + String remote_host = ""; + IPAddress remoteIP = {0, 0, 0, 0}; + long rtt = 0; + int scanNum; + + // Try to extract the UUPING retries and payload size + char *searchPtr = strstr(event, UBX_CELL_PING_COMMAND_URC); + if (searchPtr != nullptr) + { + searchPtr += strlen(UBX_CELL_PING_COMMAND_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,%d,", &retry, &p_size); - if (scanNum == 4) // Make sure we extracted enough data + if (scanNum == 2) { - // Extract TTL, should be immediately after IP address - searchPtr = strchr(searchPtr + 2, ','); // +2 to skip the quote and comma - if(searchPtr != nullptr) - { - // It's possible the TTL is not present (eg. on LARA-R6), so we - // can ignore scanNum since ttl defaults to 0 anyways - scanNum = sscanf(searchPtr, ",%d", &ttl); + if (_printDebug == true) + { + _debugPort->println(F("processReadEvent: ping")); + } + + searchPtr = strchr(++searchPtr, '\"'); // Search to the first quote - // Extract RTT, should be immediately after TTL - searchPtr = strchr(searchPtr + 1, ','); // +1 to skip the comma - if(searchPtr != nullptr) + // Extract the remote host name, stop at the next quote + while ((*(++searchPtr) != '\"') && (*searchPtr != '\0')) { - scanNum = sscanf(searchPtr, ",%ld", &rtt); + remote_host.concat(*(searchPtr)); + } - // Callback, if it exists - if (_pingRequestCallback != nullptr) - { - _pingRequestCallback(retry, p_size, remote_host, remoteIP, ttl, rtt); - } + if (*searchPtr != '\0') // Make sure we found a quote + { + // Extract IP address + int remoteIPstore[4]; + scanNum = sscanf(searchPtr, "\",\"%d.%d.%d.%d", &remoteIPstore[0], &remoteIPstore[1], &remoteIPstore[2], + &remoteIPstore[3]); + for (int i = 0; i <= 3; i++) + { + remoteIP[i] = (uint8_t)remoteIPstore[i]; + } + + if (scanNum == 4) // Make sure we extracted enough data + { + // Extract TTL, should be immediately after IP address + searchPtr = strchr(searchPtr + 2, ','); // +2 to skip the quote and comma + if (searchPtr != nullptr) + { + // It's possible the TTL is not present (eg. on LARA-R6), so we + // can ignore scanNum since ttl defaults to 0 anyways + scanNum = sscanf(searchPtr, ",%d", &ttl); + + // Extract RTT, should be immediately after TTL + searchPtr = strchr(searchPtr + 1, ','); // +1 to skip the comma + if (searchPtr != nullptr) + { + scanNum = sscanf(searchPtr, ",%ld", &rtt); + + // Callback, if it exists + if (_pingRequestCallback != nullptr) + { + _pingRequestCallback(retry, p_size, remote_host, remoteIP, ttl, rtt); + } + } + } + } } - } + return true; } - } - return true; } - } - return false; + return false; } -bool UBX_CELL::urcHandlerFTPCommand(const char* event) +bool UBX_CELL::urcHandlerFTPCommand(const char *event) { - // URC: +UUFTPCR (FTP Command Result) - int ftpCmd; - int ftpResult; - int scanNum; - char *searchPtr = strstr(event, UBX_CELL_FTP_COMMAND_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_FTP_COMMAND_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') + // URC: +UUFTPCR (FTP Command Result) + int ftpCmd; + int ftpResult; + int scanNum; + char *searchPtr = strstr(event, UBX_CELL_FTP_COMMAND_URC); + if (searchPtr != nullptr) { - searchPtr++; // skip spaces - } + searchPtr += strlen(UBX_CELL_FTP_COMMAND_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + { + searchPtr++; // skip spaces + } - scanNum = sscanf(searchPtr, "%d,%d", &ftpCmd, &ftpResult); - if (scanNum == 2 && _ftpCommandRequestCallback != nullptr) - { - _ftpCommandRequestCallback(ftpCmd, ftpResult); - return true; + scanNum = sscanf(searchPtr, "%d,%d", &ftpCmd, &ftpResult); + if (scanNum == 2 && _ftpCommandRequestCallback != nullptr) + { + _ftpCommandRequestCallback(ftpCmd, ftpResult); + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerRegistrationStatus(const char* event) +bool UBX_CELL::urcHandlerRegistrationStatus(const char *event) { - // URC: +CREG - int status = 0; - unsigned int lac = 0, ci = 0, Act = 0; - char *searchPtr = strstr(event, UBX_CELL_REGISTRATION_STATUS_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_REGISTRATION_STATUS_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - int scanNum = sscanf(searchPtr, "%d,\"%4x\",\"%4x\",%d", &status, &lac, &ci, &Act); - if (scanNum == 4) + // URC: +CREG + int status = 0; + unsigned int lac = 0, ci = 0, Act = 0; + char *searchPtr = strstr(event, UBX_CELL_REGISTRATION_STATUS_URC); + if (searchPtr != nullptr) { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: CREG")); + searchPtr += strlen(UBX_CELL_REGISTRATION_STATUS_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + int scanNum = sscanf(searchPtr, "%d,\"%4x\",\"%4x\",%d", &status, &lac, &ci, &Act); + if (scanNum == 4) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: CREG")); - if (_registrationCallback != nullptr) - { - _registrationCallback((UBX_CELL_registration_status_t)status, lac, ci, Act); - } + if (_registrationCallback != nullptr) + { + _registrationCallback((UBX_CELL_registration_status_t)status, lac, ci, Act); + } - return true; + return true; + } } - } - return false; + return false; } -bool UBX_CELL::urcHandlerEPSRegistrationStatus(const char* event) +bool UBX_CELL::urcHandlerEPSRegistrationStatus(const char *event) { - // URC: +CEREG - int status = 0; - unsigned int tac = 0, ci = 0, Act = 0; - char *searchPtr = strstr(event, UBX_CELL_EPSREGISTRATION_STATUS_URC); - if (searchPtr != nullptr) - { - searchPtr += strlen(UBX_CELL_EPSREGISTRATION_STATUS_URC); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - int scanNum = sscanf(searchPtr, "%d,\"%4x\",\"%4x\",%d", &status, &tac, &ci, &Act); - if (scanNum == 4) + // URC: +CEREG + int status = 0; + unsigned int tac = 0, ci = 0, Act = 0; + char *searchPtr = strstr(event, UBX_CELL_EPSREGISTRATION_STATUS_URC); + if (searchPtr != nullptr) { - if (_printDebug == true) - _debugPort->println(F("processReadEvent: CEREG")); + searchPtr += + strlen(UBX_CELL_EPSREGISTRATION_STATUS_URC); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + int scanNum = sscanf(searchPtr, "%d,\"%4x\",\"%4x\",%d", &status, &tac, &ci, &Act); + if (scanNum == 4) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: CEREG")); - if (_epsRegistrationCallback != nullptr) - { - _epsRegistrationCallback((UBX_CELL_registration_status_t)status, tac, ci, Act); - } + if (_epsRegistrationCallback != nullptr) + { + _epsRegistrationCallback((UBX_CELL_registration_status_t)status, tac, ci, Act); + } - return true; + return true; + } } - } - return false; + return false; } -void UBX_CELL::addURCHandler(const char* urcString, UBX_CELL_urc_handler_t urcHandler) +void UBX_CELL::addURCHandler(const char *urcString, UBX_CELL_urc_handler_t urcHandler) { - _urcStrings.push_back(urcString); - _urcHandlers.push_back(urcHandler); + _urcStrings.push_back(urcString); + _urcHandlers.push_back(urcHandler); } // Parse incoming URC's - the associated parse functions pass the data to the user via the callbacks (if defined) bool UBX_CELL::processURCEvent(const char *event) { - // Iterate through each URC handler to see if it can handle this message - for(auto urcHandler : _urcHandlers) - { - if (urcHandler(event)) + // Iterate through each URC handler to see if it can handle this message + for (auto urcHandler : _urcHandlers) { - // This handler took care of it, so we're done! - return true; + if (urcHandler(event)) + { + // This handler took care of it, so we're done! + return true; + } } - } - // None of the handlers took care of it - return false; + // None of the handlers took care of it + return false; } // This is the original poll function. @@ -834,102 +854,108 @@ bool UBX_CELL::processURCEvent(const char *event) // ::bufferedPoll is the new improved version. It processes any data in the backlog and includes a timeout. bool UBX_CELL::poll(void) { - if (_pollReentrant == true) // Check for reentry (i.e. poll has been called from inside a callback) - return false; + if (_pollReentrant == true) // Check for reentry (i.e. poll has been called from inside a callback) + return false; - _pollReentrant = true; + _pollReentrant = true; - int avail = 0; - char c = 0; - bool handled = false; + int avail = 0; + char c = 0; + bool handled = false; - memset(_saraRXBuffer, 0, _RXBuffSize); // Clear _saraRXBuffer + memset(_saraRXBuffer, 0, _RXBuffSize); // Clear _saraRXBuffer - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is NULL - { - while (c != '\n') // Copy characters into _saraRXBuffer. Stop at the first new line + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is NULL { - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is NULL - { - c = readChar(); - _saraRXBuffer[avail++] = c; - } else { - yield(); - } - } + while (c != '\n') // Copy characters into _saraRXBuffer. Stop at the first new line + { + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is NULL + { + c = readChar(); + _saraRXBuffer[avail++] = c; + } + else + { + yield(); + } + } - // Now search for all supported URC's - handled = processURCEvent(_saraRXBuffer); - if (handled && (true == _printAtDebug)) { - _debugAtPort->write(_saraRXBuffer, avail); - } - if ((handled == false) && (strlen(_saraRXBuffer) > 2)) - { - if (_printDebug == true) - { - _debugPort->print(F("poll: ")); - _debugPort->println(_saraRXBuffer); - } - } - else - { + // Now search for all supported URC's + handled = processURCEvent(_saraRXBuffer); + if (handled && (true == _printAtDebug)) + { + _debugAtPort->write(_saraRXBuffer, avail); + } + if ((handled == false) && (strlen(_saraRXBuffer) > 2)) + { + if (_printDebug == true) + { + _debugPort->print(F("poll: ")); + _debugPort->println(_saraRXBuffer); + } + } + else + { + } } - } - _pollReentrant = false; + _pollReentrant = false; - return handled; + return handled; } -void UBX_CELL::setSocketListenCallback(void (*socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, unsigned int)) +void UBX_CELL::setSocketListenCallback(void (*socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, + unsigned int)) { - _socketListenCallback = socketListenCallback; + _socketListenCallback = socketListenCallback; } void UBX_CELL::setSocketReadCallback(void (*socketReadCallback)(int, String)) { - _socketReadCallback = socketReadCallback; + _socketReadCallback = socketReadCallback; } -void UBX_CELL::setSocketReadCallbackPlus(void (*socketReadCallbackPlus)(int, const char *, int, IPAddress, int)) // socket, data, length, remoteAddress, remotePort +void UBX_CELL::setSocketReadCallbackPlus(void (*socketReadCallbackPlus)( + int, const char *, int, IPAddress, int)) // socket, data, length, remoteAddress, remotePort { - _socketReadCallbackPlus = socketReadCallbackPlus; + _socketReadCallbackPlus = socketReadCallbackPlus; } void UBX_CELL::setSocketCloseCallback(void (*socketCloseCallback)(int)) { - _socketCloseCallback = socketCloseCallback; + _socketCloseCallback = socketCloseCallback; } -void UBX_CELL::setGpsReadCallback(void (*gpsRequestCallback)(ClockData time, - PositionData gps, SpeedData spd, unsigned long uncertainty)) +void UBX_CELL::setGpsReadCallback(void (*gpsRequestCallback)(ClockData time, PositionData gps, SpeedData spd, + unsigned long uncertainty)) { - _gpsRequestCallback = gpsRequestCallback; + _gpsRequestCallback = gpsRequestCallback; } void UBX_CELL::setSIMstateReportCallback(void (*simStateReportCallback)(UBX_CELL_sim_states_t state)) { - _simStateReportCallback = simStateReportCallback; + _simStateReportCallback = simStateReportCallback; } void UBX_CELL::setPSDActionCallback(void (*psdActionRequestCallback)(int result, IPAddress ip)) { - _psdActionRequestCallback = psdActionRequestCallback; + _psdActionRequestCallback = psdActionRequestCallback; } -void UBX_CELL::setPingCallback(void (*pingRequestCallback)(int retry, int p_size, String remote_hostname, IPAddress ip, int ttl, long rtt)) +void UBX_CELL::setPingCallback(void (*pingRequestCallback)(int retry, int p_size, String remote_hostname, IPAddress ip, + int ttl, long rtt)) { - _pingRequestCallback = pingRequestCallback; + _pingRequestCallback = pingRequestCallback; } void UBX_CELL::setHTTPCommandCallback(void (*httpCommandRequestCallback)(int profile, int command, int result)) { - _httpCommandRequestCallback = httpCommandRequestCallback; + _httpCommandRequestCallback = httpCommandRequestCallback; } void UBX_CELL::setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int command, int result)) { - _mqttCommandRequestCallback = mqttCommandRequestCallback; + _mqttCommandRequestCallback = mqttCommandRequestCallback; } void UBX_CELL::setFTPCommandCallback(void (*ftpCommandRequestCallback)(int command, int result)) @@ -937,5703 +963,5668 @@ void UBX_CELL::setFTPCommandCallback(void (*ftpCommandRequestCallback)(int comma _ftpCommandRequestCallback = ftpCommandRequestCallback; } -UBX_CELL_error_t UBX_CELL::setRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, unsigned int lac, unsigned int ci, int Act)) +UBX_CELL_error_t UBX_CELL::setRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, + unsigned int lac, unsigned int ci, + int Act)) { - _registrationCallback = registrationCallback; + _registrationCallback = registrationCallback; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_REGISTRATION_STATUS) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_REGISTRATION_STATUS, 2/*enable URC with location*/); - UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + char *command = ubx_cell_calloc_char(strlen(UBX_CELL_REGISTRATION_STATUS) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_REGISTRATION_STATUS, 2 /*enable URC with location*/); + UBX_CELL_error_t err = + sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setEpsRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, unsigned int tac, unsigned int ci, int Act)) +UBX_CELL_error_t UBX_CELL::setEpsRegistrationCallback( + void (*registrationCallback)(UBX_CELL_registration_status_t status, unsigned int tac, unsigned int ci, int Act)) { - _epsRegistrationCallback = registrationCallback; + _epsRegistrationCallback = registrationCallback; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_EPSREGISTRATION_STATUS, 2/*enable URC with location*/); - UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + char *command = ubx_cell_calloc_char(strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_EPSREGISTRATION_STATUS, 2 /*enable URC with location*/); + UBX_CELL_error_t err = + sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } size_t UBX_CELL::write(uint8_t c) { - return hwWrite(c); + return hwWrite(c); } size_t UBX_CELL::write(const char *str) { - return hwPrint(str); + return hwPrint(str); } size_t UBX_CELL::write(const char *buffer, size_t size) { - return hwWriteData(buffer, size); + return hwWriteData(buffer, size); } UBX_CELL_error_t UBX_CELL::at(void) { - UBX_CELL_error_t err; + UBX_CELL_error_t err; - err = sendCommandWithResponse(nullptr, UBX_CELL_RESPONSE_OK, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(nullptr, UBX_CELL_RESPONSE_OK, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - return err; + return err; } UBX_CELL_error_t UBX_CELL::enableEcho(bool enable) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_ECHO) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s%d", UBX_CELL_COMMAND_ECHO, enable ? 1 : 0); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_ECHO) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s%d", UBX_CELL_COMMAND_ECHO, enable ? 1 : 0); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } String UBX_CELL::getManufacturerID(void) { - char *response; - char idResponse[16] = {0x00}; // E.g. u-blox - UBX_CELL_error_t err; + char *response; + char idResponse[16] = {0x00}; // E.g. u-blox + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_MANU_ID, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (sscanf(response, "\r\n%15s\r\n", idResponse) != 1) + err = sendCommandWithResponse(UBX_CELL_COMMAND_MANU_ID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - memset(idResponse, 0, 16); + if (sscanf(response, "\r\n%15s\r\n", idResponse) != 1) + { + memset(idResponse, 0, 16); + } } - } - free(response); - return String(idResponse); + free(response); + return String(idResponse); } String UBX_CELL::getModelID(void) { - char *response; - char idResponse[32] = {0x00}; // E.g. SARA-R510M8Q - UBX_CELL_error_t err; + char *response; + char idResponse[32] = {0x00}; // E.g. SARA-R510M8Q + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_MODEL_ID, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (sscanf(response, "\r\n%31s\r\n", idResponse) != 1) + err = sendCommandWithResponse(UBX_CELL_COMMAND_MODEL_ID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - memset(idResponse, 0, 16); + if (sscanf(response, "\r\n%31s\r\n", idResponse) != 1) + { + memset(idResponse, 0, 16); + } } - } - free(response); - return String(idResponse); + free(response); + return String(idResponse); } String UBX_CELL::getFirmwareVersion(void) { - char *response; - char idResponse[16] = {0x00}; // E.g. 11.40 - UBX_CELL_error_t err; + char *response; + char idResponse[16] = {0x00}; // E.g. 11.40 + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_FW_VER_ID, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (sscanf(response, "\r\n%15s\r\n", idResponse) != 1) + err = sendCommandWithResponse(UBX_CELL_COMMAND_FW_VER_ID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - memset(idResponse, 0, 16); + if (sscanf(response, "\r\n%15s\r\n", idResponse) != 1) + { + memset(idResponse, 0, 16); + } } - } - free(response); - return String(idResponse); + free(response); + return String(idResponse); } String UBX_CELL::getSerialNo(void) { - char *response; - char idResponse[32] = {0x00}; // E.g. 357520070120767 - UBX_CELL_error_t err; + char *response; + char idResponse[32] = {0x00}; // E.g. 357520070120767 + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_SERIAL_NO, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (sscanf(response, "\r\n%31s\r\n", idResponse) != 1) + err = sendCommandWithResponse(UBX_CELL_COMMAND_SERIAL_NO, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - memset(idResponse, 0, 16); + if (sscanf(response, "\r\n%31s\r\n", idResponse) != 1) + { + memset(idResponse, 0, 16); + } } - } - free(response); - return String(idResponse); + free(response); + return String(idResponse); } String UBX_CELL::getIMEI(void) { - char *response; - char imeiResponse[32] = {0x00}; // E.g. 004999010640000 - UBX_CELL_error_t err; + char *response; + char imeiResponse[32] = {0x00}; // E.g. 004999010640000 + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_IMEI, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (sscanf(response, "\r\n%31s\r\n", imeiResponse) != 1) + err = sendCommandWithResponse(UBX_CELL_COMMAND_IMEI, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - memset(imeiResponse, 0, 16); - } - } - free(response); - return String(imeiResponse); + if (sscanf(response, "\r\n%31s\r\n", imeiResponse) != 1) + { + memset(imeiResponse, 0, 16); + } + } + free(response); + return String(imeiResponse); } String UBX_CELL::getIMSI(void) { - char *response; - char imsiResponse[32] = {0x00}; // E.g. 222107701772423 - UBX_CELL_error_t err; + char *response; + char imsiResponse[32] = {0x00}; // E.g. 222107701772423 + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_IMSI, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (sscanf(response, "\r\n%31s\r\n", imsiResponse) != 1) + err = sendCommandWithResponse(UBX_CELL_COMMAND_IMSI, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - memset(imsiResponse, 0, 16); + if (sscanf(response, "\r\n%31s\r\n", imsiResponse) != 1) + { + memset(imsiResponse, 0, 16); + } } - } - free(response); - return String(imsiResponse); + free(response); + return String(imsiResponse); } String UBX_CELL::getCCID(void) { - char *response; - char ccidResponse[32] = {0x00}; // E.g. +CCID: 8939107900010087330 - UBX_CELL_error_t err; + char *response; + char ccidResponse[32] = {0x00}; // E.g. +CCID: 8939107900010087330 + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_CCID, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "\r\n+CCID:"); - if (searchPtr != nullptr) + err = sendCommandWithResponse(UBX_CELL_COMMAND_CCID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("\r\n+CCID:"); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - if (sscanf(searchPtr, "%31s", ccidResponse) != 1) - { - ccidResponse[0] = 0; - } + char *searchPtr = strstr(response, "\r\n+CCID:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("\r\n+CCID:"); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + if (sscanf(searchPtr, "%31s", ccidResponse) != 1) + { + ccidResponse[0] = 0; + } + } } - } - free(response); - return String(ccidResponse); + free(response); + return String(ccidResponse); } String UBX_CELL::getSubscriberNo(void) { - char *response; - char idResponse[128] = {0x00}; // E.g. +CNUM: "ABCD . AAA","123456789012",129 - UBX_CELL_error_t err; + char *response; + char idResponse[128] = {0x00}; // E.g. +CNUM: "ABCD . AAA","123456789012",129 + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_CNUM, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "\r\n+CNUM:"); - if (searchPtr != nullptr) + err = sendCommandWithResponse(UBX_CELL_COMMAND_CNUM, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_10_SEC_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("\r\n+CNUM:"); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - if (sscanf(searchPtr, "%127s", idResponse) != 1) - { - idResponse[0] = 0; - } + char *searchPtr = strstr(response, "\r\n+CNUM:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("\r\n+CNUM:"); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + if (sscanf(searchPtr, "%127s", idResponse) != 1) + { + idResponse[0] = 0; + } + } } - } - free(response); - return String(idResponse); + free(response); + return String(idResponse); } String UBX_CELL::getCapabilities(void) { - char *response; - char idResponse[128] = {0x00}; // E.g. +GCAP: +FCLASS, +CGSM - UBX_CELL_error_t err; + char *response; + char idResponse[128] = {0x00}; // E.g. +GCAP: +FCLASS, +CGSM + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); + response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_REQ_CAP, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "\r\n+GCAP:"); - if (searchPtr != nullptr) + err = sendCommandWithResponse(UBX_CELL_COMMAND_REQ_CAP, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("\r\n+GCAP:"); // Move searchPtr to first character - probably a space - while (*searchPtr == ' ') searchPtr++; // skip spaces - if (sscanf(searchPtr, "%127s", idResponse) != 1) - { - idResponse[0] = 0; - } + char *searchPtr = strstr(response, "\r\n+GCAP:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("\r\n+GCAP:"); // Move searchPtr to first character - probably a space + while (*searchPtr == ' ') + searchPtr++; // skip spaces + if (sscanf(searchPtr, "%127s", idResponse) != 1) + { + idResponse[0] = 0; + } + } } - } - free(response); - return String(idResponse); + free(response); + return String(idResponse); } UBX_CELL_error_t UBX_CELL::reset(void) { - UBX_CELL_error_t err; + UBX_CELL_error_t err; - err = functionality(SILENT_RESET_WITH_SIM); - if (err == UBX_CELL_ERROR_SUCCESS) - { - // Reset will set the baud rate back to 115200 - //beginSerial(9600); - err = UBX_CELL_ERROR_INVALID; - while (err != UBX_CELL_ERROR_SUCCESS) + err = functionality(SILENT_RESET_WITH_SIM); + if (err == UBX_CELL_ERROR_SUCCESS) { - beginSerial(UBX_CELL_DEFAULT_BAUD_RATE); - setBaud(_baud); - beginSerial(_baud); - err = at(); + // Reset will set the baud rate back to 115200 + // beginSerial(9600); + err = UBX_CELL_ERROR_INVALID; + while (err != UBX_CELL_ERROR_SUCCESS) + { + beginSerial(UBX_CELL_DEFAULT_BAUD_RATE); + setBaud(_baud); + beginSerial(_baud); + err = at(); + } + return init(_baud); } - return init(_baud); - } - return err; + return err; } String UBX_CELL::clock(void) { - UBX_CELL_error_t err; - char *command; - char *response; - char *clockBegin; - char *clockEnd; + UBX_CELL_error_t err; + char *command; + char *response; + char *clockBegin; + char *clockEnd; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + 2); - if (command == nullptr) - return ""; - sprintf(command, "%s?", UBX_CELL_COMMAND_CLOCK); + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + 2); + if (command == nullptr) + return ""; + sprintf(command, "%s?", UBX_CELL_COMMAND_CLOCK); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return ""; - } + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return ""; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(command); - free(response); - return ""; - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(command); + free(response); + return ""; + } - // Response format: \r\n+CCLK: "YY/MM/DD,HH:MM:SS-TZ"\r\n\r\nOK\r\n - clockBegin = strchr(response, '\"'); // Find first quote - if (clockBegin == nullptr) - { - free(command); - free(response); - return ""; - } - clockBegin += 1; // Increment pointer to begin at first number - clockEnd = strchr(clockBegin, '\"'); // Find last quote - if (clockEnd == nullptr) - { - free(command); - free(response); - return ""; - } - *(clockEnd) = '\0'; // Set last quote to null char -- end string + // Response format: \r\n+CCLK: "YY/MM/DD,HH:MM:SS-TZ"\r\n\r\nOK\r\n + clockBegin = strchr(response, '\"'); // Find first quote + if (clockBegin == nullptr) + { + free(command); + free(response); + return ""; + } + clockBegin += 1; // Increment pointer to begin at first number + clockEnd = strchr(clockBegin, '\"'); // Find last quote + if (clockEnd == nullptr) + { + free(command); + free(response); + return ""; + } + *(clockEnd) = '\0'; // Set last quote to null char -- end string - String clock = String(clockBegin); // Extract the clock as a String _before_ freeing response + String clock = String(clockBegin); // Extract the clock as a String _before_ freeing response - free(command); - free(response); + free(command); + free(response); - return (clock); + return (clock); } -UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, - uint8_t *h, uint8_t *min, uint8_t *s, int8_t *tz) +UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s, int8_t *tz) { - UBX_CELL_error_t err; - char *command; - char *response; - char tzPlusMinus; - int scanNum = 0; + UBX_CELL_error_t err; + char *command; + char *response; + char tzPlusMinus; + int scanNum = 0; - int iy, imo, id, ih, imin, is, itz; + int iy, imo, id, ih, imin, is, itz; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_COMMAND_CLOCK); + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_COMMAND_CLOCK); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - // Response format (if TZ is negative): \r\n+CCLK: "YY/MM/DD,HH:MM:SS-TZ"\r\n\r\nOK\r\n - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+CCLK:"); - if (searchPtr != nullptr) + // Response format (if TZ is negative): \r\n+CCLK: "YY/MM/DD,HH:MM:SS-TZ"\r\n\r\nOK\r\n + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("+CCLK:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "\"%d/%d/%d,%d:%d:%d%c%d\"\r\n", - &iy, &imo, &id, &ih, &imin, &is, &tzPlusMinus, &itz); + char *searchPtr = strstr(response, "+CCLK:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+CCLK:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = + sscanf(searchPtr, "\"%d/%d/%d,%d:%d:%d%c%d\"\r\n", &iy, &imo, &id, &ih, &imin, &is, &tzPlusMinus, &itz); + } + if (scanNum == 8) + { + *y = iy; + *mo = imo; + *d = id; + *h = ih; + *min = imin; + *s = is; + if (tzPlusMinus == '-') + *tz = 0 - itz; + else + *tz = itz; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - if (scanNum == 8) - { - *y = iy; - *mo = imo; - *d = id; - *h = ih; - *min = imin; - *s = is; - if (tzPlusMinus == '-') - *tz = 0 - itz; - else - *tz = itz; + + free(command); + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::setClock(uint8_t y, uint8_t mo, uint8_t d, uint8_t h, uint8_t min, uint8_t s, int8_t tz) +{ + // Convert y,mo,d,h,min,s,tz into a String + // Some platforms don't support sprintf correctly (for %02d or %+02d) so we need to build the String manually + // Format is "yy/MM/dd,hh:mm:ss+TZ" + // TZ can be +/- and is in increments of 15 minutes (not hours) + + String theTime = ""; + + theTime.concat(y / 10); + theTime.concat(y % 10); + theTime.concat('/'); + theTime.concat(mo / 10); + theTime.concat(mo % 10); + theTime.concat('/'); + theTime.concat(d / 10); + theTime.concat(d % 10); + theTime.concat(','); + theTime.concat(h / 10); + theTime.concat(h % 10); + theTime.concat(':'); + theTime.concat(min / 10); + theTime.concat(min % 10); + theTime.concat(':'); + theTime.concat(s / 10); + theTime.concat(s % 10); + if (tz < 0) + { + theTime.concat('-'); + tz = 0 - tz; } else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - free(command); - free(response); - return err; -} - -UBX_CELL_error_t UBX_CELL::setClock(uint8_t y, uint8_t mo, uint8_t d, - uint8_t h, uint8_t min, uint8_t s, int8_t tz) -{ - //Convert y,mo,d,h,min,s,tz into a String - //Some platforms don't support sprintf correctly (for %02d or %+02d) so we need to build the String manually - //Format is "yy/MM/dd,hh:mm:ss+TZ" - //TZ can be +/- and is in increments of 15 minutes (not hours) - - String theTime = ""; - - theTime.concat(y / 10); - theTime.concat(y % 10); - theTime.concat('/'); - theTime.concat(mo / 10); - theTime.concat(mo % 10); - theTime.concat('/'); - theTime.concat(d / 10); - theTime.concat(d % 10); - theTime.concat(','); - theTime.concat(h / 10); - theTime.concat(h % 10); - theTime.concat(':'); - theTime.concat(min / 10); - theTime.concat(min % 10); - theTime.concat(':'); - theTime.concat(s / 10); - theTime.concat(s % 10); - if (tz < 0) - { - theTime.concat('-'); - tz = 0 - tz; - } - else - theTime.concat('+'); - theTime.concat(tz / 10); - theTime.concat(tz % 10); - - return (setClock(theTime)); + theTime.concat('+'); + theTime.concat(tz / 10); + theTime.concat(tz % 10); + + return (setClock(theTime)); } UBX_CELL_error_t UBX_CELL::setClock(String theTime) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + theTime.length() + 8); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_COMMAND_CLOCK, theTime.c_str()); + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + theTime.length() + 8); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", UBX_CELL_COMMAND_CLOCK, theTime.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } void UBX_CELL::autoTimeZoneForBegin(bool tz) { - _autoTimeZoneForBegin = tz; + _autoTimeZoneForBegin = tz; } UBX_CELL_error_t UBX_CELL::autoTimeZone(bool enable) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_AUTO_TZ) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_COMMAND_AUTO_TZ, enable ? 1 : 0); + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_AUTO_TZ) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_COMMAND_AUTO_TZ, enable ? 1 : 0); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } int8_t UBX_CELL::rssi(void) { - char *command; - char *response; - UBX_CELL_error_t err; - int rssi; + char *command; + char *response; + UBX_CELL_error_t err; + int rssi; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SIGNAL_QUALITY) + 1); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s", UBX_CELL_SIGNAL_QUALITY); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SIGNAL_QUALITY) + 1); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s", UBX_CELL_SIGNAL_QUALITY); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, 10000, - minimumResponseAllocation, AT_COMMAND); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(command); - free(response); - return -1; - } - - int scanned = 0; - char *searchPtr = strstr(response, "+CSQ:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+CSQ:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,%*d", &rssi); - } - if (scanned != 1) - { - rssi = -1; - } - - free(command); - free(response); - return rssi; -} - -UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality& signal_quality) -{ - char *command; - char *response; - UBX_CELL_error_t err; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_EXT_SIGNAL_QUALITY) + 1); - if (command == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - sprintf(command, "%s", UBX_CELL_EXT_SIGNAL_QUALITY); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, - UBX_CELL_RESPONSE_OK_OR_ERROR, response, 10000, - minimumResponseAllocation, AT_COMMAND); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(command); - free(response); - return UBX_CELL_ERROR_ERROR; - } - - int scanned = 0; - const char * responseStr = "+CESQ:"; - char *searchPtr = strstr(response, responseStr); - if (searchPtr != nullptr) - { - searchPtr += strlen(responseStr); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%u,%u,%u,%u,%u,%u", &signal_quality.rxlev, &signal_quality.ber, - &signal_quality.rscp, &signal_quality.enc0, &signal_quality.rsrq, &signal_quality.rsrp); - } - - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - if (scanned == 6) - { - err = UBX_CELL_ERROR_SUCCESS; - } + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - free(command); - free(response); - return err; -} + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, 10000, minimumResponseAllocation, + AT_COMMAND); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(command); + free(response); + return -1; + } + + int scanned = 0; + char *searchPtr = strstr(response, "+CSQ:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+CSQ:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,%*d", &rssi); + } + if (scanned != 1) + { + rssi = -1; + } -UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int status; - const char* tag = eps ? UBX_CELL_EPSREGISTRATION_STATUS : UBX_CELL_REGISTRATION_STATUS; - command = ubx_cell_calloc_char(strlen(tag) + 3); - if (command == nullptr) - return UBX_CELL_REGISTRATION_INVALID; - sprintf(command, "%s?", tag); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_REGISTRATION_INVALID; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, - minimumResponseAllocation, AT_COMMAND); - if (err != UBX_CELL_ERROR_SUCCESS) - { free(command); free(response); - return UBX_CELL_REGISTRATION_INVALID; - } - - int scanned = 0; - const char *startTag = eps ? UBX_CELL_EPSREGISTRATION_STATUS_URC : UBX_CELL_REGISTRATION_STATUS_URC; - char *searchPtr = strstr(response, startTag); - if (searchPtr != nullptr) - { - searchPtr += eps ? strlen(UBX_CELL_EPSREGISTRATION_STATUS_URC) : strlen(UBX_CELL_REGISTRATION_STATUS_URC); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%*d,%d", &status); - } - if (scanned != 1) - status = UBX_CELL_REGISTRATION_INVALID; - - free(command); - free(response); - return (UBX_CELL_registration_status_t)status; + return rssi; } -bool UBX_CELL::setNetworkProfile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) +UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) { - mobile_network_operator_t currentMno; - - // Check currently set MNO profile - if (getMNOprofile(¤tMno) != UBX_CELL_ERROR_SUCCESS) - { - return false; - } + char *command; + char *response; + UBX_CELL_error_t err; - if (currentMno == mno) - { - return true; - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_EXT_SIGNAL_QUALITY) + 1); + if (command == nullptr) + { + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - // Disable transmit and receive so we can change operator - if (functionality(MINIMUM_FUNCTIONALITY) != UBX_CELL_ERROR_SUCCESS) - { - return false; - } + sprintf(command, "%s", UBX_CELL_EXT_SIGNAL_QUALITY); - if (setMNOprofile(mno, autoReset, urcNotification) != UBX_CELL_ERROR_SUCCESS) - { - return false; - } + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - if (reset() != UBX_CELL_ERROR_SUCCESS) - { - return false; - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, 10000, minimumResponseAllocation, + AT_COMMAND); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(command); + free(response); + return UBX_CELL_ERROR_ERROR; + } - return true; -} + int scanned = 0; + const char *responseStr = "+CESQ:"; + char *searchPtr = strstr(response, responseStr); + if (searchPtr != nullptr) + { + searchPtr += strlen(responseStr); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%u,%u,%u,%u,%u,%u", &signal_quality.rxlev, &signal_quality.ber, + &signal_quality.rscp, &signal_quality.enc0, &signal_quality.rsrq, &signal_quality.rsrp); + } -mobile_network_operator_t UBX_CELL::getNetworkProfile(void) -{ - mobile_network_operator_t mno; - UBX_CELL_error_t err; + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + if (scanned == 6) + { + err = UBX_CELL_ERROR_SUCCESS; + } - err = getMNOprofile(&mno); - if (err != UBX_CELL_ERROR_SUCCESS) - { - return MNO_INVALID; - } - return mno; + free(command); + free(response); + return err; } -UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdpType) +UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) { - UBX_CELL_error_t err; - char *command; - char pdpStr[8]; - - memset(pdpStr, 0, 8); - - if (cid >= 8) - return UBX_CELL_ERROR_UNEXPECTED_PARAM; + char *command; + char *response; + UBX_CELL_error_t err; + int status; + const char *tag = eps ? UBX_CELL_EPSREGISTRATION_STATUS : UBX_CELL_REGISTRATION_STATUS; + command = ubx_cell_calloc_char(strlen(tag) + 3); + if (command == nullptr) + return UBX_CELL_REGISTRATION_INVALID; + sprintf(command, "%s?", tag); - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_DEF) + strlen(apn.c_str()) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - switch (pdpType) - { - case PDP_TYPE_INVALID: - free(command); - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - break; - case PDP_TYPE_IP: - memcpy(pdpStr, "IP", 2); - break; - case PDP_TYPE_NONIP: - memcpy(pdpStr, "NONIP", 5); - break; - case PDP_TYPE_IPV4V6: - memcpy(pdpStr, "IPV4V6", 6); - break; - case PDP_TYPE_IPV6: - memcpy(pdpStr, "IPV6", 4); - break; - default: - free(command); - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - break; - } - if (apn == nullptr) - { - if (_printDebug == true) - _debugPort->println(F("setAPN: nullptr")); - sprintf(command, "%s=%d,\"%s\",\"\"", UBX_CELL_MESSAGE_PDP_DEF, - cid, pdpStr); - } - else - { - if (_printDebug == true) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - _debugPort->print(F("setAPN: ")); - _debugPort->println(apn); + free(command); + return UBX_CELL_REGISTRATION_INVALID; } - sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MESSAGE_PDP_DEF, - cid, pdpStr, apn.c_str()); - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - - free(command); - - return err; -} - -// Return the Access Point Name and IP address for the chosen context identifier -UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_pdp_type* pdpType) -{ - UBX_CELL_error_t err; - char *command; - char *response; - if (cid > UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) - return UBX_CELL_ERROR_ERROR; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, + minimumResponseAllocation, AT_COMMAND); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(command); + free(response); + return UBX_CELL_REGISTRATION_INVALID; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_DEF) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_MESSAGE_PDP_DEF); + int scanned = 0; + const char *startTag = eps ? UBX_CELL_EPSREGISTRATION_STATUS_URC : UBX_CELL_REGISTRATION_STATUS_URC; + char *searchPtr = strstr(response, startTag); + if (searchPtr != nullptr) + { + searchPtr += eps ? strlen(UBX_CELL_EPSREGISTRATION_STATUS_URC) + : strlen(UBX_CELL_REGISTRATION_STATUS_URC); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%*d,%d", &status); + } + if (scanned != 1) + status = UBX_CELL_REGISTRATION_INVALID; - response = ubx_cell_calloc_char(1024); - if (response == nullptr) - { free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT, 1024); - - if (err == UBX_CELL_ERROR_SUCCESS) - { - // Example: - // +CGDCONT: 0,"IP","payandgo.o2.co.uk","0.0.0.0",0,0,0,0,0,0,0,0,0,0 - // +CGDCONT: 1,"IP","payandgo.o2.co.uk.mnc010.mcc234.gprs","10.160.182.234",0,0,0,2,0,0,0,0,0,0 - int rcid = -1; - char *searchPtr = response; - - bool keepGoing = true; - while (keepGoing == true) - { - int scanned = 0; - // Find the first/next occurrence of +CGDCONT: - searchPtr = strstr(searchPtr, "+CGDCONT:"); - if (searchPtr != nullptr) - { - char strPdpType[10]; - char strApn[128]; - int ipOct[4]; - - searchPtr += strlen("+CGDCONT:"); // Point to the cid - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,\"%[^\"]\",\"%[^\"]\",\"%d.%d.%d.%d", - &rcid, strPdpType, strApn, - &ipOct[0], &ipOct[1], &ipOct[2], &ipOct[3]); - if ((scanned == 7) && (rcid == cid)) { - if (apn) *apn = strApn; - for (int o = 0; ip && (o < 4); o++) - { - (*ip)[o] = (uint8_t)ipOct[o]; - } - if (pdpType) { - *pdpType = (0 == strcmp(strPdpType, "IPV4V6")) ? PDP_TYPE_IPV4V6 : - (0 == strcmp(strPdpType, "IPV6")) ? PDP_TYPE_IPV6 : - (0 == strcmp(strPdpType, "IP")) ? PDP_TYPE_IP : - PDP_TYPE_INVALID; - } - keepGoing = false; - } - } - else // We don't have a match so let's clear the APN and IP address - { - if (apn) *apn = ""; - if (pdpType) *pdpType = PDP_TYPE_INVALID; - if (ip) *ip = {0, 0, 0, 0}; - keepGoing = false; - } - } - } - else - { - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - free(command); - free(response); - - return err; + free(response); + return (UBX_CELL_registration_status_t)status; } -UBX_CELL_error_t UBX_CELL::getSimStatus(String* code) +bool UBX_CELL::setNetworkProfile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) { - UBX_CELL_error_t err; - char *command; - char *response; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_SIMPIN) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_COMMAND_SIMPIN); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + mobile_network_operator_t currentMno; - if (err == UBX_CELL_ERROR_SUCCESS) - { - int scanned = 0; - char c[16]; - char *searchPtr = strstr(response, "+CPIN:"); - if (searchPtr != nullptr) { - searchPtr += strlen("+CPIN:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%15s\r\n", c); + // Check currently set MNO profile + if (getMNOprofile(¤tMno) != UBX_CELL_ERROR_SUCCESS) + { + return false; } - if (scanned == 1) + + if (currentMno == mno) { - if(code) - *code = c; + return true; } - else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - free(command); - free(response); + // Disable transmit and receive so we can change operator + if (functionality(MINIMUM_FUNCTIONALITY) != UBX_CELL_ERROR_SUCCESS) + { + return false; + } - return err; -} + if (setMNOprofile(mno, autoReset, urcNotification) != UBX_CELL_ERROR_SUCCESS) + { + return false; + } -UBX_CELL_error_t UBX_CELL::setSimPin(String pin) -{ - UBX_CELL_error_t err; - char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_SIMPIN) + 4 + pin.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_COMMAND_SIMPIN, pin.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + if (reset() != UBX_CELL_ERROR_SUCCESS) + { + return false; + } + + return true; } -UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) +mobile_network_operator_t UBX_CELL::getNetworkProfile(void) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SIM_STATE) + 4); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_SIM_STATE, mode); + mobile_network_operator_t mno; + UBX_CELL_error_t err; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + err = getMNOprofile(&mno); + if (err != UBX_CELL_ERROR_SUCCESS) + { + return MNO_INVALID; + } + return mno; } -UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) +UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdpType) { - UBX_CELL_error_t err; - char *command; - char *response; - - int m; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SIM_STATE) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_SIM_STATE); + UBX_CELL_error_t err; + char *command; + char pdpStr[8]; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + memset(pdpStr, 0, 8); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (cid >= 8) + return UBX_CELL_ERROR_UNEXPECTED_PARAM; - if (err == UBX_CELL_ERROR_SUCCESS) - { - int scanned = 0; - char *searchPtr = strstr(response, "+USIMSTAT:"); - if (searchPtr != nullptr) + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_DEF) + strlen(apn.c_str()) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + switch (pdpType) { - searchPtr += strlen("+USIMSTAT:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d\r\n", &m); + case PDP_TYPE_INVALID: + free(command); + return UBX_CELL_ERROR_UNEXPECTED_PARAM; + break; + case PDP_TYPE_IP: + memcpy(pdpStr, "IP", 2); + break; + case PDP_TYPE_NONIP: + memcpy(pdpStr, "NONIP", 5); + break; + case PDP_TYPE_IPV4V6: + memcpy(pdpStr, "IPV4V6", 6); + break; + case PDP_TYPE_IPV6: + memcpy(pdpStr, "IPV6", 4); + break; + default: + free(command); + return UBX_CELL_ERROR_UNEXPECTED_PARAM; + break; } - if (scanned == 1) + if (apn == nullptr) { - *mode = m; + if (_printDebug == true) + _debugPort->println(F("setAPN: nullptr")); + sprintf(command, "%s=%d,\"%s\",\"\"", UBX_CELL_MESSAGE_PDP_DEF, cid, pdpStr); } else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + { + if (_printDebug == true) + { + _debugPort->print(F("setAPN: ")); + _debugPort->println(apn); + } + sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MESSAGE_PDP_DEF, cid, pdpStr, apn.c_str()); + } - free(command); - free(response); - return err; -} + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -const char *PPP_L2P[5] = { - "", - "PPP", - "M-HEX", - "M-RAW_IP", - "M-OPT-PPP", -}; - -UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, - unsigned long dialNumber, UBX_CELL::UBX_CELL_l2p_t l2p) -{ - UBX_CELL_error_t err; - char *command; + free(command); - if ((dialing_type_char != 0) && (dialing_type_char != 'T') && - (dialing_type_char != 'P')) - { - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - } + return err; +} - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_ENTER_PPP) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (dialing_type_char != 0) - { - sprintf(command, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, - dialNumber, PPP_L2P[l2p], (unsigned int)cid); - } - else - { - sprintf(command, "%s*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, - dialNumber, PPP_L2P[l2p], (unsigned int)cid); - } +// Return the Access Point Name and IP address for the chosen context identifier +UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_pdp_type *pdpType) +{ + UBX_CELL_error_t err; + char *command; + char *response; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (cid > UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) + return UBX_CELL_ERROR_ERROR; - free(command); - return err; -} + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_DEF) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_MESSAGE_PDP_DEF); -uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) -{ - UBX_CELL_error_t err; - char *command; - char *response; - uint8_t opsSeen = 0; + response = ubx_cell_calloc_char(1024); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=?", UBX_CELL_OPERATOR_SELECTION); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, + 1024); - int responseSize = (maxOps + 1) * 48; - response = ubx_cell_calloc_char(responseSize); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_3_MIN_TIMEOUT, responseSize); - - // Sample responses: - // +COPS: (3,"Verizon Wireless","VzW","311480",8),,(0,1,2,3,4),(0,1,2) - // +COPS: (1,"313 100","313 100","313100",8),(2,"AT&T","AT&T","310410",8),(3,"311 480","311 480","311480",8),,(0,1,2,3,4),(0,1,2) - - if (_printDebug == true) - { - _debugPort->print(F("getOperators: Response: {")); - _debugPort->print(response); - _debugPort->println(F("}")); - } - - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *opBegin; - char *opEnd; - int op = 0; - int stat; - char longOp[26]; - char shortOp[11]; - int act; - unsigned long numOp; - - opBegin = response; - - for (; op < maxOps; op++) - { - opBegin = strchr(opBegin, '('); - if (opBegin == nullptr) - break; - opEnd = strchr(opBegin, ')'); - if (opEnd == nullptr) - break; + if (err == UBX_CELL_ERROR_SUCCESS) + { + // Example: + // +CGDCONT: 0,"IP","payandgo.o2.co.uk","0.0.0.0",0,0,0,0,0,0,0,0,0,0 + // +CGDCONT: 1,"IP","payandgo.o2.co.uk.mnc010.mcc234.gprs","10.160.182.234",0,0,0,2,0,0,0,0,0,0 + int rcid = -1; + char *searchPtr = response; - int sscanRead = sscanf(opBegin, "(%d,\"%[^\"]\",\"%[^\"]\",\"%lu\",%d)%*s", - &stat, longOp, shortOp, &numOp, &act); - if (sscanRead == 5) - { - opRet[op].stat = stat; - opRet[op].longOp = (String)(longOp); - opRet[op].shortOp = (String)(shortOp); - opRet[op].numOp = numOp; - opRet[op].act = act; - opsSeen += 1; - } - // TODO: Search for other possible patterns here - else - { - break; // Break out if pattern doesn't match. - } - opBegin = opEnd + 1; // Move opBegin to beginning of next value + bool keepGoing = true; + while (keepGoing == true) + { + int scanned = 0; + // Find the first/next occurrence of +CGDCONT: + searchPtr = strstr(searchPtr, "+CGDCONT:"); + if (searchPtr != nullptr) + { + char strPdpType[10]; + char strApn[128]; + int ipOct[4]; + + searchPtr += strlen("+CGDCONT:"); // Point to the cid + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,\"%[^\"]\",\"%[^\"]\",\"%d.%d.%d.%d", &rcid, strPdpType, strApn, + &ipOct[0], &ipOct[1], &ipOct[2], &ipOct[3]); + if ((scanned == 7) && (rcid == cid)) + { + if (apn) + *apn = strApn; + for (int o = 0; ip && (o < 4); o++) + { + (*ip)[o] = (uint8_t)ipOct[o]; + } + if (pdpType) + { + *pdpType = (0 == strcmp(strPdpType, "IPV4V6")) ? PDP_TYPE_IPV4V6 + : (0 == strcmp(strPdpType, "IPV6")) ? PDP_TYPE_IPV6 + : (0 == strcmp(strPdpType, "IP")) ? PDP_TYPE_IP + : PDP_TYPE_INVALID; + } + keepGoing = false; + } + } + else // We don't have a match so let's clear the APN and IP address + { + if (apn) + *apn = ""; + if (pdpType) + *pdpType = PDP_TYPE_INVALID; + if (ip) + *ip = {0, 0, 0, 0}; + keepGoing = false; + } + } + } + else + { + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - } - free(command); - free(response); + free(command); + free(response); - return opsSeen; + return err; } -UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) +UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; + char *response; + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_SIMPIN) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_COMMAND_SIMPIN); + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 24); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=1,2,\"%lu\"", UBX_CELL_OPERATOR_SELECTION, oper.numOp); + if (err == UBX_CELL_ERROR_SUCCESS) + { + int scanned = 0; + char c[16]; + char *searchPtr = strstr(response, "+CPIN:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+CPIN:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%15s\r\n", c); + } + if (scanned == 1) + { + if (code) + *code = c; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_3_MIN_TIMEOUT); + free(command); + free(response); - free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() +UBX_CELL_error_t UBX_CELL::setSimPin(String pin) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_SIMPIN) + 4 + pin.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", UBX_CELL_COMMAND_SIMPIN, pin.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 6); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=0,0", UBX_CELL_OPERATOR_SELECTION); +UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) +{ + UBX_CELL_error_t err; + char *command; - // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_3_MIN_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SIM_STATE) + 4); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_SIM_STATE, mode); - free(command); - return err; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::getOperator(String *oper) +UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) { - UBX_CELL_error_t err; - char *command; - char *response; - char *searchPtr; - char mode; + UBX_CELL_error_t err; + char *command; + char *response; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_OPERATOR_SELECTION); + int m; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_SIM_STATE) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_SIM_STATE); - // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_3_MIN_TIMEOUT); + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - if (err == UBX_CELL_ERROR_SUCCESS) - { - searchPtr = strstr(response, "+COPS:"); - if (searchPtr != nullptr) + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("+COPS:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - mode = *searchPtr; // Read first char -- should be mode - if (mode == '2') // Check for de-register - { - err = UBX_CELL_ERROR_DEREGISTERED; - } - // Otherwise if it's default, manual, set-only, or automatic - else if ((mode == '0') || (mode == '1') || (mode == '3') || (mode == '4')) - { - *oper = ""; - searchPtr = strchr(searchPtr, '\"'); // Move to first quote - if (searchPtr == nullptr) - { - err = UBX_CELL_ERROR_DEREGISTERED; - } - else + int scanned = 0; + char *searchPtr = strstr(response, "+USIMSTAT:"); + if (searchPtr != nullptr) { - while ((*(++searchPtr) != '\"') && (*searchPtr != '\0')) - { - oper->concat(*(searchPtr)); - } + searchPtr += strlen("+USIMSTAT:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d\r\n", &m); } - if (_printDebug == true) + if (scanned == 1) { - _debugPort->print(F("getOperator: ")); - _debugPort->println(*oper); + *mode = m; } - } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - } - free(response); - free(command); - return err; + free(command); + free(response); + return err; } -UBX_CELL_error_t UBX_CELL::deregisterOperator(void) +const char *PPP_L2P[5] = { + "", "PPP", "M-HEX", "M-RAW_IP", "M-OPT-PPP", +}; + +UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigned long dialNumber, + UBX_CELL::UBX_CELL_l2p_t l2p) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 4); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=2", UBX_CELL_OPERATOR_SELECTION); + if ((dialing_type_char != 0) && (dialing_type_char != 'T') && (dialing_type_char != 'P')) + { + return UBX_CELL_ERROR_UNEXPECTED_PARAM; + } + + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_ENTER_PPP) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (dialing_type_char != 0) + { + sprintf(command, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, dialNumber, PPP_L2P[l2p], + (unsigned int)cid); + } + else + { + sprintf(command, "%s*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialNumber, PPP_L2P[l2p], (unsigned int)cid); + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_3_MIN_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setSMSMessageFormat(UBX_CELL_message_format_t textMode) +uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) { - char *command; - UBX_CELL_error_t err; + UBX_CELL_error_t err; + char *command; + char *response; + uint8_t opsSeen = 0; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_FORMAT) + 4); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MESSAGE_FORMAT, - (textMode == UBX_CELL_MESSAGE_FORMAT_TEXT) ? 1 : 0); + command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=?", UBX_CELL_OPERATOR_SELECTION); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + int responseSize = (maxOps + 1) * 48; + response = ubx_cell_calloc_char(responseSize); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - free(command); - return err; -} + // AT+COPS maximum response time is 3 minutes (180000 ms) + err = + sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_3_MIN_TIMEOUT, responseSize); -UBX_CELL_error_t UBX_CELL::sendSMS(String number, String message) -{ - char *command; - char *messageCStr; - char *numberCStr; - UBX_CELL_error_t err; + // Sample responses: + // +COPS: (3,"Verizon Wireless","VzW","311480",8),,(0,1,2,3,4),(0,1,2) + // +COPS: (1,"313 100","313 100","313100",8),(2,"AT&T","AT&T","310410",8),(3,"311 480","311 + // 480","311480",8),,(0,1,2,3,4),(0,1,2) - numberCStr = ubx_cell_calloc_char(number.length() + 2); - if (numberCStr == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - number.toCharArray(numberCStr, number.length() + 1); + if (_printDebug == true) + { + _debugPort->print(F("getOperators: Response: {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEND_TEXT) + strlen(numberCStr) + 8); - if (command != nullptr) - { - sprintf(command, "%s=\"%s\"", UBX_CELL_SEND_TEXT, numberCStr); + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *opBegin; + char *opEnd; + int op = 0; + int stat; + char longOp[26]; + char shortOp[11]; + int act; + unsigned long numOp; - err = sendCommandWithResponse(command, ">", nullptr, - UBX_CELL_10_SEC_TIMEOUT); - free(command); - free(numberCStr); - if (err != UBX_CELL_ERROR_SUCCESS) - return err; + opBegin = response; - messageCStr = ubx_cell_calloc_char(message.length() + 1); - if (messageCStr == nullptr) - { - hwWrite(ASCII_CTRL_Z); - return UBX_CELL_ERROR_OUT_OF_MEMORY; + for (; op < maxOps; op++) + { + opBegin = strchr(opBegin, '('); + if (opBegin == nullptr) + break; + opEnd = strchr(opBegin, ')'); + if (opEnd == nullptr) + break; + + int sscanRead = + sscanf(opBegin, "(%d,\"%[^\"]\",\"%[^\"]\",\"%lu\",%d)%*s", &stat, longOp, shortOp, &numOp, &act); + if (sscanRead == 5) + { + opRet[op].stat = stat; + opRet[op].longOp = (String)(longOp); + opRet[op].shortOp = (String)(shortOp); + opRet[op].numOp = numOp; + opRet[op].act = act; + opsSeen += 1; + } + // TODO: Search for other possible patterns here + else + { + break; // Break out if pattern doesn't match. + } + opBegin = opEnd + 1; // Move opBegin to beginning of next value + } } - message.toCharArray(messageCStr, message.length() + 1); - messageCStr[message.length()] = ASCII_CTRL_Z; - err = sendCommandWithResponse(messageCStr, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_10_SEC_TIMEOUT, minimumResponseAllocation, NOT_AT_COMMAND); - - free(messageCStr); - } - else - { - free(numberCStr); - err = UBX_CELL_ERROR_OUT_OF_MEMORY; - } + free(command); + free(response); - return err; + return opsSeen; } -UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, String memory) +UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) { - UBX_CELL_error_t err; - char *command; - char *response; - int u; - int t; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_PREF_MESSAGE_STORE) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_PREF_MESSAGE_STORE, memory.c_str()); + UBX_CELL_error_t err; + char *command; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 24); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=1,2,\"%lu\"", UBX_CELL_OPERATOR_SELECTION, oper.numOp); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_3_MIN_TIMEOUT); + // AT+COPS maximum response time is 3 minutes (180000 ms) + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - if (err != UBX_CELL_ERROR_SUCCESS) - { free(command); - free(response); return err; - } - - int scanned = 0; - char *searchPtr = strstr(response, "+CPMS:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+CPMS:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,%d", &u, &t); - } - if (scanned == 2) - { - if (_printDebug == true) - { - _debugPort->print(F("getPreferredMessageStorage: memory1 (read and delete): ")); - _debugPort->print(memory); - _debugPort->print(F(" used: ")); - _debugPort->print(u); - _debugPort->print(F(" total: ")); - _debugPort->println(t); - } - *used = u; - *total = t; - } - else - { - err = UBX_CELL_ERROR_INVALID; - } - - free(response); - free(command); - return err; } -UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message) +UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() { - UBX_CELL_error_t err; - char *command; - char *response; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_TEXT_MESSAGE) + 5); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_READ_TEXT_MESSAGE, location); + command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 6); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=0,0", UBX_CELL_OPERATOR_SELECTION); + + // AT+COPS maximum response time is 3 minutes (180000 ms) + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - response = ubx_cell_calloc_char(1024); - if (response == nullptr) - { free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + return err; +} - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_10_SEC_TIMEOUT, 1024); +UBX_CELL_error_t UBX_CELL::getOperator(String *oper) +{ + UBX_CELL_error_t err; + char *command; + char *response; + char *searchPtr; + char mode; - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = response; + command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_OPERATOR_SELECTION); - // Find the first occurrence of +CMGR: - searchPtr = strstr(searchPtr, "+CMGR:"); - if (searchPtr != nullptr) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - searchPtr += strlen("+CMGR:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - int pointer = 0; - while ((*(++searchPtr) != '\"') && (*searchPtr != '\0') && (pointer < 12)) - { - unread->concat(*(searchPtr)); - pointer++; - } - if ((*searchPtr == '\0') || (pointer == 12)) - { - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - // Search to the next quote - searchPtr = strchr(++searchPtr, '\"'); - pointer = 0; - while ((*(++searchPtr) != '\"') && (*searchPtr != '\0') && (pointer < 24)) - { - from->concat(*(searchPtr)); - pointer++; - } - if ((*searchPtr == '\0') || (pointer == 24)) - { - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - // Skip two commas - searchPtr = strchr(++searchPtr, ','); - searchPtr = strchr(++searchPtr, ','); - // Search to the next quote - searchPtr = strchr(++searchPtr, '\"'); - pointer = 0; - while ((*(++searchPtr) != '\"') && (*searchPtr != '\0') && (pointer < 24)) - { - dateTime->concat(*(searchPtr)); - pointer++; - } - if ((*searchPtr == '\0') || (pointer == 24)) - { - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - // Search to the next new line - searchPtr = strchr(++searchPtr, '\n'); - pointer = 0; - while ((*(++searchPtr) != '\r') && (*searchPtr != '\n') && (*searchPtr != '\0') && (pointer < 512)) - { - message->concat(*(searchPtr)); - pointer++; - } - if ((*searchPtr == '\0') || (pointer == 512)) - { free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - else + + // AT+COPS maximum response time is 3 minutes (180000 ms) + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_3_MIN_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) { - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + searchPtr = strstr(response, "+COPS:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+COPS:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + mode = *searchPtr; // Read first char -- should be mode + if (mode == '2') // Check for de-register + { + err = UBX_CELL_ERROR_DEREGISTERED; + } + // Otherwise if it's default, manual, set-only, or automatic + else if ((mode == '0') || (mode == '1') || (mode == '3') || (mode == '4')) + { + *oper = ""; + searchPtr = strchr(searchPtr, '\"'); // Move to first quote + if (searchPtr == nullptr) + { + err = UBX_CELL_ERROR_DEREGISTERED; + } + else + { + while ((*(++searchPtr) != '\"') && (*searchPtr != '\0')) + { + oper->concat(*(searchPtr)); + } + } + if (_printDebug == true) + { + _debugPort->print(F("getOperator: ")); + _debugPort->println(*oper); + } + } + } } - } - else - { - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - free(command); - free(response); - return err; + free(response); + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) +UBX_CELL_error_t UBX_CELL::deregisterOperator(void) { - char *command; - UBX_CELL_error_t err; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_DELETE_MESSAGE) + 12); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (deleteFlag == 0) - sprintf(command, "%s=%d", UBX_CELL_DELETE_MESSAGE, location); - else - sprintf(command, "%s=%d,%d", UBX_CELL_DELETE_MESSAGE, location, deleteFlag); + command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 4); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=2", UBX_CELL_OPERATOR_SELECTION); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_55_SECS_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) +UBX_CELL_error_t UBX_CELL::setSMSMessageFormat(UBX_CELL_message_format_t textMode) { - UBX_CELL_error_t err; - char *command; - int b = 0; - - // Error check -- ensure supported baud - for (; b < NUM_SUPPORTED_BAUD; b++) - { - if (UBX_CELL_SUPPORTED_BAUD[b] == baud) - { - break; - } - } - if (b >= NUM_SUPPORTED_BAUD) - { - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - } - - // Construct command - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_BAUD) + 7 + 12); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%lu", UBX_CELL_COMMAND_BAUD, baud); + char *command; + UBX_CELL_error_t err; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_SET_BAUD_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_FORMAT) + 4); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_MESSAGE_FORMAT, (textMode == UBX_CELL_MESSAGE_FORMAT_TEXT) ? 1 : 0); - free(command); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) +UBX_CELL_error_t UBX_CELL::sendSMS(String number, String message) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_FLOW_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s%d", UBX_CELL_FLOW_CONTROL, value); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + char *command; + char *messageCStr; + char *numberCStr; + UBX_CELL_error_t err; - free(command); + numberCStr = ubx_cell_calloc_char(number.length() + 2); + if (numberCStr == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + number.toCharArray(numberCStr, number.length() + 1); - return err; -} + command = ubx_cell_calloc_char(strlen(UBX_CELL_SEND_TEXT) + strlen(numberCStr) + 8); + if (command != nullptr) + { + sprintf(command, "%s=\"%s\"", UBX_CELL_SEND_TEXT, numberCStr); -UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, - UBX_CELL_gpio_mode_t mode, int value) -{ - UBX_CELL_error_t err; - char *command; + err = sendCommandWithResponse(command, ">", nullptr, UBX_CELL_10_SEC_TIMEOUT); + free(command); + free(numberCStr); + if (err != UBX_CELL_ERROR_SUCCESS) + return err; - // Example command: AT+UGPIOC=16,2 - // Example command: AT+UGPIOC=23,0,1 - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GPIO) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (mode == GPIO_OUTPUT) - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode, value); - else - sprintf(command, "%s=%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode); + messageCStr = ubx_cell_calloc_char(message.length() + 1); + if (messageCStr == nullptr) + { + hwWrite(ASCII_CTRL_Z); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + message.toCharArray(messageCStr, message.length() + 1); + messageCStr[message.length()] = ASCII_CTRL_Z; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_10_SEC_TIMEOUT); + err = sendCommandWithResponse(messageCStr, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT, + minimumResponseAllocation, NOT_AT_COMMAND); - free(command); + free(messageCStr); + } + else + { + free(numberCStr); + err = UBX_CELL_ERROR_OUT_OF_MEMORY; + } - return err; + return err; } -UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) +UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, String memory) { - UBX_CELL_error_t err; - char *command; - char *response; - char gpioChar[4]; - char *gpioStart; - int gpioMode; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GPIO) + 2); - if (command == nullptr) - return GPIO_MODE_INVALID; - sprintf(command, "%s?", UBX_CELL_COMMAND_GPIO); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return GPIO_MODE_INVALID; - } + UBX_CELL_error_t err; + char *command; + char *response; + int u; + int t; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_PREF_MESSAGE_STORE) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", UBX_CELL_PREF_MESSAGE_STORE, memory.c_str()); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(command); - free(response); - return GPIO_MODE_INVALID; - } + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - sprintf(gpioChar, "%d", gpio); // Convert GPIO to char array - gpioStart = strstr(response, gpioChar); // Find first occurence of GPIO in response + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_3_MIN_TIMEOUT); - free(command); - free(response); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(command); + free(response); + return err; + } - if (gpioStart == nullptr) - return GPIO_MODE_INVALID; // If not found return invalid - sscanf(gpioStart, "%*d,%d\r\n", &gpioMode); + int scanned = 0; + char *searchPtr = strstr(response, "+CPMS:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+CPMS:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,%d", &u, &t); + } + if (scanned == 2) + { + if (_printDebug == true) + { + _debugPort->print(F("getPreferredMessageStorage: memory1 (read and delete): ")); + _debugPort->print(memory); + _debugPort->print(F(" used: ")); + _debugPort->print(u); + _debugPort->print(F(" total: ")); + _debugPort->println(t); + } + *used = u; + *total = t; + } + else + { + err = UBX_CELL_ERROR_INVALID; + } - return (UBX_CELL_gpio_mode_t)gpioMode; + free(response); + free(command); + return err; } -int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int localPort) +UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message) { - UBX_CELL_error_t err; - char *command; - char *response; - int sockId = -1; - char *responseStart; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_CREATE_SOCKET) + 10); - if (command == nullptr) - return -1; - if (localPort == 0) - sprintf(command, "%s=%d", UBX_CELL_CREATE_SOCKET, (int)protocol); - else - sprintf(command, "%s=%d,%d", UBX_CELL_CREATE_SOCKET, (int)protocol, localPort); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - if (_printDebug == true) - _debugPort->println(F("socketOpen: Fail: nullptr response")); - free(command); - return -1; - } + UBX_CELL_error_t err; + char *command; + char *response; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_TEXT_MESSAGE) + 5); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_READ_TEXT_MESSAGE, location); - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) + response = ubx_cell_calloc_char(1024); + if (response == nullptr) { - _debugPort->print(F("socketOpen: Fail: Error: ")); - _debugPort->print(err); - _debugPort->print(F(" Response: {")); - _debugPort->print(response); - _debugPort->println(F("}")); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - free(command); - free(response); - return -1; - } - responseStart = strstr(response, "+USOCR:"); - if (responseStart == nullptr) - { - if (_printDebug == true) + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT, 1024); + + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = response; + + // Find the first occurrence of +CMGR: + searchPtr = strstr(searchPtr, "+CMGR:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+CMGR:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + int pointer = 0; + while ((*(++searchPtr) != '\"') && (*searchPtr != '\0') && (pointer < 12)) + { + unread->concat(*(searchPtr)); + pointer++; + } + if ((*searchPtr == '\0') || (pointer == 12)) + { + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + // Search to the next quote + searchPtr = strchr(++searchPtr, '\"'); + pointer = 0; + while ((*(++searchPtr) != '\"') && (*searchPtr != '\0') && (pointer < 24)) + { + from->concat(*(searchPtr)); + pointer++; + } + if ((*searchPtr == '\0') || (pointer == 24)) + { + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + // Skip two commas + searchPtr = strchr(++searchPtr, ','); + searchPtr = strchr(++searchPtr, ','); + // Search to the next quote + searchPtr = strchr(++searchPtr, '\"'); + pointer = 0; + while ((*(++searchPtr) != '\"') && (*searchPtr != '\0') && (pointer < 24)) + { + dateTime->concat(*(searchPtr)); + pointer++; + } + if ((*searchPtr == '\0') || (pointer == 24)) + { + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + // Search to the next new line + searchPtr = strchr(++searchPtr, '\n'); + pointer = 0; + while ((*(++searchPtr) != '\r') && (*searchPtr != '\n') && (*searchPtr != '\0') && (pointer < 512)) + { + message->concat(*(searchPtr)); + pointer++; + } + if ((*searchPtr == '\0') || (pointer == 512)) + { + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + } + else + { + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + } + else { - _debugPort->print(F("socketOpen: Failure: {")); - _debugPort->print(response); - _debugPort->println(F("}")); + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } + free(command); free(response); - return -1; - } - - responseStart += strlen("+USOCR:"); // Move searchPtr to first char - while (*responseStart == ' ') responseStart++; // skip spaces - sscanf(responseStart, "%d", &sockId); - _lastSocketProtocol[sockId] = (int)protocol; - free(command); - free(response); - - return sockId; + return err; } -UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) +UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) { - UBX_CELL_error_t err; - char *command; - char *response; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_CLOSE_SOCKET) + 10); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - // if timeout is short, close asynchronously and don't wait for socket closure (we will get the URC later) - // this will make sure the AT command parser is not confused during init() - const char* format = (UBX_CELL_STANDARD_RESPONSE_TIMEOUT == timeout) ? "%s=%d,1" : "%s=%d"; - sprintf(command, format, UBX_CELL_CLOSE_SOCKET, socket); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, timeout); + char *command; + UBX_CELL_error_t err; - if ((err != UBX_CELL_ERROR_SUCCESS) && (_printDebug == true)) - { - _debugPort->print(F("socketClose: Error: ")); - _debugPort->println(socketGetLastError()); - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_DELETE_MESSAGE) + 12); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (deleteFlag == 0) + sprintf(command, "%s=%d", UBX_CELL_DELETE_MESSAGE, location); + else + sprintf(command, "%s=%d,%d", UBX_CELL_DELETE_MESSAGE, location, deleteFlag); - free(command); - free(response); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_55_SECS_TIMEOUT); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, - unsigned int port) +UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; + int b = 0; + + // Error check -- ensure supported baud + for (; b < NUM_SUPPORTED_BAUD; b++) + { + if (UBX_CELL_SUPPORTED_BAUD[b] == baud) + { + break; + } + } + if (b >= NUM_SUPPORTED_BAUD) + { + return UBX_CELL_ERROR_UNEXPECTED_PARAM; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_CONNECT_SOCKET) + strlen(address) + 11); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\",%d", UBX_CELL_CONNECT_SOCKET, socket, address, port); + // Construct command + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_BAUD) + 7 + 12); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%lu", UBX_CELL_COMMAND_BAUD, baud); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_IP_CONNECT_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_SET_BAUD_TIMEOUT); - free(command); + free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, - unsigned int port) +UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) { - char *charAddress = ubx_cell_calloc_char(16); - if (charAddress == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - memset(charAddress, 0, 16); - sprintf(charAddress, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); + UBX_CELL_error_t err; + char *command; - return (socketConnect(socket, (const char *)charAddress, port)); -} + command = ubx_cell_calloc_char(strlen(UBX_CELL_FLOW_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s%d", UBX_CELL_FLOW_CONTROL, value); -UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) -{ - char *command; - char *response; - UBX_CELL_error_t err; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - command = ubx_cell_calloc_char(strlen(UBX_CELL_WRITE_SOCKET) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - int dataLen = len == -1 ? strlen(str) : len; - sprintf(command, "%s=%d,%d", UBX_CELL_WRITE_SOCKET, socket, dataLen); - err = sendCommandWithResponse(command, "@", response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); + return err; +} - if (err == UBX_CELL_ERROR_SUCCESS) - { - unsigned long writeDelay = millis(); - while (millis() < (writeDelay + 50)) - delay(1); //u-blox specification says to wait 50ms after receiving "@" to write data. +UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_t mode, int value) +{ + UBX_CELL_error_t err; + char *command; - if (len == -1) - { - if (_printDebug == true) - { - _debugPort->print(F("socketWrite: writing: ")); - _debugPort->println(str); - } - hwPrint(str); - } + // Example command: AT+UGPIOC=16,2 + // Example command: AT+UGPIOC=23,0,1 + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GPIO) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (mode == GPIO_OUTPUT) + sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode, value); else - { - if (_printDebug == true) - { - _debugPort->print(F("socketWrite: writing ")); - _debugPort->print(len); - _debugPort->println(F(" bytes")); - } - hwWriteData(str, len); - } - - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_SOCKET_WRITE_TIMEOUT); - } + sprintf(command, "%s=%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode); - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) - { - _debugPort->print(F("socketWrite: Error: ")); - _debugPort->print(err); - _debugPort->print(F(" => {")); - _debugPort->print(response); - _debugPort->println(F("}")); - } - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - free(command); - free(response); - return err; -} + free(command); -UBX_CELL_error_t UBX_CELL::socketWrite(int socket, String str) -{ - return socketWrite(socket, str.c_str(), str.length()); + return err; } -UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int port, const char *str, int len) +UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) { - char *command; - char *response; - UBX_CELL_error_t err; - int dataLen = len == -1 ? strlen(str) : len; - - command = ubx_cell_calloc_char(64); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + UBX_CELL_error_t err; + char *command; + char *response; + char gpioChar[4]; + char *gpioStart; + int gpioMode; - sprintf(command, "%s=%d,\"%s\",%d,%d", UBX_CELL_WRITE_UDP_SOCKET, - socket, address, port, dataLen); - err = sendCommandWithResponse(command, "@", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GPIO) + 2); + if (command == nullptr) + return GPIO_MODE_INVALID; + sprintf(command, "%s?", UBX_CELL_COMMAND_GPIO); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (len == -1) //If binary data we need to send a length. + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - hwPrint(str); + free(command); + return GPIO_MODE_INVALID; } - else + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err != UBX_CELL_ERROR_SUCCESS) { - hwWriteData(str, len); + free(command); + free(response); + return GPIO_MODE_INVALID; } - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_SOCKET_WRITE_TIMEOUT); - } - else - { - if (_printDebug == true) - _debugPort->print(F("socketWriteUDP: Error: ")); - if (_printDebug == true) - _debugPort->println(socketGetLastError()); - } - free(command); - free(response); - return err; -} + sprintf(gpioChar, "%d", gpio); // Convert GPIO to char array + gpioStart = strstr(response, gpioChar); // Find first occurence of GPIO in response -UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len) -{ - char *charAddress = ubx_cell_calloc_char(16); - if (charAddress == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - memset(charAddress, 0, 16); - sprintf(charAddress, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); + free(command); + free(response); - return (socketWriteUDP(socket, (const char *)charAddress, port, str, len)); -} + if (gpioStart == nullptr) + return GPIO_MODE_INVALID; // If not found return invalid + sscanf(gpioStart, "%*d,%d\r\n", &gpioMode); -UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, String address, int port, String str) -{ - return socketWriteUDP(socket, address.c_str(), port, str.c_str(), str.length()); + return (UBX_CELL_gpio_mode_t)gpioMode; } -UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, int *bytesRead) +int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int localPort) { - char *command; - char *response; - char *strBegin; - int readIndexTotal = 0; - int readIndexThisRead = 0; - UBX_CELL_error_t err; - int scanNum = 0; - int readLength = 0; - int socketStore = 0; - int bytesLeftToRead = length; - int bytesToRead; - - // Set *bytesRead to zero - if (bytesRead != nullptr) - *bytesRead = 0; - - // Check if length is zero - if (length == 0) - { - if (_printDebug == true) - _debugPort->print(F("socketRead: length is 0! Call socketReadAvailable?")); - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - } - - // Allocate memory for the command - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_SOCKET) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - // Allocate memory for the response - // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing - int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_SOCKET) + minimumResponseAllocation; - response = ubx_cell_calloc_char(responseLength); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - // If there are more than _saraR5maxSocketRead (1024) bytes to be read, - // we need to do multiple reads to get all the data + UBX_CELL_error_t err; + char *command; + char *response; + int sockId = -1; + char *responseStart; - while (bytesLeftToRead > 0) - { - if (bytesLeftToRead > _saraR5maxSocketRead) // Limit a single read to _saraR5maxSocketRead - bytesToRead = _saraR5maxSocketRead; + command = ubx_cell_calloc_char(strlen(UBX_CELL_CREATE_SOCKET) + 10); + if (command == nullptr) + return -1; + if (localPort == 0) + sprintf(command, "%s=%d", UBX_CELL_CREATE_SOCKET, (int)protocol); else - bytesToRead = bytesLeftToRead; + sprintf(command, "%s=%d,%d", UBX_CELL_CREATE_SOCKET, (int)protocol, localPort); - sprintf(command, "%s=%d,%d", UBX_CELL_READ_SOCKET, socket, bytesToRead); + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + if (_printDebug == true) + _debugPort->println(F("socketOpen: Fail: nullptr response")); + free(command); + return -1; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT, responseLength); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) { - if (_printDebug == true) - { - _debugPort->print(F("socketRead: sendCommandWithResponse err ")); - _debugPort->println(err); - } - free(command); - free(response); - return err; + if (_printDebug == true) + { + _debugPort->print(F("socketOpen: Fail: Error: ")); + _debugPort->print(err); + _debugPort->print(F(" Response: {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } + free(command); + free(response); + return -1; } - // Extract the data - char *searchPtr = strstr(response, "+USORD:"); - if (searchPtr != nullptr) + responseStart = strstr(response, "+USOCR:"); + if (responseStart == nullptr) { - searchPtr += strlen("+USORD:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d", - &socketStore, &readLength); - } - if (scanNum != 2) - { - if (_printDebug == true) - { - _debugPort->print(F("socketRead: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + if (_printDebug == true) + { + _debugPort->print(F("socketOpen: Failure: {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } + free(command); + free(response); + return -1; } - // Check that readLength == bytesToRead - if (readLength != bytesToRead) - { - if (_printDebug == true) - { - _debugPort->print(F("socketRead: length mismatch! bytesToRead=")); - _debugPort->print(bytesToRead); - _debugPort->print(F(" readLength=")); - _debugPort->println(readLength); - } - } + responseStart += strlen("+USOCR:"); // Move searchPtr to first char + while (*responseStart == ' ') + responseStart++; // skip spaces + sscanf(responseStart, "%d", &sockId); + _lastSocketProtocol[sockId] = (int)protocol; - // Check that readLength > 0 - if (readLength == 0) - { - if (_printDebug == true) - { - _debugPort->println(F("socketRead: zero length!")); - } - free(command); - free(response); - return UBX_CELL_ERROR_ZERO_READ_LENGTH; - } + free(command); + free(response); - // Find the first double-quote: - strBegin = strchr(searchPtr, '\"'); + return sockId; +} - if (strBegin == nullptr) - { - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } +UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) +{ + UBX_CELL_error_t err; + char *command; + char *response; - // Now copy the data into readDest - readIndexThisRead = 1; // Start after the quote - while (readIndexThisRead < (readLength + 1)) + command = ubx_cell_calloc_char(strlen(UBX_CELL_CLOSE_SOCKET) + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - readDest[readIndexTotal] = strBegin[readIndexThisRead]; - readIndexTotal++; - readIndexThisRead++; + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } + // if timeout is short, close asynchronously and don't wait for socket closure (we will get the URC later) + // this will make sure the AT command parser is not confused during init() + const char *format = (UBX_CELL_STANDARD_RESPONSE_TIMEOUT == timeout) ? "%s=%d,1" : "%s=%d"; + sprintf(command, format, UBX_CELL_CLOSE_SOCKET, socket); - if (_printDebug == true) - _debugPort->println(F("socketRead: success")); - - // Update *bytesRead - if (bytesRead != nullptr) - *bytesRead = readIndexTotal; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, timeout); - // How many bytes are left to read? - // This would have been bytesLeftToRead -= bytesToRead - // Except the SARA can potentially return less data than requested... - // So we need to subtract readLength instead. - bytesLeftToRead -= readLength; - if (_printDebug == true) + if ((err != UBX_CELL_ERROR_SUCCESS) && (_printDebug == true)) { - if (bytesLeftToRead > 0) - { - _debugPort->print(F("socketRead: multiple read. bytesLeftToRead: ")); - _debugPort->println(bytesLeftToRead); - } + _debugPort->print(F("socketClose: Error: ")); + _debugPort->println(socketGetLastError()); } - } // /while (bytesLeftToRead > 0) - free(command); - free(response); + free(command); + free(response); - return UBX_CELL_ERROR_SUCCESS; + return err; } -UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) +UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, unsigned int port) { - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int readLength = 0; - int socketStore = 0; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_SOCKET) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,0", UBX_CELL_READ_SOCKET, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + UBX_CELL_error_t err; + char *command; - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USORD:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USORD:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d", - &socketStore, &readLength); - } - if (scanNum != 2) - { - if (_printDebug == true) - { - _debugPort->print(F("socketReadAvailable: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_CONNECT_SOCKET) + strlen(address) + 11); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\",%d", UBX_CELL_CONNECT_SOCKET, socket, address, port); - *length = readLength; - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_IP_CONNECT_TIMEOUT); - free(command); - free(response); + free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, - IPAddress *remoteIPAddress, int *remotePort, int *bytesRead) +UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, unsigned int port) { - char *command; - char *response; - char *strBegin; - int readIndexTotal = 0; - int readIndexThisRead = 0; - UBX_CELL_error_t err; - int scanNum = 0; - int remoteIPstore[4] = { 0, 0, 0, 0 }; - int portStore = 0; - int readLength = 0; - int socketStore = 0; - int bytesLeftToRead = length; - int bytesToRead; - - // Set *bytesRead to zero - if (bytesRead != nullptr) - *bytesRead = 0; - - // Check if length is zero - if (length == 0) - { - if (_printDebug == true) - _debugPort->print(F("socketReadUDP: length is 0! Call socketReadAvailableUDP?")); - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - } - - // Allocate memory for the command - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_UDP_SOCKET) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - // Allocate memory for the response - // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing - int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_UDP_SOCKET) + minimumResponseAllocation; - response = ubx_cell_calloc_char(responseLength); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - // If there are more than _saraR5maxSocketRead (1024) bytes to be read, - // we need to do multiple reads to get all the data - - while (bytesLeftToRead > 0) - { - if (bytesLeftToRead > _saraR5maxSocketRead) // Limit a single read to _saraR5maxSocketRead - bytesToRead = _saraR5maxSocketRead; - else - bytesToRead = bytesLeftToRead; - - sprintf(command, "%s=%d,%d", UBX_CELL_READ_UDP_SOCKET, socket, bytesToRead); + char *charAddress = ubx_cell_calloc_char(16); + if (charAddress == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + memset(charAddress, 0, 16); + sprintf(charAddress, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT, responseLength); + return (socketConnect(socket, (const char *)charAddress, port)); +} - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) - { - _debugPort->print(F("socketReadUDP: sendCommandWithResponse err ")); - _debugPort->println(err); - } - free(command); - free(response); - return err; - } +UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) +{ + char *command; + char *response; + UBX_CELL_error_t err; - // Extract the data - char *searchPtr = strstr(response, "+USORF:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USORF:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,\"%d.%d.%d.%d\",%d,%d", - &socketStore, &remoteIPstore[0], &remoteIPstore[1], &remoteIPstore[2], &remoteIPstore[3], - &portStore, &readLength); - } - if (scanNum != 7) + command = ubx_cell_calloc_char(strlen(UBX_CELL_WRITE_SOCKET) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - if (_printDebug == true) - { - _debugPort->print(F("socketReadUDP: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } + int dataLen = len == -1 ? strlen(str) : len; + sprintf(command, "%s=%d,%d", UBX_CELL_WRITE_SOCKET, socket, dataLen); - // Check that readLength == bytesToRead - if (readLength != bytesToRead) - { - if (_printDebug == true) - { - _debugPort->print(F("socketReadUDP: length mismatch! bytesToRead=")); - _debugPort->print(bytesToRead); - _debugPort->print(F(" readLength=")); - _debugPort->println(readLength); - } - } + err = sendCommandWithResponse(command, "@", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); - // Check that readLength > 0 - if (readLength == 0) + if (err == UBX_CELL_ERROR_SUCCESS) { - if (_printDebug == true) - { - _debugPort->println(F("socketRead: zero length!")); - } - free(command); - free(response); - return UBX_CELL_ERROR_ZERO_READ_LENGTH; - } + unsigned long writeDelay = millis(); + while (millis() < (writeDelay + 50)) + delay(1); // u-blox specification says to wait 50ms after receiving "@" to write data. - // Find the third double-quote - strBegin = strchr(searchPtr, '\"'); - strBegin = strchr(strBegin + 1, '\"'); - strBegin = strchr(strBegin + 1, '\"'); - - if (strBegin == nullptr) - { - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + if (len == -1) + { + if (_printDebug == true) + { + _debugPort->print(F("socketWrite: writing: ")); + _debugPort->println(str); + } + hwPrint(str); + } + else + { + if (_printDebug == true) + { + _debugPort->print(F("socketWrite: writing ")); + _debugPort->print(len); + _debugPort->println(F(" bytes")); + } + hwWriteData(str, len); + } - // Now copy the data into readDest - readIndexThisRead = 1; // Start after the quote - while (readIndexThisRead < (readLength + 1)) - { - readDest[readIndexTotal] = strBegin[readIndexThisRead]; - readIndexTotal++; - readIndexThisRead++; + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_SOCKET_WRITE_TIMEOUT); } - // If remoteIPaddress is not nullptr, copy the remote IP address - if (remoteIPAddress != nullptr) + if (err != UBX_CELL_ERROR_SUCCESS) { - IPAddress tempAddress; - for (int i = 0; i <= 3; i++) - { - tempAddress[i] = (uint8_t)remoteIPstore[i]; - } - *remoteIPAddress = tempAddress; + if (_printDebug == true) + { + _debugPort->print(F("socketWrite: Error: ")); + _debugPort->print(err); + _debugPort->print(F(" => {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } } - // If remotePort is not nullptr, copy the remote port - if (remotePort != nullptr) - { - *remotePort = portStore; - } + free(command); + free(response); + return err; +} - if (_printDebug == true) - _debugPort->println(F("socketReadUDP: success")); +UBX_CELL_error_t UBX_CELL::socketWrite(int socket, String str) +{ + return socketWrite(socket, str.c_str(), str.length()); +} - // Update *bytesRead - if (bytesRead != nullptr) - *bytesRead = readIndexTotal; +UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int port, const char *str, int len) +{ + char *command; + char *response; + UBX_CELL_error_t err; + int dataLen = len == -1 ? strlen(str) : len; - // How many bytes are left to read? - // This would have been bytesLeftToRead -= bytesToRead - // Except the SARA can potentially return less data than requested... - // So we need to subtract readLength instead. - bytesLeftToRead -= readLength; - if (_printDebug == true) + command = ubx_cell_calloc_char(64); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - if (bytesLeftToRead > 0) - { - _debugPort->print(F("socketReadUDP: multiple read. bytesLeftToRead: ")); - _debugPort->println(bytesLeftToRead); - } + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - } // /while (bytesLeftToRead > 0) - - free(command); - free(response); - - return UBX_CELL_ERROR_SUCCESS; -} - -UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int readLength = 0; - int socketStore = 0; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_UDP_SOCKET) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,0", UBX_CELL_READ_UDP_SOCKET, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + sprintf(command, "%s=%d,\"%s\",%d,%d", UBX_CELL_WRITE_UDP_SOCKET, socket, address, port, dataLen); + err = sendCommandWithResponse(command, "@", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USORF:"); - if (searchPtr != nullptr) + if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr += strlen("+USORF:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d", - &socketStore, &readLength); + if (len == -1) // If binary data we need to send a length. + { + hwPrint(str); + } + else + { + hwWriteData(str, len); + } + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_SOCKET_WRITE_TIMEOUT); } - if (scanNum != 2) + else { - if (_printDebug == true) - { - _debugPort->print(F("socketReadAvailableUDP: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + if (_printDebug == true) + _debugPort->print(F("socketWriteUDP: Error: ")); + if (_printDebug == true) + _debugPort->println(socketGetLastError()); } - *length = readLength; - } - - free(command); - free(response); - - return err; + free(command); + free(response); + return err; } -UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) +UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_LISTEN_SOCKET) + 9); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d", UBX_CELL_LISTEN_SOCKET, socket, port); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + char *charAddress = ubx_cell_calloc_char(16); + if (charAddress == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + memset(charAddress, 0, 16); + sprintf(charAddress, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); - free(command); - return err; + return (socketWriteUDP(socket, (const char *)charAddress, port, str, len)); } -UBX_CELL_error_t UBX_CELL::socketDirectLinkMode(int socket) +UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, String address, int port, String str) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_DIRECT_LINK) + 8); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_SOCKET_DIRECT_LINK, socket); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - - free(command); - return err; + return socketWriteUDP(socket, address.c_str(), port, str.c_str(), str.length()); } -UBX_CELL_error_t UBX_CELL::socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger) +UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, int *bytesRead) { - // valid range is 0 (trigger disabled), 100-120000 - if (!((timerTrigger == 0) || ((timerTrigger >= 100) && (timerTrigger <= 120000)))) - return UBX_CELL_ERROR_ERROR; + char *command; + char *response; + char *strBegin; + int readIndexTotal = 0; + int readIndexThisRead = 0; + UBX_CELL_error_t err; + int scanNum = 0; + int readLength = 0; + int socketStore = 0; + int bytesLeftToRead = length; + int bytesToRead; - UBX_CELL_error_t err; - char *command; + // Set *bytesRead to zero + if (bytesRead != nullptr) + *bytesRead = 0; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=5,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, timerTrigger); + // Check if length is zero + if (length == 0) + { + if (_printDebug == true) + _debugPort->print(F("socketRead: length is 0! Call socketReadAvailable?")); + return UBX_CELL_ERROR_UNEXPECTED_PARAM; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + // Allocate memory for the command + command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_SOCKET) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; - free(command); - return err; -} + // Allocate memory for the response + // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing + int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_SOCKET) + minimumResponseAllocation; + response = ubx_cell_calloc_char(responseLength); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } -UBX_CELL_error_t UBX_CELL::socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger) -{ - // valid range is 0, 3-1472 for UDP - if (!((dataLengthTrigger == 0) || ((dataLengthTrigger >= 3) && (dataLengthTrigger <= 1472)))) - return UBX_CELL_ERROR_ERROR; + // If there are more than _saraR5maxSocketRead (1024) bytes to be read, + // we need to do multiple reads to get all the data - UBX_CELL_error_t err; - char *command; + while (bytesLeftToRead > 0) + { + if (bytesLeftToRead > _saraR5maxSocketRead) // Limit a single read to _saraR5maxSocketRead + bytesToRead = _saraR5maxSocketRead; + else + bytesToRead = bytesLeftToRead; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=6,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, dataLengthTrigger); + sprintf(command, "%s=%d,%d", UBX_CELL_READ_SOCKET, socket, bytesToRead); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT, responseLength); - free(command); - return err; -} + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("socketRead: sendCommandWithResponse err ")); + _debugPort->println(err); + } + free(command); + free(response); + return err; + } -UBX_CELL_error_t UBX_CELL::socketDirectLinkCharacterTrigger(int socket, int characterTrigger) -{ - // The allowed range is -1, 0-255, the factory-programmed value is -1; -1 means trigger disabled. - if (!((characterTrigger >= -1) && (characterTrigger <= 255))) - return UBX_CELL_ERROR_ERROR; + // Extract the data + char *searchPtr = strstr(response, "+USORD:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USORD:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,%d", &socketStore, &readLength); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("socketRead: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - UBX_CELL_error_t err; - char *command; + // Check that readLength == bytesToRead + if (readLength != bytesToRead) + { + if (_printDebug == true) + { + _debugPort->print(F("socketRead: length mismatch! bytesToRead=")); + _debugPort->print(bytesToRead); + _debugPort->print(F(" readLength=")); + _debugPort->println(readLength); + } + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=7,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, characterTrigger); + // Check that readLength > 0 + if (readLength == 0) + { + if (_printDebug == true) + { + _debugPort->println(F("socketRead: zero length!")); + } + free(command); + free(response); + return UBX_CELL_ERROR_ZERO_READ_LENGTH; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + // Find the first double-quote: + strBegin = strchr(searchPtr, '\"'); - free(command); - return err; -} + if (strBegin == nullptr) + { + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } -UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer) -{ - // valid range is 0, 1000-72000 - if (!((congestionTimer == 0) || ((congestionTimer >= 1000) && (congestionTimer <= 72000)))) - return UBX_CELL_ERROR_ERROR; + // Now copy the data into readDest + readIndexThisRead = 1; // Start after the quote + while (readIndexThisRead < (readLength + 1)) + { + readDest[readIndexTotal] = strBegin[readIndexThisRead]; + readIndexTotal++; + readIndexThisRead++; + } + + if (_printDebug == true) + _debugPort->println(F("socketRead: success")); - UBX_CELL_error_t err; - char *command; + // Update *bytesRead + if (bytesRead != nullptr) + *bytesRead = readIndexTotal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=8,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, congestionTimer); + // How many bytes are left to read? + // This would have been bytesLeftToRead -= bytesToRead + // Except the SARA can potentially return less data than requested... + // So we need to subtract readLength instead. + bytesLeftToRead -= readLength; + if (_printDebug == true) + { + if (bytesLeftToRead > 0) + { + _debugPort->print(F("socketRead: multiple read. bytesLeftToRead: ")); + _debugPort->println(bytesLeftToRead); + } + } + } // /while (bytesLeftToRead > 0) - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + free(response); - free(command); - return err; + return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol) +UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) { - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - int paramVal; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,0", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int readLength = 0; + int socketStore = 0; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_SOCKET) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,0", UBX_CELL_READ_SOCKET, socket); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,0,%d", - &socketStore, ¶mVal); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - if (scanNum != 2) + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) { - if (_printDebug == true) - { - _debugPort->print(F("querySocketType: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + char *searchPtr = strstr(response, "+USORD:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USORD:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,%d", &socketStore, &readLength); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("socketReadAvailable: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - *protocol = (UBX_CELL_socket_protocol_t)paramVal; - _lastSocketProtocol[socketStore] = paramVal; - } + *length = readLength; + } - free(command); - free(response); + free(command); + free(response); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) +UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress, + int *remotePort, int *bytesRead) { - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - int paramVal; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,1", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + char *command; + char *response; + char *strBegin; + int readIndexTotal = 0; + int readIndexThisRead = 0; + UBX_CELL_error_t err; + int scanNum = 0; + int remoteIPstore[4] = {0, 0, 0, 0}; + int portStore = 0; + int readLength = 0; + int socketStore = 0; + int bytesLeftToRead = length; + int bytesToRead; + + // Set *bytesRead to zero + if (bytesRead != nullptr) + *bytesRead = 0; - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,1,%d", - &socketStore, ¶mVal); - } - if (scanNum != 2) + // Check if length is zero + if (length == 0) { - if (_printDebug == true) - { - _debugPort->print(F("querySocketLastError: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + if (_printDebug == true) + _debugPort->print(F("socketReadUDP: length is 0! Call socketReadAvailableUDP?")); + return UBX_CELL_ERROR_UNEXPECTED_PARAM; } - *error = paramVal; - } - - free(command); - free(response); - - return err; -} - -UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - long unsigned int paramVal; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,2", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + // Allocate memory for the command + command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_UDP_SOCKET) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) + // Allocate memory for the response + // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing + int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_UDP_SOCKET) + minimumResponseAllocation; + response = ubx_cell_calloc_char(responseLength); + if (response == nullptr) { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,2,%lu", - &socketStore, ¶mVal); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - if (scanNum != 2) + + // If there are more than _saraR5maxSocketRead (1024) bytes to be read, + // we need to do multiple reads to get all the data + + while (bytesLeftToRead > 0) { - if (_printDebug == true) - { - _debugPort->print(F("querySocketTotalBytesSent: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + if (bytesLeftToRead > _saraR5maxSocketRead) // Limit a single read to _saraR5maxSocketRead + bytesToRead = _saraR5maxSocketRead; + else + bytesToRead = bytesLeftToRead; - *total = (uint32_t)paramVal; - } + sprintf(command, "%s=%d,%d", UBX_CELL_READ_UDP_SOCKET, socket, bytesToRead); - free(command); - free(response); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT, responseLength); - return err; -} + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("socketReadUDP: sendCommandWithResponse err ")); + _debugPort->println(err); + } + free(command); + free(response); + return err; + } -UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *total) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - long unsigned int paramVal; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,3", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + // Extract the data + char *searchPtr = strstr(response, "+USORF:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USORF:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,\"%d.%d.%d.%d\",%d,%d", &socketStore, &remoteIPstore[0], &remoteIPstore[1], + &remoteIPstore[2], &remoteIPstore[3], &portStore, &readLength); + } + if (scanNum != 7) + { + if (_printDebug == true) + { + _debugPort->print(F("socketReadUDP: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + // Check that readLength == bytesToRead + if (readLength != bytesToRead) + { + if (_printDebug == true) + { + _debugPort->print(F("socketReadUDP: length mismatch! bytesToRead=")); + _debugPort->print(bytesToRead); + _debugPort->print(F(" readLength=")); + _debugPort->println(readLength); + } + } - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,3,%lu", - &socketStore, ¶mVal); - } - if (scanNum != 2) - { - if (_printDebug == true) - { - _debugPort->print(F("querySocketTotalBytesReceived: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + // Check that readLength > 0 + if (readLength == 0) + { + if (_printDebug == true) + { + _debugPort->println(F("socketRead: zero length!")); + } + free(command); + free(response); + return UBX_CELL_ERROR_ZERO_READ_LENGTH; + } - *total = (uint32_t)paramVal; - } + // Find the third double-quote + strBegin = strchr(searchPtr, '\"'); + strBegin = strchr(strBegin + 1, '\"'); + strBegin = strchr(strBegin + 1, '\"'); - free(command); - free(response); + if (strBegin == nullptr) + { + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - return err; -} + // Now copy the data into readDest + readIndexThisRead = 1; // Start after the quote + while (readIndexThisRead < (readLength + 1)) + { + readDest[readIndexTotal] = strBegin[readIndexThisRead]; + readIndexTotal++; + readIndexThisRead++; + } -UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *address, int *port) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - int paramVals[5]; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,4", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + // If remoteIPaddress is not nullptr, copy the remote IP address + if (remoteIPAddress != nullptr) + { + IPAddress tempAddress; + for (int i = 0; i <= 3; i++) + { + tempAddress[i] = (uint8_t)remoteIPstore[i]; + } + *remoteIPAddress = tempAddress; + } + + // If remotePort is not nullptr, copy the remote port + if (remotePort != nullptr) + { + *remotePort = portStore; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (_printDebug == true) + _debugPort->println(F("socketReadUDP: success")); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,4,\"%d.%d.%d.%d\",%d", - &socketStore, - ¶mVals[0], ¶mVals[1], ¶mVals[2], ¶mVals[3], - ¶mVals[4]); - } - if (scanNum != 6) - { - if (_printDebug == true) - { - _debugPort->print(F("querySocketRemoteIPAddress: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + // Update *bytesRead + if (bytesRead != nullptr) + *bytesRead = readIndexTotal; - IPAddress tempAddress = { (uint8_t)paramVals[0], (uint8_t)paramVals[1], - (uint8_t)paramVals[2], (uint8_t)paramVals[3] }; - *address = tempAddress; - *port = paramVals[4]; - } + // How many bytes are left to read? + // This would have been bytesLeftToRead -= bytesToRead + // Except the SARA can potentially return less data than requested... + // So we need to subtract readLength instead. + bytesLeftToRead -= readLength; + if (_printDebug == true) + { + if (bytesLeftToRead > 0) + { + _debugPort->print(F("socketReadUDP: multiple read. bytesLeftToRead: ")); + _debugPort->println(bytesLeftToRead); + } + } + } // /while (bytesLeftToRead > 0) - free(command); - free(response); + free(command); + free(response); - return err; + return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status) +UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) { - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - int paramVal; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,10", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int readLength = 0; + int socketStore = 0; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_UDP_SOCKET) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,0", UBX_CELL_READ_UDP_SOCKET, socket); - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,10,%d", - &socketStore, ¶mVal); - } - if (scanNum != 2) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - if (_printDebug == true) - { - _debugPort->print(F("querySocketStatusTCP: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - *status = (UBX_CELL_tcp_socket_status_t)paramVal; - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - free(response); + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USORF:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USORF:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,%d", &socketStore, &readLength); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("socketReadAvailableUDP: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - return err; -} + *length = readLength; + } -UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int socketStore = 0; - long unsigned int paramVal; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,11", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + free(response); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + return err; +} - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOCTL:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,11,%lu", - &socketStore, ¶mVal); - } - if (scanNum != 2) - { - if (_printDebug == true) - { - _debugPort->print(F("querySocketOutUnackData: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } +UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) +{ + UBX_CELL_error_t err; + char *command; - *total = (uint32_t)paramVal; - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_LISTEN_SOCKET) + 9); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d", UBX_CELL_LISTEN_SOCKET, socket, port); - free(command); - free(response); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - return err; + free(command); + return err; } -//Issues command to get last socket error, then prints to serial. Also updates rx/backlog buffers. -int UBX_CELL::socketGetLastError() +UBX_CELL_error_t UBX_CELL::socketDirectLinkMode(int socket) { - UBX_CELL_error_t err; - char *command; - char *response; - int errorCode = -1; - - command = ubx_cell_calloc_char(64); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - sprintf(command, "%s", UBX_CELL_GET_ERROR); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - - if (err == UBX_CELL_ERROR_SUCCESS) - { - char *searchPtr = strstr(response, "+USOER:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+USOER:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - sscanf(searchPtr, "%d", &errorCode); - } - } + UBX_CELL_error_t err; + char *command; - free(command); - free(response); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_DIRECT_LINK) + 8); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_SOCKET_DIRECT_LINK, socket); - return errorCode; -} + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -IPAddress UBX_CELL::lastRemoteIP(void) -{ - return _lastRemoteIP; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) +UBX_CELL_error_t UBX_CELL::socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger) { - UBX_CELL_error_t err; - char *command; + // valid range is 0 (trigger disabled), 100-120000 + if (!((timerTrigger == 0) || ((timerTrigger >= 100) && (timerTrigger <= 120000)))) + return UBX_CELL_ERROR_ERROR; - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_HTTP_PROFILE, profile); + command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=5,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, timerTrigger); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address) +UBX_CELL_error_t UBX_CELL::socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger) { - UBX_CELL_error_t err; - char *command; + // valid range is 0, 3-1472 for UDP + if (!((dataLengthTrigger == 0) || ((dataLengthTrigger >= 3) && (dataLengthTrigger <= 1472)))) + return UBX_CELL_ERROR_ERROR; - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 64); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_IP, - address[0], address[1], address[2], address[3]); + command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=6,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, dataLengthTrigger); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) +UBX_CELL_error_t UBX_CELL::socketDirectLinkCharacterTrigger(int socket, int characterTrigger) { - UBX_CELL_error_t err; - char *command; + // The allowed range is -1, 0-255, the factory-programmed value is -1; -1 means trigger disabled. + if (!((characterTrigger >= -1) && (characterTrigger <= 255))) + return UBX_CELL_ERROR_ERROR; - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + server.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_NAME, - server.c_str()); + command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=7,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, characterTrigger); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) +UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer) { - UBX_CELL_error_t err; - char *command; + // valid range is 0, 1000-72000 + if (!((congestionTimer == 0) || ((congestionTimer >= 1000) && (congestionTimer <= 72000)))) + return UBX_CELL_ERROR_ERROR; - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + username.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_USERNAME, - username.c_str()); + command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=8,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, congestionTimer); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) +UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol) { - UBX_CELL_error_t err; - char *command; - - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + password.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_PASSWORD, - password.c_str()); + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + int paramVal; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,0", UBX_CELL_SOCKET_CONTROL, socket); - free(command); - return err; -} + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } -UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) -{ - UBX_CELL_error_t err; - char *command; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,0,%d", &socketStore, ¶mVal); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketType: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, - authenticate); + *protocol = (UBX_CELL_socket_protocol_t)paramVal; + _lastSocketProtocol[socketStore] = paramVal; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + free(response); - free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) +UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) { - UBX_CELL_error_t err; - char *command; - - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_PORT, - port); + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + int paramVal; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,1", UBX_CELL_SOCKET_CONTROL, socket); - free(command); - return err; -} + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } -UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) -{ - UBX_CELL_error_t err; - char *command; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,1,%d", &socketStore, ¶mVal); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketLastError: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + header.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, - header.c_str()); + *error = paramVal; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + free(response); - free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofile) +UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total) { - UBX_CELL_error_t err; - char *command; - - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + long unsigned int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (secprofile == -1) - sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, - secure); - else sprintf(command, "%s=%d,%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, - secure, secprofile); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,2", UBX_CELL_SOCKET_CONTROL, socket); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - free(command); - return err; -} + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, - unsigned long timeout, int ttl) -{ - UBX_CELL_error_t err; - char *command; + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,2,%lu", &socketStore, ¶mVal); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketTotalBytesSent: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_PING_COMMAND) + 48 + - remote_host.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\",%d,%d,%ld,%d", UBX_CELL_PING_COMMAND, - remote_host.c_str(), retry, p_size, timeout, ttl); + *total = (uint32_t)paramVal; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + free(response); - free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::sendHTTPGET(int profile, String path, String responseFilename) +UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *total) { - UBX_CELL_error_t err; - char *command; - - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + - path.length() + responseFilename.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\",\"%s\"", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_GET, - path.c_str(), responseFilename.c_str()); + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + long unsigned int paramVal; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,3", UBX_CELL_SOCKET_CONTROL, socket); - free(command); - return err; -} + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } -UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String responseFilename, - String data, UBX_CELL_http_content_types_t httpContentType) -{ - UBX_CELL_error_t err; - char *command; + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,3,%lu", &socketStore, ¶mVal); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketTotalBytesReceived: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + - path.length() + responseFilename.length() + data.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_POST_DATA, - path.c_str(), responseFilename.c_str(), data.c_str(), httpContentType); + *total = (uint32_t)paramVal; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + free(response); - free(command); - return err; + return err; } -UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String responseFilename, - String requestFile, UBX_CELL_http_content_types_t httpContentType) +UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *address, int *port) { - UBX_CELL_error_t err; - char *command; + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + int paramVals[5]; - if (profile >= UBX_CELL_NUM_HTTP_PROFILES) - return UBX_CELL_ERROR_ERROR; + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,4", UBX_CELL_SOCKET_CONTROL, socket); - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + - path.length() + responseFilename.length() + requestFile.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_POST_FILE, - path.c_str(), responseFilename.c_str(), requestFile.c_str(), httpContentType); + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; -} + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,4,\"%d.%d.%d.%d\",%d", &socketStore, ¶mVals[0], ¶mVals[1], + ¶mVals[2], ¶mVals[3], ¶mVals[4]); + } + if (scanNum != 6) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketRemoteIPAddress: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } -UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, int *error_code) -{ - UBX_CELL_error_t err; - char *command; - char *response; + IPAddress tempAddress = {(uint8_t)paramVals[0], (uint8_t)paramVals[1], (uint8_t)paramVals[2], + (uint8_t)paramVals[3]}; + *address = tempAddress; + *port = paramVals[4]; + } - int rprofile, eclass, ecode; + free(command); + free(response); - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROTOCOL_ERROR) + 4); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_HTTP_PROTOCOL_ERROR, profile); + return err; +} - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } +UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status) +{ + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + int paramVal; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,10", UBX_CELL_SOCKET_CONTROL, socket); - if (err == UBX_CELL_ERROR_SUCCESS) - { - int scanned = 0; - char *searchPtr = strstr(response, "+UHTTPER:"); - if (searchPtr != nullptr) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - searchPtr += strlen("+UHTTPER:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,%d,%d\r\n", - &rprofile, &eclass, &ecode); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - if (scanned == 3) + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) { - *error_class = eclass; - *error_code = ecode; - } - else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,10,%d", &socketStore, ¶mVal); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketStatusTCP: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - free(command); - free(response); - return err; -} + *status = (UBX_CELL_tcp_socket_status_t)paramVal; + } -UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) -{ - UBX_CELL_error_t err; - char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_NVM) + 10); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MQTT_NVM, parameter); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); - return err; -} + free(response); -UBX_CELL_error_t UBX_CELL::setMQTTclientId(const String& clientId) -{ - UBX_CELL_error_t err; - char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + clientId.length() + 10); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_CLIENT_ID, clientId.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } -UBX_CELL_error_t UBX_CELL::setMQTTserver(const String& serverName, int port) +UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) { - UBX_CELL_error_t err; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + serverName.length() + 16); + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int socketStore = 0; + long unsigned int paramVal; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\",%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SERVERNAME, serverName.c_str(), port); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,11", UBX_CELL_SOCKET_CONTROL, socket); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOCTL:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = sscanf(searchPtr, "%d,11,%lu", &socketStore, ¶mVal); + } + if (scanNum != 2) + { + if (_printDebug == true) + { + _debugPort->print(F("querySocketOutUnackData: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + *total = (uint32_t)paramVal; + } + free(command); + free(response); + return err; } -UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String& userName, const String& pwd) +// Issues command to get last socket error, then prints to serial. Also updates rx/backlog buffers. +int UBX_CELL::socketGetLastError() { UBX_CELL_error_t err; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + userName.length() + pwd.length() + 16); - if (command == nullptr) { + char *response; + int errorCode = -1; + + command = ubx_cell_calloc_char(64); + if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, userName.c_str(), pwd.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + sprintf(command, "%s", UBX_CELL_GET_ERROR); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) + { + char *searchPtr = strstr(response, "+USOER:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+USOER:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + sscanf(searchPtr, "%d", &errorCode); + } + } + free(command); - return err; + free(response); + + return errorCode; } -UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) +IPAddress UBX_CELL::lastRemoteIP(void) { - UBX_CELL_error_t err; - char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (secprofile == -1) sprintf(command, "%s=%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure); - else sprintf(command, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, secprofile); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + return _lastRemoteIP; } -UBX_CELL_error_t UBX_CELL::connectMQTT(void) +UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) { UBX_CELL_error_t err; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 16); if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGIN); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_HTTP_PROFILE, profile); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) +UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address) { UBX_CELL_error_t err; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 64); if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGOUT); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; -} + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_IP, + address[0], address[1], address[2], address[3]); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String& topic) -{ - UBX_CELL_error_t err; - char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_SUBSCRIBE, max_Qos, topic.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; -} - -UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String& topic) -{ - UBX_CELL_error_t err; - char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length()); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_UNSUBSCRIBE, topic.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; -} - -UBX_CELL_error_t UBX_CELL::readMQTT(int* pQos, String* pTopic, uint8_t *readDest, int readLength, int *bytesRead) -{ - char *command; - char *response; - UBX_CELL_error_t err; - int scanNum = 0; - int total_length, topic_length, data_length; - - // Set *bytesRead to zero - if (bytesRead != nullptr) - *bytesRead = 0; - - // Allocate memory for the command - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - // Allocate memory for the response - int responseLength = readLength + minimumResponseAllocation; - response = ubx_cell_calloc_char(responseLength); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... - // To try and avoid this, look for \"\r\n\r\nOK\r\n there is a extra \r\n beetween " and the the standard \r\nOK\r\n - const char mqttReadTerm[] = "\"\r\n\r\nOK\r\n"; - sprintf(command, "%s=%d,%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_READ, 1); - err = sendCommandWithResponse(command, mqttReadTerm, response, - (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), responseLength); - - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) - { - _debugPort->print(F("readMQTT: sendCommandWithResponse err ")); - _debugPort->println(err); - } free(command); - free(response); return err; - } - - // Extract the data - char *searchPtr = strstr(response, "+UMQTTC:"); - int cmd = 0; - if (searchPtr != nullptr) - { - searchPtr += strlen("+UMQTTC:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanNum = sscanf(searchPtr, "%d,%d,%d,%d,\"%*[^\"]\",%d,\"", &cmd, pQos, &total_length, &topic_length, &data_length); - } - if ((scanNum != 5) || (cmd != UBX_CELL_MQTT_COMMAND_READ)) - { - if (_printDebug == true) - { - _debugPort->print(F("readMQTT: error: scanNum is ")); - _debugPort->println(scanNum); - } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - err = UBX_CELL_ERROR_SUCCESS; - searchPtr = strstr(searchPtr, "\""); - if (searchPtr!= nullptr) { - if (pTopic) { - searchPtr[topic_length + 1] = '\0'; // zero terminate - *pTopic = searchPtr + 1; - searchPtr[topic_length + 1] = '\"'; // restore - } - searchPtr = strstr(searchPtr + topic_length + 2, "\""); - if (readDest && (searchPtr != nullptr) && (response + responseLength >= searchPtr + data_length + 1) && (searchPtr[data_length + 1] == '"')) { - if (data_length > readLength) { - data_length = readLength; - if (_printDebug == true) { - _debugPort->print(F("readMQTT: error: trucate message")); - } - err = UBX_CELL_ERROR_OUT_OF_MEMORY; - } - memcpy(readDest, searchPtr+1, data_length); - *bytesRead = data_length; - } else { - if (_printDebug == true) { - _debugPort->print(F("readMQTT: error: message end ")); - } - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - } - free(command); - free(response); - - return err; } -UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String& topic, const char * const msg, uint8_t qos, bool retain) +UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) { - if (topic.length() < 1 || msg == nullptr) - { - return UBX_CELL_ERROR_INVALID; - } - - UBX_CELL_error_t err; - - char sanitized_msg[MAX_MQTT_DIRECT_MSG_LEN + 1]; - memset(sanitized_msg, 0, sizeof(sanitized_msg)); - - // Check the message length and truncate if necessary. - size_t msg_len = strnlen(msg, MAX_MQTT_DIRECT_MSG_LEN); - if (msg_len > MAX_MQTT_DIRECT_MSG_LEN) - { - msg_len = MAX_MQTT_DIRECT_MSG_LEN; - } - - strncpy(sanitized_msg, msg, msg_len); - char * msg_ptr = sanitized_msg; - while (*msg_ptr != 0) - { - if (*msg_ptr == '"') - { - *msg_ptr = ' '; - } - - msg_ptr++; - } + UBX_CELL_error_t err; + char *command; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + msg_len); - if (command == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - sprintf(command, "%s=%d,%u,%u,0,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISH, qos, (retain ? 1:0), topic.c_str(), sanitized_msg); + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + server.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_NAME, + server.c_str()); - sendCommand(command, true); - err = waitForResponse(UBX_CELL_RESPONSE_MORE, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - sendCommand(msg, false); - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - } - - free(command); - return err; -} - -UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String& topic, const char * const msg, size_t msg_len, uint8_t qos, bool retain) -{ - /* - * The modem prints the '>' as the signal to send the binary message content. - * at+umqttc=9,0,0,"topic",4 - * - * >"xY" - * OK - * - * +UUMQTTC: 9,1 - */ - if (topic.length() < 1|| msg == nullptr || msg_len > MAX_MQTT_DIRECT_MSG_LEN) - { - return UBX_CELL_ERROR_INVALID; - } - - UBX_CELL_error_t err; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length()); - if (command == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - sprintf(command, "%s=%d,%u,%u,\"%s\",%u", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, qos, (retain ? 1:0), topic.c_str(), msg_len); - - sendCommand(command, true); - err = waitForResponse(UBX_CELL_RESPONSE_MORE, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - sendCommand(msg, false); - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String& topic, const String& filename, uint8_t qos, bool retain) +UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) { - if (topic.length() < 1|| filename.length() < 1) - { - return UBX_CELL_ERROR_INVALID; - } + UBX_CELL_error_t err; + char *command; - UBX_CELL_error_t err; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + filename.length()); - if (command == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - sprintf(command, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, qos, (retain ? 1:0), topic.c_str(), filename.c_str()); + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + username.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_USERNAME, + username.c_str()); - sendCommand(command, true); - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code2) +UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) { - UBX_CELL_error_t err; - char *response; - - int code, code2; + UBX_CELL_error_t err; + char *command; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - err = sendCommandWithResponse(UBX_CELL_MQTT_PROTOCOL_ERROR, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + password.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_PASSWORD, + password.c_str()); - if (err == UBX_CELL_ERROR_SUCCESS) - { - int scanned = 0; - char *searchPtr = strstr(response, "+UMQTTER:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+UMQTTER:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,%d\r\n", - &code, &code2); - } - if (scanned == 2) - { - *error_code = code; - *error_code2 = code2; - } - else - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(response); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::setFTPserver(const String& serverName) +UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) { - constexpr size_t cmd_len = 145; - char command[cmd_len]; // long enough for AT+UFTP=1,<128 bytes> - - snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_SERVERNAME, serverName.c_str()); - return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -} + UBX_CELL_error_t err; + char *command; -UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, const unsigned int data_linger) -{ - constexpr size_t cmd_len = 64; - char command[cmd_len]; // long enough for AT+UFTP=1,<128 bytes> + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - snprintf(command, cmd_len - 1, "%s=%d,%u,%u,%u", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_TIMEOUT, timeout, cmd_linger, data_linger); - return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -} + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, authenticate); -UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String& userName, const String& pwd) -{ - UBX_CELL_error_t err; - constexpr size_t cmd_len = 48; - char command[cmd_len]; // long enough for AT+UFTP=n,<30 bytes> + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_USERNAME, userName.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err != UBX_CELL_ERROR_SUCCESS) - { + free(command); return err; - } - - snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_PWD, pwd.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - - return err; -} - -UBX_CELL_error_t UBX_CELL::connectFTP(void) -{ - constexpr size_t cmd_len = 16; - char command[cmd_len]; // long enough for AT+UFTPC=n - - snprintf(command, cmd_len - 1, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGIN); - return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } -UBX_CELL_error_t UBX_CELL::disconnectFTP(void) +UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) { - constexpr size_t cmd_len = 16; - char command[cmd_len]; // long enough for AT+UFTPC=n + UBX_CELL_error_t err; + char *command; - snprintf(command, cmd_len - 1, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGOUT); - return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); -} + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; -UBX_CELL_error_t UBX_CELL::ftpGetFile(const String& filename) -{ - char * command = ubx_cell_calloc_char(strlen(UBX_CELL_FTP_COMMAND) + (2 * filename.length()) + 16); - if (command == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_PORT, port); - sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, filename.c_str(), filename.c_str()); - //memset(response, 0, sizeof(response)); - //sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, response, 8000 /* ms */, response_len); - UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2) +UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) { - UBX_CELL_error_t err; - char *response; - - int code, code2; - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + UBX_CELL_error_t err; + char *command; - err = sendCommandWithResponse(UBX_CELL_FTP_PROTOCOL_ERROR, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - if (err == UBX_CELL_ERROR_SUCCESS) - { - int scanned = 0; - char *searchPtr = strstr(response, "+UFTPER:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+UFTPER:"); // Move searchPtr to first char - while (*searchPtr == ' ') - { - searchPtr++; // skip spaces - } - scanned = sscanf(searchPtr, "%d,%d\r\n", &code, &code2); - } + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + header.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, + header.c_str()); - if (scanned == 2) - { - *error_code = code; - *error_code2 = code2; - } - else - { - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(response); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) +UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofile) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + 6); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - sprintf(command, "%s=%d", UBX_CELL_SEC_PROFILE, secprofile); + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (secprofile == -1) + sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure); + else + sprintf(command, "%s=%d,%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure, + secprofile); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value) +UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, unsigned long timeout, int ttl) { UBX_CELL_error_t err; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + 10); + command = ubx_cell_calloc_char(strlen(UBX_CELL_PING_COMMAND) + 48 + remote_host.length()); if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_SEC_PROFILE, secprofile,parameter,value); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\",%d,%d,%ld,%d", UBX_CELL_PING_COMMAND, remote_host.c_str(), retry, p_size, timeout, ttl); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::configSecurityProfileString(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, String value) +UBX_CELL_error_t UBX_CELL::sendHTTPGET(int profile, String path, String responseFilename) { UBX_CELL_error_t err; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + value.length() + 10); + + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length()); if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_SEC_PROFILE, secprofile,parameter,value.c_str()); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\",\"%s\"", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_GET, path.c_str(), + responseFilename.c_str()); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, UBX_CELL_sec_manager_parameter_t parameter, String name, String data) +UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String responseFilename, String data, + UBX_CELL_http_content_types_t httpContentType) { - char *command; - char *response; - UBX_CELL_error_t err; + UBX_CELL_error_t err; + char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_MANAGER) + name.length() + 20); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - int dataLen = data.length(); - sprintf(command, "%s=%d,%d,\"%s\",%d", UBX_CELL_SEC_MANAGER, opcode, parameter, name.c_str(), dataLen); - - err = sendCommandWithResponse(command, ">", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) - { - _debugPort->print(F("dataDownload: writing ")); - _debugPort->print(dataLen); - _debugPort->println(F(" bytes")); - } - hwWriteData(data.c_str(), dataLen); - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT*3); - } + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length() + + data.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, + UBX_CELL_HTTP_COMMAND_POST_DATA, path.c_str(), responseFilename.c_str(), data.c_str(), httpContentType); - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) - { - _debugPort->print(F("dataDownload: Error: ")); - _debugPort->print(err); - _debugPort->print(F(" => {")); - _debugPort->print(response); - _debugPort->println(F("}")); - } - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - free(response); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) +UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String responseFilename, String requestFile, + UBX_CELL_http_content_types_t httpContentType) { - UBX_CELL_error_t err; - char *command; + UBX_CELL_error_t err; + char *command; - if (cid >= UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) - return UBX_CELL_ERROR_ERROR; + if (profile >= UBX_CELL_NUM_HTTP_PROFILES) + return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE) + 32); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (cid == -1) - sprintf(command, "%s=%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status); - else - sprintf(command, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status, cid); + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length() + + requestFile.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, + UBX_CELL_HTTP_COMMAND_POST_FILE, path.c_str(), responseFilename.c_str(), requestFile.c_str(), + httpContentType); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; + free(command); + return err; } -bool UBX_CELL::isGPSon(void) +UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, int *error_code) { - UBX_CELL_error_t err; - char *command; - char *response; - bool on = false; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_POWER) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_POWER); + UBX_CELL_error_t err; + char *command; + char *response; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + int rprofile, eclass, ecode; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, - UBX_CELL_10_SEC_TIMEOUT); + command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROTOCOL_ERROR) + 4); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_HTTP_PROTOCOL_ERROR, profile); - if (err == UBX_CELL_ERROR_SUCCESS) - { - // Example response: "+UGPS: 0" for off "+UGPS: 1,0,1" for on - // Search for a ':' followed by a '1' or ' 1' - char *pch1 = strchr(response, ':'); - if (pch1 != nullptr) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - char *pch2 = strchr(response, '1'); - if ((pch2 != nullptr) && ((pch2 == pch1 + 1) || (pch2 == pch1 + 2))) - on = true; + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - } - - free(command); - free(response); - - return on; -} - -UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_aiding_mode_t gnss_aiding) -{ - UBX_CELL_error_t err; - char *command; - bool gpsState; - - // Don't turn GPS on/off if it's already on/off - gpsState = isGPSon(); - if ((enable && gpsState) || (!enable && !gpsState)) - { - return UBX_CELL_ERROR_SUCCESS; - } - // GPS power management - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_POWER) + 32); // gnss_sys could be up to three digits - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (enable) - { - sprintf(command, "%s=1,%d,%d", UBX_CELL_GNSS_POWER, gnss_aiding, gnss_sys); - } - else - { - sprintf(command, "%s=0", UBX_CELL_GNSS_POWER); - } + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, 10000); + if (err == UBX_CELL_ERROR_SUCCESS) + { + int scanned = 0; + char *searchPtr = strstr(response, "+UHTTPER:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UHTTPER:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,%d,%d\r\n", &rprofile, &eclass, &ecode); + } + if (scanned == 3) + { + *error_class = eclass; + *error_code = ecode; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - free(command); - return err; + free(command); + free(response); + return err; } -/* -UBX_CELL_error_t UBX_CELL::gpsEnableClock(bool enable) +UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) { - // AT+UGZDA=<0,1> - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_NVM) + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_MQTT_NVM, parameter); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::gpsGetClock(struct ClockData *clock) +UBX_CELL_error_t UBX_CELL::setMQTTclientId(const String &clientId) { - // AT+UGZDA? - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + clientId.length() + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_CLIENT_ID, clientId.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::gpsEnableFix(bool enable) +UBX_CELL_error_t UBX_CELL::setMQTTserver(const String &serverName, int port) { - // AT+UGGGA=<0,1> - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + serverName.length() + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\",%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SERVERNAME, serverName.c_str(), + port); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::gpsGetFix(struct PositionData *pos) +UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const String &pwd) { - // AT+UGGGA? - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; - return err; -} - -UBX_CELL_error_t UBX_CELL::gpsEnablePos(bool enable) -{ - // AT+UGGLL=<0,1> - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + userName.length() + pwd.length() + 16); + if (command == nullptr) + { + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, userName.c_str(), + pwd.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::gpsGetPos(struct PositionData *pos) +UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) { - // AT+UGGLL? - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (secprofile == -1) + sprintf(command, "%s=%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure); + else + sprintf(command, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, secprofile); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::gpsEnableSat(bool enable) +UBX_CELL_error_t UBX_CELL::connectMQTT(void) { - // AT+UGGSV=<0,1> - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGIN); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -UBX_CELL_error_t UBX_CELL::gpsGetSat(uint8_t *sats) +UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) { - // AT+UGGSV? - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -*/ - -UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) -{ - // AT+UGRMC=<0,1> - UBX_CELL_error_t err; - char *command; - - // ** Don't call gpsPower here. It causes problems for +UTIME and the PPS signal ** - // ** Call isGPSon and gpsPower externally if required ** - // if (!isGPSon()) - // { - // err = gpsPower(true); - // if (err != UBX_CELL_ERROR_SUCCESS) - // { - // return err; - // } - // } - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_GPRMC) + 3); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_GNSS_GPRMC, enable ? 1 : 0); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - - free(command); - return err; -} -UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData *spd, - struct ClockData *clk, bool *valid) +UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String &topic) { - UBX_CELL_error_t err; - char *command; - char *response; - char *rmcBegin; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_GPRMC) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_GPRMC); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_SUBSCRIBE, max_Qos, topic.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); - if (err == UBX_CELL_ERROR_SUCCESS) - { - // Fast-forward response string to $GPRMC starter - rmcBegin = strstr(response, "$GPRMC"); - if (rmcBegin == nullptr) - { - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - else - { - *valid = parseGPRMCString(rmcBegin, pos, clk, spd); - } - } - - free(command); - free(response); - return err; -} - -/* -UBX_CELL_error_t UBX_CELL::gpsEnableSpeed(bool enable) -{ - // AT+UGVTG=<0,1> - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsGetSpeed(struct SpeedData *speed) +UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String &topic) { - // AT+UGVTG? - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length()); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_UNSUBSCRIBE, topic.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); return err; } -*/ - -UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, - bool detailed, unsigned int sensor) -{ - // AT+ULOC=2,,,, - UBX_CELL_error_t err; - char *command; - - // This function will only work if the GPS module is initially turned off. - if (isGPSon()) - { - gpsPower(false); - } - - if (timeout > 999) - timeout = 999; - if (accuracy > 999999) - accuracy = 999999; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_LOCATION) + 24); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; -#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - sprintf(command, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, - sensor, detailed ? 1 : 0, timeout, accuracy); -#else - sprintf(command, "%s=2,%d,%d,%d,%ld", UBX_CELL_GNSS_REQUEST_LOCATION, - sensor, detailed ? 1 : 0, timeout, accuracy); -#endif - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - - free(command); - return err; -} - -UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const char *secondaryServer, const char *authToken, - unsigned int days, unsigned int period, unsigned int resolution, - unsigned int gnssTypes, unsigned int mode, unsigned int dataType) -{ - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_AIDING_SERVER_CONFIGURATION) + 256); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - sprintf(command, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, - primaryServer, secondaryServer, authToken, - days, period, resolution, gnssTypes, mode, dataType); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - - free(command); - return err; -} - -// OK for text files. But will fail with binary files (containing \0) on some platforms. -UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, int len) +UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest, int readLength, int *bytesRead) { - char *command; - char *response; - UBX_CELL_error_t err; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - int dataLen = len == -1 ? strlen(str) : len; - sprintf(command, "%s=\"%s\",%d", UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE, filename.c_str(), dataLen); - - err = sendCommandWithResponse(command, ">", response, - UBX_CELL_STANDARD_RESPONSE_TIMEOUT*2); + char *command; + char *response; + UBX_CELL_error_t err; + int scanNum = 0; + int total_length, topic_length, data_length; - unsigned long writeDelay = millis(); - while (millis() < (writeDelay + 50)) - delay(1); //uBlox specification says to wait 50ms after receiving "@" to write data. + // Set *bytesRead to zero + if (bytesRead != nullptr) + *bytesRead = 0; - if (err == UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) - { - _debugPort->print(F("fileDownload: writing ")); - _debugPort->print(dataLen); - _debugPort->println(F(" bytes")); - } - hwWriteData(str, dataLen); + // Allocate memory for the command + command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; - err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT*5); - } - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) + // Allocate memory for the response + int responseLength = readLength + minimumResponseAllocation; + response = ubx_cell_calloc_char(responseLength); + if (response == nullptr) { - _debugPort->print(F("fileDownload: Error: ")); - _debugPort->print(err); - _debugPort->print(F(" => {")); - _debugPort->print(response); - _debugPort->println(F("}")); + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - } - - free(command); - free(response); - return err; -} - -UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, String str) -{ - return appendFileContents(filename, str.c_str(), str.length()); -} + // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... + // To try and avoid this, look for \"\r\n\r\nOK\r\n there is a extra \r\n beetween " and the the standard \r\nOK\r\n + const char mqttReadTerm[] = "\"\r\n\r\nOK\r\n"; + sprintf(command, "%s=%d,%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_READ, 1); + err = sendCommandWithResponse(command, mqttReadTerm, response, (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), + responseLength); -// OK for text files. But will fail with binary files (containing \0) on some platforms. -UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) -{ - UBX_CELL_error_t err; - char *command; - char *response; - - // Start by getting the file size so we know in advance how much data to expect - int fileSize = 0; - err = getFileSize(filename, &fileSize); - if (err != UBX_CELL_SUCCESS) - { - if (_printDebug == true) + if (err != UBX_CELL_ERROR_SUCCESS) { - _debugPort->print(F("getFileContents: getFileSize returned err ")); - _debugPort->println(err); + if (_printDebug == true) + { + _debugPort->print(F("readMQTT: sendCommandWithResponse err ")); + _debugPort->println(err); + } + free(command); + free(response); + return err; } - return err; - } - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); - - response = ubx_cell_calloc_char(fileSize + minimumResponseAllocation); - if (response == nullptr) - { - if (_printDebug == true) - { - _debugPort->print(F("getFileContents: response alloc failed: ")); - _debugPort->println(fileSize + minimumResponseAllocation); - } - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - // A large file will completely fill the backlog buffer - but it will be pruned afterwards - // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... - // To try and avoid this, look for \"\r\nOK\r\n - const char fileReadTerm[] = "\r\nOK\r\n"; //LARA-R6 returns "\"\r\n\r\nOK\r\n" while SARA-R5 return "\"\r\nOK\r\n"; - err = sendCommandWithResponse(command, fileReadTerm, - response, (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), - (fileSize + minimumResponseAllocation)); - - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) + // Extract the data + char *searchPtr = strstr(response, "+UMQTTC:"); + int cmd = 0; + if (searchPtr != nullptr) { - _debugPort->print(F("getFileContents: sendCommandWithResponse returned err ")); - _debugPort->println(err); + searchPtr += strlen("+UMQTTC:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanNum = + sscanf(searchPtr, "%d,%d,%d,%d,\"%*[^\"]\",%d,\"", &cmd, pQos, &total_length, &topic_length, &data_length); } - free(command); - free(response); - return err; - } - - // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n - int scanned = 0; - int readFileSize = 0; - char *searchPtr = strstr(response, "+URDFILE:"); - if (searchPtr != nullptr) - { - searchPtr = strchr(searchPtr, '\"'); // Find the first quote - searchPtr = strchr(++searchPtr, '\"'); // Find the second quote - - scanned = sscanf(searchPtr, "\",%d,", &readFileSize); // Get the file size (again) - if (scanned == 1) + if ((scanNum != 5) || (cmd != UBX_CELL_MQTT_COMMAND_READ)) { - searchPtr = strchr(++searchPtr, '\"'); // Find the third quote - - if (searchPtr == nullptr) - { if (_printDebug == true) { - _debugPort->println(F("getFileContents: third quote not found!")); + _debugPort->print(F("readMQTT: error: scanNum is ")); + _debugPort->println(scanNum); } free(command); free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - int bytesRead = 0; - - while (bytesRead < readFileSize) - { - searchPtr++; // Increment searchPtr then copy file char into contents - // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible. - // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's. - // The only true binary-compatible solution is to use getFileContents(String filename, char *contents)... - contents->concat(*(searchPtr)); // Append file char to contents - bytesRead++; - } - if (_printDebug == true) - { - _debugPort->print(F("getFileContents: total bytes read: ")); - _debugPort->println(bytesRead); - } - err = UBX_CELL_ERROR_SUCCESS; } - else + + err = UBX_CELL_ERROR_SUCCESS; + searchPtr = strstr(searchPtr, "\""); + if (searchPtr != nullptr) { - if (_printDebug == true) - { - _debugPort->print(F("getFileContents: sscanf failed! scanned is ")); - _debugPort->println(scanned); - } - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + if (pTopic) + { + searchPtr[topic_length + 1] = '\0'; // zero terminate + *pTopic = searchPtr + 1; + searchPtr[topic_length + 1] = '\"'; // restore + } + searchPtr = strstr(searchPtr + topic_length + 2, "\""); + if (readDest && (searchPtr != nullptr) && (response + responseLength >= searchPtr + data_length + 1) && + (searchPtr[data_length + 1] == '"')) + { + if (data_length > readLength) + { + data_length = readLength; + if (_printDebug == true) + { + _debugPort->print(F("readMQTT: error: trucate message")); + } + err = UBX_CELL_ERROR_OUT_OF_MEMORY; + } + memcpy(readDest, searchPtr + 1, data_length); + *bytesRead = data_length; + } + else + { + if (_printDebug == true) + { + _debugPort->print(F("readMQTT: error: message end ")); + } + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } } - } - else - { - if (_printDebug == true) - _debugPort->println(F("getFileContents: strstr failed!")); - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + free(command); + free(response); - free(command); - free(response); - return err; + return err; } -// OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize. -UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) +UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String &topic, const char *const msg, uint8_t qos, bool retain) { - UBX_CELL_error_t err; - char *command; - char *response; - - // Start by getting the file size so we know in advance how much data to expect - int fileSize = 0; - err = getFileSize(filename, &fileSize); - if (err != UBX_CELL_SUCCESS) - { - if (_printDebug == true) + if (topic.length() < 1 || msg == nullptr) { - _debugPort->print(F("getFileContents: getFileSize returned err ")); - _debugPort->println(err); + return UBX_CELL_ERROR_INVALID; } - return err; - } - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); + UBX_CELL_error_t err; - response = ubx_cell_calloc_char(fileSize + minimumResponseAllocation); - if (response == nullptr) - { - if (_printDebug == true) - { - _debugPort->print(F("getFileContents: response alloc failed: ")); - _debugPort->println(fileSize + minimumResponseAllocation); - } - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - // A large file will completely fill the backlog buffer - but it will be pruned afterwards - // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... - // To try and avoid this, look for \"\r\nOK\r\n - const char fileReadTerm[] = "\"\r\nOK\r\n"; - err = sendCommandWithResponse(command, fileReadTerm, - response, (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), - (fileSize + minimumResponseAllocation)); - - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) + char sanitized_msg[MAX_MQTT_DIRECT_MSG_LEN + 1]; + memset(sanitized_msg, 0, sizeof(sanitized_msg)); + + // Check the message length and truncate if necessary. + size_t msg_len = strnlen(msg, MAX_MQTT_DIRECT_MSG_LEN); + if (msg_len > MAX_MQTT_DIRECT_MSG_LEN) { - _debugPort->print(F("getFileContents: sendCommandWithResponse returned err ")); - _debugPort->println(err); + msg_len = MAX_MQTT_DIRECT_MSG_LEN; } - free(command); - free(response); - return err; - } - - // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n - int scanned = 0; - int readFileSize = 0; - char *searchPtr = strstr(response, "+URDFILE:"); - if (searchPtr != nullptr) - { - searchPtr = strchr(searchPtr, '\"'); // Find the first quote - searchPtr = strchr(++searchPtr, '\"'); // Find the second quote - scanned = sscanf(searchPtr, "\",%d,", &readFileSize); // Get the file size (again) - if (scanned == 1) + strncpy(sanitized_msg, msg, msg_len); + char *msg_ptr = sanitized_msg; + while (*msg_ptr != 0) { - searchPtr = strchr(++searchPtr, '\"'); // Find the third quote - - if (searchPtr == nullptr) - { - if (_printDebug == true) + if (*msg_ptr == '"') { - _debugPort->println(F("getFileContents: third quote not found!")); + *msg_ptr = ' '; } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - int bytesRead = 0; - - while (bytesRead < readFileSize) - { - searchPtr++; // Increment searchPtr then copy file char into contents - contents[bytesRead] = *searchPtr; // Append file char to contents - bytesRead++; - } - if (_printDebug == true) - { - _debugPort->print(F("getFileContents: total bytes read: ")); - _debugPort->println(bytesRead); - } - err = UBX_CELL_ERROR_SUCCESS; + + msg_ptr++; } - else + + char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + msg_len); + if (command == nullptr) { - if (_printDebug == true) - { - _debugPort->print(F("getFileContents: sscanf failed! scanned is ")); - _debugPort->println(scanned); - } - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - } - else - { - if (_printDebug == true) - _debugPort->println(F("getFileContents: strstr failed!")); - err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - free(command); - free(response); - return err; -} - -UBX_CELL_error_t UBX_CELL::getFileBlock(const String& filename, char* buffer, size_t offset, size_t requested_length, size_t& bytes_read) -{ - bytes_read = 0; - if (filename.length() < 1 || buffer == nullptr || requested_length < 1) - { - return UBX_CELL_ERROR_UNEXPECTED_PARAM; - } + sprintf(command, "%s=%d,%u,%u,0,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISH, qos, + (retain ? 1 : 0), topic.c_str(), sanitized_msg); - // trying to get a byte at a time does not seem to be reliable so this method must use - // a real UART. - if (_hardSerial == nullptr) - { - if (_printDebug == true) + sendCommand(command, true); + err = waitForResponse(UBX_CELL_RESPONSE_MORE, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) { - _debugPort->println(F("getFileBlock: only works with a hardware UART")); + sendCommand(msg, false); + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } - return UBX_CELL_ERROR_INVALID; - } - - size_t cmd_len = filename.length() + 32; - char* cmd = ubx_cell_calloc_char(cmd_len); - sprintf(cmd, "at+urdblock=\"%s\",%zu,%zu\r\n", filename.c_str(), offset, requested_length); - sendCommand(cmd, false); - int ich; - char ch; - int quote_count = 0; - size_t comma_idx = 0; + free(command); + return err; +} - while (quote_count < 3) - { - ich = _hardSerial->read(); - if (ich < 0) - { - continue; - } - ch = (char)(ich & 0xFF); - cmd[bytes_read++] = ch; - if (ch == '"') +UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String &topic, const char *const msg, size_t msg_len, uint8_t qos, + bool retain) +{ + /* + * The modem prints the '>' as the signal to send the binary message content. + * at+umqttc=9,0,0,"topic",4 + * + * >"xY" + * OK + * + * +UUMQTTC: 9,1 + */ + if (topic.length() < 1 || msg == nullptr || msg_len > MAX_MQTT_DIRECT_MSG_LEN) { - quote_count++; + return UBX_CELL_ERROR_INVALID; } - else if (ch == ',' && comma_idx == 0) + + UBX_CELL_error_t err; + char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length()); + if (command == nullptr) { - comma_idx = bytes_read; + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - } - cmd[bytes_read] = 0; - cmd[bytes_read - 2] = 0; + sprintf(command, "%s=%d,%u,%u,\"%s\",%u", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, qos, + (retain ? 1 : 0), topic.c_str(), msg_len); - // Example response: - // +URDBLOCK: "wombat.bin",64000,"... " - size_t data_length = strtoul(&cmd[comma_idx], nullptr, 10); - free(cmd); - - bytes_read = 0; - size_t bytes_remaining = data_length; - while (bytes_read < data_length) - { - // This method seems more reliable than reading a byte at a time. - size_t rc = _hardSerial->readBytes(&buffer[bytes_read], bytes_remaining); - bytes_read += rc; - bytes_remaining -= rc; - } + sendCommand(command, true); + err = waitForResponse(UBX_CELL_RESPONSE_MORE, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) + { + sendCommand(msg, false); + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + } - return UBX_CELL_ERROR_SUCCESS; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) +UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String &filename, uint8_t qos, bool retain) { - UBX_CELL_error_t err; - char *command; - char *response; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_LIST_FILES) + filename.length() + 8); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=2,\"%s\"", UBX_CELL_FILE_SYSTEM_LIST_FILES, filename.c_str()); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) + if (topic.length() < 1 || filename.length() < 1) { - _debugPort->print(F("getFileSize: Fail: Error: ")); - _debugPort->print(err); - _debugPort->print(F(" Response: {")); - _debugPort->print(response); - _debugPort->println(F("}")); + return UBX_CELL_ERROR_INVALID; } - free(command); - free(response); - return err; - } - char *responseStart = strstr(response, "+ULSTFILE:"); - if (responseStart == nullptr) - { - if (_printDebug == true) + UBX_CELL_error_t err; + char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + filename.length()); + if (command == nullptr) { - _debugPort->print(F("getFileSize: Failure: {")); - _debugPort->print(response); - _debugPort->println(F("}")); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - free(command); - free(response); - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - int fileSize; - responseStart += strlen("+ULSTFILE:"); // Move searchPtr to first char - while (*responseStart == ' ') responseStart++; // skip spaces - sscanf(responseStart, "%d", &fileSize); - *size = fileSize; + sprintf(command, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, qos, + (retain ? 1 : 0), topic.c_str(), filename.c_str()); + + sendCommand(command, true); + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - free(response); - return err; + free(command); + return err; } -UBX_CELL_error_t UBX_CELL::deleteFile(String filename) +UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code2) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_DELETE_FILE) + filename.length() + 8); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_DELETE_FILE, filename.c_str()); + UBX_CELL_error_t err; + char *response; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + int code, code2; - if (err != UBX_CELL_ERROR_SUCCESS) - { - if (_printDebug == true) + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) { - _debugPort->print(F("deleteFile: Fail: Error: ")); - _debugPort->println(err); + return UBX_CELL_ERROR_OUT_OF_MEMORY; } - } - - free(command); - return err; -} -UBX_CELL_error_t UBX_CELL::modulePowerOff(void) -{ - UBX_CELL_error_t err; - char *command; + err = sendCommandWithResponse(UBX_CELL_MQTT_PROTOCOL_ERROR, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_POWER_OFF) + 6); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (err == UBX_CELL_ERROR_SUCCESS) + { + int scanned = 0; + char *searchPtr = strstr(response, "+UMQTTER:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UMQTTER:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,%d\r\n", &code, &code2); + } + if (scanned == 2) + { + *error_code = code; + *error_code2 = code2; + } + else + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::setFTPserver(const String &serverName) +{ + constexpr size_t cmd_len = 145; + char command[cmd_len]; // long enough for AT+UFTP=1,<128 bytes> + + snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_SERVERNAME, + serverName.c_str()); + return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); +} + +UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, + const unsigned int data_linger) +{ + constexpr size_t cmd_len = 64; + char command[cmd_len]; // long enough for AT+UFTP=1,<128 bytes> + + snprintf(command, cmd_len - 1, "%s=%d,%u,%u,%u", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_TIMEOUT, timeout, + cmd_linger, data_linger); + return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); +} + +UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const String &pwd) +{ + UBX_CELL_error_t err; + constexpr size_t cmd_len = 48; + char command[cmd_len]; // long enough for AT+UFTP=n,<30 bytes> + + snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_USERNAME, + userName.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err != UBX_CELL_ERROR_SUCCESS) + { + return err; + } + + snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_PWD, pwd.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + return err; +} + +UBX_CELL_error_t UBX_CELL::connectFTP(void) +{ + constexpr size_t cmd_len = 16; + char command[cmd_len]; // long enough for AT+UFTPC=n + + snprintf(command, cmd_len - 1, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGIN); + return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); +} + +UBX_CELL_error_t UBX_CELL::disconnectFTP(void) +{ + constexpr size_t cmd_len = 16; + char command[cmd_len]; // long enough for AT+UFTPC=n + + snprintf(command, cmd_len - 1, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGOUT); + return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); +} + +UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) +{ + char *command = ubx_cell_calloc_char(strlen(UBX_CELL_FTP_COMMAND) + (2 * filename.length()) + 16); + if (command == nullptr) + { + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, filename.c_str(), + filename.c_str()); + // memset(response, 0, sizeof(response)); + // sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, response, 8000 /* ms */, response_len); + UBX_CELL_error_t err = + sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2) +{ + UBX_CELL_error_t err; + char *response; + + int code, code2; + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(UBX_CELL_FTP_PROTOCOL_ERROR, UBX_CELL_RESPONSE_OK_OR_ERROR, response, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) + { + int scanned = 0; + char *searchPtr = strstr(response, "+UFTPER:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UFTPER:"); // Move searchPtr to first char + while (*searchPtr == ' ') + { + searchPtr++; // skip spaces + } + scanned = sscanf(searchPtr, "%d,%d\r\n", &code, &code2); + } + + if (scanned == 2) + { + *error_code = code; + *error_code2 = code2; + } + else + { + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + } + + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + 6); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + + sprintf(command, "%s=%d", UBX_CELL_SEC_PROFILE, secprofile); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", UBX_CELL_SEC_PROFILE, secprofile, parameter, value); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::configSecurityProfileString(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, + String value) +{ + UBX_CELL_error_t err; + char *command; + command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + value.length() + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_SEC_PROFILE, secprofile, parameter, value.c_str()); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, + UBX_CELL_sec_manager_parameter_t parameter, String name, String data) +{ + char *command; + char *response; + UBX_CELL_error_t err; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_MANAGER) + name.length() + 20); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + int dataLen = data.length(); + sprintf(command, "%s=%d,%d,\"%s\",%d", UBX_CELL_SEC_MANAGER, opcode, parameter, name.c_str(), dataLen); + + err = sendCommandWithResponse(command, ">", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("dataDownload: writing ")); + _debugPort->print(dataLen); + _debugPort->println(F(" bytes")); + } + hwWriteData(data.c_str(), dataLen); + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 3); + } + + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("dataDownload: Error: ")); + _debugPort->print(err); + _debugPort->print(F(" => {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } + } + + free(command); + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) +{ + UBX_CELL_error_t err; + char *command; + + if (cid >= UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) + return UBX_CELL_ERROR_ERROR; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE) + 32); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (cid == -1) + sprintf(command, "%s=%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status); + else + sprintf(command, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status, cid); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +bool UBX_CELL::isGPSon(void) +{ + UBX_CELL_error_t err; + char *command; + char *response; + bool on = false; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_POWER) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_GNSS_POWER); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); + + if (err == UBX_CELL_ERROR_SUCCESS) + { + // Example response: "+UGPS: 0" for off "+UGPS: 1,0,1" for on + // Search for a ':' followed by a '1' or ' 1' + char *pch1 = strchr(response, ':'); + if (pch1 != nullptr) + { + char *pch2 = strchr(response, '1'); + if ((pch2 != nullptr) && ((pch2 == pch1 + 1) || (pch2 == pch1 + 2))) + on = true; + } + } + + free(command); + free(response); + + return on; +} + +UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_aiding_mode_t gnss_aiding) +{ + UBX_CELL_error_t err; + char *command; + bool gpsState; + + // Don't turn GPS on/off if it's already on/off + gpsState = isGPSon(); + if ((enable && gpsState) || (!enable && !gpsState)) + { + return UBX_CELL_ERROR_SUCCESS; + } + + // GPS power management + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_POWER) + 32); // gnss_sys could be up to three digits + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (enable) + { + sprintf(command, "%s=1,%d,%d", UBX_CELL_GNSS_POWER, gnss_aiding, gnss_sys); + } + else + { + sprintf(command, "%s=0", UBX_CELL_GNSS_POWER); + } + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, 10000); + + free(command); + return err; +} + +/* +UBX_CELL_error_t UBX_CELL::gpsEnableClock(bool enable) +{ + // AT+UGZDA=<0,1> + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsGetClock(struct ClockData *clock) +{ + // AT+UGZDA? + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsEnableFix(bool enable) +{ + // AT+UGGGA=<0,1> + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsGetFix(struct PositionData *pos) +{ + // AT+UGGGA? + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsEnablePos(bool enable) +{ + // AT+UGGLL=<0,1> + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsGetPos(struct PositionData *pos) +{ + // AT+UGGLL? + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsEnableSat(bool enable) +{ + // AT+UGGSV=<0,1> + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsGetSat(uint8_t *sats) +{ + // AT+UGGSV? + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} +*/ + +UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) +{ + // AT+UGRMC=<0,1> + UBX_CELL_error_t err; + char *command; + + // ** Don't call gpsPower here. It causes problems for +UTIME and the PPS signal ** + // ** Call isGPSon and gpsPower externally if required ** + // if (!isGPSon()) + // { + // err = gpsPower(true); + // if (err != UBX_CELL_ERROR_SUCCESS) + // { + // return err; + // } + // } + + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_GPRMC) + 3); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_GNSS_GPRMC, enable ? 1 : 0); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); + + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData *spd, struct ClockData *clk, + bool *valid) +{ + UBX_CELL_error_t err; + char *command; + char *response; + char *rmcBegin; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_GPRMC) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_GNSS_GPRMC); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); + if (err == UBX_CELL_ERROR_SUCCESS) + { + // Fast-forward response string to $GPRMC starter + rmcBegin = strstr(response, "$GPRMC"); + if (rmcBegin == nullptr) + { + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + else + { + *valid = parseGPRMCString(rmcBegin, pos, clk, spd); + } + } + + free(command); + free(response); + return err; +} + +/* +UBX_CELL_error_t UBX_CELL::gpsEnableSpeed(bool enable) +{ + // AT+UGVTG=<0,1> + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsGetSpeed(struct SpeedData *speed) +{ + // AT+UGVTG? + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; + return err; +} +*/ + +UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, bool detailed, unsigned int sensor) +{ + // AT+ULOC=2,,,, + UBX_CELL_error_t err; + char *command; + + // This function will only work if the GPS module is initially turned off. + if (isGPSon()) + { + gpsPower(false); + } + + if (timeout > 999) + timeout = 999; + if (accuracy > 999999) + accuracy = 999999; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_LOCATION) + 24); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + sprintf(command, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); +#else + sprintf(command, "%s=2,%d,%d,%d,%ld", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); +#endif + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); + + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const char *secondaryServer, + const char *authToken, unsigned int days, unsigned int period, + unsigned int resolution, unsigned int gnssTypes, unsigned int mode, + unsigned int dataType) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_AIDING_SERVER_CONFIGURATION) + 256); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + + sprintf(command, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, primaryServer, + secondaryServer, authToken, days, period, resolution, gnssTypes, mode, dataType); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +// OK for text files. But will fail with binary files (containing \0) on some platforms. +UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, int len) +{ + char *command; + char *response; + UBX_CELL_error_t err; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + int dataLen = len == -1 ? strlen(str) : len; + sprintf(command, "%s=\"%s\",%d", UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE, filename.c_str(), dataLen); + + err = sendCommandWithResponse(command, ">", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 2); + + unsigned long writeDelay = millis(); + while (millis() < (writeDelay + 50)) + delay(1); // uBlox specification says to wait 50ms after receiving "@" to write data. + + if (err == UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("fileDownload: writing ")); + _debugPort->print(dataLen); + _debugPort->println(F(" bytes")); + } + hwWriteData(str, dataLen); + + err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); + } + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("fileDownload: Error: ")); + _debugPort->print(err); + _debugPort->print(F(" => {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } + } + + free(command); + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, String str) +{ + return appendFileContents(filename, str.c_str(), str.length()); +} + +// OK for text files. But will fail with binary files (containing \0) on some platforms. +UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) +{ + UBX_CELL_error_t err; + char *command; + char *response; + + // Start by getting the file size so we know in advance how much data to expect + int fileSize = 0; + err = getFileSize(filename, &fileSize); + if (err != UBX_CELL_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: getFileSize returned err ")); + _debugPort->println(err); + } + return err; + } + + command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); + + response = ubx_cell_calloc_char(fileSize + minimumResponseAllocation); + if (response == nullptr) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: response alloc failed: ")); + _debugPort->println(fileSize + minimumResponseAllocation); + } + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + // A large file will completely fill the backlog buffer - but it will be pruned afterwards + // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... + // To try and avoid this, look for \"\r\nOK\r\n + const char fileReadTerm[] = "\r\nOK\r\n"; // LARA-R6 returns "\"\r\n\r\nOK\r\n" while SARA-R5 return "\"\r\nOK\r\n"; + err = sendCommandWithResponse(command, fileReadTerm, response, (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), + (fileSize + minimumResponseAllocation)); + + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: sendCommandWithResponse returned err ")); + _debugPort->println(err); + } + free(command); + free(response); + return err; + } + + // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n + int scanned = 0; + int readFileSize = 0; + char *searchPtr = strstr(response, "+URDFILE:"); + if (searchPtr != nullptr) + { + searchPtr = strchr(searchPtr, '\"'); // Find the first quote + searchPtr = strchr(++searchPtr, '\"'); // Find the second quote + + scanned = sscanf(searchPtr, "\",%d,", &readFileSize); // Get the file size (again) + if (scanned == 1) + { + searchPtr = strchr(++searchPtr, '\"'); // Find the third quote + + if (searchPtr == nullptr) + { + if (_printDebug == true) + { + _debugPort->println(F("getFileContents: third quote not found!")); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + int bytesRead = 0; + + while (bytesRead < readFileSize) + { + searchPtr++; // Increment searchPtr then copy file char into contents + // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible. + // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's. + // The only true binary-compatible solution is to use getFileContents(String filename, char + // *contents)... + contents->concat(*(searchPtr)); // Append file char to contents + bytesRead++; + } + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: total bytes read: ")); + _debugPort->println(bytesRead); + } + err = UBX_CELL_ERROR_SUCCESS; + } + else + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: sscanf failed! scanned is ")); + _debugPort->println(scanned); + } + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + } + else + { + if (_printDebug == true) + _debugPort->println(F("getFileContents: strstr failed!")); + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + free(command); + free(response); + return err; +} + +// OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize. +UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) +{ + UBX_CELL_error_t err; + char *command; + char *response; + + // Start by getting the file size so we know in advance how much data to expect + int fileSize = 0; + err = getFileSize(filename, &fileSize); + if (err != UBX_CELL_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: getFileSize returned err ")); + _debugPort->println(err); + } + return err; + } + + command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); + + response = ubx_cell_calloc_char(fileSize + minimumResponseAllocation); + if (response == nullptr) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: response alloc failed: ")); + _debugPort->println(fileSize + minimumResponseAllocation); + } + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + // A large file will completely fill the backlog buffer - but it will be pruned afterwards + // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... + // To try and avoid this, look for \"\r\nOK\r\n + const char fileReadTerm[] = "\"\r\nOK\r\n"; + err = sendCommandWithResponse(command, fileReadTerm, response, (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), + (fileSize + minimumResponseAllocation)); + + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: sendCommandWithResponse returned err ")); + _debugPort->println(err); + } + free(command); + free(response); + return err; + } + + // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n + int scanned = 0; + int readFileSize = 0; + char *searchPtr = strstr(response, "+URDFILE:"); + if (searchPtr != nullptr) + { + searchPtr = strchr(searchPtr, '\"'); // Find the first quote + searchPtr = strchr(++searchPtr, '\"'); // Find the second quote + + scanned = sscanf(searchPtr, "\",%d,", &readFileSize); // Get the file size (again) + if (scanned == 1) + { + searchPtr = strchr(++searchPtr, '\"'); // Find the third quote + + if (searchPtr == nullptr) + { + if (_printDebug == true) + { + _debugPort->println(F("getFileContents: third quote not found!")); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + int bytesRead = 0; + + while (bytesRead < readFileSize) + { + searchPtr++; // Increment searchPtr then copy file char into contents + contents[bytesRead] = *searchPtr; // Append file char to contents + bytesRead++; + } + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: total bytes read: ")); + _debugPort->println(bytesRead); + } + err = UBX_CELL_ERROR_SUCCESS; + } + else + { + if (_printDebug == true) + { + _debugPort->print(F("getFileContents: sscanf failed! scanned is ")); + _debugPort->println(scanned); + } + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + } + else + { + if (_printDebug == true) + _debugPort->println(F("getFileContents: strstr failed!")); + err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + free(command); + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::getFileBlock(const String &filename, char *buffer, size_t offset, size_t requested_length, + size_t &bytes_read) +{ + bytes_read = 0; + if (filename.length() < 1 || buffer == nullptr || requested_length < 1) + { + return UBX_CELL_ERROR_UNEXPECTED_PARAM; + } + + // trying to get a byte at a time does not seem to be reliable so this method must use + // a real UART. + if (_hardSerial == nullptr) + { + if (_printDebug == true) + { + _debugPort->println(F("getFileBlock: only works with a hardware UART")); + } + return UBX_CELL_ERROR_INVALID; + } + + size_t cmd_len = filename.length() + 32; + char *cmd = ubx_cell_calloc_char(cmd_len); + sprintf(cmd, "at+urdblock=\"%s\",%zu,%zu\r\n", filename.c_str(), offset, requested_length); + sendCommand(cmd, false); + + int ich; + char ch; + int quote_count = 0; + size_t comma_idx = 0; + + while (quote_count < 3) + { + ich = _hardSerial->read(); + if (ich < 0) + { + continue; + } + ch = (char)(ich & 0xFF); + cmd[bytes_read++] = ch; + if (ch == '"') + { + quote_count++; + } + else if (ch == ',' && comma_idx == 0) + { + comma_idx = bytes_read; + } + } + + cmd[bytes_read] = 0; + cmd[bytes_read - 2] = 0; + + // Example response: + // +URDBLOCK: "wombat.bin",64000,"... " + size_t data_length = strtoul(&cmd[comma_idx], nullptr, 10); + free(cmd); + + bytes_read = 0; + size_t bytes_remaining = data_length; + while (bytes_read < data_length) + { + // This method seems more reliable than reading a byte at a time. + size_t rc = _hardSerial->readBytes(&buffer[bytes_read], bytes_remaining); + bytes_read += rc; + bytes_remaining -= rc; + } + + return UBX_CELL_ERROR_SUCCESS; +} + +UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) +{ + UBX_CELL_error_t err; + char *command; + char *response; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_LIST_FILES) + filename.length() + 8); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=2,\"%s\"", UBX_CELL_FILE_SYSTEM_LIST_FILES, filename.c_str()); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileSize: Fail: Error: ")); + _debugPort->print(err); + _debugPort->print(F(" Response: {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } + free(command); + free(response); + return err; + } + + char *responseStart = strstr(response, "+ULSTFILE:"); + if (responseStart == nullptr) + { + if (_printDebug == true) + { + _debugPort->print(F("getFileSize: Failure: {")); + _debugPort->print(response); + _debugPort->println(F("}")); + } + free(command); + free(response); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } + + int fileSize; + responseStart += strlen("+ULSTFILE:"); // Move searchPtr to first char + while (*responseStart == ' ') + responseStart++; // skip spaces + sscanf(responseStart, "%d", &fileSize); + *size = fileSize; + + free(command); + free(response); + return err; +} + +UBX_CELL_error_t UBX_CELL::deleteFile(String filename) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_DELETE_FILE) + filename.length() + 8); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_DELETE_FILE, filename.c_str()); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("deleteFile: Fail: Error: ")); + _debugPort->println(err); + } + } + + free(command); + return err; +} + +UBX_CELL_error_t UBX_CELL::modulePowerOff(void) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_POWER_OFF) + 6); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s", UBX_CELL_COMMAND_POWER_OFF); + sprintf(command, "%s", UBX_CELL_COMMAND_POWER_OFF); - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, - UBX_CELL_POWER_OFF_TIMEOUT); + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_POWER_OFF_TIMEOUT); - free(command); - return err; + free(command); + return err; } void UBX_CELL::modulePowerOn(void) { - if (_powerPin >= 0) - { - powerOn(); - } - else - { - if (_printDebug == true) - _debugPort->println(F("modulePowerOn: not supported. _powerPin not defined.")); - } + if (_powerPin >= 0) + { + powerOn(); + } + else + { + if (_printDebug == true) + _debugPort->println(F("modulePowerOn: not supported. _powerPin not defined.")); + } } ///////////// // Private // ///////////// -UBX_CELL_error_t UBX_CELL::init(unsigned long baud, - UBX_CELL::UBX_CELL_init_type_t initType) +UBX_CELL_error_t UBX_CELL::init(unsigned long baud, UBX_CELL::UBX_CELL_init_type_t initType) { - int retries = _maxInitTries; - UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; - - beginSerial(baud); + int retries = _maxInitTries; + UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; - do - { - if (_printDebug == true) - _debugPort->println(F("init: Begin module init.")); + beginSerial(baud); - if (initType == UBX_CELL_INIT_AUTOBAUD) + do { - if (_printDebug == true) - _debugPort->println(F("init: Attempting autobaud connection to module.")); + if (_printDebug == true) + _debugPort->println(F("init: Begin module init.")); + + if (initType == UBX_CELL_INIT_AUTOBAUD) + { + if (_printDebug == true) + _debugPort->println(F("init: Attempting autobaud connection to module.")); - err = autobaud(baud); + err = autobaud(baud); - if (err != UBX_CELL_ERROR_SUCCESS) { - initType = UBX_CELL_INIT_RESET; - } - } - else if (initType == UBX_CELL_INIT_RESET) - { - if (_printDebug == true) - _debugPort->println(F("init: Power cycling module.")); + if (err != UBX_CELL_ERROR_SUCCESS) + { + initType = UBX_CELL_INIT_RESET; + } + } + else if (initType == UBX_CELL_INIT_RESET) + { + if (_printDebug == true) + _debugPort->println(F("init: Power cycling module.")); - powerOff(); - delay(UBX_CELL_POWER_OFF_PULSE_PERIOD); - powerOn(); - beginSerial(baud); - delay(2000); + powerOff(); + delay(UBX_CELL_POWER_OFF_PULSE_PERIOD); + powerOn(); + beginSerial(baud); + delay(2000); - err = at(); - if (err != UBX_CELL_ERROR_SUCCESS) - { - initType = UBX_CELL_INIT_AUTOBAUD; - } - } - if (err == UBX_CELL_ERROR_SUCCESS) + err = at(); + if (err != UBX_CELL_ERROR_SUCCESS) + { + initType = UBX_CELL_INIT_AUTOBAUD; + } + } + if (err == UBX_CELL_ERROR_SUCCESS) + { + err = enableEcho(false); // = disableEcho + if (err != UBX_CELL_ERROR_SUCCESS) + { + if (_printDebug == true) + _debugPort->println(F("init: Module failed echo test.")); + initType = UBX_CELL_INIT_AUTOBAUD; + } + } + } while ((retries--) && (err != UBX_CELL_ERROR_SUCCESS)); + + // we tried but seems failed + if (err != UBX_CELL_ERROR_SUCCESS) { - err = enableEcho(false); // = disableEcho - if (err != UBX_CELL_ERROR_SUCCESS) - { if (_printDebug == true) - _debugPort->println(F("init: Module failed echo test.")); - initType = UBX_CELL_INIT_AUTOBAUD; - } + _debugPort->println(F("init: Module failed to init. Exiting.")); + return (UBX_CELL_ERROR_NO_RESPONSE); } - } - while ((retries --) && (err != UBX_CELL_ERROR_SUCCESS)); - // we tried but seems failed - if (err != UBX_CELL_ERROR_SUCCESS) { if (_printDebug == true) - _debugPort->println(F("init: Module failed to init. Exiting.")); - return (UBX_CELL_ERROR_NO_RESPONSE); - } + _debugPort->println(F("init: Module responded successfully.")); - if (_printDebug == true) - _debugPort->println(F("init: Module responded successfully.")); - - _baud = baud; - setGpioMode(GPIO1, NETWORK_STATUS); - //setGpioMode(GPIO2, GNSS_SUPPLY_ENABLE); - setGpioMode(GPIO6, TIME_PULSE_OUTPUT); - setSMSMessageFormat(UBX_CELL_MESSAGE_FORMAT_TEXT); - autoTimeZone(_autoTimeZoneForBegin); - for (int i = 0; i < UBX_CELL_NUM_SOCKETS; i++) - { - socketClose(i, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - } + _baud = baud; + setGpioMode(GPIO1, NETWORK_STATUS); + // setGpioMode(GPIO2, GNSS_SUPPLY_ENABLE); + setGpioMode(GPIO6, TIME_PULSE_OUTPUT); + setSMSMessageFormat(UBX_CELL_MESSAGE_FORMAT_TEXT); + autoTimeZone(_autoTimeZoneForBegin); + for (int i = 0; i < UBX_CELL_NUM_SOCKETS; i++) + { + socketClose(i, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + } - return UBX_CELL_ERROR_SUCCESS; + return UBX_CELL_ERROR_SUCCESS; } void UBX_CELL::invertPowerPin(bool invert) { - _invertPowerPin = invert; + _invertPowerPin = invert; } // Do a graceful power off. Hold the PWR_ON pin low for UBX_CELL_POWER_OFF_PULSE_PERIOD // Note: +CPWROFF () is preferred to this. void UBX_CELL::powerOff(void) { - if (_powerPin >= 0) - { - if (_invertPowerPin) // Set the pin state before making it an output - digitalWrite(_powerPin, HIGH); - else - digitalWrite(_powerPin, LOW); - pinMode(_powerPin, OUTPUT); - if (_invertPowerPin) // Set the pin state - digitalWrite(_powerPin, HIGH); - else - digitalWrite(_powerPin, LOW); - delay(UBX_CELL_POWER_OFF_PULSE_PERIOD); - pinMode(_powerPin, INPUT); // Return to high-impedance, rely on (e.g.) SARA module internal pull-up - if (_printDebug == true) - _debugPort->println(F("powerOff: complete")); - } + if (_powerPin >= 0) + { + if (_invertPowerPin) // Set the pin state before making it an output + digitalWrite(_powerPin, HIGH); + else + digitalWrite(_powerPin, LOW); + pinMode(_powerPin, OUTPUT); + if (_invertPowerPin) // Set the pin state + digitalWrite(_powerPin, HIGH); + else + digitalWrite(_powerPin, LOW); + delay(UBX_CELL_POWER_OFF_PULSE_PERIOD); + pinMode(_powerPin, INPUT); // Return to high-impedance, rely on (e.g.) SARA module internal pull-up + if (_printDebug == true) + _debugPort->println(F("powerOff: complete")); + } } void UBX_CELL::powerOn(void) { - if (_powerPin >= 0) - { - if (_invertPowerPin) // Set the pin state before making it an output - digitalWrite(_powerPin, HIGH); + if (_powerPin >= 0) + { + if (_invertPowerPin) // Set the pin state before making it an output + digitalWrite(_powerPin, HIGH); + else + digitalWrite(_powerPin, LOW); + pinMode(_powerPin, OUTPUT); + if (_invertPowerPin) // Set the pin state + digitalWrite(_powerPin, HIGH); + else + digitalWrite(_powerPin, LOW); + delay(UBX_CELL_POWER_ON_PULSE_PERIOD); + pinMode(_powerPin, INPUT); // Return to high-impedance, rely on (e.g.) SARA module internal pull-up + // delay(2000); // Do this in init. Wait before sending AT commands to module. 100 is too short. + if (_printDebug == true) + _debugPort->println(F("powerOn: complete")); + } +} + +// This does an abrupt emergency hardware shutdown of the SARA-R5 series modules. +// It only works if you have access to both the RESET_N and PWR_ON pins. +// You cannot use this function on the SparkFun Asset Tracker and RESET_N is tied to the MicroMod processor !RESET!... +void UBX_CELL::hwReset(void) +{ + if ((_resetPin >= 0) && (_powerPin >= 0)) + { + digitalWrite(_resetPin, HIGH); // Start by making sure the RESET_N pin is high + pinMode(_resetPin, OUTPUT); + digitalWrite(_resetPin, HIGH); + + if (_invertPowerPin) // Now pull PWR_ON low - invert as necessary (on the Asset Tracker) + { + digitalWrite(_powerPin, HIGH); // Inverted - Asset Tracker + pinMode(_powerPin, OUTPUT); + digitalWrite(_powerPin, HIGH); + } + else + { + digitalWrite(_powerPin, LOW); // Not inverted + pinMode(_powerPin, OUTPUT); + digitalWrite(_powerPin, LOW); + } + + delay(UBX_CELL_RESET_PULSE_PERIOD); // Wait 23 seconds... (Yes, really!) + + digitalWrite(_resetPin, LOW); // Now pull RESET_N low + + delay(100); // Wait a little... (The data sheet doesn't say how long for) + + if (_invertPowerPin) // Now pull PWR_ON high - invert as necessary (on the Asset Tracker) + { + digitalWrite(_powerPin, LOW); // Inverted - Asset Tracker + } + else + { + digitalWrite(_powerPin, HIGH); // Not inverted + } + + delay(1500); // Wait 1.5 seconds + + digitalWrite(_resetPin, HIGH); // Now pull RESET_N high again + + pinMode(_resetPin, INPUT); // Return to high-impedance, rely on SARA module internal pull-up + pinMode(_powerPin, INPUT); // Return to high-impedance, rely on SARA module internal pull-up + } +} + +UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_FUNC) + 16); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_COMMAND_FUNC, function); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); + + free(command); + + return err; +} + +UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) +{ + UBX_CELL_error_t err; + char *command; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_MNO) + 9); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + if (mno == MNO_SIM_ICCID) // Only add autoReset and urcNotification if mno is MNO_SIM_ICCID + sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno, (uint8_t)autoReset, + (uint8_t)urcNotification); else - digitalWrite(_powerPin, LOW); - pinMode(_powerPin, OUTPUT); - if (_invertPowerPin) // Set the pin state - digitalWrite(_powerPin, HIGH); + sprintf(command, "%s=%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno); + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + + free(command); + + return err; +} + +UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) +{ + UBX_CELL_error_t err; + char *command; + char *response; + mobile_network_operator_t o; + int d; + int r; + int u; + int oStore; + + command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_MNO) + 2); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", UBX_CELL_COMMAND_MNO); + + response = ubx_cell_calloc_char(minimumResponseAllocation); + if (response == nullptr) + { + free(command); + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(command); + free(response); + return err; + } + + int scanned = 0; + char *searchPtr = strstr(response, "+UMNOPROF:"); + if (searchPtr != nullptr) + { + searchPtr += strlen("+UMNOPROF:"); // Move searchPtr to first char + while (*searchPtr == ' ') + searchPtr++; // skip spaces + scanned = sscanf(searchPtr, "%d,%d,%d,%d", &oStore, &d, &r, &u); + } + o = (mobile_network_operator_t)oStore; + + if (scanned >= 1) + { + if (_printDebug == true) + { + _debugPort->print(F("getMNOprofile: MNO is: ")); + _debugPort->println(o); + } + *mno = o; + } else - digitalWrite(_powerPin, LOW); - delay(UBX_CELL_POWER_ON_PULSE_PERIOD); - pinMode(_powerPin, INPUT); // Return to high-impedance, rely on (e.g.) SARA module internal pull-up - //delay(2000); // Do this in init. Wait before sending AT commands to module. 100 is too short. - if (_printDebug == true) - _debugPort->println(F("powerOn: complete")); - } + { + err = UBX_CELL_ERROR_INVALID; + } + + free(command); + free(response); + + return err; } -//This does an abrupt emergency hardware shutdown of the SARA-R5 series modules. -//It only works if you have access to both the RESET_N and PWR_ON pins. -//You cannot use this function on the SparkFun Asset Tracker and RESET_N is tied to the MicroMod processor !RESET!... -void UBX_CELL::hwReset(void) +UBX_CELL_error_t UBX_CELL::waitForResponse(const char *expectedResponse, const char *expectedError, uint16_t timeout) +{ + unsigned long timeIn; + bool found = false; + bool error = false; + int responseIndex = 0, errorIndex = 0; + // bool printedSomething = false; + + timeIn = millis(); + + int responseLen = (int)strlen(expectedResponse); + int errorLen = (int)strlen(expectedError); + + while ((!found) && ((timeIn + timeout) > millis())) + { + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is nullptr + { + char c = readChar(); + // if (_printDebug == true) + // { + // if (printedSomething == false) + // _debugPort->print(F("waitForResponse: ")); + // _debugPort->write(c); + // printedSomething = true; + // } + if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) + { + if (++responseIndex == responseLen) + { + found = true; + } + } + else + { + responseIndex = ((responseIndex < responseLen) && (c == expectedResponse[0])) ? 1 : 0; + } + if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) + { + if (++errorIndex == errorLen) + { + error = true; + found = true; + } + } + else + { + errorIndex = ((errorIndex < errorLen) && (c == expectedError[0])) ? 1 : 0; + } + //_saraResponseBacklog is a global array that holds the backlog of any events + // that came in while waiting for response. To be processed later within bufferedPoll(). + // Note: the expectedResponse or expectedError will also be added to the backlog. + // The backlog is only used by bufferedPoll to process the URCs - which are all readable. + // bufferedPoll uses strtok - which does not like nullptr characters. + // So let's make sure no NULLs end up in the backlog! + if (_saraResponseBacklogLength < _RXBuffSize) // Don't overflow the buffer + { + if (c == '\0') + _saraResponseBacklog[_saraResponseBacklogLength++] = '0'; // Change NULLs to ASCII Zeros + else + _saraResponseBacklog[_saraResponseBacklogLength++] = c; + } + } + else + { + yield(); + } + } + + // if (_printDebug == true) + // if (printedSomething) + // _debugPort->println(); + + pruneBacklog(); // Prune any incoming non-actionable URC's and responses/errors from the backlog + + if (found == true) + { + if (true == _printAtDebug) + { + _debugAtPort->print((error == true) ? expectedError : expectedResponse); + } + + return (error == true) ? UBX_CELL_ERROR_ERROR : UBX_CELL_ERROR_SUCCESS; + } + + return UBX_CELL_ERROR_NO_RESPONSE; +} + +UBX_CELL_error_t UBX_CELL::sendCommandWithResponse(const char *command, const char *expectedResponse, + char *responseDest, unsigned long commandTimeout, int destSize, + bool at) { - if ((_resetPin >= 0) && (_powerPin >= 0)) - { - digitalWrite(_resetPin, HIGH); // Start by making sure the RESET_N pin is high - pinMode(_resetPin, OUTPUT); - digitalWrite(_resetPin, HIGH); + bool found = false; + bool error = false; + int responseIndex = 0; + int errorIndex = 0; + int destIndex = 0; + unsigned int charsRead = 0; + int responseLen = 0; + int errorLen = 0; + const char *expectedError = nullptr; + bool printResponse = false; // Change to true to print the full response + bool printedSomething = false; + + if (_printDebug == true) + { + _debugPort->print(F("sendCommandWithResponse: Command: ")); + _debugPort->println(String(command)); + } - if (_invertPowerPin) // Now pull PWR_ON low - invert as necessary (on the Asset Tracker) + sendCommand(command, at); // Sending command needs to dump data to backlog buffer as well. + unsigned long timeIn = millis(); + if (UBX_CELL_RESPONSE_OK_OR_ERROR == expectedResponse) { - digitalWrite(_powerPin, HIGH); // Inverted - Asset Tracker - pinMode(_powerPin, OUTPUT); - digitalWrite(_powerPin, HIGH); + expectedResponse = UBX_CELL_RESPONSE_OK; + expectedError = UBX_CELL_RESPONSE_ERROR; + responseLen = sizeof(UBX_CELL_RESPONSE_OK) - 1; + errorLen = sizeof(UBX_CELL_RESPONSE_ERROR) - 1; } else { - digitalWrite(_powerPin, LOW); // Not inverted - pinMode(_powerPin, OUTPUT); - digitalWrite(_powerPin, LOW); + responseLen = (int)strlen(expectedResponse); } - delay(UBX_CELL_RESET_PULSE_PERIOD); // Wait 23 seconds... (Yes, really!) + while ((!found) && ((timeIn + commandTimeout) > millis())) + { + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is nullptr + { + char c = readChar(); + if ((printResponse = true) && (_printDebug == true)) + { + if (printedSomething == false) + { + _debugPort->print(F("sendCommandWithResponse: Response: ")); + printedSomething = true; + } + _debugPort->write(c); + } + if (responseDest != nullptr) + { + if (destIndex < destSize) // Only add this char to response if there is room for it + responseDest[destIndex] = c; + destIndex++; + if (destIndex == destSize) + { + if (_printDebug == true) + { + if ((printResponse = true) && (printedSomething)) + _debugPort->println(); + _debugPort->print(F("sendCommandWithResponse: Panic! responseDest is full!")); + if ((printResponse = true) && (printedSomething)) + _debugPort->print(F("sendCommandWithResponse: Ignored response: ")); + } + } + } + charsRead++; + if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) + { + if (++errorIndex == errorLen) + { + error = true; + found = true; + } + } + else + { + errorIndex = ((errorIndex < errorLen) && (c == expectedError[0])) ? 1 : 0; + } + if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) + { + if (++responseIndex == responseLen) + { + found = true; + } + } + else + { + responseIndex = ((responseIndex < responseLen) && (c == expectedResponse[0])) ? 1 : 0; + } + //_saraResponseBacklog is a global array that holds the backlog of any events + // that came in while waiting for response. To be processed later within bufferedPoll(). + // Note: the expectedResponse or expectedError will also be added to the backlog + // The backlog is only used by bufferedPoll to process the URCs - which are all readable. + // bufferedPoll uses strtok - which does not like NULL characters. + // So let's make sure no NULLs end up in the backlog! + if (_saraResponseBacklogLength < _RXBuffSize) // Don't overflow the buffer + { + if (c == '\0') + _saraResponseBacklog[_saraResponseBacklogLength++] = '0'; // Change NULLs to ASCII Zeros + else + _saraResponseBacklog[_saraResponseBacklogLength++] = c; + } + } + else + { + yield(); + } + } - digitalWrite(_resetPin, LOW); // Now pull RESET_N low + if (_printDebug == true) + if ((printResponse = true) && (printedSomething)) + _debugPort->println(); - delay(100); // Wait a little... (The data sheet doesn't say how long for) + pruneBacklog(); // Prune any incoming non-actionable URC's and responses/errors from the backlog - if (_invertPowerPin) // Now pull PWR_ON high - invert as necessary (on the Asset Tracker) + if (found) + { + if ((true == _printAtDebug) && ((nullptr != responseDest) || (nullptr != expectedResponse))) + { + _debugAtPort->print((nullptr != responseDest) ? responseDest : expectedResponse); + } + return error ? UBX_CELL_ERROR_ERROR : UBX_CELL_ERROR_SUCCESS; + } + else if (charsRead == 0) { - digitalWrite(_powerPin, LOW); // Inverted - Asset Tracker + return UBX_CELL_ERROR_NO_RESPONSE; } else { - digitalWrite(_powerPin, HIGH); // Not inverted + if ((true == _printAtDebug) && (nullptr != responseDest)) + { + _debugAtPort->print(responseDest); + } + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - - delay(1500); // Wait 1.5 seconds - - digitalWrite(_resetPin, HIGH); // Now pull RESET_N high again - - pinMode(_resetPin, INPUT); // Return to high-impedance, rely on SARA module internal pull-up - pinMode(_powerPin, INPUT); // Return to high-impedance, rely on SARA module internal pull-up - } } -UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) +// Send a custom command with an expected (potentially partial) response, store entire response +UBX_CELL_error_t UBX_CELL::sendCustomCommandWithResponse(const char *command, const char *expectedResponse, + char *responseDest, unsigned long commandTimeout, bool at) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_FUNC) + 16); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_COMMAND_FUNC, function); - - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_3_MIN_TIMEOUT); - - free(command); - - return err; + // Assume the user has allocated enough storage for any response. Set destSize to 32766. + return sendCommandWithResponse(command, expectedResponse, responseDest, commandTimeout, 32766, at); } -UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) +void UBX_CELL::sendCommand(const char *command, bool at) { - UBX_CELL_error_t err; - char *command; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_MNO) + 9); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - if (mno == MNO_SIM_ICCID) // Only add autoReset and urcNotification if mno is MNO_SIM_ICCID - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno, (uint8_t)autoReset, (uint8_t)urcNotification); - else - sprintf(command, "%s=%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno); + // Check for incoming serial data. Copy it into the backlog - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + // Important note: + // On ESP32, Serial.available only provides an update every ~120 bytes during the reception of long messages: + // https://gitter.im/espressif/arduino-esp32?at=5e25d6370a1cf54144909c85 + // Be aware that if a long message is being received, the code below will timeout after _rxWindowMillis = 2 millis. + // At 115200 baud, hwAvailable takes ~120 * 10 / 115200 = 10.4 millis before it indicates that data is being + // received. - free(command); + unsigned long timeIn = millis(); + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is NULL + { + while (((millis() - timeIn) < _rxWindowMillis) && + (_saraResponseBacklogLength < _RXBuffSize)) // May need to escape on newline? + { + if (hwAvailable() > 0) // hwAvailable can return -1 if the serial port is NULL + { + //_saraResponseBacklog is a global array that holds the backlog of any events + // that came in while waiting for response. To be processed later within bufferedPoll(). + // Note: the expectedResponse or expectedError will also be added to the backlog + // The backlog is only used by bufferedPoll to process the URCs - which are all readable. + // bufferedPoll uses strtok - which does not like NULL characters. + // So let's make sure no NULLs end up in the backlog! + char c = readChar(); + if (c == '\0') // Make sure no NULL characters end up in the backlog! Change them to ASCII Zeros + c = '0'; + _saraResponseBacklog[_saraResponseBacklogLength++] = c; + timeIn = millis(); + } + else + { + yield(); + } + } + } - return err; + // Now send the command + if (at) + { + hwPrint(UBX_CELL_COMMAND_AT); + hwPrint(command); + hwPrint("\r\n"); + } + else + { + hwPrint(command); + } } -UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) +UBX_CELL_error_t UBX_CELL::parseSocketReadIndication(int socket, int length) { - UBX_CELL_error_t err; - char *command; - char *response; - mobile_network_operator_t o; - int d; - int r; - int u; - int oStore; - - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_MNO) + 2); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_COMMAND_MNO); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + UBX_CELL_error_t err; + char *readDest; - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(command); - free(response); - return err; - } - - int scanned = 0; - char *searchPtr = strstr(response, "+UMNOPROF:"); - if (searchPtr != nullptr) - { - searchPtr += strlen("+UMNOPROF:"); // Move searchPtr to first char - while (*searchPtr == ' ') searchPtr++; // skip spaces - scanned = sscanf(searchPtr, "%d,%d,%d,%d", &oStore, &d, &r, &u); - } - o = (mobile_network_operator_t)oStore; - - if (scanned >= 1) - { - if (_printDebug == true) + if ((socket < 0) || (length < 0)) { - _debugPort->print(F("getMNOprofile: MNO is: ")); - _debugPort->println(o); + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - *mno = o; - } - else - { - err = UBX_CELL_ERROR_INVALID; - } - free(command); - free(response); + // Return now if both callbacks pointers are nullptr - otherwise the data will be read and lost! + if ((_socketReadCallback == nullptr) && (_socketReadCallbackPlus == nullptr)) + return UBX_CELL_ERROR_INVALID; - return err; -} + readDest = ubx_cell_calloc_char(length + 1); + if (readDest == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; -UBX_CELL_error_t UBX_CELL::waitForResponse(const char *expectedResponse, const char *expectedError, uint16_t timeout) -{ - unsigned long timeIn; - bool found = false; - bool error = false; - int responseIndex = 0, errorIndex = 0; - // bool printedSomething = false; - - timeIn = millis(); - - int responseLen = (int)strlen(expectedResponse); - int errorLen = (int)strlen(expectedError); - - while ((!found) && ((timeIn + timeout) > millis())) - { - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is nullptr - { - char c = readChar(); - // if (_printDebug == true) - // { - // if (printedSomething == false) - // _debugPort->print(F("waitForResponse: ")); - // _debugPort->write(c); - // printedSomething = true; - // } - if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) - { - if (++responseIndex == responseLen) - { - found = true; - } - } - else - { - responseIndex = ((responseIndex < responseLen) && (c == expectedResponse[0])) ? 1 : 0; - } - if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) - { - if (++errorIndex == errorLen) - { - error = true; - found = true; - } - } - else - { - errorIndex = ((errorIndex < errorLen) && (c == expectedError[0])) ? 1 : 0; - } - //_saraResponseBacklog is a global array that holds the backlog of any events - //that came in while waiting for response. To be processed later within bufferedPoll(). - //Note: the expectedResponse or expectedError will also be added to the backlog. - //The backlog is only used by bufferedPoll to process the URCs - which are all readable. - //bufferedPoll uses strtok - which does not like nullptr characters. - //So let's make sure no NULLs end up in the backlog! - if (_saraResponseBacklogLength < _RXBuffSize) // Don't overflow the buffer - { - if (c == '\0') - _saraResponseBacklog[_saraResponseBacklogLength++] = '0'; // Change NULLs to ASCII Zeros - else - _saraResponseBacklog[_saraResponseBacklogLength++] = c; - } - } else { - yield(); - } - } - - // if (_printDebug == true) - // if (printedSomething) - // _debugPort->println(); - - pruneBacklog(); // Prune any incoming non-actionable URC's and responses/errors from the backlog - - if (found == true) - { - if (true == _printAtDebug) { - _debugAtPort->print((error == true) ? expectedError : expectedResponse); - } - - return (error == true) ? UBX_CELL_ERROR_ERROR : UBX_CELL_ERROR_SUCCESS; - } - - return UBX_CELL_ERROR_NO_RESPONSE; -} - -UBX_CELL_error_t UBX_CELL::sendCommandWithResponse( - const char *command, const char *expectedResponse, char *responseDest, - unsigned long commandTimeout, int destSize, bool at) -{ - bool found = false; - bool error = false; - int responseIndex = 0; - int errorIndex = 0; - int destIndex = 0; - unsigned int charsRead = 0; - int responseLen = 0; - int errorLen = 0; - const char* expectedError= nullptr; - bool printResponse = false; // Change to true to print the full response - bool printedSomething = false; - - if (_printDebug == true) - { - _debugPort->print(F("sendCommandWithResponse: Command: ")); - _debugPort->println(String(command)); - } - - sendCommand(command, at); //Sending command needs to dump data to backlog buffer as well. - unsigned long timeIn = millis(); - if (UBX_CELL_RESPONSE_OK_OR_ERROR == expectedResponse) { - expectedResponse = UBX_CELL_RESPONSE_OK; - expectedError = UBX_CELL_RESPONSE_ERROR; - responseLen = sizeof(UBX_CELL_RESPONSE_OK)-1; - errorLen = sizeof(UBX_CELL_RESPONSE_ERROR)-1; - } else { - responseLen = (int)strlen(expectedResponse); - } - - while ((!found) && ((timeIn + commandTimeout) > millis())) - { - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is nullptr - { - char c = readChar(); - if ((printResponse = true) && (_printDebug == true)) - { - if (printedSomething == false) - { - _debugPort->print(F("sendCommandWithResponse: Response: ")); - printedSomething = true; - } - _debugPort->write(c); - } - if (responseDest != nullptr) - { - if (destIndex < destSize) // Only add this char to response if there is room for it - responseDest[destIndex] = c; - destIndex++; - if (destIndex == destSize) - { - if (_printDebug == true) - { - if ((printResponse = true) && (printedSomething)) - _debugPort->println(); - _debugPort->print(F("sendCommandWithResponse: Panic! responseDest is full!")); - if ((printResponse = true) && (printedSomething)) - _debugPort->print(F("sendCommandWithResponse: Ignored response: ")); - } - } - } - charsRead++; - if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) - { - if (++errorIndex == errorLen) - { - error = true; - found = true; - } - } - else - { - errorIndex = ((errorIndex < errorLen) && (c == expectedError[0])) ? 1 : 0; - } - if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) - { - if (++responseIndex == responseLen) - { - found = true; - } - } - else - { - responseIndex = ((responseIndex < responseLen) && (c == expectedResponse[0])) ? 1 : 0; - } - //_saraResponseBacklog is a global array that holds the backlog of any events - //that came in while waiting for response. To be processed later within bufferedPoll(). - //Note: the expectedResponse or expectedError will also be added to the backlog - //The backlog is only used by bufferedPoll to process the URCs - which are all readable. - //bufferedPoll uses strtok - which does not like NULL characters. - //So let's make sure no NULLs end up in the backlog! - if (_saraResponseBacklogLength < _RXBuffSize) // Don't overflow the buffer - { - if (c == '\0') - _saraResponseBacklog[_saraResponseBacklogLength++] = '0'; // Change NULLs to ASCII Zeros - else - _saraResponseBacklog[_saraResponseBacklogLength++] = c; - } - } else { - yield(); + int bytesRead; + err = socketRead(socket, length, readDest, &bytesRead); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(readDest); + return err; } - } - if (_printDebug == true) - if ((printResponse = true) && (printedSomething)) - _debugPort->println(); - - pruneBacklog(); // Prune any incoming non-actionable URC's and responses/errors from the backlog - - if (found) - { - if ((true == _printAtDebug) && ((nullptr != responseDest) || (nullptr != expectedResponse))) { - _debugAtPort->print((nullptr != responseDest) ? responseDest : expectedResponse); - } - return error ? UBX_CELL_ERROR_ERROR : UBX_CELL_ERROR_SUCCESS; - } - else if (charsRead == 0) - { - return UBX_CELL_ERROR_NO_RESPONSE; - } - else - { - if ((true == _printAtDebug) && (nullptr != responseDest)) { - _debugAtPort->print(responseDest); + if (_socketReadCallback != nullptr) + { + String dataAsString = ""; // Create an empty string + // Copy the data from readDest into the String in a binary-compatible way + // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible. + // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's. + // The only true binary-compatible solution is to use socketReadCallbackPlus... + for (int i = 0; i < bytesRead; i++) + dataAsString.concat(readDest[i]); + _socketReadCallback(socket, dataAsString); } - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } -} -// Send a custom command with an expected (potentially partial) response, store entire response -UBX_CELL_error_t UBX_CELL::sendCustomCommandWithResponse(const char *command, const char *expectedResponse, - char *responseDest, unsigned long commandTimeout, bool at) -{ - // Assume the user has allocated enough storage for any response. Set destSize to 32766. - return sendCommandWithResponse(command, expectedResponse, responseDest, commandTimeout, 32766, at); -} + if (_socketReadCallbackPlus != nullptr) + { + IPAddress dummyAddress = {0, 0, 0, 0}; + int dummyPort = 0; + _socketReadCallbackPlus(socket, (const char *)readDest, bytesRead, dummyAddress, dummyPort); + } -void UBX_CELL::sendCommand(const char *command, bool at) -{ - //Check for incoming serial data. Copy it into the backlog - - // Important note: - // On ESP32, Serial.available only provides an update every ~120 bytes during the reception of long messages: - // https://gitter.im/espressif/arduino-esp32?at=5e25d6370a1cf54144909c85 - // Be aware that if a long message is being received, the code below will timeout after _rxWindowMillis = 2 millis. - // At 115200 baud, hwAvailable takes ~120 * 10 / 115200 = 10.4 millis before it indicates that data is being received. - - unsigned long timeIn = millis(); - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is NULL - { - while (((millis() - timeIn) < _rxWindowMillis) && (_saraResponseBacklogLength < _RXBuffSize)) //May need to escape on newline? - { - if (hwAvailable() > 0) //hwAvailable can return -1 if the serial port is NULL - { - //_saraResponseBacklog is a global array that holds the backlog of any events - //that came in while waiting for response. To be processed later within bufferedPoll(). - //Note: the expectedResponse or expectedError will also be added to the backlog - //The backlog is only used by bufferedPoll to process the URCs - which are all readable. - //bufferedPoll uses strtok - which does not like NULL characters. - //So let's make sure no NULLs end up in the backlog! - char c = readChar(); - if (c == '\0') // Make sure no NULL characters end up in the backlog! Change them to ASCII Zeros - c = '0'; - _saraResponseBacklog[_saraResponseBacklogLength++] = c; - timeIn = millis(); - } else { - yield(); - } - } - } - - //Now send the command - if (at) - { - hwPrint(UBX_CELL_COMMAND_AT); - hwPrint(command); - hwPrint("\r\n"); - } - else - { - hwPrint(command); - } + free(readDest); + return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::parseSocketReadIndication(int socket, int length) +UBX_CELL_error_t UBX_CELL::parseSocketReadIndicationUDP(int socket, int length) { - UBX_CELL_error_t err; - char *readDest; - - if ((socket < 0) || (length < 0)) - { - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } + UBX_CELL_error_t err; + char *readDest; + IPAddress remoteAddress = {0, 0, 0, 0}; + int remotePort = 0; - // Return now if both callbacks pointers are nullptr - otherwise the data will be read and lost! - if ((_socketReadCallback == nullptr) && (_socketReadCallbackPlus == nullptr)) - return UBX_CELL_ERROR_INVALID; + if ((socket < 0) || (length < 0)) + { + return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; + } - readDest = ubx_cell_calloc_char(length + 1); - if (readDest == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + // Return now if both callbacks pointers are nullptr - otherwise the data will be read and lost! + if ((_socketReadCallback == nullptr) && (_socketReadCallbackPlus == nullptr)) + return UBX_CELL_ERROR_INVALID; - int bytesRead; - err = socketRead(socket, length, readDest, &bytesRead); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(readDest); - return err; - } - - if (_socketReadCallback != nullptr) - { - String dataAsString = ""; // Create an empty string - // Copy the data from readDest into the String in a binary-compatible way - // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible. - // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's. - // The only true binary-compatible solution is to use socketReadCallbackPlus... - for (int i = 0; i < bytesRead; i++) - dataAsString.concat(readDest[i]); - _socketReadCallback(socket, dataAsString); - } - - if (_socketReadCallbackPlus != nullptr) - { - IPAddress dummyAddress = { 0, 0, 0, 0 }; - int dummyPort = 0; - _socketReadCallbackPlus(socket, (const char *)readDest, bytesRead, dummyAddress, dummyPort); - } - - free(readDest); - return UBX_CELL_ERROR_SUCCESS; -} + readDest = ubx_cell_calloc_char(length + 1); + if (readDest == nullptr) + { + return UBX_CELL_ERROR_OUT_OF_MEMORY; + } -UBX_CELL_error_t UBX_CELL::parseSocketReadIndicationUDP(int socket, int length) -{ - UBX_CELL_error_t err; - char *readDest; - IPAddress remoteAddress = { 0, 0, 0, 0 }; - int remotePort = 0; - - if ((socket < 0) || (length < 0)) - { - return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; - } - - // Return now if both callbacks pointers are nullptr - otherwise the data will be read and lost! - if ((_socketReadCallback == nullptr) && (_socketReadCallbackPlus == nullptr)) - return UBX_CELL_ERROR_INVALID; - - readDest = ubx_cell_calloc_char(length + 1); - if (readDest == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - int bytesRead; - err = socketReadUDP(socket, length, readDest, &remoteAddress, &remotePort, &bytesRead); - if (err != UBX_CELL_ERROR_SUCCESS) - { - free(readDest); - return err; - } + int bytesRead; + err = socketReadUDP(socket, length, readDest, &remoteAddress, &remotePort, &bytesRead); + if (err != UBX_CELL_ERROR_SUCCESS) + { + free(readDest); + return err; + } - if (_socketReadCallback != nullptr) - { - String dataAsString = ""; // Create an empty string - // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible. - // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's. - // The only true binary-compatible solution is to use socketReadCallbackPlus... - for (int i = 0; i < bytesRead; i++) // Copy the data from readDest into the String in a binary-compatible way - dataAsString.concat(readDest[i]); - _socketReadCallback(socket, dataAsString); - } + if (_socketReadCallback != nullptr) + { + String dataAsString = ""; // Create an empty string + // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible. + // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's. + // The only true binary-compatible solution is to use socketReadCallbackPlus... + for (int i = 0; i < bytesRead; i++) // Copy the data from readDest into the String in a binary-compatible way + dataAsString.concat(readDest[i]); + _socketReadCallback(socket, dataAsString); + } - if (_socketReadCallbackPlus != nullptr) - { - _socketReadCallbackPlus(socket, (const char *)readDest, bytesRead, remoteAddress, remotePort); - } + if (_socketReadCallbackPlus != nullptr) + { + _socketReadCallbackPlus(socket, (const char *)readDest, bytesRead, remoteAddress, remotePort); + } - free(readDest); - return UBX_CELL_ERROR_SUCCESS; + free(readDest); + return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::parseSocketListenIndication(int listeningSocket, IPAddress localIP, unsigned int listeningPort, int socket, IPAddress remoteIP, unsigned int port) +UBX_CELL_error_t UBX_CELL::parseSocketListenIndication(int listeningSocket, IPAddress localIP, + unsigned int listeningPort, int socket, IPAddress remoteIP, + unsigned int port) { - _lastLocalIP = localIP; - _lastRemoteIP = remoteIP; + _lastLocalIP = localIP; + _lastRemoteIP = remoteIP; - if (_socketListenCallback != nullptr) - { - _socketListenCallback(listeningSocket, localIP, listeningPort, socket, remoteIP, port); - } + if (_socketListenCallback != nullptr) + { + _socketListenCallback(listeningSocket, localIP, listeningPort, socket, remoteIP, port); + } - return UBX_CELL_ERROR_SUCCESS; + return UBX_CELL_ERROR_SUCCESS; } UBX_CELL_error_t UBX_CELL::parseSocketCloseIndication(String *closeIndication) { - int search; - int socket; + int search; + int socket; - search = closeIndication->indexOf(UBX_CELL_CLOSE_SOCKET_URC); - search += strlen(UBX_CELL_CLOSE_SOCKET_URC); - while (closeIndication->charAt(search) == ' ') search ++; // skip spaces + search = closeIndication->indexOf(UBX_CELL_CLOSE_SOCKET_URC); + search += strlen(UBX_CELL_CLOSE_SOCKET_URC); + while (closeIndication->charAt(search) == ' ') + search++; // skip spaces - // Socket will be first integer, should be single-digit number between 0-6: - socket = closeIndication->substring(search, search + 1).toInt(); + // Socket will be first integer, should be single-digit number between 0-6: + socket = closeIndication->substring(search, search + 1).toInt(); - if (_socketCloseCallback != nullptr) - { - _socketCloseCallback(socket); - } + if (_socketCloseCallback != nullptr) + { + _socketCloseCallback(socket); + } - return UBX_CELL_ERROR_SUCCESS; + return UBX_CELL_ERROR_SUCCESS; } size_t UBX_CELL::hwPrint(const char *s) { - if ((true == _printAtDebug) && (nullptr != s)) { - _debugAtPort->print(s); - } - if (_hardSerial != nullptr) - { - return _hardSerial->print(s); - } + if ((true == _printAtDebug) && (nullptr != s)) + { + _debugAtPort->print(s); + } + if (_hardSerial != nullptr) + { + return _hardSerial->print(s); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - return _softSerial->print(s); - } + else if (_softSerial != nullptr) + { + return _softSerial->print(s); + } #endif - return (size_t)0; + return (size_t)0; } size_t UBX_CELL::hwWriteData(const char *buff, int len) { - if ((true == _printAtDebug) && (nullptr != buff) && (0 < len) ) { - _debugAtPort->write(buff,len); - } - if (_hardSerial != nullptr) - { - return _hardSerial->write((const uint8_t *)buff, len); - } + if ((true == _printAtDebug) && (nullptr != buff) && (0 < len)) + { + _debugAtPort->write(buff, len); + } + if (_hardSerial != nullptr) + { + return _hardSerial->write((const uint8_t *)buff, len); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - return _softSerial->write((const uint8_t *)buff, len); - } + else if (_softSerial != nullptr) + { + return _softSerial->write((const uint8_t *)buff, len); + } #endif - return (size_t)0; + return (size_t)0; } size_t UBX_CELL::hwWrite(const char c) { - if (true == _printAtDebug) { - _debugAtPort->write(c); - } - if (_hardSerial != nullptr) - { - return _hardSerial->write(c); - } + if (true == _printAtDebug) + { + _debugAtPort->write(c); + } + if (_hardSerial != nullptr) + { + return _hardSerial->write(c); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - return _softSerial->write(c); - } + else if (_softSerial != nullptr) + { + return _softSerial->write(c); + } #endif - return (size_t)0; + return (size_t)0; } int UBX_CELL::readAvailable(char *inString) { - int len = 0; + int len = 0; - if (_hardSerial != nullptr) - { - while (_hardSerial->available()) - { - char c = (char)_hardSerial->read(); - if (inString != nullptr) - { - inString[len++] = c; - } - } - if (inString != nullptr) + if (_hardSerial != nullptr) { - inString[len] = 0; + while (_hardSerial->available()) + { + char c = (char)_hardSerial->read(); + if (inString != nullptr) + { + inString[len++] = c; + } + } + if (inString != nullptr) + { + inString[len] = 0; + } + // if (_printDebug == true) + // _debugPort->println(inString); } - //if (_printDebug == true) - // _debugPort->println(inString); - } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - while (_softSerial->available()) - { - char c = (char)_softSerial->read(); - if (inString != nullptr) - { - inString[len++] = c; - } - } - if (inString != nullptr) + else if (_softSerial != nullptr) { - inString[len] = 0; + while (_softSerial->available()) + { + char c = (char)_softSerial->read(); + if (inString != nullptr) + { + inString[len++] = c; + } + } + if (inString != nullptr) + { + inString[len] = 0; + } } - } #endif - return len; + return len; } char UBX_CELL::readChar(void) { - char ret = 0; + char ret = 0; - if (_hardSerial != nullptr) - { - ret = (char)_hardSerial->read(); - } + if (_hardSerial != nullptr) + { + ret = (char)_hardSerial->read(); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - ret = (char)_softSerial->read(); - } + else if (_softSerial != nullptr) + { + ret = (char)_softSerial->read(); + } #endif - return ret; + return ret; } int UBX_CELL::hwAvailable(void) { - if (_hardSerial != nullptr) - { - return _hardSerial->available(); - } + if (_hardSerial != nullptr) + { + return _hardSerial->available(); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - return _softSerial->available(); - } + else if (_softSerial != nullptr) + { + return _softSerial->available(); + } #endif - return -1; + return -1; } void UBX_CELL::beginSerial(unsigned long baud) { - delay(100); - if (_hardSerial != nullptr) - { - _hardSerial->end(); - _hardSerial->begin(baud); - } + delay(100); + if (_hardSerial != nullptr) + { + _hardSerial->end(); + _hardSerial->begin(baud); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - _softSerial->end(); - _softSerial->begin(baud); - } + else if (_softSerial != nullptr) + { + _softSerial->end(); + _softSerial->begin(baud); + } #endif - delay(100); + delay(100); } void UBX_CELL::setTimeout(unsigned long timeout) { - if (_hardSerial != nullptr) - { - _hardSerial->setTimeout(timeout); - } + if (_hardSerial != nullptr) + { + _hardSerial->setTimeout(timeout); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - _softSerial->setTimeout(timeout); - } + else if (_softSerial != nullptr) + { + _softSerial->setTimeout(timeout); + } #endif } bool UBX_CELL::find(char *target) { - bool found = false; - if (_hardSerial != nullptr) - { - found = _hardSerial->find(target); - } + bool found = false; + if (_hardSerial != nullptr) + { + found = _hardSerial->find(target); + } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != nullptr) - { - found = _softSerial->find(target); - } + else if (_softSerial != nullptr) + { + found = _softSerial->find(target); + } #endif - return found; + return found; } UBX_CELL_error_t UBX_CELL::autobaud(unsigned long desiredBaud) { - UBX_CELL_error_t err = UBX_CELL_ERROR_INVALID; - int b = 0; + UBX_CELL_error_t err = UBX_CELL_ERROR_INVALID; + int b = 0; - while ((err != UBX_CELL_ERROR_SUCCESS) && (b < NUM_SUPPORTED_BAUD)) - { - beginSerial(UBX_CELL_SUPPORTED_BAUD[b++]); - setBaud(desiredBaud); - beginSerial(desiredBaud); - err = at(); - } - if (err == UBX_CELL_ERROR_SUCCESS) - { - beginSerial(desiredBaud); - } - return err; + while ((err != UBX_CELL_ERROR_SUCCESS) && (b < NUM_SUPPORTED_BAUD)) + { + beginSerial(UBX_CELL_SUPPORTED_BAUD[b++]); + setBaud(desiredBaud); + beginSerial(desiredBaud); + err = at(); + } + if (err == UBX_CELL_ERROR_SUCCESS) + { + beginSerial(desiredBaud); + } + return err; } char *UBX_CELL::ubx_cell_calloc_char(size_t num) { - return (char *)calloc(num, sizeof(char)); + return (char *)calloc(num, sizeof(char)); } -//This prunes the backlog of non-actionable events. If new actionable events are added, you must modify the if statement. +// This prunes the backlog of non-actionable events. If new actionable events are added, you must modify the if +// statement. void UBX_CELL::pruneBacklog() { - char *event; - - // if (_printDebug == true) - // { - // if (_saraResponseBacklogLength > 0) //Handy for debugging new parsing. - // { - // _debugPort->println(F("pruneBacklog: before pruning, backlog was:")); - // _debugPort->println(_saraResponseBacklog); - // _debugPort->println(F("pruneBacklog: end of backlog")); - // } - // else - // { - // _debugPort->println(F("pruneBacklog: backlog was empty")); - // } - // } - - memset(_pruneBuffer, 0, _RXBuffSize); // Clear the _pruneBuffer - - _saraResponseBacklogLength = 0; // Zero the backlog length - - char *preservedEvent; - event = strtok_r(_saraResponseBacklog, "\r\n", &preservedEvent); // Look for an 'event' - something ending in \r\n - - while (event != nullptr) //If event is actionable, add it to pruneBuffer. - { - // These are the events we want to keep so they can be processed by poll / bufferedPoll - for(auto urcString : _urcStrings) - { - if(strstr(event, urcString) != nullptr) - { - strcat(_pruneBuffer, event); // The URCs are all readable text so using strcat is OK - strcat(_pruneBuffer, "\r\n"); // strtok blows away delimiter, but we want that for later. - _saraResponseBacklogLength += strlen(event) + 2; // Add the length of this event to _saraResponseBacklogLength - break; // No need to check any other events - } - } - - event = strtok_r(nullptr, "\r\n", &preservedEvent); // Walk though any remaining events - } - - memset(_saraResponseBacklog, 0, _RXBuffSize); //Clear out backlog buffer. - memcpy(_saraResponseBacklog, _pruneBuffer, _saraResponseBacklogLength); //Copy the pruned buffer back into the backlog - - // if (_printDebug == true) - // { - // if (_saraResponseBacklogLength > 0) //Handy for debugging new parsing. - // { - // _debugPort->println(F("pruneBacklog: after pruning, backlog is now:")); - // _debugPort->println(_saraResponseBacklog); - // _debugPort->println(F("pruneBacklog: end of backlog")); - // } - // else - // { - // _debugPort->println(F("pruneBacklog: backlog is now empty")); - // } - // } + char *event; + + // if (_printDebug == true) + // { + // if (_saraResponseBacklogLength > 0) //Handy for debugging new parsing. + // { + // _debugPort->println(F("pruneBacklog: before pruning, backlog was:")); + // _debugPort->println(_saraResponseBacklog); + // _debugPort->println(F("pruneBacklog: end of backlog")); + // } + // else + // { + // _debugPort->println(F("pruneBacklog: backlog was empty")); + // } + // } + + memset(_pruneBuffer, 0, _RXBuffSize); // Clear the _pruneBuffer + + _saraResponseBacklogLength = 0; // Zero the backlog length + + char *preservedEvent; + event = strtok_r(_saraResponseBacklog, "\r\n", &preservedEvent); // Look for an 'event' - something ending in \r\n + + while (event != nullptr) // If event is actionable, add it to pruneBuffer. + { + // These are the events we want to keep so they can be processed by poll / bufferedPoll + for (auto urcString : _urcStrings) + { + if (strstr(event, urcString) != nullptr) + { + strcat(_pruneBuffer, event); // The URCs are all readable text so using strcat is OK + strcat(_pruneBuffer, "\r\n"); // strtok blows away delimiter, but we want that for later. + _saraResponseBacklogLength += + strlen(event) + 2; // Add the length of this event to _saraResponseBacklogLength + break; // No need to check any other events + } + } + + event = strtok_r(nullptr, "\r\n", &preservedEvent); // Walk though any remaining events + } + + memset(_saraResponseBacklog, 0, _RXBuffSize); // Clear out backlog buffer. + memcpy(_saraResponseBacklog, _pruneBuffer, + _saraResponseBacklogLength); // Copy the pruned buffer back into the backlog + + // if (_printDebug == true) + // { + // if (_saraResponseBacklogLength > 0) //Handy for debugging new parsing. + // { + // _debugPort->println(F("pruneBacklog: after pruning, backlog is now:")); + // _debugPort->println(_saraResponseBacklog); + // _debugPort->println(F("pruneBacklog: end of backlog")); + // } + // else + // { + // _debugPort->println(F("pruneBacklog: backlog is now empty")); + // } + // } } // GPS Helper Functions: // Read a source string until a delimiter is hit, store the result in destination -char *UBX_CELL::readDataUntil(char *destination, unsigned int destSize, - char *source, char delimiter) -{ - - char *strEnd; - size_t len; - - strEnd = strchr(source, delimiter); - - if (strEnd != nullptr) - { - len = strEnd - source; - memset(destination, 0, destSize); - memcpy(destination, source, len); - } - - return strEnd; -} - -bool UBX_CELL::parseGPRMCString(char *rmcString, PositionData *pos, - ClockData *clk, SpeedData *spd) -{ - char *ptr, *search; - unsigned long tTemp; - char tempData[TEMP_NMEA_DATA_SIZE]; - - // if (_printDebug == true) - // { - // _debugPort->println(F("parseGPRMCString: rmcString: ")); - // _debugPort->println(rmcString); - // } - - // Fast-forward test to first value: - ptr = strchr(rmcString, ','); - ptr++; // Move ptr past first comma - - // If the next character is another comma, there's no time data - // Find time: - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - // Next comma should be present and not the next position - if ((search != nullptr) && (search != ptr)) - { - pos->utc = atof(tempData); // Extract hhmmss.ss as float - tTemp = pos->utc; // Convert to unsigned long (discard the digits beyond the decimal point) - clk->time.ms = ((unsigned int)(pos->utc * 100)) % 100; // Extract the milliseconds - clk->time.hour = tTemp / 10000; - tTemp -= ((unsigned long)clk->time.hour * 10000); - clk->time.minute = tTemp / 100; - tTemp -= ((unsigned long)clk->time.minute * 100); - clk->time.second = tTemp; - } - else - { - pos->utc = 0.0; - clk->time.hour = 0; - clk->time.minute = 0; - clk->time.second = 0; - } - ptr = search + 1; // Move pointer to next value - - // Find status character: - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - // Should be a single character: V = Data invalid, A = Data valid - if ((search != nullptr) && (search == ptr + 1)) - { - pos->status = *ptr; // Assign char at ptr to status - } - else - { - pos->status = 'X'; // Made up very bad status - } - ptr = search + 1; - - // Find latitude: - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search != ptr)) - { - pos->lat = atof(tempData); // Extract ddmm.mmmmm as float - unsigned long lat_deg = pos->lat / 100; // Extract the degrees - pos->lat -= (float)lat_deg * 100.0; // Subtract the degrees leaving only the minutes - pos->lat /= 60.0; // Convert minutes into degrees - pos->lat += (float)lat_deg; // Finally add the degrees back on again - } - else - { - pos->lat = 0.0; - } - ptr = search + 1; - - // Find latitude hemishpere - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search == ptr + 1)) - { - if (*ptr == 'S') // Is the latitude South - pos->lat *= -1.0; // Make lat negative - } - ptr = search + 1; - - // Find longitude: - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search != ptr)) - { - pos->lon = atof(tempData); // Extract dddmm.mmmmm as float - unsigned long lon_deg = pos->lon / 100; // Extract the degrees - pos->lon -= (float)lon_deg * 100.0; // Subtract the degrees leaving only the minutes - pos->lon /= 60.0; // Convert minutes into degrees - pos->lon += (float)lon_deg; // Finally add the degrees back on again - } - else - { - pos->lon = 0.0; - } - ptr = search + 1; - - // Find longitude hemishpere - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search == ptr + 1)) - { - if (*ptr == 'W') // Is the longitude West - pos->lon *= -1.0; // Make lon negative - } - ptr = search + 1; - - // Find speed - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search != ptr)) - { - spd->speed = atof(tempData); // Extract speed over ground in knots - spd->speed *= 0.514444; // Convert to m/s - } - else - { - spd->speed = 0.0; - } - ptr = search + 1; - - // Find course over ground - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search != ptr)) - { - spd->cog = atof(tempData); - } - else - { - spd->cog = 0.0; - } - ptr = search + 1; - - // Find date - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search != ptr)) - { - tTemp = atol(tempData); - clk->date.day = tTemp / 10000; - tTemp -= ((unsigned long)clk->date.day * 10000); - clk->date.month = tTemp / 100; - tTemp -= ((unsigned long)clk->date.month * 100); - clk->date.year = tTemp; - } - else - { - clk->date.day = 0; - clk->date.month = 0; - clk->date.year = 0; - } - ptr = search + 1; - - // Find magnetic variation in degrees: - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search != ptr)) - { - spd->magVar = atof(tempData); - } - else - { - spd->magVar = 0.0; - } - ptr = search + 1; - - // Find magnetic variation direction - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); - if ((search != nullptr) && (search == ptr + 1)) - { - if (*ptr == 'W') // Is the magnetic variation West - spd->magVar *= -1.0; // Make magnetic variation negative - } - ptr = search + 1; - - // Find position system mode - // Possible values for posMode: N = No fix, E = Estimated/Dead reckoning fix, A = Autonomous GNSS fix, - // D = Differential GNSS fix, F = RTK float, R = RTK fixed - search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, '*'); - if ((search != nullptr) && (search = ptr + 1)) - { - pos->mode = *ptr; - } - else - { - pos->mode = 'X'; - } - ptr = search + 1; - - if (pos->status == 'A') - { - return true; - } - return false; +char *UBX_CELL::readDataUntil(char *destination, unsigned int destSize, char *source, char delimiter) +{ + + char *strEnd; + size_t len; + + strEnd = strchr(source, delimiter); + + if (strEnd != nullptr) + { + len = strEnd - source; + memset(destination, 0, destSize); + memcpy(destination, source, len); + } + + return strEnd; +} + +bool UBX_CELL::parseGPRMCString(char *rmcString, PositionData *pos, ClockData *clk, SpeedData *spd) +{ + char *ptr, *search; + unsigned long tTemp; + char tempData[TEMP_NMEA_DATA_SIZE]; + + // if (_printDebug == true) + // { + // _debugPort->println(F("parseGPRMCString: rmcString: ")); + // _debugPort->println(rmcString); + // } + + // Fast-forward test to first value: + ptr = strchr(rmcString, ','); + ptr++; // Move ptr past first comma + + // If the next character is another comma, there's no time data + // Find time: + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + // Next comma should be present and not the next position + if ((search != nullptr) && (search != ptr)) + { + pos->utc = atof(tempData); // Extract hhmmss.ss as float + tTemp = pos->utc; // Convert to unsigned long (discard the digits beyond the decimal point) + clk->time.ms = ((unsigned int)(pos->utc * 100)) % 100; // Extract the milliseconds + clk->time.hour = tTemp / 10000; + tTemp -= ((unsigned long)clk->time.hour * 10000); + clk->time.minute = tTemp / 100; + tTemp -= ((unsigned long)clk->time.minute * 100); + clk->time.second = tTemp; + } + else + { + pos->utc = 0.0; + clk->time.hour = 0; + clk->time.minute = 0; + clk->time.second = 0; + } + ptr = search + 1; // Move pointer to next value + + // Find status character: + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + // Should be a single character: V = Data invalid, A = Data valid + if ((search != nullptr) && (search == ptr + 1)) + { + pos->status = *ptr; // Assign char at ptr to status + } + else + { + pos->status = 'X'; // Made up very bad status + } + ptr = search + 1; + + // Find latitude: + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search != ptr)) + { + pos->lat = atof(tempData); // Extract ddmm.mmmmm as float + unsigned long lat_deg = pos->lat / 100; // Extract the degrees + pos->lat -= (float)lat_deg * 100.0; // Subtract the degrees leaving only the minutes + pos->lat /= 60.0; // Convert minutes into degrees + pos->lat += (float)lat_deg; // Finally add the degrees back on again + } + else + { + pos->lat = 0.0; + } + ptr = search + 1; + + // Find latitude hemishpere + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search == ptr + 1)) + { + if (*ptr == 'S') // Is the latitude South + pos->lat *= -1.0; // Make lat negative + } + ptr = search + 1; + + // Find longitude: + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search != ptr)) + { + pos->lon = atof(tempData); // Extract dddmm.mmmmm as float + unsigned long lon_deg = pos->lon / 100; // Extract the degrees + pos->lon -= (float)lon_deg * 100.0; // Subtract the degrees leaving only the minutes + pos->lon /= 60.0; // Convert minutes into degrees + pos->lon += (float)lon_deg; // Finally add the degrees back on again + } + else + { + pos->lon = 0.0; + } + ptr = search + 1; + + // Find longitude hemishpere + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search == ptr + 1)) + { + if (*ptr == 'W') // Is the longitude West + pos->lon *= -1.0; // Make lon negative + } + ptr = search + 1; + + // Find speed + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search != ptr)) + { + spd->speed = atof(tempData); // Extract speed over ground in knots + spd->speed *= 0.514444; // Convert to m/s + } + else + { + spd->speed = 0.0; + } + ptr = search + 1; + + // Find course over ground + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search != ptr)) + { + spd->cog = atof(tempData); + } + else + { + spd->cog = 0.0; + } + ptr = search + 1; + + // Find date + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search != ptr)) + { + tTemp = atol(tempData); + clk->date.day = tTemp / 10000; + tTemp -= ((unsigned long)clk->date.day * 10000); + clk->date.month = tTemp / 100; + tTemp -= ((unsigned long)clk->date.month * 100); + clk->date.year = tTemp; + } + else + { + clk->date.day = 0; + clk->date.month = 0; + clk->date.year = 0; + } + ptr = search + 1; + + // Find magnetic variation in degrees: + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search != ptr)) + { + spd->magVar = atof(tempData); + } + else + { + spd->magVar = 0.0; + } + ptr = search + 1; + + // Find magnetic variation direction + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, ','); + if ((search != nullptr) && (search == ptr + 1)) + { + if (*ptr == 'W') // Is the magnetic variation West + spd->magVar *= -1.0; // Make magnetic variation negative + } + ptr = search + 1; + + // Find position system mode + // Possible values for posMode: N = No fix, E = Estimated/Dead reckoning fix, A = Autonomous GNSS fix, + // D = Differential GNSS fix, F = RTK float, R = RTK fixed + search = readDataUntil(tempData, TEMP_NMEA_DATA_SIZE, ptr, '*'); + if ((search != nullptr) && (search = ptr + 1)) + { + pos->mode = *ptr; + } + else + { + pos->mode = 'X'; + } + ptr = search + 1; + + if (pos->status == 'A') + { + return true; + } + return false; } diff --git a/src/sfe_ublox_cellular.h b/src/sfe_ublox_cellular.h index c3540d8..f0a21a5 100644 --- a/src/sfe_ublox_cellular.h +++ b/src/sfe_ublox_cellular.h @@ -1,7 +1,6 @@ /* - Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod Asset Tracker - By: Paul Clark - October 19th 2020 + Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod + Asset Tracker By: Paul Clark October 19th 2020 Based extensively on the: Arduino Library for the SparkFun LTE CAT M1/NB-IoT Shield - SARA-R4 @@ -23,22 +22,22 @@ #include "WProgram.h" #endif -#ifdef ARDUINO_ARCH_AVR // Arduino AVR boards (Uno, Pro Micro, etc.) +#ifdef ARDUINO_ARCH_AVR // Arduino AVR boards (Uno, Pro Micro, etc.) #define UBX_CELL_SOFTWARE_SERIAL_ENABLED // Enable software serial #endif -#ifdef ARDUINO_ARCH_SAMD // Arduino SAMD boards (SAMD21, etc.) +#ifdef ARDUINO_ARCH_SAMD // Arduino SAMD boards (SAMD21, etc.) #define UBX_CELL_SOFTWARE_SERIAL_ENABLEDx // Disable software serial #endif -#ifdef ARDUINO_ARCH_APOLLO3 // Arduino Apollo boards (Artemis module, RedBoard Artemis, etc) +#ifdef ARDUINO_ARCH_APOLLO3 // Arduino Apollo boards (Artemis module, RedBoard Artemis, etc) #define UBX_CELL_SOFTWARE_SERIAL_ENABLEDx // Disable software serial (no longer supported with v2 of Apollo3) // Note: paulvha has provided software serial support for v2 of the Apollo3 / Artemis core. // Further details are available at: // https://github.com/paulvha/apollo3/tree/master/SoftwareSerial #endif -#ifdef ARDUINO_ARCH_STM32 // STM32 based boards (Disco, Nucleo, etc) +#ifdef ARDUINO_ARCH_STM32 // STM32 based boards (Disco, Nucleo, etc) #define UBX_CELL_SOFTWARE_SERIAL_ENABLED // Enable software serial #endif @@ -84,8 +83,9 @@ #define UBX_CELL_3_MIN_TIMEOUT 180000 #define UBX_CELL_SET_BAUD_TIMEOUT 500 #define UBX_CELL_POWER_OFF_PULSE_PERIOD 3200 // Hold PWR_ON low for this long to power the module off -#define UBX_CELL_POWER_ON_PULSE_PERIOD 100 // Hold PWR_ON low for this long to power the module on (SARA-R510M8S) -#define UBX_CELL_RESET_PULSE_PERIOD 23000 // Used to perform an abrupt emergency hardware shutdown. 23 seconds... (Yes, really!) +#define UBX_CELL_POWER_ON_PULSE_PERIOD 100 // Hold PWR_ON low for this long to power the module on (SARA-R510M8S) +#define UBX_CELL_RESET_PULSE_PERIOD \ + 23000 // Used to perform an abrupt emergency hardware shutdown. 23 seconds... (Yes, really!) #define UBX_CELL_POWER_OFF_TIMEOUT 40000 // Datasheet says 40 seconds... #define UBX_CELL_IP_CONNECT_TIMEOUT 130000 #define UBX_CELL_POLL_DELAY 1 @@ -93,122 +93,124 @@ // ## Suported AT Commands // ### General -const char* const UBX_CELL_COMMAND_AT = "AT"; // AT "Test" -const char* const UBX_CELL_COMMAND_ECHO = "E"; // Local Echo -const char* const UBX_CELL_COMMAND_MANU_ID = "+CGMI"; // Manufacturer identification -const char* const UBX_CELL_COMMAND_MODEL_ID = "+CGMM"; // Model identification -const char* const UBX_CELL_COMMAND_FW_VER_ID = "+CGMR"; // Firmware version identification -const char* const UBX_CELL_COMMAND_SERIAL_NO = "+CGSN"; // Product serial number -const char* const UBX_CELL_COMMAND_IMEI = "+GSN"; // IMEI identification -const char* const UBX_CELL_COMMAND_IMSI = "+CIMI"; // IMSI identification -const char* const UBX_CELL_COMMAND_CCID = "+CCID"; // SIM CCID -const char* const UBX_CELL_COMMAND_REQ_CAP = "+GCAP"; // Request capabilities list +const char *const UBX_CELL_COMMAND_AT = "AT"; // AT "Test" +const char *const UBX_CELL_COMMAND_ECHO = "E"; // Local Echo +const char *const UBX_CELL_COMMAND_MANU_ID = "+CGMI"; // Manufacturer identification +const char *const UBX_CELL_COMMAND_MODEL_ID = "+CGMM"; // Model identification +const char *const UBX_CELL_COMMAND_FW_VER_ID = "+CGMR"; // Firmware version identification +const char *const UBX_CELL_COMMAND_SERIAL_NO = "+CGSN"; // Product serial number +const char *const UBX_CELL_COMMAND_IMEI = "+GSN"; // IMEI identification +const char *const UBX_CELL_COMMAND_IMSI = "+CIMI"; // IMSI identification +const char *const UBX_CELL_COMMAND_CCID = "+CCID"; // SIM CCID +const char *const UBX_CELL_COMMAND_REQ_CAP = "+GCAP"; // Request capabilities list // ### Control and status -const char* const UBX_CELL_COMMAND_POWER_OFF = "+CPWROFF"; // Module switch off -const char* const UBX_CELL_COMMAND_FUNC = "+CFUN"; // Functionality (reset, etc.) -const char* const UBX_CELL_COMMAND_CLOCK = "+CCLK"; // Real-time clock -const char* const UBX_CELL_COMMAND_AUTO_TZ = "+CTZU"; // Automatic time zone update -const char* const UBX_CELL_COMMAND_TZ_REPORT = "+CTZR"; // Time zone reporting +const char *const UBX_CELL_COMMAND_POWER_OFF = "+CPWROFF"; // Module switch off +const char *const UBX_CELL_COMMAND_FUNC = "+CFUN"; // Functionality (reset, etc.) +const char *const UBX_CELL_COMMAND_CLOCK = "+CCLK"; // Real-time clock +const char *const UBX_CELL_COMMAND_AUTO_TZ = "+CTZU"; // Automatic time zone update +const char *const UBX_CELL_COMMAND_TZ_REPORT = "+CTZR"; // Time zone reporting // ### Network service -const char* const UBX_CELL_COMMAND_CNUM = "+CNUM"; // Subscriber number -const char* const UBX_CELL_SIGNAL_QUALITY = "+CSQ"; -const char* const UBX_CELL_EXT_SIGNAL_QUALITY = "+CESQ"; -const char* const UBX_CELL_OPERATOR_SELECTION = "+COPS"; -const char* const UBX_CELL_REGISTRATION_STATUS = "+CREG"; -const char* const UBX_CELL_EPSREGISTRATION_STATUS = "+CEREG"; -const char* const UBX_CELL_READ_OPERATOR_NAMES = "+COPN"; -const char* const UBX_CELL_COMMAND_MNO = "+UMNOPROF"; // MNO (mobile network operator) Profile +const char *const UBX_CELL_COMMAND_CNUM = "+CNUM"; // Subscriber number +const char *const UBX_CELL_SIGNAL_QUALITY = "+CSQ"; +const char *const UBX_CELL_EXT_SIGNAL_QUALITY = "+CESQ"; +const char *const UBX_CELL_OPERATOR_SELECTION = "+COPS"; +const char *const UBX_CELL_REGISTRATION_STATUS = "+CREG"; +const char *const UBX_CELL_EPSREGISTRATION_STATUS = "+CEREG"; +const char *const UBX_CELL_READ_OPERATOR_NAMES = "+COPN"; +const char *const UBX_CELL_COMMAND_MNO = "+UMNOPROF"; // MNO (mobile network operator) Profile // ### SIM -const char* const UBX_CELL_SIM_STATE = "+USIMSTAT"; -const char* const UBX_CELL_COMMAND_SIMPIN = "+CPIN"; // SIM PIN +const char *const UBX_CELL_SIM_STATE = "+USIMSTAT"; +const char *const UBX_CELL_COMMAND_SIMPIN = "+CPIN"; // SIM PIN // ### SMS -const char* const UBX_CELL_MESSAGE_FORMAT = "+CMGF"; // Set SMS message format -const char* const UBX_CELL_SEND_TEXT = "+CMGS"; // Send SMS message -const char* const UBX_CELL_NEW_MESSAGE_IND = "+CNMI"; // New [SMS] message indication -const char* const UBX_CELL_PREF_MESSAGE_STORE = "+CPMS"; // Preferred message storage -const char* const UBX_CELL_READ_TEXT_MESSAGE = "+CMGR"; // Read message -const char* const UBX_CELL_DELETE_MESSAGE = "+CMGD"; // Delete message +const char *const UBX_CELL_MESSAGE_FORMAT = "+CMGF"; // Set SMS message format +const char *const UBX_CELL_SEND_TEXT = "+CMGS"; // Send SMS message +const char *const UBX_CELL_NEW_MESSAGE_IND = "+CNMI"; // New [SMS] message indication +const char *const UBX_CELL_PREF_MESSAGE_STORE = "+CPMS"; // Preferred message storage +const char *const UBX_CELL_READ_TEXT_MESSAGE = "+CMGR"; // Read message +const char *const UBX_CELL_DELETE_MESSAGE = "+CMGD"; // Delete message // V24 control and V25ter (UART interface) -const char* const UBX_CELL_FLOW_CONTROL = "&K"; // Flow control -const char* const UBX_CELL_COMMAND_BAUD = "+IPR"; // Baud rate +const char *const UBX_CELL_FLOW_CONTROL = "&K"; // Flow control +const char *const UBX_CELL_COMMAND_BAUD = "+IPR"; // Baud rate // ### Packet switched data services -const char* const UBX_CELL_MESSAGE_PDP_DEF = "+CGDCONT"; // Packet switched Data Profile context definition -const char* const UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE = "+CGACT"; // Activates or deactivates the specified PDP context -const char* const UBX_CELL_MESSAGE_ENTER_PPP = "D"; +const char *const UBX_CELL_MESSAGE_PDP_DEF = "+CGDCONT"; // Packet switched Data Profile context definition +const char *const UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE = + "+CGACT"; // Activates or deactivates the specified PDP context +const char *const UBX_CELL_MESSAGE_ENTER_PPP = "D"; // ### GPIO -const char* const UBX_CELL_COMMAND_GPIO = "+UGPIOC"; // GPIO Configuration +const char *const UBX_CELL_COMMAND_GPIO = "+UGPIOC"; // GPIO Configuration // ### IP -const char* const UBX_CELL_CREATE_SOCKET = "+USOCR"; // Create a new socket -const char* const UBX_CELL_CLOSE_SOCKET = "+USOCL"; // Close a socket -const char* const UBX_CELL_CONNECT_SOCKET = "+USOCO"; // Connect to server on socket -const char* const UBX_CELL_WRITE_SOCKET = "+USOWR"; // Write data to a socket -const char* const UBX_CELL_WRITE_UDP_SOCKET = "+USOST"; // Write data to a UDP socket -const char* const UBX_CELL_READ_SOCKET = "+USORD"; // Read from a socket -const char* const UBX_CELL_READ_UDP_SOCKET = "+USORF"; // Read UDP data from a socket -const char* const UBX_CELL_LISTEN_SOCKET = "+USOLI"; // Listen for connection on socket -const char* const UBX_CELL_GET_ERROR = "+USOER"; // Get last socket error. -const char* const UBX_CELL_SOCKET_DIRECT_LINK = "+USODL"; // Set socket in Direct Link mode -const char* const UBX_CELL_SOCKET_CONTROL = "+USOCTL"; // Query the socket parameters -const char* const UBX_CELL_UD_CONFIGURATION = "+UDCONF"; // User Datagram Configuration +const char *const UBX_CELL_CREATE_SOCKET = "+USOCR"; // Create a new socket +const char *const UBX_CELL_CLOSE_SOCKET = "+USOCL"; // Close a socket +const char *const UBX_CELL_CONNECT_SOCKET = "+USOCO"; // Connect to server on socket +const char *const UBX_CELL_WRITE_SOCKET = "+USOWR"; // Write data to a socket +const char *const UBX_CELL_WRITE_UDP_SOCKET = "+USOST"; // Write data to a UDP socket +const char *const UBX_CELL_READ_SOCKET = "+USORD"; // Read from a socket +const char *const UBX_CELL_READ_UDP_SOCKET = "+USORF"; // Read UDP data from a socket +const char *const UBX_CELL_LISTEN_SOCKET = "+USOLI"; // Listen for connection on socket +const char *const UBX_CELL_GET_ERROR = "+USOER"; // Get last socket error. +const char *const UBX_CELL_SOCKET_DIRECT_LINK = "+USODL"; // Set socket in Direct Link mode +const char *const UBX_CELL_SOCKET_CONTROL = "+USOCTL"; // Query the socket parameters +const char *const UBX_CELL_UD_CONFIGURATION = "+UDCONF"; // User Datagram Configuration // ### Ping -const char* const UBX_CELL_PING_COMMAND = "+UPING"; // Ping +const char *const UBX_CELL_PING_COMMAND = "+UPING"; // Ping // ### HTTP -const char* const UBX_CELL_HTTP_PROFILE = "+UHTTP"; // Configure the HTTP profile. Up to 4 different profiles can be defined -const char* const UBX_CELL_HTTP_COMMAND = "+UHTTPC"; // Trigger the specified HTTP command -const char* const UBX_CELL_HTTP_PROTOCOL_ERROR = "+UHTTPER"; // Retrieves the error class and code of the latest HTTP operation on the specified HTTP profile. - -const char* const UBX_CELL_MQTT_NVM = "+UMQTTNV"; -const char* const UBX_CELL_MQTT_PROFILE = "+UMQTT"; -const char* const UBX_CELL_MQTT_COMMAND = "+UMQTTC"; -const char* const UBX_CELL_MQTT_PROTOCOL_ERROR = "+UMQTTER"; +const char *const UBX_CELL_HTTP_PROFILE = + "+UHTTP"; // Configure the HTTP profile. Up to 4 different profiles can be defined +const char *const UBX_CELL_HTTP_COMMAND = "+UHTTPC"; // Trigger the specified HTTP command +const char *const UBX_CELL_HTTP_PROTOCOL_ERROR = + "+UHTTPER"; // Retrieves the error class and code of the latest HTTP operation on the specified HTTP profile. + +const char *const UBX_CELL_MQTT_NVM = "+UMQTTNV"; +const char *const UBX_CELL_MQTT_PROFILE = "+UMQTT"; +const char *const UBX_CELL_MQTT_COMMAND = "+UMQTTC"; +const char *const UBX_CELL_MQTT_PROTOCOL_ERROR = "+UMQTTER"; // ### FTP -const char* const UBX_CELL_FTP_PROFILE = "+UFTP"; -const char* const UBX_CELL_FTP_COMMAND = "+UFTPC"; -const char* const UBX_CELL_FTP_PROTOCOL_ERROR = "+UFTPER"; +const char *const UBX_CELL_FTP_PROFILE = "+UFTP"; +const char *const UBX_CELL_FTP_COMMAND = "+UFTPC"; +const char *const UBX_CELL_FTP_PROTOCOL_ERROR = "+UFTPER"; // ### GNSS -const char* const UBX_CELL_GNSS_POWER = "+UGPS"; // GNSS power management configuration -const char* const UBX_CELL_GNSS_ASSISTED_IND = "+UGIND"; // Assisted GNSS unsolicited indication -const char* const UBX_CELL_GNSS_REQUEST_LOCATION = "+ULOC"; // Ask for localization information -const char* const UBX_CELL_GNSS_GPRMC = "+UGRMC"; // Ask for localization information -const char* const UBX_CELL_GNSS_CONFIGURE_SENSOR = "+ULOCGNSS"; // Configure GNSS sensor -const char* const UBX_CELL_GNSS_CONFIGURE_LOCATION = "+ULOCCELL"; // Configure cellular location sensor (CellLocate®) -const char* const UBX_CELL_AIDING_SERVER_CONFIGURATION = "+UGSRV"; // Configure aiding server (CellLocate®) +const char *const UBX_CELL_GNSS_POWER = "+UGPS"; // GNSS power management configuration +const char *const UBX_CELL_GNSS_ASSISTED_IND = "+UGIND"; // Assisted GNSS unsolicited indication +const char *const UBX_CELL_GNSS_REQUEST_LOCATION = "+ULOC"; // Ask for localization information +const char *const UBX_CELL_GNSS_GPRMC = "+UGRMC"; // Ask for localization information +const char *const UBX_CELL_GNSS_CONFIGURE_SENSOR = "+ULOCGNSS"; // Configure GNSS sensor +const char *const UBX_CELL_GNSS_CONFIGURE_LOCATION = "+ULOCCELL"; // Configure cellular location sensor (CellLocate®) +const char *const UBX_CELL_AIDING_SERVER_CONFIGURATION = "+UGSRV"; // Configure aiding server (CellLocate®) // ### File System // TO DO: Add support for file tags. Default tag to USER -const char* const UBX_CELL_FILE_SYSTEM_READ_FILE = "+URDFILE"; // Read a file -const char* const UBX_CELL_FILE_SYSTEM_READ_BLOCK = "+URDBLOCK"; // Read a block from a file -const char* const UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE = "+UDWNFILE"; // Download a file into the module -const char* const UBX_CELL_FILE_SYSTEM_LIST_FILES = "+ULSTFILE"; // List of files, size of file, etc. -const char* const UBX_CELL_FILE_SYSTEM_DELETE_FILE = "+UDELFILE"; // Delete a file +const char *const UBX_CELL_FILE_SYSTEM_READ_FILE = "+URDFILE"; // Read a file +const char *const UBX_CELL_FILE_SYSTEM_READ_BLOCK = "+URDBLOCK"; // Read a block from a file +const char *const UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE = "+UDWNFILE"; // Download a file into the module +const char *const UBX_CELL_FILE_SYSTEM_LIST_FILES = "+ULSTFILE"; // List of files, size of file, etc. +const char *const UBX_CELL_FILE_SYSTEM_DELETE_FILE = "+UDELFILE"; // Delete a file // ### File System // TO DO: Add support for file tags. Default tag to USER -const char* const UBX_CELL_SEC_PROFILE = "+USECPRF"; -const char* const UBX_CELL_SEC_MANAGER = "+USECMNG"; - +const char *const UBX_CELL_SEC_PROFILE = "+USECPRF"; +const char *const UBX_CELL_SEC_MANAGER = "+USECMNG"; // ### URC strings -const char* const UBX_CELL_READ_SOCKET_URC = "+UUSORD:"; -const char* const UBX_CELL_READ_UDP_SOCKET_URC = "+UUSORF:"; -const char* const UBX_CELL_LISTEN_SOCKET_URC = "+UUSOLI:"; -const char* const UBX_CELL_CLOSE_SOCKET_URC = "+UUSOCL:"; -const char* const UBX_CELL_GNSS_REQUEST_LOCATION_URC = "+UULOC:"; -const char* const UBX_CELL_SIM_STATE_URC = "+UUSIMSTAT:"; -const char* const UBX_CELL_HTTP_COMMAND_URC = "+UUHTTPCR:"; -const char* const UBX_CELL_MQTT_COMMAND_URC = "+UUMQTTC:"; -const char* const UBX_CELL_PING_COMMAND_URC = "+UUPING:"; -const char* const UBX_CELL_REGISTRATION_STATUS_URC = "+CREG:"; -const char* const UBX_CELL_EPSREGISTRATION_STATUS_URC = "+CEREG:"; -const char* const UBX_CELL_FTP_COMMAND_URC = "+UUFTPCR:"; +const char *const UBX_CELL_READ_SOCKET_URC = "+UUSORD:"; +const char *const UBX_CELL_READ_UDP_SOCKET_URC = "+UUSORF:"; +const char *const UBX_CELL_LISTEN_SOCKET_URC = "+UUSOLI:"; +const char *const UBX_CELL_CLOSE_SOCKET_URC = "+UUSOCL:"; +const char *const UBX_CELL_GNSS_REQUEST_LOCATION_URC = "+UULOC:"; +const char *const UBX_CELL_SIM_STATE_URC = "+UUSIMSTAT:"; +const char *const UBX_CELL_HTTP_COMMAND_URC = "+UUHTTPCR:"; +const char *const UBX_CELL_MQTT_COMMAND_URC = "+UUMQTTC:"; +const char *const UBX_CELL_PING_COMMAND_URC = "+UUPING:"; +const char *const UBX_CELL_REGISTRATION_STATUS_URC = "+CREG:"; +const char *const UBX_CELL_EPSREGISTRATION_STATUS_URC = "+CEREG:"; +const char *const UBX_CELL_FTP_COMMAND_URC = "+UUFTPCR:"; // ### Response -const char* const UBX_CELL_RESPONSE_MORE = "\n>"; -const char* const UBX_CELL_RESPONSE_OK = "\nOK\r\n"; -const char* const UBX_CELL_RESPONSE_ERROR = "\nERROR\r\n"; -const char* const UBX_CELL_RESPONSE_CONNECT = "\r\nCONNECT\r\n"; +const char *const UBX_CELL_RESPONSE_MORE = "\n>"; +const char *const UBX_CELL_RESPONSE_OK = "\nOK\r\n"; +const char *const UBX_CELL_RESPONSE_ERROR = "\nERROR\r\n"; +const char *const UBX_CELL_RESPONSE_CONNECT = "\r\nCONNECT\r\n"; #define UBX_CELL_RESPONSE_OK_OR_ERROR nullptr // URC handler type definition -typedef std::function UBX_CELL_urc_handler_t; +typedef std::function UBX_CELL_urc_handler_t; // CTRL+Z and ESC ASCII codes for SMS message sends const char ASCII_CTRL_Z = 0x1A; @@ -227,22 +229,15 @@ const char ASCII_ESC = 0x1B; #define UBX_CELL_NUM_SOCKETS 6 #define NUM_SUPPORTED_BAUD 6 -const unsigned long UBX_CELL_SUPPORTED_BAUD[NUM_SUPPORTED_BAUD] = - { - 115200, - 9600, - 19200, - 38400, - 57600, - 230400}; +const unsigned long UBX_CELL_SUPPORTED_BAUD[NUM_SUPPORTED_BAUD] = {115200, 9600, 19200, 38400, 57600, 230400}; #define UBX_CELL_DEFAULT_BAUD_RATE 115200 // Flow control definitions for AT&K // Note: SW (XON/XOFF) flow control is not supported on the UBX_CELL typedef enum { - UBX_CELL_DISABLE_FLOW_CONTROL = 0, - UBX_CELL_ENABLE_FLOW_CONTROL = 3 + UBX_CELL_DISABLE_FLOW_CONTROL = 0, + UBX_CELL_ENABLE_FLOW_CONTROL = 3 } UBX_CELL_flow_control_t; // The standard Europe profile should be used as the basis for all other MNOs in Europe outside of Vodafone @@ -251,108 +246,109 @@ typedef enum // consult with the preferred network provider. typedef enum { - MNO_INVALID = -1, - MNO_SW_DEFAULT = 0, // Undefined / regulatory - MNO_SIM_ICCID = 1, - MNO_ATT = 2, // AT&T - MNO_VERIZON = 3, - MNO_TELSTRA = 4, - MNO_TMO = 5, // T-Mobile US - MNO_CT = 6, // China Telecom - MNO_SPRINT = 8, - MNO_VODAFONE = 19, - MNO_NTT_DOCOMO = 20, - MNO_TELUS = 21, - MNO_SOFTBANK = 28, - MNO_DT = 31, // Deutsche Telekom - MNO_US_CELLULAR = 32, - MNO_SKT = 39, - MNO_GLOBAL = 90, - MNO_STD_EUROPE = 100, - MNO_STD_EU_NOEPCO = 101 + MNO_INVALID = -1, + MNO_SW_DEFAULT = 0, // Undefined / regulatory + MNO_SIM_ICCID = 1, + MNO_ATT = 2, // AT&T + MNO_VERIZON = 3, + MNO_TELSTRA = 4, + MNO_TMO = 5, // T-Mobile US + MNO_CT = 6, // China Telecom + MNO_SPRINT = 8, + MNO_VODAFONE = 19, + MNO_NTT_DOCOMO = 20, + MNO_TELUS = 21, + MNO_SOFTBANK = 28, + MNO_DT = 31, // Deutsche Telekom + MNO_US_CELLULAR = 32, + MNO_SKT = 39, + MNO_GLOBAL = 90, + MNO_STD_EUROPE = 100, + MNO_STD_EU_NOEPCO = 101 } mobile_network_operator_t; typedef enum { - UBX_CELL_ERROR_INVALID = -1, // -1 - UBX_CELL_ERROR_SUCCESS = 0, // 0 - UBX_CELL_ERROR_OUT_OF_MEMORY, // 1 - UBX_CELL_ERROR_TIMEOUT, // 2 - UBX_CELL_ERROR_UNEXPECTED_PARAM, // 3 - UBX_CELL_ERROR_UNEXPECTED_RESPONSE, // 4 - UBX_CELL_ERROR_NO_RESPONSE, // 5 - UBX_CELL_ERROR_DEREGISTERED, // 6 - UBX_CELL_ERROR_ZERO_READ_LENGTH, // 7 - UBX_CELL_ERROR_ERROR // 8 + UBX_CELL_ERROR_INVALID = -1, // -1 + UBX_CELL_ERROR_SUCCESS = 0, // 0 + UBX_CELL_ERROR_OUT_OF_MEMORY, // 1 + UBX_CELL_ERROR_TIMEOUT, // 2 + UBX_CELL_ERROR_UNEXPECTED_PARAM, // 3 + UBX_CELL_ERROR_UNEXPECTED_RESPONSE, // 4 + UBX_CELL_ERROR_NO_RESPONSE, // 5 + UBX_CELL_ERROR_DEREGISTERED, // 6 + UBX_CELL_ERROR_ZERO_READ_LENGTH, // 7 + UBX_CELL_ERROR_ERROR // 8 } UBX_CELL_error_t; #define UBX_CELL_SUCCESS UBX_CELL_ERROR_SUCCESS typedef enum { - UBX_CELL_REGISTRATION_INVALID = -1, - UBX_CELL_REGISTRATION_NOT_REGISTERED = 0, - UBX_CELL_REGISTRATION_HOME = 1, - UBX_CELL_REGISTRATION_SEARCHING = 2, - UBX_CELL_REGISTRATION_DENIED = 3, - UBX_CELL_REGISTRATION_UNKNOWN = 4, - UBX_CELL_REGISTRATION_ROAMING = 5, - UBX_CELL_REGISTRATION_HOME_SMS_ONLY = 6, - UBX_CELL_REGISTRATION_ROAMING_SMS_ONLY = 7, - UBX_CELL_REGISTRATION_EMERGENCY_SERV_ONLY = 8, - UBX_CELL_REGISTRATION_HOME_CSFB_NOT_PREFERRED = 9, - UBX_CELL_REGISTRATION_ROAMING_CSFB_NOT_PREFERRED = 10 + UBX_CELL_REGISTRATION_INVALID = -1, + UBX_CELL_REGISTRATION_NOT_REGISTERED = 0, + UBX_CELL_REGISTRATION_HOME = 1, + UBX_CELL_REGISTRATION_SEARCHING = 2, + UBX_CELL_REGISTRATION_DENIED = 3, + UBX_CELL_REGISTRATION_UNKNOWN = 4, + UBX_CELL_REGISTRATION_ROAMING = 5, + UBX_CELL_REGISTRATION_HOME_SMS_ONLY = 6, + UBX_CELL_REGISTRATION_ROAMING_SMS_ONLY = 7, + UBX_CELL_REGISTRATION_EMERGENCY_SERV_ONLY = 8, + UBX_CELL_REGISTRATION_HOME_CSFB_NOT_PREFERRED = 9, + UBX_CELL_REGISTRATION_ROAMING_CSFB_NOT_PREFERRED = 10 } UBX_CELL_registration_status_t; struct DateData { - uint8_t day; - uint8_t month; - unsigned int year; + uint8_t day; + uint8_t month; + unsigned int year; }; struct TimeData { - uint8_t hour; - uint8_t minute; - uint8_t second; - unsigned int ms; - uint8_t tzh; - uint8_t tzm; + uint8_t hour; + uint8_t minute; + uint8_t second; + unsigned int ms; + uint8_t tzh; + uint8_t tzm; }; struct ClockData { - struct DateData date; - struct TimeData time; + struct DateData date; + struct TimeData time; }; struct PositionData { - float utc; - float lat; // Degrees: +/- 90 - float lon; // Degrees: +/- 180 - float alt; - char mode; - char status; + float utc; + float lat; // Degrees: +/- 90 + float lon; // Degrees: +/- 180 + float alt; + char mode; + char status; }; struct SpeedData { - float speed; // m/s - float cog; // Degrees - float magVar; // Degrees + float speed; // m/s + float cog; // Degrees + float magVar; // Degrees }; struct operator_stats { - uint8_t stat; - String shortOp; - String longOp; - unsigned long numOp; - uint8_t act; + uint8_t stat; + String shortOp; + String longOp; + unsigned long numOp; + uint8_t act; }; -typedef struct ext_signal_quality_ { +typedef struct ext_signal_quality_ +{ unsigned int rxlev; unsigned int ber; unsigned int rscp; @@ -363,68 +359,68 @@ typedef struct ext_signal_quality_ { typedef enum { - UBX_CELL_TCP = 6, - UBX_CELL_UDP = 17 + UBX_CELL_TCP = 6, + UBX_CELL_UDP = 17 } UBX_CELL_socket_protocol_t; typedef enum { - UBX_CELL_TCP_SOCKET_STATUS_INACTIVE, - UBX_CELL_TCP_SOCKET_STATUS_LISTEN, - UBX_CELL_TCP_SOCKET_STATUS_SYN_SENT, - UBX_CELL_TCP_SOCKET_STATUS_SYN_RCVD, - UBX_CELL_TCP_SOCKET_STATUS_ESTABLISHED, - UBX_CELL_TCP_SOCKET_STATUS_FIN_WAIT_1, - UBX_CELL_TCP_SOCKET_STATUS_FIN_WAIT_2, - UBX_CELL_TCP_SOCKET_STATUS_CLOSE_WAIT, - UBX_CELL_TCP_SOCKET_STATUS_CLOSING, - UBX_CELL_TCP_SOCKET_STATUS_LAST_ACK, - UBX_CELL_TCP_SOCKET_STATUS_TIME_WAIT + UBX_CELL_TCP_SOCKET_STATUS_INACTIVE, + UBX_CELL_TCP_SOCKET_STATUS_LISTEN, + UBX_CELL_TCP_SOCKET_STATUS_SYN_SENT, + UBX_CELL_TCP_SOCKET_STATUS_SYN_RCVD, + UBX_CELL_TCP_SOCKET_STATUS_ESTABLISHED, + UBX_CELL_TCP_SOCKET_STATUS_FIN_WAIT_1, + UBX_CELL_TCP_SOCKET_STATUS_FIN_WAIT_2, + UBX_CELL_TCP_SOCKET_STATUS_CLOSE_WAIT, + UBX_CELL_TCP_SOCKET_STATUS_CLOSING, + UBX_CELL_TCP_SOCKET_STATUS_LAST_ACK, + UBX_CELL_TCP_SOCKET_STATUS_TIME_WAIT } UBX_CELL_tcp_socket_status_t; typedef enum { - UBX_CELL_MESSAGE_FORMAT_PDU = 0, - UBX_CELL_MESSAGE_FORMAT_TEXT = 1 + UBX_CELL_MESSAGE_FORMAT_PDU = 0, + UBX_CELL_MESSAGE_FORMAT_TEXT = 1 } UBX_CELL_message_format_t; typedef enum { - UBX_CELL_UTIME_MODE_STOP = 0, - UBX_CELL_UTIME_MODE_PPS, - UBX_CELL_UTIME_MODE_ONE_SHOT, - UBX_CELL_UTIME_MODE_EXT_INT + UBX_CELL_UTIME_MODE_STOP = 0, + UBX_CELL_UTIME_MODE_PPS, + UBX_CELL_UTIME_MODE_ONE_SHOT, + UBX_CELL_UTIME_MODE_EXT_INT } UBX_CELL_utime_mode_t; typedef enum { - UBX_CELL_UTIME_SENSOR_NONE = 0, - UBX_CELL_UTIME_SENSOR_GNSS_LTE = 1, - UBX_CELL_UTIME_SENSOR_LTE + UBX_CELL_UTIME_SENSOR_NONE = 0, + UBX_CELL_UTIME_SENSOR_GNSS_LTE = 1, + UBX_CELL_UTIME_SENSOR_LTE } UBX_CELL_utime_sensor_t; typedef enum { - UBX_CELL_UTIME_URC_CONFIGURATION_DISABLED = 0, - UBX_CELL_UTIME_URC_CONFIGURATION_ENABLED + UBX_CELL_UTIME_URC_CONFIGURATION_DISABLED = 0, + UBX_CELL_UTIME_URC_CONFIGURATION_ENABLED } UBX_CELL_utime_urc_configuration_t; typedef enum { - UBX_CELL_SIM_NOT_PRESENT = 0, - UBX_CELL_SIM_PIN_NEEDED, - UBX_CELL_SIM_PIN_BLOCKED, - UBX_CELL_SIM_PUK_BLOCKED, - UBX_CELL_SIM_NOT_OPERATIONAL, - UBX_CELL_SIM_RESTRICTED, - UBX_CELL_SIM_OPERATIONAL - //UBX_CELL_SIM_PHONEBOOK_READY, // Not reported by SARA-R5 - //UBX_CELL_SIM_USIM_PHONEBOOK_READY, // Not reported by SARA-R5 - //UBX_CELL_SIM_TOOLKIT_REFRESH_SUCCESSFUL, // Not reported by SARA-R5 - //UBX_CELL_SIM_TOOLKIT_REFRESH_UNSUCCESSFUL, // Not reported by SARA-R5 - //UBX_CELL_SIM_PPP_CONNECTION_ACTIVE, // Not reported by SARA-R5 - //UBX_CELL_SIM_VOICE_CALL_ACTIVE, // Not reported by SARA-R5 - //UBX_CELL_SIM_CSD_CALL_ACTIVE // Not reported by SARA-R5 + UBX_CELL_SIM_NOT_PRESENT = 0, + UBX_CELL_SIM_PIN_NEEDED, + UBX_CELL_SIM_PIN_BLOCKED, + UBX_CELL_SIM_PUK_BLOCKED, + UBX_CELL_SIM_NOT_OPERATIONAL, + UBX_CELL_SIM_RESTRICTED, + UBX_CELL_SIM_OPERATIONAL + // UBX_CELL_SIM_PHONEBOOK_READY, // Not reported by SARA-R5 + // UBX_CELL_SIM_USIM_PHONEBOOK_READY, // Not reported by SARA-R5 + // UBX_CELL_SIM_TOOLKIT_REFRESH_SUCCESSFUL, // Not reported by SARA-R5 + // UBX_CELL_SIM_TOOLKIT_REFRESH_UNSUCCESSFUL, // Not reported by SARA-R5 + // UBX_CELL_SIM_PPP_CONNECTION_ACTIVE, // Not reported by SARA-R5 + // UBX_CELL_SIM_VOICE_CALL_ACTIVE, // Not reported by SARA-R5 + // UBX_CELL_SIM_CSD_CALL_ACTIVE // Not reported by SARA-R5 } UBX_CELL_sim_states_t; #define UBX_CELL_NUM_PSD_PROFILES 6 // Number of supported PSD profiles @@ -433,37 +429,37 @@ typedef enum typedef enum { - UBX_CELL_HTTP_OP_CODE_SERVER_IP = 0, - UBX_CELL_HTTP_OP_CODE_SERVER_NAME, - UBX_CELL_HTTP_OP_CODE_USERNAME, - UBX_CELL_HTTP_OP_CODE_PASSWORD, - UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, - UBX_CELL_HTTP_OP_CODE_SERVER_PORT, - UBX_CELL_HTTP_OP_CODE_SECURE, - UBX_CELL_HTTP_OP_CODE_REQUEST_TIMEOUT, - UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS = 9 + UBX_CELL_HTTP_OP_CODE_SERVER_IP = 0, + UBX_CELL_HTTP_OP_CODE_SERVER_NAME, + UBX_CELL_HTTP_OP_CODE_USERNAME, + UBX_CELL_HTTP_OP_CODE_PASSWORD, + UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, + UBX_CELL_HTTP_OP_CODE_SERVER_PORT, + UBX_CELL_HTTP_OP_CODE_SECURE, + UBX_CELL_HTTP_OP_CODE_REQUEST_TIMEOUT, + UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS = 9 } UBX_CELL_http_op_codes_t; typedef enum { - UBX_CELL_HTTP_COMMAND_HEAD = 0, - UBX_CELL_HTTP_COMMAND_GET, - UBX_CELL_HTTP_COMMAND_DELETE, - UBX_CELL_HTTP_COMMAND_PUT, - UBX_CELL_HTTP_COMMAND_POST_FILE, - UBX_CELL_HTTP_COMMAND_POST_DATA, - UBX_CELL_HTTP_COMMAND_GET_FOTA = 100 + UBX_CELL_HTTP_COMMAND_HEAD = 0, + UBX_CELL_HTTP_COMMAND_GET, + UBX_CELL_HTTP_COMMAND_DELETE, + UBX_CELL_HTTP_COMMAND_PUT, + UBX_CELL_HTTP_COMMAND_POST_FILE, + UBX_CELL_HTTP_COMMAND_POST_DATA, + UBX_CELL_HTTP_COMMAND_GET_FOTA = 100 } UBX_CELL_http_commands_t; typedef enum { - UBX_CELL_HTTP_CONTENT_APPLICATION_X_WWW = 0, - UBX_CELL_HTTP_CONTENT_TEXT_PLAIN, - UBX_CELL_HTTP_CONTENT_APPLICATION_OCTET, - UBX_CELL_HTTP_CONTENT_MULTIPART_FORM, - UBX_CELL_HTTP_CONTENT_APPLICATION_JSON, - UBX_CELL_HTTP_CONTENT_APPLICATION_XML, - UBX_CELL_HTTP_CONTENT_USER_DEFINED + UBX_CELL_HTTP_CONTENT_APPLICATION_X_WWW = 0, + UBX_CELL_HTTP_CONTENT_TEXT_PLAIN, + UBX_CELL_HTTP_CONTENT_APPLICATION_OCTET, + UBX_CELL_HTTP_CONTENT_MULTIPART_FORM, + UBX_CELL_HTTP_CONTENT_APPLICATION_JSON, + UBX_CELL_HTTP_CONTENT_APPLICATION_XML, + UBX_CELL_HTTP_CONTENT_USER_DEFINED } UBX_CELL_http_content_types_t; typedef enum @@ -489,17 +485,17 @@ typedef enum typedef enum { - UBX_CELL_MQTT_COMMAND_INVALID = -1, - UBX_CELL_MQTT_COMMAND_LOGOUT = 0, - UBX_CELL_MQTT_COMMAND_LOGIN, - UBX_CELL_MQTT_COMMAND_PUBLISH, - UBX_CELL_MQTT_COMMAND_PUBLISHFILE, - UBX_CELL_MQTT_COMMAND_SUBSCRIBE, - UBX_CELL_MQTT_COMMAND_UNSUBSCRIBE, - UBX_CELL_MQTT_COMMAND_READ, - UBX_CELL_MQTT_COMMAND_RCVMSGFORMAT, - UBX_CELL_MQTT_COMMAND_PING, - UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, + UBX_CELL_MQTT_COMMAND_INVALID = -1, + UBX_CELL_MQTT_COMMAND_LOGOUT = 0, + UBX_CELL_MQTT_COMMAND_LOGIN, + UBX_CELL_MQTT_COMMAND_PUBLISH, + UBX_CELL_MQTT_COMMAND_PUBLISHFILE, + UBX_CELL_MQTT_COMMAND_SUBSCRIBE, + UBX_CELL_MQTT_COMMAND_UNSUBSCRIBE, + UBX_CELL_MQTT_COMMAND_READ, + UBX_CELL_MQTT_COMMAND_RCVMSGFORMAT, + UBX_CELL_MQTT_COMMAND_PING, + UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, } UBX_CELL_mqtt_command_opcode_t; constexpr uint16_t MAX_MQTT_HEX_MSG_LEN = 512; @@ -518,90 +514,90 @@ typedef enum typedef enum { - UBX_CELL_FTP_COMMAND_INVALID = -1, - UBX_CELL_FTP_COMMAND_LOGOUT = 0, - UBX_CELL_FTP_COMMAND_LOGIN, - UBX_CELL_FTP_COMMAND_DELETE_FILE, - UBX_CELL_FTP_COMMAND_RENAME_FILE, - UBX_CELL_FTP_COMMAND_GET_FILE, - UBX_CELL_FTP_COMMAND_PUT_FILE, - UBX_CELL_FTP_COMMAND_GET_FILE_DIRECT, - UBX_CELL_FTP_COMMAND_PUT_FILE_DIRECT, - UBX_CELL_FTP_COMMAND_CHANGE_DIR, - UBX_CELL_FTP_COMMAND_MKDIR = 10, - UBX_CELL_FTP_COMMAND_RMDIR, - UBX_CELL_FTP_COMMAND_DIR_INFO = 13, - UBX_CELL_FTP_COMMAND_LS, - UBX_CELL_FTP_COMMAND_GET_FOTA_FILE = 100 + UBX_CELL_FTP_COMMAND_INVALID = -1, + UBX_CELL_FTP_COMMAND_LOGOUT = 0, + UBX_CELL_FTP_COMMAND_LOGIN, + UBX_CELL_FTP_COMMAND_DELETE_FILE, + UBX_CELL_FTP_COMMAND_RENAME_FILE, + UBX_CELL_FTP_COMMAND_GET_FILE, + UBX_CELL_FTP_COMMAND_PUT_FILE, + UBX_CELL_FTP_COMMAND_GET_FILE_DIRECT, + UBX_CELL_FTP_COMMAND_PUT_FILE_DIRECT, + UBX_CELL_FTP_COMMAND_CHANGE_DIR, + UBX_CELL_FTP_COMMAND_MKDIR = 10, + UBX_CELL_FTP_COMMAND_RMDIR, + UBX_CELL_FTP_COMMAND_DIR_INFO = 13, + UBX_CELL_FTP_COMMAND_LS, + UBX_CELL_FTP_COMMAND_GET_FOTA_FILE = 100 } UBX_CELL_ftp_command_opcode_t; typedef enum { - UBX_CELL_PSD_CONFIG_PARAM_PROTOCOL = 0, - UBX_CELL_PSD_CONFIG_PARAM_APN, - //UBX_CELL_PSD_CONFIG_PARAM_USERNAME, // Not allowed on SARA-R5 - //UBX_CELL_PSD_CONFIG_PARAM_PASSWORD, // Not allowed on SARA-R5 - UBX_CELL_PSD_CONFIG_PARAM_DNS1 = 4, - UBX_CELL_PSD_CONFIG_PARAM_DNS2, - //UBX_CELL_PSD_CONFIG_PARAM_AUTHENTICATION, // Not allowed on SARA-R5 - //UBX_CELL_PSD_CONFIG_PARAM_IP_ADDRESS, // Not allowed on SARA-R5 - //UBX_CELL_PSD_CONFIG_PARAM_DATA_COMPRESSION, // Not allowed on SARA-R5 - //UBX_CELL_PSD_CONFIG_PARAM_HEADER_COMPRESSION, // Not allowed on SARA-R5 - UBX_CELL_PSD_CONFIG_PARAM_MAP_TO_CID = 100 + UBX_CELL_PSD_CONFIG_PARAM_PROTOCOL = 0, + UBX_CELL_PSD_CONFIG_PARAM_APN, + // UBX_CELL_PSD_CONFIG_PARAM_USERNAME, // Not allowed on SARA-R5 + // UBX_CELL_PSD_CONFIG_PARAM_PASSWORD, // Not allowed on SARA-R5 + UBX_CELL_PSD_CONFIG_PARAM_DNS1 = 4, + UBX_CELL_PSD_CONFIG_PARAM_DNS2, + // UBX_CELL_PSD_CONFIG_PARAM_AUTHENTICATION, // Not allowed on SARA-R5 + // UBX_CELL_PSD_CONFIG_PARAM_IP_ADDRESS, // Not allowed on SARA-R5 + // UBX_CELL_PSD_CONFIG_PARAM_DATA_COMPRESSION, // Not allowed on SARA-R5 + // UBX_CELL_PSD_CONFIG_PARAM_HEADER_COMPRESSION, // Not allowed on SARA-R5 + UBX_CELL_PSD_CONFIG_PARAM_MAP_TO_CID = 100 } UBX_CELL_pdp_configuration_parameter_t; typedef enum { - UBX_CELL_PSD_PROTOCOL_IPV4 = 0, - UBX_CELL_PSD_PROTOCOL_IPV6, - UBX_CELL_PSD_PROTOCOL_IPV4V6_V4_PREF, - UBX_CELL_PSD_PROTOCOL_IPV4V6_V6_PREF + UBX_CELL_PSD_PROTOCOL_IPV4 = 0, + UBX_CELL_PSD_PROTOCOL_IPV6, + UBX_CELL_PSD_PROTOCOL_IPV4V6_V4_PREF, + UBX_CELL_PSD_PROTOCOL_IPV4V6_V6_PREF } UBX_CELL_pdp_protocol_type_t; typedef enum { - UBX_CELL_PSD_ACTION_RESET = 0, - UBX_CELL_PSD_ACTION_STORE, - UBX_CELL_PSD_ACTION_LOAD, - UBX_CELL_PSD_ACTION_ACTIVATE, - UBX_CELL_PSD_ACTION_DEACTIVATE + UBX_CELL_PSD_ACTION_RESET = 0, + UBX_CELL_PSD_ACTION_STORE, + UBX_CELL_PSD_ACTION_LOAD, + UBX_CELL_PSD_ACTION_ACTIVATE, + UBX_CELL_PSD_ACTION_DEACTIVATE } UBX_CELL_pdp_actions_t; typedef enum { - UBX_CELL_SEC_PROFILE_PARAM_CERT_VAL_LEVEL = 0, - UBX_CELL_SEC_PROFILE_PARAM_TLS_VER, - UBX_CELL_SEC_PROFILE_PARAM_CYPHER_SUITE, - UBX_CELL_SEC_PROFILE_PARAM_ROOT_CA, - UBX_CELL_SEC_PROFILE_PARAM_HOSTNAME, - UBX_CELL_SEC_PROFILE_PARAM_CLIENT_CERT, - UBX_CELL_SEC_PROFILE_PARAM_CLIENT_KEY, - UBX_CELL_SEC_PROFILE_PARAM_CLIENT_KEY_PWD, - UBX_CELL_SEC_PROFILE_PARAM_PSK, - UBX_CELL_SEC_PROFILE_PARAM_PSK_IDENT, - UBX_CELL_SEC_PROFILE_PARAM_SNI, + UBX_CELL_SEC_PROFILE_PARAM_CERT_VAL_LEVEL = 0, + UBX_CELL_SEC_PROFILE_PARAM_TLS_VER, + UBX_CELL_SEC_PROFILE_PARAM_CYPHER_SUITE, + UBX_CELL_SEC_PROFILE_PARAM_ROOT_CA, + UBX_CELL_SEC_PROFILE_PARAM_HOSTNAME, + UBX_CELL_SEC_PROFILE_PARAM_CLIENT_CERT, + UBX_CELL_SEC_PROFILE_PARAM_CLIENT_KEY, + UBX_CELL_SEC_PROFILE_PARAM_CLIENT_KEY_PWD, + UBX_CELL_SEC_PROFILE_PARAM_PSK, + UBX_CELL_SEC_PROFILE_PARAM_PSK_IDENT, + UBX_CELL_SEC_PROFILE_PARAM_SNI, } UBX_CELL_sec_profile_parameter_t; typedef enum { - UBX_CELL_SEC_PROFILE_CERTVAL_OPCODE_NO = 0, - UBX_CELL_SEC_PROFILE_CERTVAL_OPCODE_YESNOURL, - UBX_CELL_SEC_PROFILE_CERVTAL_OPCODE_YESURL, - UBX_CELL_SEC_PROFILE_CERTVAL_OPCODE_YESURLDATE, + UBX_CELL_SEC_PROFILE_CERTVAL_OPCODE_NO = 0, + UBX_CELL_SEC_PROFILE_CERTVAL_OPCODE_YESNOURL, + UBX_CELL_SEC_PROFILE_CERVTAL_OPCODE_YESURL, + UBX_CELL_SEC_PROFILE_CERTVAL_OPCODE_YESURLDATE, } UBX_CELL_sec_profile_certval_op_code_t; typedef enum { - UBX_CELL_SEC_PROFILE_TLS_OPCODE_ANYVER = 0, - UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_0, - UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_1, - UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_2, - UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_3, + UBX_CELL_SEC_PROFILE_TLS_OPCODE_ANYVER = 0, + UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_0, + UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_1, + UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_2, + UBX_CELL_SEC_PROFILE_TLS_OPCODE_VER1_3, } UBX_CELL_sec_profile_tls_op_code_t; typedef enum { - UBX_CELL_SEC_PROFILE_SUITE_OPCODE_PROPOSEDDEFAULT = 0, + UBX_CELL_SEC_PROFILE_SUITE_OPCODE_PROPOSEDDEFAULT = 0, } UBX_CELL_sec_profile_suite_op_code_t; typedef enum @@ -619,515 +615,580 @@ typedef enum typedef enum { - MINIMUM_FUNCTIONALITY = 0, // (disable both transmit and receive RF circuits by deactivating both CS and PS services) - FULL_FUNCTIONALITY = 1, - AIRPLANE_MODE = 4, - SIM_TOOLKIT_ENABLE_DEDICATED = 6, - SIM_TOOLKIT_DISABLE_DEDICATED = 7, - SIM_TOOLKIT_ENABLE_RAW = 9, - FAST_SAFE_POWER_OFF = 10, - //SILENT_RESET_WITHOUT_SIM = 15, // Not supported on SARA-R5 - SILENT_RESET_WITH_SIM = 16 - //MINIMUM_FUNCTIONALITY = 19, // Not supported on SARA-R5 - //DEEP_LOW_POWER_STATE = 127 // Not supported on SARA-R5 + MINIMUM_FUNCTIONALITY = + 0, // (disable both transmit and receive RF circuits by deactivating both CS and PS services) + FULL_FUNCTIONALITY = 1, + AIRPLANE_MODE = 4, + SIM_TOOLKIT_ENABLE_DEDICATED = 6, + SIM_TOOLKIT_DISABLE_DEDICATED = 7, + SIM_TOOLKIT_ENABLE_RAW = 9, + FAST_SAFE_POWER_OFF = 10, + // SILENT_RESET_WITHOUT_SIM = 15, // Not supported on SARA-R5 + SILENT_RESET_WITH_SIM = 16 + // MINIMUM_FUNCTIONALITY = 19, // Not supported on SARA-R5 + // DEEP_LOW_POWER_STATE = 127 // Not supported on SARA-R5 } UBX_CELL_functionality_t; class UBX_CELL : public Print { -public: - // Constructor - // The library will use the powerPin and resetPin (if provided) to power the module off/on and perform an emergency reset - // maxInitTries sets the maximum number of initialization attempts. .init is called by .begin. - UBX_CELL(int powerPin = UBX_CELL_POWER_PIN, int resetPin = UBX_CELL_RESET_PIN, uint8_t maxInitTries = 9); - - ~UBX_CELL(); - // Begin -- initialize module and ensure it's connected + public: + // Constructor + // The library will use the powerPin and resetPin (if provided) to power the module off/on and perform an emergency + // reset maxInitTries sets the maximum number of initialization attempts. .init is called by .begin. + UBX_CELL(int powerPin = UBX_CELL_POWER_PIN, int resetPin = UBX_CELL_RESET_PIN, uint8_t maxInitTries = 9); + + ~UBX_CELL(); + // Begin -- initialize module and ensure it's connected #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - bool begin(SoftwareSerial &softSerial, unsigned long baud = UBX_CELL_DEFAULT_BAUD_RATE); + bool begin(SoftwareSerial &softSerial, unsigned long baud = UBX_CELL_DEFAULT_BAUD_RATE); #endif - bool begin(HardwareSerial &hardSerial, unsigned long baud = UBX_CELL_DEFAULT_BAUD_RATE); - - // Debug prints - void enableDebugging(Print &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. - void enableAtDebugging(Print &debugPort = Serial); //Turn on AT debug printing. If user doesn't specify then Serial will be used. - - // Invert the polarity of the power pin - if required - // Normally the SARA's power pin is pulled low and released to toggle the power - // But the Asset Tracker needs this to be pulled high and released instead - void invertPowerPin(bool invert = false); - - UBX_CELL_error_t modulePowerOff(void); // Graceful disconnect and shutdown using +CPWROFF. - void modulePowerOn(void); // Requires access to the PWR_ON pin - - // Loop polling and polling setup - process URC's etc. from the module - - // This function was originally written by Matthew Menze for the LTE Shield (SARA-R4) library - // See: https://github.com/sparkfun/SparkFun_LTE_Shield_Arduino_Library/pull/8 - // It does the same job as ::poll but also processes any 'old' data stored in the backlog first - // It also has a built-in timeout - which ::poll does not - // Use this - it is way better than ::poll. Thank you Matthew! - bool bufferedPoll(void); - - // This is the original poll function. - // It is 'blocking' - it does not return when serial data is available until it receives a `\n`. - // ::bufferedPoll is the new improved version. It processes any data in the backlog and includes a timeout. - // Retained for backward-compatibility and just in case you do want to (temporarily) ignore any data in the backlog - bool poll(void); - - // Callbacks (called during polling) - void setSocketListenCallback(void (*socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, unsigned int)); // listen Socket, local IP Address, listen Port, socket, remote IP Address, port - // This is the original read socket callback - called when a +UUSORD or +UUSORF URC is received - // It works - and handles binary data correctly - but the remote IP Address and Port are lost for UDP connections - // setSocketReadCallbackPlus is preferred! - void setSocketReadCallback(void (*socketReadCallback)(int, String)); // socket, read data - void setSocketReadCallbackPlus(void (*socketReadCallbackPlus)(int, const char *, int, IPAddress, int)); // socket, read data, length, remoteAddress, remotePort - void setSocketCloseCallback(void (*socketCloseCallback)(int)); // socket - void setGpsReadCallback(void (*gpsRequestCallback)(ClockData time, - PositionData gps, SpeedData spd, unsigned long uncertainty)); - void setSIMstateReportCallback(void (*simStateRequestCallback)(UBX_CELL_sim_states_t state)); - void setPSDActionCallback(void (*psdActionRequestCallback)(int result, IPAddress ip)); - void setPingCallback(void (*pingRequestCallback)(int retry, int p_size, String remote_hostname, IPAddress ip, int ttl, long rtt)); - void setHTTPCommandCallback(void (*httpCommandRequestCallback)(int profile, int command, int result)); - void setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int command, int result)); - void setFTPCommandCallback(void (*ftpCommandRequestCallback)(int command, int result)); - - UBX_CELL_error_t setRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, - unsigned int lac, unsigned int ci, int Act)); - UBX_CELL_error_t setEpsRegistrationCallback(void (*epsRegistrationCallback)(UBX_CELL_registration_status_t status, - unsigned int tac, unsigned int ci, int Act)); - - // Direct write/print to cell serial port - virtual size_t write(uint8_t c); - virtual size_t write(const char *str); - virtual size_t write(const char *buffer, size_t size); - - // General AT Commands - UBX_CELL_error_t at(void); - UBX_CELL_error_t enableEcho(bool enable = true); - String getManufacturerID(void); - String getModelID(void); - String getFirmwareVersion(void); - String getSerialNo(void); - String getIMEI(void); - String getIMSI(void); - String getCCID(void); - String getSubscriberNo(void); - String getCapabilities(void); - - // Control and status AT commands - UBX_CELL_error_t reset(void); - String clock(void); - // TODO: Return a clock struct - UBX_CELL_error_t clock(uint8_t *y, uint8_t *mo, uint8_t *d, - uint8_t *h, uint8_t *min, uint8_t *s, int8_t *tz); // TZ can be +/- and is in increments of 15 minutes. -28 == 7 hours behind UTC/GMT - UBX_CELL_error_t setClock(String theTime); - UBX_CELL_error_t setClock(uint8_t y, uint8_t mo, uint8_t d, - uint8_t h, uint8_t min, uint8_t s, int8_t tz); // TZ can be +/- and is in increments of 15 minutes. -28 == 7 hours behind UTC/GMT - void autoTimeZoneForBegin(bool enable = true); // Call autoTimeZoneForBegin(false) _before_ .begin if you want to disable the automatic time zone - UBX_CELL_error_t autoTimeZone(bool enable); // Enable/disable automatic time zone adjustment - - // Network service AT commands - int8_t rssi(void); // Receive signal strength - UBX_CELL_error_t getExtSignalQuality(signal_quality& signal_quality); - - UBX_CELL_registration_status_t registration(bool eps = true); - bool setNetworkProfile(mobile_network_operator_t mno, bool autoReset = false, bool urcNotification = false); - mobile_network_operator_t getNetworkProfile(void); - typedef enum - { - PDP_TYPE_INVALID = -1, - PDP_TYPE_IP = 0, - PDP_TYPE_NONIP = 1, - PDP_TYPE_IPV4V6 = 2, - PDP_TYPE_IPV6 = 3 - } UBX_CELL_pdp_type; - UBX_CELL_error_t setAPN(String apn, uint8_t cid = 1, UBX_CELL_pdp_type pdpType = PDP_TYPE_IP); // Set the Access Point Name - UBX_CELL_error_t getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_pdp_type* pdpType = nullptr); // Return the apn and IP address for the chosen context identifier - - UBX_CELL_error_t getSimStatus(String* code); - UBX_CELL_error_t setSimPin(String pin); - - // SIM - // Status report Mode: - // Bit States reported - // 0 Reports the (U)SIM initialization status ('s from 0 to 6 may be reported) - // 1 Reports the (U)SIM phonebook initialization status ('s from 7 to 8 may be reported) - // 2 Reports the (U)SIM toolkit REFRESH proactive command execution result ('s from 9 to 13 may be reported) - // Note: For the SARA-R5: =7, 8, 9, 10, 11, 12 and 13 are not reported. - UBX_CELL_error_t setSIMstateReportingMode(int mode); - UBX_CELL_error_t getSIMstateReportingMode(int *mode); - - typedef enum - { - L2P_DEFAULT, - L2P_PPP, - L2P_M_HEX, - L2P_M_RAW_IP, - L2P_M_OPT_PPP - } UBX_CELL_l2p_t; - UBX_CELL_error_t enterPPP(uint8_t cid = 1, char dialing_type_char = 0, - unsigned long dialNumber = 99, UBX_CELL_l2p_t l2p = L2P_DEFAULT); - - uint8_t getOperators(struct operator_stats *op, int maxOps = 3); - UBX_CELL_error_t registerOperator(struct operator_stats oper); - UBX_CELL_error_t automaticOperatorSelection(); - UBX_CELL_error_t getOperator(String *oper); - UBX_CELL_error_t deregisterOperator(void); - - // SMS -- Short Messages Service - UBX_CELL_error_t setSMSMessageFormat(UBX_CELL_message_format_t textMode = UBX_CELL_MESSAGE_FORMAT_TEXT); - UBX_CELL_error_t sendSMS(String number, String message); - UBX_CELL_error_t getPreferredMessageStorage(int *used, int *total, String memory = "ME"); - UBX_CELL_error_t readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message); - UBX_CELL_error_t deleteSMSmessage(int location, int deleteFlag = 0); // Default to deleting the single message at the specified location - UBX_CELL_error_t deleteReadSMSmessages(void) { return (deleteSMSmessage( 1, 1 )); }; // Delete all the read messages from preferred storage - UBX_CELL_error_t deleteReadSentSMSmessages(void) { return (deleteSMSmessage( 1, 2 )); }; // Delete the read and sent messages from preferred storage - UBX_CELL_error_t deleteReadSentUnsentSMSmessages(void) { return (deleteSMSmessage( 1, 3 )); }; // Delete the read, sent and unsent messages from preferred storage - UBX_CELL_error_t deleteAllSMSmessages(void) { return (deleteSMSmessage( 1, 4 )); }; // Delete the read, sent, unsent and unread messages from preferred storage - - // V24 Control and V25ter (UART interface) AT commands - UBX_CELL_error_t setBaud(unsigned long baud); - UBX_CELL_error_t setFlowControl(UBX_CELL_flow_control_t value = UBX_CELL_ENABLE_FLOW_CONTROL); - - // GPIO - // GPIO pin map - typedef enum - { - GPIO1 = 16, - GPIO2 = 23, - GPIO3 = 24, - GPIO4 = 25, - GPIO5 = 42, - GPIO6 = 19 - } UBX_CELL_gpio_t; - // GPIO pin modes - typedef enum - { - GPIO_MODE_INVALID = -1, - GPIO_OUTPUT = 0, - GPIO_INPUT, - NETWORK_STATUS, - GNSS_SUPPLY_ENABLE, - GNSS_DATA_READY, - GNSS_RTC_SHARING, - JAMMING_DETECTION, - SIM_CARD_DETECTION, - HEADSET_DETECTION, - GSM_TX_BURST_INDICATION, - MODULE_STATUS_INDICATION, - MODULE_OPERATING_MODE_INDICATION, - I2S_DIGITAL_AUDIO_INTERFACE, - SPI_SERIAL_INTERFACE, - MASTER_CLOCK_GENRATION, - UART_INTERFACE, - WIFI_ENABLE, - RING_INDICATION = 18, - LAST_GASP_ENABLE, - EXTERNAL_GNSS_ANTENNA, - TIME_PULSE_GNSS, - TIME_PULSE_OUTPUT, - TIMESTAMP, - FAST_POWER_OFF, - LWM2M_PULSE, - HARDWARE_FLOW_CONTROL, - ANTENNA_TUNING, - EXT_GNSS_TIME_PULSE, - EXT_GNSS_TIMESTAMP, - DTR_MODE, - KHZ_32768_OUT = 32, - PAD_DISABLED = 255 - } UBX_CELL_gpio_mode_t; - UBX_CELL_error_t setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_t mode, int value = 0); - UBX_CELL_gpio_mode_t getGpioMode(UBX_CELL_gpio_t gpio); - - // IP Transport Layer - int socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int localPort = 0); // Open a socket. Returns the socket number. - UBX_CELL_error_t socketClose(int socket, unsigned long timeout = UBX_CELL_2_MIN_TIMEOUT); // Close the socket - UBX_CELL_error_t socketConnect(int socket, const char *address, unsigned int port); // TCP - connect to a remote IP Address using the specified port. Not required for UDP sockets. - UBX_CELL_error_t socketConnect(int socket, IPAddress address, unsigned int port); - // Write data to the specified socket. Works with binary data - but you must specify the data length when using the const char * version - // Works with both TCP and UDP sockets - but socketWriteUDP is preferred for UDP and doesn't require socketOpen to be called first - UBX_CELL_error_t socketWrite(int socket, const char *str, int len = -1); - UBX_CELL_error_t socketWrite(int socket, String str); // OK for binary data - // Write UDP data to the specified IP Address and port. - // Works with binary data - but you must specify the data length when using the const char * versions - // If you let len default to -1, strlen is used to calculate the data length - and will be incorrect for binary data - UBX_CELL_error_t socketWriteUDP(int socket, const char *address, int port, const char *str, int len = -1); - UBX_CELL_error_t socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len = -1); - UBX_CELL_error_t socketWriteUDP(int socket, String address, int port, String str); - // Read data from the specified socket - // Call socketReadAvailable first to determine how much data is available - or use the callbacks (triggered by URC's) - // Works for both TCP and UDP - but socketReadUDP is preferred for UDP as it records the remote IP Address and port - // bytesRead - if provided - will be updated with the number of bytes actually read. This could be less than length! - UBX_CELL_error_t socketRead(int socket, int length, char *readDest, int *bytesRead = nullptr); - // Return the number of bytes available (waiting to be read) on the chosen socket - // Uses +USORD. Valid for both TCP and UDP sockets - but socketReadAvailableUDP is preferred for UDP - UBX_CELL_error_t socketReadAvailable(int socket, int *length); - // Read data from the specified UDP port - // Call socketReadAvailableUDP first to determine how much data is available - or use the callbacks (triggered by URC's) - // The remote IP Address and port are returned via *remoteIPAddress and *remotePort (if not nullptr) - // bytesRead - if provided - will be updated with the number of bytes actually read. This could be less than length! - UBX_CELL_error_t socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress = nullptr, int *remotePort = nullptr, int *bytesRead = nullptr); - // Return the number of bytes available (waiting to be read) on the chosen UDP socket - UBX_CELL_error_t socketReadAvailableUDP(int socket, int *length); - // Start listening for a connection on the specified port. The connection is reported via the socket listen callback - UBX_CELL_error_t socketListen(int socket, unsigned int port); - // Place the socket into direct link mode - making it easy to transfer binary data. Wait two seconds and then send +++ to exit the link. - UBX_CELL_error_t socketDirectLinkMode(int socket); - // Configure when direct link data is sent - UBX_CELL_error_t socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger); - UBX_CELL_error_t socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger); - UBX_CELL_error_t socketDirectLinkCharacterTrigger(int socket, int characterTrigger); - UBX_CELL_error_t socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer); - // Use +USOCTL (Socket control) to query the socket parameters - UBX_CELL_error_t querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol); - UBX_CELL_error_t querySocketLastError(int socket, int *error); - UBX_CELL_error_t querySocketTotalBytesSent(int socket, uint32_t *total); - UBX_CELL_error_t querySocketTotalBytesReceived(int socket, uint32_t *total); - UBX_CELL_error_t querySocketRemoteIPAddress(int socket, IPAddress *address, int *port); - UBX_CELL_error_t querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status); - UBX_CELL_error_t querySocketOutUnackData(int socket, uint32_t *total); - // Return the most recent socket error - int socketGetLastError(); - // Return the remote IP Address from the most recent socket listen indication (socket connection) - // Use the socket listen callback to get the full address and port information - IPAddress lastRemoteIP(void); - - // Ping - UBX_CELL_error_t ping(String remote_host, int retry = 4, int p_size = 32, unsigned long timeout = 5000, int ttl = 32); - - // HTTP - UBX_CELL_error_t resetHTTPprofile(int profile); // Reset the HTTP profile. Note: The configured HTTP profile parameters are not saved in the non volatile memory. - UBX_CELL_error_t setHTTPserverIPaddress(int profile, IPAddress address); // Default: empty string - UBX_CELL_error_t setHTTPserverName(int profile, String server); // Default: empty string - UBX_CELL_error_t setHTTPusername(int profile, String username); // Default: empty string - UBX_CELL_error_t setHTTPpassword(int profile, String password); // Default: empty string - UBX_CELL_error_t setHTTPauthentication(int profile, bool authenticate); // Default: no authentication - UBX_CELL_error_t setHTTPserverPort(int profile, int port); // Default: 80 - UBX_CELL_error_t setHTTPcustomHeader(int profile, String header); // Default: format 0:Content-Type:application/json" - UBX_CELL_error_t setHTTPsecure(int profile, bool secure, int secprofile = -1); // Default: disabled (HTTP on port 80). Set to true for HTTPS on port 443 - // TO DO: Add custom request headers - UBX_CELL_error_t getHTTPprotocolError(int profile, int *error_class, int *error_code); // Read the most recent HTTP protocol error for this profile - UBX_CELL_error_t sendHTTPGET(int profile, String path, String responseFilename); - UBX_CELL_error_t sendHTTPPOSTdata(int profile, String path, String responseFilename, String data, UBX_CELL_http_content_types_t httpContentType); - UBX_CELL_error_t sendHTTPPOSTfile(int profile, String path, String responseFilename, String requestFile, UBX_CELL_http_content_types_t httpContentType); - - UBX_CELL_error_t nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter); - UBX_CELL_error_t setMQTTclientId(const String& clientId); - UBX_CELL_error_t setMQTTserver(const String& serverName, int port); - UBX_CELL_error_t setMQTTcredentials(const String& userName, const String& pwd); - UBX_CELL_error_t setMQTTsecure(bool secure, int secprofile = -1); - UBX_CELL_error_t connectMQTT(void); - UBX_CELL_error_t disconnectMQTT(void); - UBX_CELL_error_t subscribeMQTTtopic(int max_Qos, const String& topic); - UBX_CELL_error_t unsubscribeMQTTtopic(const String& topic); - UBX_CELL_error_t readMQTT(int* pQos, String* pTopic, uint8_t *readDest, int readLength, int *bytesRead); - UBX_CELL_error_t mqttPublishTextMsg(const String& topic, const char * const msg, uint8_t qos = 0, bool retain = false); - UBX_CELL_error_t mqttPublishBinaryMsg(const String& topic, const char * const msg, size_t msg_len, uint8_t qos = 0, bool retain = false); - UBX_CELL_error_t mqttPublishFromFile(const String& topic, const String& filename, uint8_t qos = 0, bool retain = false); - UBX_CELL_error_t getMQTTprotocolError(int *error_code, int *error_code2); - - // FTP - UBX_CELL_error_t setFTPserver(const String& serverName); - UBX_CELL_error_t setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, const unsigned int data_linger); - UBX_CELL_error_t setFTPcredentials(const String& userName, const String& pwd); - UBX_CELL_error_t connectFTP(void); - UBX_CELL_error_t disconnectFTP(void); - UBX_CELL_error_t ftpGetFile(const String& filename); - UBX_CELL_error_t getFTPprotocolError(int *error_code, int *error_code2); - - // Configure security profiles - UBX_CELL_error_t resetSecurityProfile(int secprofile); - UBX_CELL_error_t configSecurityProfileString(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, String value); - UBX_CELL_error_t configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value); - UBX_CELL_error_t setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, UBX_CELL_sec_manager_parameter_t parameter, String name, String data); - - UBX_CELL_error_t activatePDPcontext(bool status, int cid = -1); // Activates or deactivates the specified PDP context. Default to all (cid = -1) - - // GPS - typedef enum - { - GNSS_SYSTEM_GPS = 1, - GNSS_SYSTEM_SBAS = 2, - GNSS_SYSTEM_GALILEO = 4, - GNSS_SYSTEM_BEIDOU = 8, - GNSS_SYSTEM_IMES = 16, - GNSS_SYSTEM_QZSS = 32, - GNSS_SYSTEM_GLONASS = 64 - } gnss_system_t; - typedef enum - { - GNSS_AIDING_MODE_NONE = 0, - GNSS_AIDING_MODE_AUTOMATIC = 1, - GNSS_AIDING_MODE_ASSISTNOW_OFFLINE = 2, - GNSS_AIDING_MODE_ASSISTNOW_ONLINE = 4, - GNSS_AIDING_MODE_ASSISTNOW_AUTONOMOUS = 8 - } gnss_aiding_mode_t; - bool isGPSon(void); - UBX_CELL_error_t gpsPower(bool enable = true, - gnss_system_t gnss_sys = GNSS_SYSTEM_GPS, - gnss_aiding_mode_t gnss_aiding = GNSS_AIDING_MODE_AUTOMATIC); - //UBX_CELL_error_t gpsEnableClock(bool enable = true); - //UBX_CELL_error_t gpsGetClock(struct ClockData *clock); - //UBX_CELL_error_t gpsEnableFix(bool enable = true); - //UBX_CELL_error_t gpsGetFix(float *lat, float *lon, unsigned int *alt, uint8_t *quality, uint8_t *sat); - //UBX_CELL_error_t gpsGetFix(struct PositionData *pos); - //UBX_CELL_error_t gpsEnablePos(bool enable = true); - //UBX_CELL_error_t gpsGetPos(struct PositionData *pos); - //UBX_CELL_error_t gpsEnableSat(bool enable = true); - //UBX_CELL_error_t gpsGetSat(uint8_t *sats); - UBX_CELL_error_t gpsEnableRmc(bool enable = true); // Enable GPRMC messages - UBX_CELL_error_t gpsGetRmc(struct PositionData *pos, struct SpeedData *speed, struct ClockData *clk, bool *valid); //Parse a GPRMC message - //UBX_CELL_error_t gpsEnableSpeed(bool enable = true); - //UBX_CELL_error_t gpsGetSpeed(struct SpeedData *speed); - - UBX_CELL_error_t gpsRequest(unsigned int timeout, uint32_t accuracy, bool detailed = true, unsigned int sensor = 3); - - //CellLocate - UBX_CELL_error_t gpsAidingServerConf(const char *primaryServer, const char *secondaryServer, const char *authToken, - unsigned int days = 14, unsigned int period = 4, unsigned int resolution = 1, - unsigned int gnssTypes = 65, unsigned int mode = 0, unsigned int dataType = 15); - - // File system - // TO DO: add full support for file tags. Default tag to USER - UBX_CELL_error_t getFileContents(String filename, String *contents); // OK for text files. But will fail with binary files (containing \0) on some platforms. - UBX_CELL_error_t getFileContents(String filename, char *contents); // OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize. - UBX_CELL_error_t getFileBlock(const String& filename, char* buffer, size_t offset, size_t length, size_t& bytes_read); // OK for binary files. Make sure buffer can hold the requested block size. - - // Append data to a file, delete file first to not appends the data. - UBX_CELL_error_t appendFileContents(String filename, String str); - UBX_CELL_error_t appendFileContents(String filename, const char *str, int len); - UBX_CELL_error_t getFileSize(String filename, int *size); - UBX_CELL_error_t deleteFile(String filename); - - // Functionality - UBX_CELL_error_t functionality(UBX_CELL_functionality_t function = FULL_FUNCTIONALITY); - - // Send a custom command with an expected (potentially partial) response, store entire response - UBX_CELL_error_t sendCustomCommandWithResponse(const char *command, const char *expectedResponse, - char *responseDest, unsigned long commandTimeout = UBX_CELL_STANDARD_RESPONSE_TIMEOUT, bool at = true); - - // Send command with an expected (potentially partial) response, store entire response - UBX_CELL_error_t sendCommandWithResponse(const char *command, const char *expectedResponse, - char *responseDest, unsigned long commandTimeout, int destSize = minimumResponseAllocation, bool at = true); - - char *ubx_cell_calloc_char(size_t num); - - // Add a URC handler - void addURCHandler(const char* urcString, UBX_CELL_urc_handler_t urcHandler); - -protected: - HardwareSerial *_hardSerial; + bool begin(HardwareSerial &hardSerial, unsigned long baud = UBX_CELL_DEFAULT_BAUD_RATE); + + // Debug prints + void enableDebugging( + Print &debugPort = Serial); // Turn on debug printing. If user doesn't specify then Serial will be used. + void enableAtDebugging( + Print &debugPort = Serial); // Turn on AT debug printing. If user doesn't specify then Serial will be used. + + // Invert the polarity of the power pin - if required + // Normally the SARA's power pin is pulled low and released to toggle the power + // But the Asset Tracker needs this to be pulled high and released instead + void invertPowerPin(bool invert = false); + + UBX_CELL_error_t modulePowerOff(void); // Graceful disconnect and shutdown using +CPWROFF. + void modulePowerOn(void); // Requires access to the PWR_ON pin + + // Loop polling and polling setup - process URC's etc. from the module + + // This function was originally written by Matthew Menze for the LTE Shield (SARA-R4) library + // See: https://github.com/sparkfun/SparkFun_LTE_Shield_Arduino_Library/pull/8 + // It does the same job as ::poll but also processes any 'old' data stored in the backlog first + // It also has a built-in timeout - which ::poll does not + // Use this - it is way better than ::poll. Thank you Matthew! + bool bufferedPoll(void); + + // This is the original poll function. + // It is 'blocking' - it does not return when serial data is available until it receives a `\n`. + // ::bufferedPoll is the new improved version. It processes any data in the backlog and includes a timeout. + // Retained for backward-compatibility and just in case you do want to (temporarily) ignore any data in the backlog + bool poll(void); + + // Callbacks (called during polling) + void setSocketListenCallback(void (*socketListenCallback)( + int, IPAddress, unsigned int, int, IPAddress, + unsigned int)); // listen Socket, local IP Address, listen Port, socket, remote IP Address, port + // This is the original read socket callback - called when a +UUSORD or +UUSORF URC is received + // It works - and handles binary data correctly - but the remote IP Address and Port are lost for UDP connections + // setSocketReadCallbackPlus is preferred! + void setSocketReadCallback(void (*socketReadCallback)(int, String)); // socket, read data + void setSocketReadCallbackPlus(void (*socketReadCallbackPlus)( + int, const char *, int, IPAddress, int)); // socket, read data, length, remoteAddress, remotePort + void setSocketCloseCallback(void (*socketCloseCallback)(int)); // socket + void setGpsReadCallback(void (*gpsRequestCallback)(ClockData time, PositionData gps, SpeedData spd, + unsigned long uncertainty)); + void setSIMstateReportCallback(void (*simStateRequestCallback)(UBX_CELL_sim_states_t state)); + void setPSDActionCallback(void (*psdActionRequestCallback)(int result, IPAddress ip)); + void setPingCallback(void (*pingRequestCallback)(int retry, int p_size, String remote_hostname, IPAddress ip, + int ttl, long rtt)); + void setHTTPCommandCallback(void (*httpCommandRequestCallback)(int profile, int command, int result)); + void setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int command, int result)); + void setFTPCommandCallback(void (*ftpCommandRequestCallback)(int command, int result)); + + UBX_CELL_error_t setRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, + unsigned int lac, unsigned int ci, int Act)); + UBX_CELL_error_t setEpsRegistrationCallback(void (*epsRegistrationCallback)(UBX_CELL_registration_status_t status, + unsigned int tac, unsigned int ci, + int Act)); + + // Direct write/print to cell serial port + virtual size_t write(uint8_t c); + virtual size_t write(const char *str); + virtual size_t write(const char *buffer, size_t size); + + // General AT Commands + UBX_CELL_error_t at(void); + UBX_CELL_error_t enableEcho(bool enable = true); + String getManufacturerID(void); + String getModelID(void); + String getFirmwareVersion(void); + String getSerialNo(void); + String getIMEI(void); + String getIMSI(void); + String getCCID(void); + String getSubscriberNo(void); + String getCapabilities(void); + + // Control and status AT commands + UBX_CELL_error_t reset(void); + String clock(void); + // TODO: Return a clock struct + UBX_CELL_error_t clock( + uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s, + int8_t *tz); // TZ can be +/- and is in increments of 15 minutes. -28 == 7 hours behind UTC/GMT + UBX_CELL_error_t setClock(String theTime); + UBX_CELL_error_t setClock( + uint8_t y, uint8_t mo, uint8_t d, uint8_t h, uint8_t min, uint8_t s, + int8_t tz); // TZ can be +/- and is in increments of 15 minutes. -28 == 7 hours behind UTC/GMT + void autoTimeZoneForBegin(bool enable = true); // Call autoTimeZoneForBegin(false) _before_ .begin if you want to + // disable the automatic time zone + UBX_CELL_error_t autoTimeZone(bool enable); // Enable/disable automatic time zone adjustment + + // Network service AT commands + int8_t rssi(void); // Receive signal strength + UBX_CELL_error_t getExtSignalQuality(signal_quality &signal_quality); + + UBX_CELL_registration_status_t registration(bool eps = true); + bool setNetworkProfile(mobile_network_operator_t mno, bool autoReset = false, bool urcNotification = false); + mobile_network_operator_t getNetworkProfile(void); + typedef enum + { + PDP_TYPE_INVALID = -1, + PDP_TYPE_IP = 0, + PDP_TYPE_NONIP = 1, + PDP_TYPE_IPV4V6 = 2, + PDP_TYPE_IPV6 = 3 + } UBX_CELL_pdp_type; + UBX_CELL_error_t setAPN(String apn, uint8_t cid = 1, + UBX_CELL_pdp_type pdpType = PDP_TYPE_IP); // Set the Access Point Name + UBX_CELL_error_t getAPN( + int cid, String *apn, IPAddress *ip, + UBX_CELL_pdp_type *pdpType = nullptr); // Return the apn and IP address for the chosen context identifier + + UBX_CELL_error_t getSimStatus(String *code); + UBX_CELL_error_t setSimPin(String pin); + + // SIM + // Status report Mode: + // Bit States reported + // 0 Reports the (U)SIM initialization status ('s from 0 to 6 may be reported) + // 1 Reports the (U)SIM phonebook initialization status ('s from 7 to 8 may be reported) + // 2 Reports the (U)SIM toolkit REFRESH proactive command execution result ('s from 9 to 13 may be + // reported) Note: For the SARA-R5: =7, 8, 9, 10, 11, 12 and 13 are not reported. + UBX_CELL_error_t setSIMstateReportingMode(int mode); + UBX_CELL_error_t getSIMstateReportingMode(int *mode); + + typedef enum + { + L2P_DEFAULT, + L2P_PPP, + L2P_M_HEX, + L2P_M_RAW_IP, + L2P_M_OPT_PPP + } UBX_CELL_l2p_t; + UBX_CELL_error_t enterPPP(uint8_t cid = 1, char dialing_type_char = 0, unsigned long dialNumber = 99, + UBX_CELL_l2p_t l2p = L2P_DEFAULT); + + uint8_t getOperators(struct operator_stats *op, int maxOps = 3); + UBX_CELL_error_t registerOperator(struct operator_stats oper); + UBX_CELL_error_t automaticOperatorSelection(); + UBX_CELL_error_t getOperator(String *oper); + UBX_CELL_error_t deregisterOperator(void); + + // SMS -- Short Messages Service + UBX_CELL_error_t setSMSMessageFormat(UBX_CELL_message_format_t textMode = UBX_CELL_MESSAGE_FORMAT_TEXT); + UBX_CELL_error_t sendSMS(String number, String message); + UBX_CELL_error_t getPreferredMessageStorage(int *used, int *total, String memory = "ME"); + UBX_CELL_error_t readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message); + UBX_CELL_error_t deleteSMSmessage( + int location, int deleteFlag = 0); // Default to deleting the single message at the specified location + UBX_CELL_error_t deleteReadSMSmessages(void) + { + return (deleteSMSmessage(1, 1)); + }; // Delete all the read messages from preferred storage + UBX_CELL_error_t deleteReadSentSMSmessages(void) + { + return (deleteSMSmessage(1, 2)); + }; // Delete the read and sent messages from preferred storage + UBX_CELL_error_t deleteReadSentUnsentSMSmessages(void) + { + return (deleteSMSmessage(1, 3)); + }; // Delete the read, sent and unsent messages from preferred storage + UBX_CELL_error_t deleteAllSMSmessages(void) + { + return (deleteSMSmessage(1, 4)); + }; // Delete the read, sent, unsent and unread messages from preferred storage + + // V24 Control and V25ter (UART interface) AT commands + UBX_CELL_error_t setBaud(unsigned long baud); + UBX_CELL_error_t setFlowControl(UBX_CELL_flow_control_t value = UBX_CELL_ENABLE_FLOW_CONTROL); + + // GPIO + // GPIO pin map + typedef enum + { + GPIO1 = 16, + GPIO2 = 23, + GPIO3 = 24, + GPIO4 = 25, + GPIO5 = 42, + GPIO6 = 19 + } UBX_CELL_gpio_t; + // GPIO pin modes + typedef enum + { + GPIO_MODE_INVALID = -1, + GPIO_OUTPUT = 0, + GPIO_INPUT, + NETWORK_STATUS, + GNSS_SUPPLY_ENABLE, + GNSS_DATA_READY, + GNSS_RTC_SHARING, + JAMMING_DETECTION, + SIM_CARD_DETECTION, + HEADSET_DETECTION, + GSM_TX_BURST_INDICATION, + MODULE_STATUS_INDICATION, + MODULE_OPERATING_MODE_INDICATION, + I2S_DIGITAL_AUDIO_INTERFACE, + SPI_SERIAL_INTERFACE, + MASTER_CLOCK_GENRATION, + UART_INTERFACE, + WIFI_ENABLE, + RING_INDICATION = 18, + LAST_GASP_ENABLE, + EXTERNAL_GNSS_ANTENNA, + TIME_PULSE_GNSS, + TIME_PULSE_OUTPUT, + TIMESTAMP, + FAST_POWER_OFF, + LWM2M_PULSE, + HARDWARE_FLOW_CONTROL, + ANTENNA_TUNING, + EXT_GNSS_TIME_PULSE, + EXT_GNSS_TIMESTAMP, + DTR_MODE, + KHZ_32768_OUT = 32, + PAD_DISABLED = 255 + } UBX_CELL_gpio_mode_t; + UBX_CELL_error_t setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_t mode, int value = 0); + UBX_CELL_gpio_mode_t getGpioMode(UBX_CELL_gpio_t gpio); + + // IP Transport Layer + int socketOpen(UBX_CELL_socket_protocol_t protocol, + unsigned int localPort = 0); // Open a socket. Returns the socket number. + UBX_CELL_error_t socketClose(int socket, unsigned long timeout = UBX_CELL_2_MIN_TIMEOUT); // Close the socket + UBX_CELL_error_t socketConnect(int socket, const char *address, + unsigned int port); // TCP - connect to a remote IP Address using the specified port. + // Not required for UDP sockets. + UBX_CELL_error_t socketConnect(int socket, IPAddress address, unsigned int port); + // Write data to the specified socket. Works with binary data - but you must specify the data length when using the + // const char * version Works with both TCP and UDP sockets - but socketWriteUDP is preferred for UDP and doesn't + // require socketOpen to be called first + UBX_CELL_error_t socketWrite(int socket, const char *str, int len = -1); + UBX_CELL_error_t socketWrite(int socket, String str); // OK for binary data + // Write UDP data to the specified IP Address and port. + // Works with binary data - but you must specify the data length when using the const char * versions + // If you let len default to -1, strlen is used to calculate the data length - and will be incorrect for binary data + UBX_CELL_error_t socketWriteUDP(int socket, const char *address, int port, const char *str, int len = -1); + UBX_CELL_error_t socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len = -1); + UBX_CELL_error_t socketWriteUDP(int socket, String address, int port, String str); + // Read data from the specified socket + // Call socketReadAvailable first to determine how much data is available - or use the callbacks (triggered by + // URC's) Works for both TCP and UDP - but socketReadUDP is preferred for UDP as it records the remote IP Address + // and port bytesRead - if provided - will be updated with the number of bytes actually read. This could be less + // than length! + UBX_CELL_error_t socketRead(int socket, int length, char *readDest, int *bytesRead = nullptr); + // Return the number of bytes available (waiting to be read) on the chosen socket + // Uses +USORD. Valid for both TCP and UDP sockets - but socketReadAvailableUDP is preferred for UDP + UBX_CELL_error_t socketReadAvailable(int socket, int *length); + // Read data from the specified UDP port + // Call socketReadAvailableUDP first to determine how much data is available - or use the callbacks (triggered by + // URC's) The remote IP Address and port are returned via *remoteIPAddress and *remotePort (if not nullptr) + // bytesRead - if provided - will be updated with the number of bytes actually read. This could be less than length! + UBX_CELL_error_t socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress = nullptr, + int *remotePort = nullptr, int *bytesRead = nullptr); + // Return the number of bytes available (waiting to be read) on the chosen UDP socket + UBX_CELL_error_t socketReadAvailableUDP(int socket, int *length); + // Start listening for a connection on the specified port. The connection is reported via the socket listen callback + UBX_CELL_error_t socketListen(int socket, unsigned int port); + // Place the socket into direct link mode - making it easy to transfer binary data. Wait two seconds and then send + // +++ to exit the link. + UBX_CELL_error_t socketDirectLinkMode(int socket); + // Configure when direct link data is sent + UBX_CELL_error_t socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger); + UBX_CELL_error_t socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger); + UBX_CELL_error_t socketDirectLinkCharacterTrigger(int socket, int characterTrigger); + UBX_CELL_error_t socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer); + // Use +USOCTL (Socket control) to query the socket parameters + UBX_CELL_error_t querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol); + UBX_CELL_error_t querySocketLastError(int socket, int *error); + UBX_CELL_error_t querySocketTotalBytesSent(int socket, uint32_t *total); + UBX_CELL_error_t querySocketTotalBytesReceived(int socket, uint32_t *total); + UBX_CELL_error_t querySocketRemoteIPAddress(int socket, IPAddress *address, int *port); + UBX_CELL_error_t querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status); + UBX_CELL_error_t querySocketOutUnackData(int socket, uint32_t *total); + // Return the most recent socket error + int socketGetLastError(); + // Return the remote IP Address from the most recent socket listen indication (socket connection) + // Use the socket listen callback to get the full address and port information + IPAddress lastRemoteIP(void); + + // Ping + UBX_CELL_error_t ping(String remote_host, int retry = 4, int p_size = 32, unsigned long timeout = 5000, + int ttl = 32); + + // HTTP + UBX_CELL_error_t resetHTTPprofile(int profile); // Reset the HTTP profile. Note: The configured HTTP profile + // parameters are not saved in the non volatile memory. + UBX_CELL_error_t setHTTPserverIPaddress(int profile, IPAddress address); // Default: empty string + UBX_CELL_error_t setHTTPserverName(int profile, String server); // Default: empty string + UBX_CELL_error_t setHTTPusername(int profile, String username); // Default: empty string + UBX_CELL_error_t setHTTPpassword(int profile, String password); // Default: empty string + UBX_CELL_error_t setHTTPauthentication(int profile, bool authenticate); // Default: no authentication + UBX_CELL_error_t setHTTPserverPort(int profile, int port); // Default: 80 + UBX_CELL_error_t setHTTPcustomHeader(int profile, + String header); // Default: format 0:Content-Type:application/json" + UBX_CELL_error_t setHTTPsecure( + int profile, bool secure, + int secprofile = -1); // Default: disabled (HTTP on port 80). Set to true for HTTPS on port 443 + // TO DO: Add custom request headers + UBX_CELL_error_t getHTTPprotocolError(int profile, int *error_class, + int *error_code); // Read the most recent HTTP protocol error for this profile + UBX_CELL_error_t sendHTTPGET(int profile, String path, String responseFilename); + UBX_CELL_error_t sendHTTPPOSTdata(int profile, String path, String responseFilename, String data, + UBX_CELL_http_content_types_t httpContentType); + UBX_CELL_error_t sendHTTPPOSTfile(int profile, String path, String responseFilename, String requestFile, + UBX_CELL_http_content_types_t httpContentType); + + UBX_CELL_error_t nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter); + UBX_CELL_error_t setMQTTclientId(const String &clientId); + UBX_CELL_error_t setMQTTserver(const String &serverName, int port); + UBX_CELL_error_t setMQTTcredentials(const String &userName, const String &pwd); + UBX_CELL_error_t setMQTTsecure(bool secure, int secprofile = -1); + UBX_CELL_error_t connectMQTT(void); + UBX_CELL_error_t disconnectMQTT(void); + UBX_CELL_error_t subscribeMQTTtopic(int max_Qos, const String &topic); + UBX_CELL_error_t unsubscribeMQTTtopic(const String &topic); + UBX_CELL_error_t readMQTT(int *pQos, String *pTopic, uint8_t *readDest, int readLength, int *bytesRead); + UBX_CELL_error_t mqttPublishTextMsg(const String &topic, const char *const msg, uint8_t qos = 0, + bool retain = false); + UBX_CELL_error_t mqttPublishBinaryMsg(const String &topic, const char *const msg, size_t msg_len, uint8_t qos = 0, + bool retain = false); + UBX_CELL_error_t mqttPublishFromFile(const String &topic, const String &filename, uint8_t qos = 0, + bool retain = false); + UBX_CELL_error_t getMQTTprotocolError(int *error_code, int *error_code2); + + // FTP + UBX_CELL_error_t setFTPserver(const String &serverName); + UBX_CELL_error_t setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, + const unsigned int data_linger); + UBX_CELL_error_t setFTPcredentials(const String &userName, const String &pwd); + UBX_CELL_error_t connectFTP(void); + UBX_CELL_error_t disconnectFTP(void); + UBX_CELL_error_t ftpGetFile(const String &filename); + UBX_CELL_error_t getFTPprotocolError(int *error_code, int *error_code2); + + // Configure security profiles + UBX_CELL_error_t resetSecurityProfile(int secprofile); + UBX_CELL_error_t configSecurityProfileString(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, + String value); + UBX_CELL_error_t configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value); + UBX_CELL_error_t setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, + UBX_CELL_sec_manager_parameter_t parameter, String name, String data); + + UBX_CELL_error_t activatePDPcontext( + bool status, int cid = -1); // Activates or deactivates the specified PDP context. Default to all (cid = -1) + + // GPS + typedef enum + { + GNSS_SYSTEM_GPS = 1, + GNSS_SYSTEM_SBAS = 2, + GNSS_SYSTEM_GALILEO = 4, + GNSS_SYSTEM_BEIDOU = 8, + GNSS_SYSTEM_IMES = 16, + GNSS_SYSTEM_QZSS = 32, + GNSS_SYSTEM_GLONASS = 64 + } gnss_system_t; + typedef enum + { + GNSS_AIDING_MODE_NONE = 0, + GNSS_AIDING_MODE_AUTOMATIC = 1, + GNSS_AIDING_MODE_ASSISTNOW_OFFLINE = 2, + GNSS_AIDING_MODE_ASSISTNOW_ONLINE = 4, + GNSS_AIDING_MODE_ASSISTNOW_AUTONOMOUS = 8 + } gnss_aiding_mode_t; + bool isGPSon(void); + UBX_CELL_error_t gpsPower(bool enable = true, gnss_system_t gnss_sys = GNSS_SYSTEM_GPS, + gnss_aiding_mode_t gnss_aiding = GNSS_AIDING_MODE_AUTOMATIC); + // UBX_CELL_error_t gpsEnableClock(bool enable = true); + // UBX_CELL_error_t gpsGetClock(struct ClockData *clock); + // UBX_CELL_error_t gpsEnableFix(bool enable = true); + // UBX_CELL_error_t gpsGetFix(float *lat, float *lon, unsigned int *alt, uint8_t *quality, uint8_t *sat); + // UBX_CELL_error_t gpsGetFix(struct PositionData *pos); + // UBX_CELL_error_t gpsEnablePos(bool enable = true); + // UBX_CELL_error_t gpsGetPos(struct PositionData *pos); + // UBX_CELL_error_t gpsEnableSat(bool enable = true); + // UBX_CELL_error_t gpsGetSat(uint8_t *sats); + UBX_CELL_error_t gpsEnableRmc(bool enable = true); // Enable GPRMC messages + UBX_CELL_error_t gpsGetRmc(struct PositionData *pos, struct SpeedData *speed, struct ClockData *clk, + bool *valid); // Parse a GPRMC message + // UBX_CELL_error_t gpsEnableSpeed(bool enable = true); + // UBX_CELL_error_t gpsGetSpeed(struct SpeedData *speed); + + UBX_CELL_error_t gpsRequest(unsigned int timeout, uint32_t accuracy, bool detailed = true, unsigned int sensor = 3); + + // CellLocate + UBX_CELL_error_t gpsAidingServerConf(const char *primaryServer, const char *secondaryServer, const char *authToken, + unsigned int days = 14, unsigned int period = 4, unsigned int resolution = 1, + unsigned int gnssTypes = 65, unsigned int mode = 0, + unsigned int dataType = 15); + + // File system + // TO DO: add full support for file tags. Default tag to USER + UBX_CELL_error_t getFileContents( + String filename, + String *contents); // OK for text files. But will fail with binary files (containing \0) on some platforms. + UBX_CELL_error_t getFileContents(String filename, + char *contents); // OK for binary files. Make sure contents can hold the entire + // file. Get the size first with getFileSize. + UBX_CELL_error_t getFileBlock( + const String &filename, char *buffer, size_t offset, size_t length, + size_t &bytes_read); // OK for binary files. Make sure buffer can hold the requested block size. + + // Append data to a file, delete file first to not appends the data. + UBX_CELL_error_t appendFileContents(String filename, String str); + UBX_CELL_error_t appendFileContents(String filename, const char *str, int len); + UBX_CELL_error_t getFileSize(String filename, int *size); + UBX_CELL_error_t deleteFile(String filename); + + // Functionality + UBX_CELL_error_t functionality(UBX_CELL_functionality_t function = FULL_FUNCTIONALITY); + + // Send a custom command with an expected (potentially partial) response, store entire response + UBX_CELL_error_t sendCustomCommandWithResponse(const char *command, const char *expectedResponse, + char *responseDest, + unsigned long commandTimeout = UBX_CELL_STANDARD_RESPONSE_TIMEOUT, + bool at = true); + + // Send command with an expected (potentially partial) response, store entire response + UBX_CELL_error_t sendCommandWithResponse(const char *command, const char *expectedResponse, char *responseDest, + unsigned long commandTimeout, int destSize = minimumResponseAllocation, + bool at = true); + + char *ubx_cell_calloc_char(size_t num); + + // Add a URC handler + void addURCHandler(const char *urcString, UBX_CELL_urc_handler_t urcHandler); + + protected: + HardwareSerial *_hardSerial; #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED - SoftwareSerial *_softSerial; + SoftwareSerial *_softSerial; #endif - Print *_debugPort; //The stream to send debug messages to if enabled. Usually Serial. - bool _printDebug = false; //Flag to print debugging variables - Print *_debugAtPort; //The stream to send debug messages to if enabled. Usually Serial. - bool _printAtDebug = false; //Flag to print debugging variables - - int _powerPin; - int _resetPin; - bool _invertPowerPin = false; - - unsigned long _baud; - IPAddress _lastRemoteIP; - IPAddress _lastLocalIP; - uint8_t _maxInitTries; - bool _autoTimeZoneForBegin = true; - bool _bufferedPollReentrant = false; // Prevent reentry of bufferedPoll - just in case it gets called from a callback - bool _pollReentrant = false; // Prevent reentry of poll - just in case it gets called from a callback - - #define _RXBuffSize 2056 - const unsigned long _rxWindowMillis = 2; // 1ms is not quite long enough for a single char at 9600 baud. millis roll over much less often than micros. See notes in .cpp re. ESP32! - char *_saraRXBuffer; // Allocated in UBX_CELL::begin - char *_pruneBuffer; - char *_saraResponseBacklog; - int _saraResponseBacklogLength = 0; // The backlog could contain binary data so we can't use strlen to find its length - - void (*_socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, unsigned int); - void (*_socketReadCallback)(int, String); - void (*_socketReadCallbackPlus)(int, const char *, int, IPAddress, int); // socket, data, length, remoteAddress, remotePort - void (*_socketCloseCallback)(int); - void (*_gpsRequestCallback)(ClockData, PositionData, SpeedData, unsigned long); - void (*_simStateReportCallback)(UBX_CELL_sim_states_t); - void (*_psdActionRequestCallback)(int, IPAddress); - void (*_pingRequestCallback)(int, int, String, IPAddress, int, long); - void (*_httpCommandRequestCallback)(int, int, int); - void (*_mqttCommandRequestCallback)(int, int); - void (*_ftpCommandRequestCallback)(int, int); - void (*_registrationCallback)(UBX_CELL_registration_status_t status, unsigned int lac, unsigned int ci, int Act); - void (*_epsRegistrationCallback)(UBX_CELL_registration_status_t status, unsigned int tac, unsigned int ci, int Act); - - // Vectors of URC strings and handlers - std::vector _urcStrings; - std::vector _urcHandlers; - - int _lastSocketProtocol[UBX_CELL_NUM_SOCKETS]; // Record the protocol for each socket to avoid having to call querySocketType in parseSocketReadIndication - - typedef enum - { - UBX_CELL_INIT_STANDARD, - UBX_CELL_INIT_AUTOBAUD, - UBX_CELL_INIT_RESET - } UBX_CELL_init_type_t; - - UBX_CELL_error_t init(unsigned long baud, UBX_CELL_init_type_t initType = UBX_CELL_INIT_STANDARD); - - void powerOn(void); // Brief pulse on PWR_ON to turn module back on - void powerOff(void); // Long pulse on PWR_ON to do a graceful shutdown. Note modulePowerOff (+CPWROFF) is preferred. - - void hwReset(void); - - UBX_CELL_error_t setMNOprofile(mobile_network_operator_t mno, bool autoReset = false, bool urcNotification = false); - UBX_CELL_error_t getMNOprofile(mobile_network_operator_t *mno); - - // Wait for an expected response (don't send a command) - UBX_CELL_error_t waitForResponse(const char *expectedResponse, const char *expectedError, uint16_t timeout); - - // Send a command -- prepend AT if at is true - void sendCommand(const char *command, bool at); - - const int _saraR5maxSocketRead = 1024; // The limit on bytes that can be read in a single read - - UBX_CELL_error_t parseSocketReadIndication(int socket, int length); - UBX_CELL_error_t parseSocketReadIndicationUDP(int socket, int length); - UBX_CELL_error_t parseSocketListenIndication(int listeningSocket, IPAddress localIP, unsigned int listeningPort, int socket, IPAddress remoteIP, unsigned int port); - UBX_CELL_error_t parseSocketCloseIndication(String *closeIndication); - - // UART Functions - size_t hwPrint(const char *s); - size_t hwWriteData(const char *buff, int len); - size_t hwWrite(const char c); - int readAvailable(char *inString); - char readChar(void); - int hwAvailable(void); - virtual void beginSerial(unsigned long baud); - void setTimeout(unsigned long timeout); - bool find(char *target); - - UBX_CELL_error_t autobaud(unsigned long desiredBaud); - - bool urcHandlerReadSocket(const char* event); - bool urcHandlerReadUDPSocket(const char* event); - bool urcHandlerListeningSocket(const char* event); - bool urcHandlerCloseSocket(const char* event); - bool urcHandlerGNSSRequestLocation(const char* event); - bool urcHandlerSIMState(const char* event); - bool urcHandlerHTTPCommand(const char* event); - bool urcHandlerMQTTCommand(const char* event); - bool urcHandlerPingCommand(const char* event); - bool urcHandlerFTPCommand(const char* event); - bool urcHandlerRegistrationStatus(const char* event); - bool urcHandlerEPSRegistrationStatus(const char* event); - - bool processURCEvent(const char *event); - void pruneBacklog(void); - - // GPS Helper functions - char *readDataUntil(char *destination, unsigned int destSize, char *source, char delimiter); - bool parseGPRMCString(char *rmcString, PositionData *pos, ClockData *clk, SpeedData *spd); + Print *_debugPort; // The stream to send debug messages to if enabled. Usually Serial. + bool _printDebug = false; // Flag to print debugging variables + Print *_debugAtPort; // The stream to send debug messages to if enabled. Usually Serial. + bool _printAtDebug = false; // Flag to print debugging variables + + int _powerPin; + int _resetPin; + bool _invertPowerPin = false; + + unsigned long _baud; + IPAddress _lastRemoteIP; + IPAddress _lastLocalIP; + uint8_t _maxInitTries; + bool _autoTimeZoneForBegin = true; + bool _bufferedPollReentrant = + false; // Prevent reentry of bufferedPoll - just in case it gets called from a callback + bool _pollReentrant = false; // Prevent reentry of poll - just in case it gets called from a callback + +#define _RXBuffSize 2056 + const unsigned long _rxWindowMillis = 2; // 1ms is not quite long enough for a single char at 9600 baud. millis roll + // over much less often than micros. See notes in .cpp re. ESP32! + char *_saraRXBuffer; // Allocated in UBX_CELL::begin + char *_pruneBuffer; + char *_saraResponseBacklog; + int _saraResponseBacklogLength = + 0; // The backlog could contain binary data so we can't use strlen to find its length + + void (*_socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, unsigned int); + void (*_socketReadCallback)(int, String); + void (*_socketReadCallbackPlus)(int, const char *, int, IPAddress, + int); // socket, data, length, remoteAddress, remotePort + void (*_socketCloseCallback)(int); + void (*_gpsRequestCallback)(ClockData, PositionData, SpeedData, unsigned long); + void (*_simStateReportCallback)(UBX_CELL_sim_states_t); + void (*_psdActionRequestCallback)(int, IPAddress); + void (*_pingRequestCallback)(int, int, String, IPAddress, int, long); + void (*_httpCommandRequestCallback)(int, int, int); + void (*_mqttCommandRequestCallback)(int, int); + void (*_ftpCommandRequestCallback)(int, int); + void (*_registrationCallback)(UBX_CELL_registration_status_t status, unsigned int lac, unsigned int ci, int Act); + void (*_epsRegistrationCallback)(UBX_CELL_registration_status_t status, unsigned int tac, unsigned int ci, int Act); + + // Vectors of URC strings and handlers + std::vector _urcStrings; + std::vector _urcHandlers; + + int _lastSocketProtocol[UBX_CELL_NUM_SOCKETS]; // Record the protocol for each socket to avoid having to call + // querySocketType in parseSocketReadIndication + + typedef enum + { + UBX_CELL_INIT_STANDARD, + UBX_CELL_INIT_AUTOBAUD, + UBX_CELL_INIT_RESET + } UBX_CELL_init_type_t; + + UBX_CELL_error_t init(unsigned long baud, UBX_CELL_init_type_t initType = UBX_CELL_INIT_STANDARD); + + void powerOn(void); // Brief pulse on PWR_ON to turn module back on + void powerOff(void); // Long pulse on PWR_ON to do a graceful shutdown. Note modulePowerOff (+CPWROFF) is preferred. + + void hwReset(void); + + UBX_CELL_error_t setMNOprofile(mobile_network_operator_t mno, bool autoReset = false, bool urcNotification = false); + UBX_CELL_error_t getMNOprofile(mobile_network_operator_t *mno); + + // Wait for an expected response (don't send a command) + UBX_CELL_error_t waitForResponse(const char *expectedResponse, const char *expectedError, uint16_t timeout); + + // Send a command -- prepend AT if at is true + void sendCommand(const char *command, bool at); + + const int _saraR5maxSocketRead = 1024; // The limit on bytes that can be read in a single read + + UBX_CELL_error_t parseSocketReadIndication(int socket, int length); + UBX_CELL_error_t parseSocketReadIndicationUDP(int socket, int length); + UBX_CELL_error_t parseSocketListenIndication(int listeningSocket, IPAddress localIP, unsigned int listeningPort, + int socket, IPAddress remoteIP, unsigned int port); + UBX_CELL_error_t parseSocketCloseIndication(String *closeIndication); + + // UART Functions + size_t hwPrint(const char *s); + size_t hwWriteData(const char *buff, int len); + size_t hwWrite(const char c); + int readAvailable(char *inString); + char readChar(void); + int hwAvailable(void); + virtual void beginSerial(unsigned long baud); + void setTimeout(unsigned long timeout); + bool find(char *target); + + UBX_CELL_error_t autobaud(unsigned long desiredBaud); + + bool urcHandlerReadSocket(const char *event); + bool urcHandlerReadUDPSocket(const char *event); + bool urcHandlerListeningSocket(const char *event); + bool urcHandlerCloseSocket(const char *event); + bool urcHandlerGNSSRequestLocation(const char *event); + bool urcHandlerSIMState(const char *event); + bool urcHandlerHTTPCommand(const char *event); + bool urcHandlerMQTTCommand(const char *event); + bool urcHandlerPingCommand(const char *event); + bool urcHandlerFTPCommand(const char *event); + bool urcHandlerRegistrationStatus(const char *event); + bool urcHandlerEPSRegistrationStatus(const char *event); + + bool processURCEvent(const char *event); + void pruneBacklog(void); + + // GPS Helper functions + char *readDataUntil(char *destination, unsigned int destSize, char *source, char delimiter); + bool parseGPRMCString(char *rmcString, PositionData *pos, ClockData *clk, SpeedData *spd); }; -#endif //SPARKFUN_UBX_CELL_ARDUINO_LIBRARY_H +#endif // SPARKFUN_UBX_CELL_ARDUINO_LIBRARY_H diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index 9ceee64..17454eb 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -3,176 +3,175 @@ #include "sfe_ublox_cellular.h" -const char* const UBX_CELL_COMMAND_DIAL = "D"; // Dial command -const char* const UBX_CELL_COMMAND_ANSWER = "A"; // Answer call -const char* const UBX_CELL_COMMAND_HANG_UP = "+CHUP"; // Hang up call -const char* const UBX_CELL_COMMAND_PLAY_AUDIO = "+UPAR"; // Play audio resource -const char* const UBX_CELL_COMMAND_STOP_AUDIO = "+USAR"; // Stop audio resource -const char* const UBX_CELL_COMMAND_GENERATE_TONE = "+UTGN"; // Tone generator +const char *const UBX_CELL_COMMAND_DIAL = "D"; // Dial command +const char *const UBX_CELL_COMMAND_ANSWER = "A"; // Answer call +const char *const UBX_CELL_COMMAND_HANG_UP = "+CHUP"; // Hang up call +const char *const UBX_CELL_COMMAND_PLAY_AUDIO = "+UPAR"; // Play audio resource +const char *const UBX_CELL_COMMAND_STOP_AUDIO = "+USAR"; // Stop audio resource +const char *const UBX_CELL_COMMAND_GENERATE_TONE = "+UTGN"; // Tone generator -const char* const UBX_CELL_RING_URC = "RING"; +const char *const UBX_CELL_RING_URC = "RING"; typedef enum { - UBX_CELL_AUDIO_RESOURCE_TONE = 0, - UBX_CELL_AUDIO_RESOURCE_MIDI = 1, - UBX_CELL_AUDIO_RESOURCE_LOOPBACK = 2 + UBX_CELL_AUDIO_RESOURCE_TONE = 0, + UBX_CELL_AUDIO_RESOURCE_MIDI = 1, + UBX_CELL_AUDIO_RESOURCE_LOOPBACK = 2 } UBX_CELL_audio_resource_t; // Base class for any modules supporting voice calls -template -class UBX_CELL_VOICE +template class UBX_CELL_VOICE { -public: - UBX_CELL_VOICE(void) - { - // Set ring URC callback to nullptr - _ringCallback = nullptr; - - // Add handler for ring URC - static_cast(this)->addURCHandler(UBX_CELL_RING_URC, [this](const char* event){return this->urcCheckRing(event);}); - } - - UBX_CELL_error_t dial(String number) - { - char *command; - char *numberCStr; - UBX_CELL_error_t err; - - numberCStr = static_cast(this)->ubx_cell_calloc_char(number.length() + 1); - if (numberCStr == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - number.toCharArray(numberCStr, number.length() + 1); - - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_DIAL) + strlen(numberCStr) + 3); - if (command != nullptr) + public: + UBX_CELL_VOICE(void) { - // Heads up! The dial command is one of the only commands that requires a - // semicolon at the end of it! - sprintf(command, "%s=%s;", UBX_CELL_COMMAND_DIAL, numberCStr); - - err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, - nullptr, UBX_CELL_10_SEC_TIMEOUT); - - free(command); + // Set ring URC callback to nullptr + _ringCallback = nullptr; + + // Add handler for ring URC + static_cast(this)->addURCHandler(UBX_CELL_RING_URC, + [this](const char *event) { return this->urcCheckRing(event); }); + } + + UBX_CELL_error_t dial(String number) + { + char *command; + char *numberCStr; + UBX_CELL_error_t err; + + numberCStr = static_cast(this)->ubx_cell_calloc_char(number.length() + 1); + if (numberCStr == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + number.toCharArray(numberCStr, number.length() + 1); + + command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_DIAL) + strlen(numberCStr) + 3); + if (command != nullptr) + { + // Heads up! The dial command is one of the only commands that requires a + // semicolon at the end of it! + sprintf(command, "%s=%s;", UBX_CELL_COMMAND_DIAL, numberCStr); + + err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, nullptr, + UBX_CELL_10_SEC_TIMEOUT); + + free(command); + } + else + { + err = UBX_CELL_ERROR_OUT_OF_MEMORY; + } + + free(numberCStr); + + return err; + } + + UBX_CELL_error_t answer(void) + { + return static_cast(this)->sendCommandWithResponse(UBX_CELL_COMMAND_ANSWER, UBX_CELL_RESPONSE_OK_OR_ERROR, + nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + } + + UBX_CELL_error_t hangUp(void) + { + return static_cast(this)->sendCommandWithResponse(UBX_CELL_COMMAND_HANG_UP, UBX_CELL_RESPONSE_OK_OR_ERROR, + nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + } + + UBX_CELL_error_t playAudioResource(uint8_t audio_resource, uint8_t tone_id = 0, uint8_t nof_repeat = 0) + { + UBX_CELL_error_t err; + char *command; + + command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_PLAY_AUDIO) + 13); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_PLAY_AUDIO, audio_resource, tone_id, nof_repeat); + + err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; + } + + UBX_CELL_error_t stopAudioResource(uint8_t audio_resource) + { + UBX_CELL_error_t err; + char *command; + + command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_STOP_AUDIO) + 5); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", UBX_CELL_COMMAND_STOP_AUDIO, audio_resource); + + err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; + } + + UBX_CELL_error_t generateToneFreq(uint16_t frequency, uint16_t duration, uint8_t volume) + { + UBX_CELL_error_t err; + char *command; + char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; + + command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 15); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, frequency, duration, volume); + + err = static_cast(this)->sendCommandWithResponse(command, response, nullptr, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } - else + + UBX_CELL_error_t generateToneDTMF(char dtmf_character, uint16_t duration, uint8_t volume) { - err = UBX_CELL_ERROR_OUT_OF_MEMORY; + UBX_CELL_error_t err; + char *command; + char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; + + command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 14); + if (command == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%c\",%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, dtmf_character, duration, volume); + + err = static_cast(this)->sendCommandWithResponse(command, response, nullptr, + UBX_CELL_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; } - free(numberCStr); - - return err; - } - - UBX_CELL_error_t answer(void) - { - return static_cast(this)->sendCommandWithResponse(UBX_CELL_COMMAND_ANSWER, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - } - - UBX_CELL_error_t hangUp(void) - { - return static_cast(this)->sendCommandWithResponse(UBX_CELL_COMMAND_HANG_UP, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - } - - UBX_CELL_error_t playAudioResource(uint8_t audio_resource, uint8_t tone_id = 0, uint8_t nof_repeat = 0) - { - UBX_CELL_error_t err; - char *command; - - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_PLAY_AUDIO) + 13); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_PLAY_AUDIO, audio_resource, tone_id, nof_repeat); - - err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; - } - - UBX_CELL_error_t stopAudioResource(uint8_t audio_resource) - { - UBX_CELL_error_t err; - char *command; - - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_STOP_AUDIO) + 5); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_COMMAND_STOP_AUDIO, audio_resource); - - err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; - } - - UBX_CELL_error_t generateToneFreq(uint16_t frequency, uint16_t duration, uint8_t volume) - { - UBX_CELL_error_t err; - char *command; - char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; - - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 15); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, frequency, duration, volume); - - err = static_cast(this)->sendCommandWithResponse(command, response, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; - } - - UBX_CELL_error_t generateToneDTMF(char dtmf_character, uint16_t duration, uint8_t volume) - { - UBX_CELL_error_t err; - char *command; - char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; - - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 14); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%c\",%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, dtmf_character, duration, volume); - - err = static_cast(this)->sendCommandWithResponse(command, response, - nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; - } - - void setRingCallback(void (*callback)(void)) - { - _ringCallback = callback; - } - -protected: - // Callback for incoming calls - void (*_ringCallback)(void); - - bool urcCheckRing(const char *event) - { - int socket, length; - char *searchPtr = strstr(event, UBX_CELL_RING_URC); - if (searchPtr != nullptr) + void setRingCallback(void (*callback)(void)) { - if(_ringCallback != nullptr) - { - _ringCallback(); - } - return true; + _ringCallback = callback; } - return false; - } + protected: + // Callback for incoming calls + void (*_ringCallback)(void); + + bool urcCheckRing(const char *event) + { + int socket, length; + char *searchPtr = strstr(event, UBX_CELL_RING_URC); + if (searchPtr != nullptr) + { + if (_ringCallback != nullptr) + { + _ringCallback(); + } + return true; + } + + return false; + } }; class UBX_CELL_VOICE_BASE : public UBX_CELL, public UBX_CELL_VOICE { - }; #endif \ No newline at end of file From 14c52f3bc0645ddbea7e23da7c61b7ceaf001f1d Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Wed, 13 Dec 2023 13:03:50 -0700 Subject: [PATCH 2/8] Run examples through formatter Clang formatter in VS Code set to Microsoft style --- .../AudioExample1_PlayTone.ino | 218 ++++---- .../AudioExample2_Loopback.ino | 99 ++-- .../AudioExample3_CallControl.ino | 198 ++++---- .../Example1_DeviceIdentification.ino | 112 ++--- .../Example2_NetworkInfo.ino | 171 +++---- .../Example3_RegisterOperator.ino | 465 ++++++++++-------- examples/Example4_Clock/Example4_Clock.ino | 84 ++-- examples/Example5_Ping/Example5_Ping.ino | 204 ++++---- .../Example6_ReceiveSMS.ino | 413 ++++++++-------- .../Example7_SendSMS/Example7_SendSMS.ino | 192 ++++---- 10 files changed, 1118 insertions(+), 1038 deletions(-) diff --git a/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino index 60f802d..c270e19 100644 --- a/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino +++ b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino @@ -13,117 +13,133 @@ UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modul void setup() { - Serial.begin(115200); // Start the serial console - - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Audio Example 1 - Play Tone")); - - Serial.println(); - Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); - Serial.println(F("This example requires an audio codec attached to the I2S interface")); - Serial.println(F("of the cellular modem. Please add one and update this example as")); - Serial.println(F("needed to configure your audio codec!")); - Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); - Serial.println(); - - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); - - Serial.println(F("Beginning...")); - - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); - - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Audio Example 1 - Play Tone")); + + Serial.println(); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); + Serial.println(F("This example requires an audio codec attached to the I2S interface")); + Serial.println(F("of the cellular modem. Please add one and update this example as")); + Serial.println(F("needed to configure your audio codec!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); + Serial.println(); + + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); } void loop() { - String inputString; - char dtmfChar = 0; - uint16_t frequency = 0; - uint16_t duration = 0; - uint8_t volume = 0; - - while(true) - { - while(Serial.available() != 0){Serial.read();} - Serial.println(F("Enter a frequency in Hz (300-3400) or a DTMF character (0-9, *, #)")); - while(Serial.available() == 0){} - - inputString = Serial.readStringUntil('\n'); - - if(inputString.length() == 1) + String inputString; + char dtmfChar = 0; + uint16_t frequency = 0; + uint16_t duration = 0; + uint8_t volume = 0; + + while (true) { - dtmfChar = inputString.charAt(0); - if((dtmfChar >= '0' && dtmfChar <= '9') || dtmfChar == '*' || dtmfChar == '#') - { - break; - } + while (Serial.available() != 0) + { + Serial.read(); + } + Serial.println(F("Enter a frequency in Hz (300-3400) or a DTMF character (0-9, *, #)")); + while (Serial.available() == 0) + { + } + + inputString = Serial.readStringUntil('\n'); + + if (inputString.length() == 1) + { + dtmfChar = inputString.charAt(0); + if ((dtmfChar >= '0' && dtmfChar <= '9') || dtmfChar == '*' || dtmfChar == '#') + { + break; + } + } + else + { + frequency = inputString.toInt(); + if (frequency >= 300 && frequency <= 3400) + { + dtmfChar == 0; + break; + } + } } - else + + while (true) { - frequency = inputString.toInt(); - if(frequency >= 300 && frequency <= 3400) - { - dtmfChar == 0; - break; - } + while (Serial.available() != 0) + { + Serial.read(); + } + Serial.println(F("Enter a duration in ms (50-1360)")); + while (Serial.available() == 0) + { + } + + inputString = Serial.readStringUntil('\n'); + duration = inputString.toInt(); + if (duration >= 50 && duration <= 1360) + { + break; + } } - } - - while(true) - { - while(Serial.available() != 0){Serial.read();} - Serial.println(F("Enter a duration in ms (50-1360)")); - while(Serial.available() == 0){} - - inputString = Serial.readStringUntil('\n'); - duration = inputString.toInt(); - if(duration >= 50 && duration <= 1360) + + while (true) { - break; + while (Serial.available() != 0) + { + Serial.read(); + } + Serial.println(F("Enter a volume (0-100)")); + while (Serial.available() == 0) + { + } + + inputString = Serial.readStringUntil('\n'); + volume = inputString.toInt(); + if (volume <= 100) + { + break; + } } - } - - while(true) - { - while(Serial.available() != 0){Serial.read();} - Serial.println(F("Enter a volume (0-100)")); - while(Serial.available() == 0){} - - inputString = Serial.readStringUntil('\n'); - volume = inputString.toInt(); - if(volume <= 100) + + if (dtmfChar == 0) + { + myModule.generateToneFreq(frequency, duration, volume); + } + else { - break; + myModule.generateToneDTMF(dtmfChar, duration, volume); } - } - - if(dtmfChar == 0) - { - myModule.generateToneFreq(frequency, duration, volume); - } - else - { - myModule.generateToneDTMF(dtmfChar, duration, volume); - } } \ No newline at end of file diff --git a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino index b07ce47..44aaee0 100644 --- a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino +++ b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino @@ -13,59 +13,70 @@ UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modul void setup() { - Serial.begin(115200); // Start the serial console + Serial.begin(115200); // Start the serial console - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Audio Example 2 - Loopback")); + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Audio Example 2 - Loopback")); - Serial.println(); - Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); - Serial.println(F("This example requires an audio codec attached to the I2S interface")); - Serial.println(F("of the cellular modem. Please add one and update this example as")); - Serial.println(F("needed to configure your audio codec!")); - Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); - Serial.println(); + Serial.println(); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); + Serial.println(F("This example requires an audio codec attached to the I2S interface")); + Serial.println(F("of the cellular modem. Please add one and update this example as")); + Serial.println(F("needed to configure your audio codec!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); + Serial.println(); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); + Serial.println(F("Press any key to begin")); - Serial.println(F("Beginning...")); + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + Serial.println(F("Beginning...")); - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); } void loop() { - while(Serial.available() != 0){Serial.read();} - Serial.println(F("Enter any key to begin loopback")); - while(Serial.available() == 0){} - - myModule.playAudioResource(UBX_CELL_AUDIO_RESOURCE_LOOPBACK); - - while(Serial.available() != 0){Serial.read();} - Serial.println(F("Enter any key to stop loopback")); - while(Serial.available() == 0){} - - myModule.stopAudioResource(UBX_CELL_AUDIO_RESOURCE_LOOPBACK); + while (Serial.available() != 0) + { + Serial.read(); + } + Serial.println(F("Enter any key to begin loopback")); + while (Serial.available() == 0) + { + } + + myModule.playAudioResource(UBX_CELL_AUDIO_RESOURCE_LOOPBACK); + + while (Serial.available() != 0) + { + Serial.read(); + } + Serial.println(F("Enter any key to stop loopback")); + while (Serial.available() == 0) + { + } + + myModule.stopAudioResource(UBX_CELL_AUDIO_RESOURCE_LOOPBACK); } \ No newline at end of file diff --git a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino index 47f407f..77f8b31 100644 --- a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino +++ b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino @@ -16,114 +16,122 @@ bool incomingCall = false; void ringCallback() { - Serial.println(F("Incoming call! Enter \"A\" to answer, or anything else to reject")); - incomingCall = true; + Serial.println(F("Incoming call! Enter \"A\" to answer, or anything else to reject")); + incomingCall = true; } void setup() { - String currentOperator = ""; - - Serial.begin(115200); // Start the serial console - - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Audio Example 3 - Call Control")); - - Serial.println(); - Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); - Serial.println(F("This example requires an audio codec attached to the I2S interface")); - Serial.println(F("of the cellular modem. Please add one and update this example as")); - Serial.println(F("needed to configure your audio codec!")); - Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); - Serial.println(); - - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); - - Serial.println(F("Beginning...")); - - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); - - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); - - // First check to see if we're connected to an operator: - if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) - { - Serial.print(F("Connected to: ")); - Serial.println(currentOperator); - } - else - { - Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); - while (1) - ; // Do nothing more - } - - // Set callback function for when a new call is received - myModule.setRingCallback(&ringCallback); - - Serial.println(F("Enter a number to dial")); - - // Clear any input - while(Serial.available()){Serial.read();} -} + String currentOperator = ""; -void loop() -{ - String inputString; + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Audio Example 3 - Call Control")); + + Serial.println(); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); + Serial.println(F("This example requires an audio codec attached to the I2S interface")); + Serial.println(F("of the cellular modem. Please add one and update this example as")); + Serial.println(F("needed to configure your audio codec!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); + Serial.println(); + + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); - myModule.bufferedPoll(); + Serial.println(F("Beginning...")); - if(Serial.available()) - { - inputString = Serial.readStringUntil('\n'); - while(Serial.available()){Serial.read();} + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - if(incomingCall) + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else { - if(inputString == "A" || inputString == "a") - { - Serial.println(F("Answering call, enter any key to hang up")); - myModule.answer(); - callInProgress = true; - } - else - { - Serial.println(F("Rejecting call")); - myModule.hangUp(); - } - incomingCall = false; + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail } - else if(callInProgress == false) + Serial.println(); + + // First check to see if we're connected to an operator: + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) { - Serial.println("Dialing " + inputString + ", enter any key to hang up"); - myModule.dial(inputString); - callInProgress = true; + Serial.print(F("Connected to: ")); + Serial.println(currentOperator); } else { - Serial.println(F("Hanging up, enter a new number to dial")); - myModule.hangUp(); - callInProgress = false; + Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. " + "Or wait and retry. Freezing...")); + while (1) + ; // Do nothing more + } + + // Set callback function for when a new call is received + myModule.setRingCallback(&ringCallback); + + Serial.println(F("Enter a number to dial")); + + // Clear any input + while (Serial.available()) + { + Serial.read(); + } +} + +void loop() +{ + String inputString; + + myModule.bufferedPoll(); + + if (Serial.available()) + { + inputString = Serial.readStringUntil('\n'); + while (Serial.available()) + { + Serial.read(); + } + + if (incomingCall) + { + if (inputString == "A" || inputString == "a") + { + Serial.println(F("Answering call, enter any key to hang up")); + myModule.answer(); + callInProgress = true; + } + else + { + Serial.println(F("Rejecting call")); + myModule.hangUp(); + } + incomingCall = false; + } + else if (callInProgress == false) + { + Serial.println("Dialing " + inputString + ", enter any key to hang up"); + myModule.dial(inputString); + callInProgress = true; + } + else + { + Serial.println(F("Hanging up, enter a new number to dial")); + myModule.hangUp(); + callInProgress = false; + } } - } } \ No newline at end of file diff --git a/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino b/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino index ba5591c..fa50999 100644 --- a/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino +++ b/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino @@ -22,80 +22,80 @@ UBX_CELL myModule; // This example works with all modules, so the base class can // LARA_R6801D myModule; // Map SIM states to more readable strings -String simStateString[] = -{ - "Not present", // 0 - "PIN needed", // 1 - "PIN blocked", // 2 - "PUK blocked", // 3 - "Not operational", // 4 - "Restricted", // 5 - "Operational" // 6 +String simStateString[] = { + "Not present", // 0 + "PIN needed", // 1 + "PIN blocked", // 2 + "PUK blocked", // 3 + "Not operational", // 4 + "Restricted", // 5 + "Operational" // 6 }; -// processSIMstate is provided to the u-blox cellular library via a +// processSIMstate is provided to the u-blox cellular library via a // callback setter -- setSIMstateReadCallback. (See setup()) void processSIMstate(UBX_CELL_sim_states_t state) { - Serial.println(); - Serial.print(F("SIM state: ")); - Serial.print(String(state)); - Serial.println(); + Serial.println(); + Serial.print(F("SIM state: ")); + Serial.print(String(state)); + Serial.println(); } void setup() { - Serial.begin(115200); // Start the serial console + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 1 - Device Identification")); + Serial.println(F("Press any key to begin")); - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 1 - Device Identification")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); - Serial.println(F("Beginning...")); + Serial.println(F("Beginning...")); - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); - Serial.println("Manufacturer ID: " + String(myModule.getManufacturerID())); - Serial.println("Model ID: " + String(myModule.getModelID())); - Serial.println("Firmware Version: " + String(myModule.getFirmwareVersion())); - Serial.println("Product Serial No.: " + String(myModule.getSerialNo())); - Serial.println("IMEI: " + String(myModule.getIMEI())); - Serial.println("IMSI: " + String(myModule.getIMSI())); - Serial.println("SIM CCID: " + String(myModule.getCCID())); - Serial.println("Subscriber No.: " + String(myModule.getSubscriberNo())); - Serial.println("Capabilities: " + String(myModule.getCapabilities())); + Serial.println("Manufacturer ID: " + String(myModule.getManufacturerID())); + Serial.println("Model ID: " + String(myModule.getModelID())); + Serial.println("Firmware Version: " + String(myModule.getFirmwareVersion())); + Serial.println("Product Serial No.: " + String(myModule.getSerialNo())); + Serial.println("IMEI: " + String(myModule.getIMEI())); + Serial.println("IMSI: " + String(myModule.getIMSI())); + Serial.println("SIM CCID: " + String(myModule.getCCID())); + Serial.println("Subscriber No.: " + String(myModule.getSubscriberNo())); + Serial.println("Capabilities: " + String(myModule.getCapabilities())); - // Set a callback to return the SIM state once requested - myModule.setSIMstateReportCallback(&processSIMstate); - // Now enable SIM state reporting for states 0 to 6 (by setting the reporting mode LSb) - if (myModule.setSIMstateReportingMode(1) == UBX_CELL_SUCCESS) - Serial.println("SIM state reports requested..."); - // You can disable the SIM staus reports again by calling assetTracker.setSIMstateReportingMode(0) + // Set a callback to return the SIM state once requested + myModule.setSIMstateReportCallback(&processSIMstate); + // Now enable SIM state reporting for states 0 to 6 (by setting the reporting mode LSb) + if (myModule.setSIMstateReportingMode(1) == UBX_CELL_SUCCESS) + Serial.println("SIM state reports requested..."); + // You can disable the SIM staus reports again by calling assetTracker.setSIMstateReportingMode(0) } void loop() { - myModule.poll(); // Keep processing data from the module so we can extract the SIM status + myModule.poll(); // Keep processing data from the module so we can extract the SIM status } \ No newline at end of file diff --git a/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino b/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino index 6b62f57..cf32155 100644 --- a/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino +++ b/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino @@ -22,19 +22,18 @@ UBX_CELL myModule; // This example works with all modules, so the base class can // LARA_R6801D myModule; // Map registration status messages to more readable strings -String registrationString[] = -{ - "Not registered", // 0 - "Registered, home", // 1 - "Searching for operator", // 2 - "Registration denied", // 3 - "Registration unknown", // 4 - "Registered, roaming", // 5 - "Registered, home (SMS only)", // 6 - "Registered, roaming (SMS only)", // 7 - "Registered, emergency service only", // 8 - "Registered, home, CSFB not preferred", // 9 - "Registered, roaming, CSFB not prefered" // 10 +String registrationString[] = { + "Not registered", // 0 + "Registered, home", // 1 + "Searching for operator", // 2 + "Registration denied", // 3 + "Registration unknown", // 4 + "Registered, roaming", // 5 + "Registered, home (SMS only)", // 6 + "Registered, roaming (SMS only)", // 7 + "Registered, emergency service only", // 8 + "Registered, home, CSFB not preferred", // 9 + "Registered, roaming, CSFB not prefered" // 10 }; // If you are based in Europe, you will (probably) need to select MNO_STD_EUROPE @@ -42,82 +41,84 @@ const mobile_network_operator_t MOBILE_NETWORK_OPERATOR = MNO_GLOBAL; void setup() { - Serial.begin(115200); // Start the serial console - - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 2 - Network Info")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); - - Serial.println(F("Beginning...")); - - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); - - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); - - if (!myModule.setNetworkProfile(MOBILE_NETWORK_OPERATOR)) - { - Serial.println(F("Error setting network. Try cycling the power.")); - while (1) ; - } - - Serial.println(F("Network profile set. Ready to go!")); - - // RSSI: Received signal strength: - Serial.println("RSSI: " + String(myModule.rssi())); - // Registration Status - int regStatus = myModule.registration(); - if ((regStatus >= 0) && (regStatus <= 10)) - { - Serial.println("Network registration: " + registrationString[regStatus]); - } - - // Print the Context IDs, Access Point Names and IP Addresses - Serial.println(F("Available PDP (Packet Data Protocol) APNs (Access Point Names) and IP Addresses:")); - Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); - for (int cid = 0; cid < UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) - { - String apn = ""; - IPAddress ip(0, 0, 0, 0); - myModule.getAPN(cid, &apn, &ip); - if (apn.length() > 0) + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 2 - Network Info")); + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); + + if (!myModule.setNetworkProfile(MOBILE_NETWORK_OPERATOR)) + { + Serial.println(F("Error setting network. Try cycling the power.")); + while (1) + ; + } + + Serial.println(F("Network profile set. Ready to go!")); + + // RSSI: Received signal strength: + Serial.println("RSSI: " + String(myModule.rssi())); + // Registration Status + int regStatus = myModule.registration(); + if ((regStatus >= 0) && (regStatus <= 10)) + { + Serial.println("Network registration: " + registrationString[regStatus]); + } + + // Print the Context IDs, Access Point Names and IP Addresses + Serial.println(F("Available PDP (Packet Data Protocol) APNs (Access Point Names) and IP Addresses:")); + Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); + for (int cid = 0; cid < UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) + { + String apn = ""; + IPAddress ip(0, 0, 0, 0); + myModule.getAPN(cid, &apn, &ip); + if (apn.length() > 0) + { + Serial.print(cid); + Serial.print(F("\t\t")); + Serial.print(apn); + Serial.print(F("\t")); + Serial.println(ip); + } + } + + Serial.println(); + + if (regStatus > 0) { - Serial.print(cid); - Serial.print(F("\t\t")); - Serial.print(apn); - Serial.print(F("\t")); - Serial.println(ip); + Serial.println(F("All set. Go to the next example!")); } - } - - Serial.println(); - - if (regStatus > 0) - { - Serial.println(F("All set. Go to the next example!")); - } } void loop() { - // Do nothing. Now that we're registered move on to the next example. + // Do nothing. Now that we're registered move on to the next example. } \ No newline at end of file diff --git a/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino b/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino index 6532dc8..324b2bc 100644 --- a/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino +++ b/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino @@ -22,34 +22,48 @@ UBX_CELL myModule; // This example works with all modules, so the base class can // LARA_R6801D myModule; // Map registration status messages to more readable strings -String registrationString[] = -{ - "Not registered", // 0 - "Registered, home", // 1 - "Searching for operator", // 2 - "Registration denied", // 3 - "Registration unknown", // 4 - "Registered, roaming", // 5 - "Registered, home (SMS only)", // 6 - "Registered, roaming (SMS only)", // 7 - "Registered, emergency service only", // 8 - "Registered, home, CSFB not preferred", // 9 - "Registered, roaming, CSFB not prefered" // 10 +String registrationString[] = { + "Not registered", // 0 + "Registered, home", // 1 + "Searching for operator", // 2 + "Registration denied", // 3 + "Registration unknown", // 4 + "Registered, roaming", // 5 + "Registered, home (SMS only)", // 6 + "Registered, roaming (SMS only)", // 7 + "Registered, emergency service only", // 8 + "Registered, home, CSFB not preferred", // 9 + "Registered, roaming, CSFB not prefered" // 10 }; // If you are based in Europe, you will (probably) need to select MNO_STD_EUROPE const mobile_network_operator_t MOBILE_NETWORK_OPERATOR = MNO_GLOBAL; -const String MOBILE_NETWORK_STRINGS[] = {"default (Undefined/Regulatory)", "SIM ICCID", "AT&T", "Verizon", - "Telstra", "T-Mobile US", "China Telecom", "Sprint", "Vodafone", "NTT DoCoMo", "Telus", "SoftBank", - "Deutsche Telekom", "US Cellular", "SKT", "global (factory default)", "standard Europe", - "standard Europe No-ePCO", "NOT RECOGNIZED"}; +const String MOBILE_NETWORK_STRINGS[] = {"default (Undefined/Regulatory)", + "SIM ICCID", + "AT&T", + "Verizon", + "Telstra", + "T-Mobile US", + "China Telecom", + "Sprint", + "Vodafone", + "NTT DoCoMo", + "Telus", + "SoftBank", + "Deutsche Telekom", + "US Cellular", + "SKT", + "global (factory default)", + "standard Europe", + "standard Europe No-ePCO", + "NOT RECOGNIZED"}; // Convert the operator number into an index for MOBILE_NETWORK_STRINGS -int convertOperatorNumber( mobile_network_operator_t mno) +int convertOperatorNumber(mobile_network_operator_t mno) { - switch (mno) - { + switch (mno) + { case 0: case 1: case 2: @@ -57,32 +71,32 @@ int convertOperatorNumber( mobile_network_operator_t mno) case 4: case 5: case 6: - return ((int)mno); + return ((int)mno); case 8: - return 7; + return 7; case 19: - return 8; + return 8; case 20: - return 9; + return 9; case 21: - return 10; + return 10; case 28: - return 11; + return 11; case 31: - return 12; + return 12; case 32: - return 13; + return 13; case 39: - return 14; + return 14; case 90: - return 15; + return 15; case 100: - return 16; + return 16; case 101: - return 17; + return 17; default: // NOT RECOGNIZED - return 18; - } + return 18; + } } // This defines the size of the ops struct array. To narrow the operator @@ -91,236 +105,255 @@ int convertOperatorNumber( mobile_network_operator_t mno) #define MAX_OPERATORS 10 // Uncomment this line if you want to be able to communicate directly with the module in the main loop -//#define DEBUG_PASSTHROUGH_ENABLED +// #define DEBUG_PASSTHROUGH_ENABLED void setup() { - int opsAvailable; - struct operator_stats ops[MAX_OPERATORS]; - String currentOperator = ""; - bool newConnection = true; + int opsAvailable; + struct operator_stats ops[MAX_OPERATORS]; + String currentOperator = ""; + bool newConnection = true; - Serial.begin(115200); // Start the serial console + Serial.begin(115200); // Start the serial console - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 3 - Register Operator")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 3 - Register Operator")); + Serial.println(F("Press any key to begin")); - Serial.println(F("Beginning...")); + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + Serial.println(F("Beginning...")); - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); - // First check to see if we're already connected to an operator: - if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) { - Serial.print(F("Already connected to: ")); - Serial.println(currentOperator); - // If already connected provide the option to type y to connect to new operator - Serial.println(F("Press y to connect to a new operator, or any other key to continue.\r\n")); - while (!Serial.available()) ; - if (Serial.read() != 'y') + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) { - newConnection = false; + Serial.println(F("Module connected!")); } else { - myModule.deregisterOperator(); // Deregister from the current operator so we can connect to a new one + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail } - while (Serial.available()) Serial.read(); - } + Serial.println(); - if (newConnection) { - // Set MNO to either Verizon, T-Mobile, AT&T, Telstra, etc. - // This will narrow the operator options during our scan later - Serial.println(F("Setting mobile-network operator")); - if (myModule.setNetworkProfile(MOBILE_NETWORK_OPERATOR)) + // First check to see if we're already connected to an operator: + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) { - Serial.print(F("Set mobile network operator to ")); - Serial.println(MOBILE_NETWORK_STRINGS[convertOperatorNumber(MOBILE_NETWORK_OPERATOR)] + "\r\n"); + Serial.print(F("Already connected to: ")); + Serial.println(currentOperator); + // If already connected provide the option to type y to connect to new operator + Serial.println(F("Press y to connect to a new operator, or any other key to continue.\r\n")); + while (!Serial.available()) + ; + if (Serial.read() != 'y') + { + newConnection = false; + } + else + { + myModule.deregisterOperator(); // Deregister from the current operator so we can connect to a new one + } + while (Serial.available()) + Serial.read(); } - else + + if (newConnection) { - Serial.println(F("Error setting MNO. Try cycling the power. Freezing...")); - while (1) ; - } - - // Wait for user to press button before initiating network scan. - Serial.println(F("Press any key scan for networks..")); - serialWait(); + // Set MNO to either Verizon, T-Mobile, AT&T, Telstra, etc. + // This will narrow the operator options during our scan later + Serial.println(F("Setting mobile-network operator")); + if (myModule.setNetworkProfile(MOBILE_NETWORK_OPERATOR)) + { + Serial.print(F("Set mobile network operator to ")); + Serial.println(MOBILE_NETWORK_STRINGS[convertOperatorNumber(MOBILE_NETWORK_OPERATOR)] + "\r\n"); + } + else + { + Serial.println(F("Error setting MNO. Try cycling the power. Freezing...")); + while (1) + ; + } - Serial.println(F("Scanning for networks...this may take up to 3 minutes\r\n")); - // myModule.getOperators takes in a operator_stats struct pointer and max number of - // structs to scan for, then fills up those objects with operator names and numbers - opsAvailable = myModule.getOperators(ops, MAX_OPERATORS); // This will block for up to 3 minutes + // Wait for user to press button before initiating network scan. + Serial.println(F("Press any key scan for networks..")); + serialWait(); - if (opsAvailable > 0) - { - // Pretty-print operators we found: - Serial.println("Found " + String(opsAvailable) + " operators:"); - printOperators(ops, opsAvailable); - Serial.println(String(opsAvailable + 1) + ": use automatic selection"); - Serial.println(); + Serial.println(F("Scanning for networks...this may take up to 3 minutes\r\n")); + // myModule.getOperators takes in a operator_stats struct pointer and max number of + // structs to scan for, then fills up those objects with operator names and numbers + opsAvailable = myModule.getOperators(ops, MAX_OPERATORS); // This will block for up to 3 minutes - // Wait until the user presses a key to initiate an operator connection - Serial.println("Press 1-" + String(opsAvailable + 1) + " to select an operator."); - char c = 0; - bool selected = false; - while (!selected) { - while (!Serial.available()) ; - c = Serial.read(); - int selection = c - '0'; - if ((selection >= 1) && (selection <= (opsAvailable + 1))) { - selected = true; - Serial.println("Connecting to option " + String(selection)); - if (selection == (opsAvailable + 1)) - { - if (myModule.automaticOperatorSelection() == UBX_CELL_SUCCESS) - { - Serial.println("Automatic operator selection: successful\r\n"); - } - else - { - Serial.println(F("Automatic operator selection: error. Reset and try again, or try another network.")); - } - } - else - { - if (myModule.registerOperator(ops[selection - 1]) == UBX_CELL_SUCCESS) - { - Serial.println("Network " + ops[selection - 1].longOp + " registered\r\n"); - } - else + if (opsAvailable > 0) + { + // Pretty-print operators we found: + Serial.println("Found " + String(opsAvailable) + " operators:"); + printOperators(ops, opsAvailable); + Serial.println(String(opsAvailable + 1) + ": use automatic selection"); + Serial.println(); + + // Wait until the user presses a key to initiate an operator connection + Serial.println("Press 1-" + String(opsAvailable + 1) + " to select an operator."); + char c = 0; + bool selected = false; + while (!selected) { - Serial.println(F("Error connecting to operator. Reset and try again, or try another network.")); + while (!Serial.available()) + ; + c = Serial.read(); + int selection = c - '0'; + if ((selection >= 1) && (selection <= (opsAvailable + 1))) + { + selected = true; + Serial.println("Connecting to option " + String(selection)); + if (selection == (opsAvailable + 1)) + { + if (myModule.automaticOperatorSelection() == UBX_CELL_SUCCESS) + { + Serial.println("Automatic operator selection: successful\r\n"); + } + else + { + Serial.println( + F("Automatic operator selection: error. Reset and try again, or try another network.")); + } + } + else + { + if (myModule.registerOperator(ops[selection - 1]) == UBX_CELL_SUCCESS) + { + Serial.println("Network " + ops[selection - 1].longOp + " registered\r\n"); + } + else + { + Serial.println( + F("Error connecting to operator. Reset and try again, or try another network.")); + } + } + } } - } } - } - } - else - { - Serial.println(F("Did not find an operator. Double-check SIM and antenna, reset and try again, or try another network.")); - while (1) ; + else + { + Serial.println(F("Did not find an operator. Double-check SIM and antenna, reset and try again, or try " + "another network.")); + while (1) + ; + } } - } - // At the very end print connection information - printInfo(); + // At the very end print connection information + printInfo(); } void loop() { - // Loop provides a debugging interface. - if (mySerial.available()) { - Serial.write((char) mySerial.read()); - } + // Loop provides a debugging interface. + if (mySerial.available()) + { + Serial.write((char)mySerial.read()); + } #ifdef DEBUG_PASSTHROUGH_ENABLED - if (Serial.available()) { - mySerial.write((char) Serial.read()); - } + if (Serial.available()) + { + mySerial.write((char)Serial.read()); + } #endif } -void printInfo(void) { - String currentApn = ""; - IPAddress ip(0, 0, 0, 0); - String currentOperator = ""; - - Serial.println(F("Connection info:")); - Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); - for (int cid = 0; cid < UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) - { - String apn = ""; +void printInfo(void) +{ + String currentApn = ""; IPAddress ip(0, 0, 0, 0); - myModule.getAPN(cid, &apn, &ip); - if (apn.length() > 0) + String currentOperator = ""; + + Serial.println(F("Connection info:")); + Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); + for (int cid = 0; cid < UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) { - Serial.print(cid); - Serial.print(F("\t\t")); - Serial.print(apn); - Serial.print(F("\t")); - Serial.println(ip); + String apn = ""; + IPAddress ip(0, 0, 0, 0); + myModule.getAPN(cid, &apn, &ip); + if (apn.length() > 0) + { + Serial.print(cid); + Serial.print(F("\t\t")); + Serial.print(apn); + Serial.print(F("\t")); + Serial.println(ip); + } } - } - // Operator name or number - if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) - { - Serial.print(F("Operator: ")); - Serial.println(currentOperator); - } + // Operator name or number + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) + { + Serial.print(F("Operator: ")); + Serial.println(currentOperator); + } - // Received signal strength - Serial.println("RSSI: " + String(myModule.rssi())); - Serial.println(); + // Received signal strength + Serial.println("RSSI: " + String(myModule.rssi())); + Serial.println(); } -void printOperators(struct operator_stats * ops, int operatorsAvailable) +void printOperators(struct operator_stats *ops, int operatorsAvailable) { - for (int i = 0; i < operatorsAvailable; i++) - { - Serial.print(String(i + 1) + ": "); - Serial.print(ops[i].longOp + " (" + String(ops[i].numOp) + ") - "); - switch (ops[i].stat) + for (int i = 0; i < operatorsAvailable; i++) { - case 0: - Serial.print(F("UNKNOWN")); - break; - case 1: - Serial.print(F("AVAILABLE")); - break; - case 2: - Serial.print(F("CURRENT")); - break; - case 3: - Serial.print(F("FORBIDDEN")); - break; - } - switch (ops[i].act) - { - case 0: - Serial.print(F(" - GSM")); - break; - case 2: - Serial.print(F(" - UTRAN")); - break; - case 3: - Serial.print(F(" - GSM/GPRS with EDGE")); - break; - case 7: - Serial.print(F(" - LTE")); // SARA-R5 only supports LTE - break; + Serial.print(String(i + 1) + ": "); + Serial.print(ops[i].longOp + " (" + String(ops[i].numOp) + ") - "); + switch (ops[i].stat) + { + case 0: + Serial.print(F("UNKNOWN")); + break; + case 1: + Serial.print(F("AVAILABLE")); + break; + case 2: + Serial.print(F("CURRENT")); + break; + case 3: + Serial.print(F("FORBIDDEN")); + break; + } + switch (ops[i].act) + { + case 0: + Serial.print(F(" - GSM")); + break; + case 2: + Serial.print(F(" - UTRAN")); + break; + case 3: + Serial.print(F(" - GSM/GPRS with EDGE")); + break; + case 7: + Serial.print(F(" - LTE")); // SARA-R5 only supports LTE + break; + } + Serial.println(); } Serial.println(); - } - Serial.println(); } void serialWait() { - while (Serial.available()) Serial.read(); - while (!Serial.available()) ; - delay(100); - while (Serial.available()) Serial.read(); + while (Serial.available()) + Serial.read(); + while (!Serial.available()) + ; + delay(100); + while (Serial.available()) + Serial.read(); } \ No newline at end of file diff --git a/examples/Example4_Clock/Example4_Clock.ino b/examples/Example4_Clock/Example4_Clock.ino index a7a1b25..2e3232b 100644 --- a/examples/Example4_Clock/Example4_Clock.ino +++ b/examples/Example4_Clock/Example4_Clock.ino @@ -23,58 +23,60 @@ UBX_CELL myModule; // This example works with all modules, so the base class can void setup() { - String currentOperator = ""; + String currentOperator = ""; - Serial.begin(115200); // Start the serial console + Serial.begin(115200); // Start the serial console - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 4 - Clock")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 4 - Clock")); + Serial.println(F("Press any key to begin")); - Serial.println(F("Beginning...")); + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + Serial.println(F("Beginning...")); - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); - // Make sure automatic time zone updates are enabled - if (myModule.autoTimeZone(true) != UBX_CELL_SUCCESS) - Serial.println(F("Enable autoTimeZone failed!")); + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); - // Read and print the clock as a String - String theTime = myModule.clock(); - Serial.println(theTime); + // Make sure automatic time zone updates are enabled + if (myModule.autoTimeZone(true) != UBX_CELL_SUCCESS) + Serial.println(F("Enable autoTimeZone failed!")); - // Read and print the hour, minute, etc. separately - uint8_t year, month, day, hour, minute, second; - int8_t timeZone; - if (myModule.clock( &year, &month, &day, &hour, &minute, &second, &timeZone ) == UBX_CELL_SUCCESS) - // Note: not all Arduino boards implement printf correctly. The formatting may not be correct on some boards. - // Note: the timeZone is defined in 15 minute increments, not hours. -28 indicates the time zone is 7 hours behind UTC/GMT. - Serial.printf("%02d/%02d/%02d %02d:%02d:%02d %+d\r\n", year, month, day, hour, minute, second, timeZone); + // Read and print the clock as a String + String theTime = myModule.clock(); + Serial.println(theTime); + + // Read and print the hour, minute, etc. separately + uint8_t year, month, day, hour, minute, second; + int8_t timeZone; + if (myModule.clock(&year, &month, &day, &hour, &minute, &second, &timeZone) == UBX_CELL_SUCCESS) + // Note: not all Arduino boards implement printf correctly. The formatting may not be correct on some boards. + // Note: the timeZone is defined in 15 minute increments, not hours. -28 indicates the time zone is 7 hours + // behind UTC/GMT. + Serial.printf("%02d/%02d/%02d %02d:%02d:%02d %+d\r\n", year, month, day, hour, minute, second, timeZone); } void loop() { - // Nothing to do here + // Nothing to do here } \ No newline at end of file diff --git a/examples/Example5_Ping/Example5_Ping.ino b/examples/Example5_Ping/Example5_Ping.ino index 1de835c..3cc6678 100644 --- a/examples/Example5_Ping/Example5_Ping.ino +++ b/examples/Example5_Ping/Example5_Ping.ino @@ -23,118 +23,120 @@ UBX_CELL myModule; // This example works with all modules, so the base class can String pingMe = ""; // The name of the server we are going to ping -// processPingResult is provided to the u-blox cellular library via a +// processPingResult is provided to the u-blox cellular library via a // callback setter -- setPingCallback. (See the end of setup()) void processPingResult(int retry, int p_size, String remote_hostname, IPAddress ip, int ttl, long rtt) { - Serial.println(); - Serial.print(F("Ping Result: Retry #:")); - Serial.print(retry); - Serial.print(F(" Ping Size (Bytes):")); - Serial.print(p_size); - Serial.print(F(" Remote Host:\"")); - Serial.print(remote_hostname); - Serial.print(F("\" IP Address:\"")); - Serial.print(String(ip[0])); - Serial.print(F(".")); - Serial.print(String(ip[1])); - Serial.print(F(".")); - Serial.print(String(ip[2])); - Serial.print(F(".")); - Serial.print(String(ip[3])); - Serial.print(F("\" Time To Live (hops):")); - Serial.print(ttl); - Serial.print(F(" Round Trip (ms):")); - Serial.print(rtt); - Serial.println(); + Serial.println(); + Serial.print(F("Ping Result: Retry #:")); + Serial.print(retry); + Serial.print(F(" Ping Size (Bytes):")); + Serial.print(p_size); + Serial.print(F(" Remote Host:\"")); + Serial.print(remote_hostname); + Serial.print(F("\" IP Address:\"")); + Serial.print(String(ip[0])); + Serial.print(F(".")); + Serial.print(String(ip[1])); + Serial.print(F(".")); + Serial.print(String(ip[2])); + Serial.print(F(".")); + Serial.print(String(ip[3])); + Serial.print(F("\" Time To Live (hops):")); + Serial.print(ttl); + Serial.print(F(" Round Trip (ms):")); + Serial.print(rtt); + Serial.println(); } void setup() { - String currentOperator = ""; - - Serial.begin(115200); // Start the serial console - - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 5 - Ping")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); - - Serial.println(F("Beginning...")); - - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); - - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); - - // First check to see if we're connected to an operator: - if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) - { - Serial.print(F("Connected to: ")); - Serial.println(currentOperator); - } - else - { - Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); - while (1) - ; // Do nothing more - } - - Serial.println(); - Serial.println(F("*** Set the Serial Monitor line ending to Newline ***")); - - Serial.println(); - Serial.println(F("Enter the name of the server you want to ping (followed by LF / Newline): ")); - Serial.println(F("Example: \"www.google.com\"")); - - // Set a callback to process the Ping result - myModule.setPingCallback(&processPingResult); -} + String currentOperator = ""; -void loop() -{ - if (Serial.available()) - { - char c = Serial.read(); - if (c == '\n') + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 5 - Ping")); + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) { - // Newline received so let's do that ping! - Serial.println("Pinging " + pingMe + "..."); - myModule.ping(pingMe); // Use the default parameters - - // Use custom parameters - //int retries = 4; // number of retries - //int p_size = 32; // packet size (bytes) - //unsigned long timeout = 5000; // timeout (ms) - //int ttl = 32; // Time To Live - //myModule.ping(pingMe, retries, p_size, timeout, ttl); - - pingMe = ""; // Clear the server name for the next try + Serial.println(F("Module connected!")); } else { - // Add serial characters to the server address - pingMe += c; + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); + + // First check to see if we're connected to an operator: + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) + { + Serial.print(F("Connected to: ")); + Serial.println(currentOperator); } - } - - myModule.poll(); // Keep processing data from the module so we can catch the Ping result + else + { + Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. " + "Or wait and retry. Freezing...")); + while (1) + ; // Do nothing more + } + + Serial.println(); + Serial.println(F("*** Set the Serial Monitor line ending to Newline ***")); + + Serial.println(); + Serial.println(F("Enter the name of the server you want to ping (followed by LF / Newline): ")); + Serial.println(F("Example: \"www.google.com\"")); + + // Set a callback to process the Ping result + myModule.setPingCallback(&processPingResult); +} + +void loop() +{ + if (Serial.available()) + { + char c = Serial.read(); + if (c == '\n') + { + // Newline received so let's do that ping! + Serial.println("Pinging " + pingMe + "..."); + myModule.ping(pingMe); // Use the default parameters + + // Use custom parameters + // int retries = 4; // number of retries + // int p_size = 32; // packet size (bytes) + // unsigned long timeout = 5000; // timeout (ms) + // int ttl = 32; // Time To Live + // myModule.ping(pingMe, retries, p_size, timeout, ttl); + + pingMe = ""; // Clear the server name for the next try + } + else + { + // Add serial characters to the server address + pingMe += c; + } + } + + myModule.poll(); // Keep processing data from the module so we can catch the Ping result } \ No newline at end of file diff --git a/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino b/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino index ae5a336..416b45f 100644 --- a/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino +++ b/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino @@ -23,234 +23,239 @@ UBX_CELL myModule; // This example works with all modules, so the base class can void setup() { - String currentOperator = ""; + String currentOperator = ""; - Serial.begin(115200); // Start the serial console + Serial.begin(115200); // Start the serial console - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 6 - Receive SMS")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 6 - Receive SMS")); + Serial.println(F("Press any key to begin")); - Serial.println(F("Beginning...")); + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + Serial.println(F("Beginning...")); - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); - // First check to see if we're connected to an operator: - if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) - { - Serial.print(F("Connected to: ")); - Serial.println(currentOperator); - } - else - { - Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); - while (1) - ; // Do nothing more - } + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); + + // First check to see if we're connected to an operator: + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) + { + Serial.print(F("Connected to: ")); + Serial.println(currentOperator); + } + else + { + Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. " + "Or wait and retry. Freezing...")); + while (1) + ; // Do nothing more + } - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); } void loop() { - static bool printReadMessages = true; // Print all messages once. Then only print new messages. Unless a message is deleted. - static int previousUsed = -1; // Store the previous number of used memory locations - - // Read the number of used and total messages - int used; - int total; - if (myModule.getPreferredMessageStorage(&used, &total) != UBX_CELL_SUCCESS) - { - Serial.println(F("An error occurred when trying to read ME memory!")); - } - else - { - if ((used != previousUsed) || printReadMessages) // Has a new message arrived? Or was the delete menu opened? - { - Serial.print(F("\r\nNumber of used memory locations: ")); - Serial.println(used); - Serial.print(F("Total number of memory locations: ")); - Serial.println(total); - Serial.println(); + static bool printReadMessages = + true; // Print all messages once. Then only print new messages. Unless a message is deleted. + static int previousUsed = -1; // Store the previous number of used memory locations - int memoryLocation = 0; - int foundMessages = 0; - // Keep reading until we find all the messages or we reach the end of the memory - while ((foundMessages < used) && (memoryLocation <= total)) - { - String unread = ""; - String from = ""; - String dateTime = ""; - String message = ""; - // Read the message from this location. Reading from empty message locations returns an ERROR - // unread can be: "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT" - // If the location is empty, readSMSmessage will return a UBX_CELL_ERROR_UNEXPECTED_RESPONSE - if (myModule.readSMSmessage(memoryLocation, &unread, &from, &dateTime, &message) == UBX_CELL_SUCCESS) + // Read the number of used and total messages + int used; + int total; + if (myModule.getPreferredMessageStorage(&used, &total) != UBX_CELL_SUCCESS) + { + Serial.println(F("An error occurred when trying to read ME memory!")); + } + else + { + if ((used != previousUsed) || printReadMessages) // Has a new message arrived? Or was the delete menu opened? { - if (printReadMessages || (unread == "REC UNREAD")) - { - Serial.print(F("Message location: ")); - Serial.println(memoryLocation); - Serial.print(F("Status: ")); - Serial.println(unread); - Serial.print(F("Originator: ")); - Serial.println(from); - Serial.print(F("Date and time: ")); - Serial.println(dateTime); - Serial.println(message); + Serial.print(F("\r\nNumber of used memory locations: ")); + Serial.println(used); + Serial.print(F("Total number of memory locations: ")); + Serial.println(total); Serial.println(); - } - foundMessages++; // We found a message - } - memoryLocation++; // Move on to the next memory location - } - printReadMessages = false; - previousUsed = used; // Update previousUsed + int memoryLocation = 0; + int foundMessages = 0; + // Keep reading until we find all the messages or we reach the end of the memory + while ((foundMessages < used) && (memoryLocation <= total)) + { + String unread = ""; + String from = ""; + String dateTime = ""; + String message = ""; + // Read the message from this location. Reading from empty message locations returns an ERROR + // unread can be: "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT" + // If the location is empty, readSMSmessage will return a UBX_CELL_ERROR_UNEXPECTED_RESPONSE + if (myModule.readSMSmessage(memoryLocation, &unread, &from, &dateTime, &message) == UBX_CELL_SUCCESS) + { + if (printReadMessages || (unread == "REC UNREAD")) + { + Serial.print(F("Message location: ")); + Serial.println(memoryLocation); + Serial.print(F("Status: ")); + Serial.println(unread); + Serial.print(F("Originator: ")); + Serial.println(from); + Serial.print(F("Date and time: ")); + Serial.println(dateTime); + Serial.println(message); + Serial.println(); + } + foundMessages++; // We found a message + } + memoryLocation++; // Move on to the next memory location + } - Serial.println(F("Waiting for a new message...")); - Serial.println(); - Serial.println(F("Hit any key to delete a message...")); - Serial.println(); - } - } + printReadMessages = false; + previousUsed = used; // Update previousUsed - int delayCount = 0; - while (delayCount < 5000) - { - delay(1); // Delay for five seconds, unless the user presses a key - delayCount++; + Serial.println(F("Waiting for a new message...")); + Serial.println(); + Serial.println(F("Hit any key to delete a message...")); + Serial.println(); + } + } - if (Serial.available()) + int delayCount = 0; + while (delayCount < 5000) { - Serial.println(F("To delete a single message: enter its location followed by LF / Newline")); - Serial.println(F("To delete all read messages: enter r followed by LF / Newline")); - Serial.println(F("To delete all read and sent messages: enter s followed by LF / Newline")); - Serial.println(F("To delete all read, sent and unsent messages: enter u followed by LF / Newline")); - Serial.println(F("To delete all messages, including unread messages: enter a followed by LF / Newline")); - Serial.println(F("To exit: enter LF / Newline")); + delay(1); // Delay for five seconds, unless the user presses a key + delayCount++; - Serial.read(); // Read and discard the char that opened the menu - - int location = 0; - bool selected = false; - while (!selected) - { - while (!Serial.available()) ; // Wait for a character to arrive - char c = Serial.read(); // Read it - if (c == '\n') // Is it a LF? + if (Serial.available()) { - if ((location >= 1) && (location <= total)) // Delete a single message at location - { - if (myModule.deleteSMSmessage(location) == UBX_CELL_SUCCESS) - { - Serial.println(F("\r\nMessage deleted!\r\n")); - printReadMessages = true; - } - else - { - Serial.println(F("\r\nMessage not deleted!\r\n")); - } - } - else if (location == 1001) // r - { - if (myModule.deleteReadSMSmessages() == UBX_CELL_SUCCESS) - { - Serial.println(F("\r\nRead messages deleted!\r\n")); - printReadMessages = true; - } - else - { - Serial.println(F("\r\nMessages not deleted!\r\n")); - } - } - else if (location == 1002) // s - { - if (myModule.deleteReadSentSMSmessages() == UBX_CELL_SUCCESS) - { - Serial.println(F("\r\nRead and sent messages deleted!\r\n")); - printReadMessages = true; - } - else - { - Serial.println(F("\r\nMessages not deleted!\r\n")); - } - } - else if (location == 1003) // u - { - if (myModule.deleteReadSentUnsentSMSmessages() == UBX_CELL_SUCCESS) - { - Serial.println(F("\r\nRead, sent and unsent messages deleted!\r\n")); - printReadMessages = true; - } - else - { - Serial.println(F("\r\nMessages not deleted!\r\n")); - } - } - else if (location == 1004) // a - { - if (myModule.deleteAllSMSmessages() == UBX_CELL_SUCCESS) - { - Serial.println(F("\r\nAll messages deleted!\r\n")); - printReadMessages = true; - } - else + Serial.println( + F("To delete a single message: enter its location followed by LF / Newline")); + Serial.println(F("To delete all read messages: enter r followed by LF / Newline")); + Serial.println(F("To delete all read and sent messages: enter s followed by LF / Newline")); + Serial.println(F("To delete all read, sent and unsent messages: enter u followed by LF / Newline")); + Serial.println(F("To delete all messages, including unread messages: enter a followed by LF / Newline")); + Serial.println(F("To exit: enter LF / Newline")); + + Serial.read(); // Read and discard the char that opened the menu + + int location = 0; + bool selected = false; + while (!selected) { - Serial.println(F("\r\nMessages not deleted!\r\n")); + while (!Serial.available()) + ; // Wait for a character to arrive + char c = Serial.read(); // Read it + if (c == '\n') // Is it a LF? + { + if ((location >= 1) && (location <= total)) // Delete a single message at location + { + if (myModule.deleteSMSmessage(location) == UBX_CELL_SUCCESS) + { + Serial.println(F("\r\nMessage deleted!\r\n")); + printReadMessages = true; + } + else + { + Serial.println(F("\r\nMessage not deleted!\r\n")); + } + } + else if (location == 1001) // r + { + if (myModule.deleteReadSMSmessages() == UBX_CELL_SUCCESS) + { + Serial.println(F("\r\nRead messages deleted!\r\n")); + printReadMessages = true; + } + else + { + Serial.println(F("\r\nMessages not deleted!\r\n")); + } + } + else if (location == 1002) // s + { + if (myModule.deleteReadSentSMSmessages() == UBX_CELL_SUCCESS) + { + Serial.println(F("\r\nRead and sent messages deleted!\r\n")); + printReadMessages = true; + } + else + { + Serial.println(F("\r\nMessages not deleted!\r\n")); + } + } + else if (location == 1003) // u + { + if (myModule.deleteReadSentUnsentSMSmessages() == UBX_CELL_SUCCESS) + { + Serial.println(F("\r\nRead, sent and unsent messages deleted!\r\n")); + printReadMessages = true; + } + else + { + Serial.println(F("\r\nMessages not deleted!\r\n")); + } + } + else if (location == 1004) // a + { + if (myModule.deleteAllSMSmessages() == UBX_CELL_SUCCESS) + { + Serial.println(F("\r\nAll messages deleted!\r\n")); + printReadMessages = true; + } + else + { + Serial.println(F("\r\nMessages not deleted!\r\n")); + } + } + else + Serial.println(F("\r\nExit...\r\n")); + selected = true; + } + else if ((c >= '0') && (c <= '9')) + { + location *= 10; // Multiply by 10 + location += c - '0'; // Add the digit + } + else if (c == 'r') + { + location = 1001; + } + else if (c == 's') + { + location = 1002; + } + else if (c == 'u') + { + location = 1003; + } + else if (c == 'a') + { + location = 1004; + } } - } - else - Serial.println(F("\r\nExit...\r\n")); - selected = true; - } - else if ((c >= '0') && (c <= '9')) - { - location *= 10; // Multiply by 10 - location += c - '0'; // Add the digit - } - else if (c == 'r') - { - location = 1001; - } - else if (c == 's') - { - location = 1002; - } - else if (c == 'u') - { - location = 1003; - } - else if (c == 'a') - { - location = 1004; - } - } - delayCount = 5000; + delayCount = 5000; + } } - } } \ No newline at end of file diff --git a/examples/Example7_SendSMS/Example7_SendSMS.ino b/examples/Example7_SendSMS/Example7_SendSMS.ino index 79bda44..8e6e11f 100644 --- a/examples/Example7_SendSMS/Example7_SendSMS.ino +++ b/examples/Example7_SendSMS/Example7_SendSMS.ino @@ -23,107 +23,109 @@ UBX_CELL myModule; // This example works with all modules, so the base class can void setup() { - String currentOperator = ""; - - Serial.begin(115200); // Start the serial console - - // Wait for user to press key to begin - Serial.println(F("u-blox Cellular Example 7 - Send SMS")); - Serial.println(F("Press any key to begin")); - - while (!Serial.available()) // Wait for the user to press a key (send any serial character) - ; - while (Serial.available()) // Empty the serial RX buffer - Serial.read(); - - Serial.println(F("Beginning...")); - - // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - - // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low - // Uncomment the next line if required - // myModule.invertPowerPin(true); - - // Initialize the module - if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) - { - Serial.println(F("Module connected!")); - } - else - { - Serial.println(F("Unable to communicate with the module.")); - Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); - while (1) ; // Loop forever on fail - } - Serial.println(); - - // First check to see if we're connected to an operator: - if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) - { - Serial.print(F("Connected to: ")); - Serial.println(currentOperator); - } - else - { - Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); - while (1) - ; // Do nothing more - } - - Serial.println(); - Serial.println(F("*** Set the Serial Monitor line ending to Newline ***")); + String currentOperator = ""; + + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Example 7 - Send SMS")); + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE)) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) + ; // Loop forever on fail + } + Serial.println(); + + // First check to see if we're connected to an operator: + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) + { + Serial.print(F("Connected to: ")); + Serial.println(currentOperator); + } + else + { + Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. " + "Or wait and retry. Freezing...")); + while (1) + ; // Do nothing more + } + + Serial.println(); + Serial.println(F("*** Set the Serial Monitor line ending to Newline ***")); } void loop() { - String destinationNumber = ""; - String message = ""; - boolean keepGoing = true; - - Serial.println(); - Serial.println(F("Enter the destination number (followed by LF / Newline): ")); - - while (keepGoing) - { - if (Serial.available()) + String destinationNumber = ""; + String message = ""; + boolean keepGoing = true; + + Serial.println(); + Serial.println(F("Enter the destination number (followed by LF / Newline): ")); + + while (keepGoing) + { + if (Serial.available()) + { + char c = Serial.read(); + if (c == '\n') + { + keepGoing = false; // Stop if we receive a newline + } + else + { + destinationNumber += c; // Add serial characters to the destination number + } + } + } + + keepGoing = true; + Serial.println(); + Serial.println(F("Enter the message (followed by LF): ")); + + while (keepGoing) { - char c = Serial.read(); - if (c == '\n') - { - keepGoing = false; // Stop if we receive a newline - } - else - { - destinationNumber += c; // Add serial characters to the destination number - } + if (Serial.available()) + { + char c = Serial.read(); + if (c == '\n') + { + keepGoing = false; // Stop if we receive a newline + } + else + { + message += c; // Add serial characters to the destination number + } + } } - } - - keepGoing = true; - Serial.println(); - Serial.println(F("Enter the message (followed by LF): ")); - - while (keepGoing) - { - if (Serial.available()) + + // Once we receive a newline, send the text. + Serial.println("Sending: \"" + message + "\" to " + destinationNumber); + // Call myModule.sendSMS(String number, String message) to send an SMS message. + if (myModule.sendSMS(destinationNumber, message) == UBX_CELL_SUCCESS) { - char c = Serial.read(); - if (c == '\n') - { - keepGoing = false; // Stop if we receive a newline - } - else - { - message += c; // Add serial characters to the destination number - } + Serial.println(F("sendSMS was successful")); } - } - - // Once we receive a newline, send the text. - Serial.println("Sending: \"" + message + "\" to " + destinationNumber); - // Call myModule.sendSMS(String number, String message) to send an SMS message. - if (myModule.sendSMS(destinationNumber, message) == UBX_CELL_SUCCESS) - { - Serial.println(F("sendSMS was successful")); - } } \ No newline at end of file From 6a7ee7ff973567e1c309b954755db73d55c18dee Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 18 Dec 2023 12:55:13 -0700 Subject: [PATCH 3/8] Change sprintf to snprintf --- src/sfe_sara_r5.cpp | 59 ++-- src/sfe_ublox_cellular.cpp | 607 ++++++++++++++++++++------------- src/sfe_ublox_cellular_voice.h | 25 +- 3 files changed, 411 insertions(+), 280 deletions(-) diff --git a/src/sfe_sara_r5.cpp b/src/sfe_sara_r5.cpp index 34a4992..ae66359 100644 --- a/src/sfe_sara_r5.cpp +++ b/src/sfe_sara_r5.cpp @@ -9,15 +9,16 @@ SARA_R5::SARA_R5() UBX_CELL_error_t SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utime_sensor_t sensor) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_TIME) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_TIME) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (mode == UBX_CELL_UTIME_MODE_STOP) // stop UTIME does not require a sensor - sprintf(command, "%s=%d", UBX_CELL_GNSS_REQUEST_TIME, mode); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_GNSS_REQUEST_TIME, mode); else - sprintf(command, "%s=%d,%d", UBX_CELL_GNSS_REQUEST_TIME, mode, sensor); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_GNSS_REQUEST_TIME, mode, sensor); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); free(command); @@ -27,16 +28,17 @@ UBX_CELL_error_t SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utim UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_utime_sensor_t *sensor) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_TIME) + 2; char *command; char *response; UBX_CELL_utime_mode_t m; UBX_CELL_utime_sensor_t s; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_TIME) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_REQUEST_TIME); + snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_REQUEST_TIME); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -83,12 +85,13 @@ UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_uti UBX_CELL_error_t SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t config) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_INDICATION) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_INDICATION) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_GNSS_TIME_INDICATION, config); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_GNSS_TIME_INDICATION, config); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -98,15 +101,16 @@ UBX_CELL_error_t SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t *config) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_INDICATION) + 2; char *command; char *response; UBX_CELL_utime_urc_configuration_t c; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_INDICATION) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_TIME_INDICATION); + snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_TIME_INDICATION); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -146,15 +150,16 @@ UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32_t offsetSeconds) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 48; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 48); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - sprintf(command, "%s=%d,%d", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); #else - sprintf(command, "%s=%ld,%ld", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); + snprintf(command, cmdLen, "%s=%ld,%ld", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); #endif err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -165,16 +170,17 @@ UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32 UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 2; char *command; char *response; int32_t ons; int32_t os; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_TIME_CONFIGURATION); + snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_TIME_CONFIGURATION); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -218,15 +224,16 @@ UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int3 UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, int value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 24; char *command; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 24); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -244,15 +251,16 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur String value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64; char *command; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value.c_str()); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -264,15 +272,16 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur IPAddress value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64; char *command; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value[0], value[1], + snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value[0], value[1], value[2], value[3]); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -284,15 +293,16 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur UBX_CELL_error_t SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t action) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_ACTION) + 32; char *command; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_ACTION) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_ACTION, profile, action); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_ACTION, profile, action); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -302,6 +312,7 @@ UBX_CELL_error_t SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t a UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *address) { + size_t cmdLen = strlen(UBX_CELL_NETWORK_ASSIGNED_DATA) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -310,10 +321,10 @@ UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *ad int paramTag = 0; // 0: IP address: dynamic IP address assigned during PDP context activation int paramVals[4]; - command = ubx_cell_calloc_char(strlen(UBX_CELL_NETWORK_ASSIGNED_DATA) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d", UBX_CELL_NETWORK_ASSIGNED_DATA, profile, paramTag); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_NETWORK_ASSIGNED_DATA, profile, paramTag); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index e7fbe8f..1238c76 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -969,10 +969,11 @@ UBX_CELL_error_t UBX_CELL::setRegistrationCallback(void (*registrationCallback)( { _registrationCallback = registrationCallback; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_REGISTRATION_STATUS) + 3); + size_t cmdLen = strlen(UBX_CELL_REGISTRATION_STATUS) + 3; + char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_REGISTRATION_STATUS, 2 /*enable URC with location*/); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_REGISTRATION_STATUS, 2 /*enable URC with location*/); UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -984,10 +985,11 @@ UBX_CELL_error_t UBX_CELL::setEpsRegistrationCallback( { _epsRegistrationCallback = registrationCallback; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3); + size_t cmdLen = strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3; + char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_EPSREGISTRATION_STATUS, 2 /*enable URC with location*/); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_EPSREGISTRATION_STATUS, 2 /*enable URC with location*/); UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -1021,12 +1023,13 @@ UBX_CELL_error_t UBX_CELL::at(void) UBX_CELL_error_t UBX_CELL::enableEcho(bool enable) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_ECHO) + 2; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_ECHO) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s%d", UBX_CELL_COMMAND_ECHO, enable ? 1 : 0); + snprintf(command, cmdLen, "%s%d", UBX_CELL_COMMAND_ECHO, enable ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -1267,15 +1270,16 @@ UBX_CELL_error_t UBX_CELL::reset(void) String UBX_CELL::clock(void) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + 2; char *command; char *response; char *clockBegin; char *clockEnd; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return ""; - sprintf(command, "%s?", UBX_CELL_COMMAND_CLOCK); + snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_CLOCK); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -1321,6 +1325,7 @@ String UBX_CELL::clock(void) UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s, int8_t *tz) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + 2; char *command; char *response; char tzPlusMinus; @@ -1328,10 +1333,10 @@ UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h int iy, imo, id, ih, imin, is, itz; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_COMMAND_CLOCK); + snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_CLOCK); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -1379,7 +1384,7 @@ UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h UBX_CELL_error_t UBX_CELL::setClock(uint8_t y, uint8_t mo, uint8_t d, uint8_t h, uint8_t min, uint8_t s, int8_t tz) { // Convert y,mo,d,h,min,s,tz into a String - // Some platforms don't support sprintf correctly (for %02d or %+02d) so we need to build the String manually + // Some platforms don't support snprintf correctly (for %02d or %+02d) so we need to build the String manually // Format is "yy/MM/dd,hh:mm:ss+TZ" // TZ can be +/- and is in increments of 15 minutes (not hours) @@ -1418,12 +1423,13 @@ UBX_CELL_error_t UBX_CELL::setClock(uint8_t y, uint8_t mo, uint8_t d, uint8_t h, UBX_CELL_error_t UBX_CELL::setClock(String theTime) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + theTime.length() + 8; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_CLOCK) + theTime.length() + 8); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_COMMAND_CLOCK, theTime.c_str()); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_COMMAND_CLOCK, theTime.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -1439,12 +1445,13 @@ void UBX_CELL::autoTimeZoneForBegin(bool tz) UBX_CELL_error_t UBX_CELL::autoTimeZone(bool enable) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_AUTO_TZ) + 3; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_AUTO_TZ) + 3); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_COMMAND_AUTO_TZ, enable ? 1 : 0); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_AUTO_TZ, enable ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -1453,15 +1460,16 @@ UBX_CELL_error_t UBX_CELL::autoTimeZone(bool enable) int8_t UBX_CELL::rssi(void) { + size_t cmdLen = strlen(UBX_CELL_SIGNAL_QUALITY) + 1; char *command; char *response; UBX_CELL_error_t err; int rssi; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SIGNAL_QUALITY) + 1); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s", UBX_CELL_SIGNAL_QUALITY); + snprintf(command, cmdLen, "%s", UBX_CELL_SIGNAL_QUALITY); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -1500,17 +1508,15 @@ int8_t UBX_CELL::rssi(void) UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) { + size_t cmdLen = strlen(UBX_CELL_EXT_SIGNAL_QUALITY) + 1; char *command; char *response; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(strlen(UBX_CELL_EXT_SIGNAL_QUALITY) + 1); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - - sprintf(command, "%s", UBX_CELL_EXT_SIGNAL_QUALITY); + snprintf(command, cmdLen, "%s", UBX_CELL_EXT_SIGNAL_QUALITY); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -1553,15 +1559,17 @@ UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) { + const char *tag = eps ? UBX_CELL_EPSREGISTRATION_STATUS : UBX_CELL_REGISTRATION_STATUS; + size_t cmdLen = strlen(tag) + 3; char *command; char *response; UBX_CELL_error_t err; int status; - const char *tag = eps ? UBX_CELL_EPSREGISTRATION_STATUS : UBX_CELL_REGISTRATION_STATUS; - command = ubx_cell_calloc_char(strlen(tag) + 3); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_REGISTRATION_INVALID; - sprintf(command, "%s?", tag); + snprintf(command, cmdLen, "%s?", tag); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -1648,6 +1656,7 @@ mobile_network_operator_t UBX_CELL::getNetworkProfile(void) UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdpType) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_DEF) + strlen(apn.c_str()) + 16; char *command; char pdpStr[8]; @@ -1656,7 +1665,7 @@ UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdp if (cid >= 8) return UBX_CELL_ERROR_UNEXPECTED_PARAM; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_DEF) + strlen(apn.c_str()) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; switch (pdpType) @@ -1686,7 +1695,7 @@ UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdp { if (_printDebug == true) _debugPort->println(F("setAPN: nullptr")); - sprintf(command, "%s=%d,\"%s\",\"\"", UBX_CELL_MESSAGE_PDP_DEF, cid, pdpStr); + snprintf(command, cmdLen, "%s=%d,\"%s\",\"\"", UBX_CELL_MESSAGE_PDP_DEF, cid, pdpStr); } else { @@ -1695,7 +1704,7 @@ UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdp _debugPort->print(F("setAPN: ")); _debugPort->println(apn); } - sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MESSAGE_PDP_DEF, cid, pdpStr, apn.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MESSAGE_PDP_DEF, cid, pdpStr, apn.c_str()); } err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -1709,16 +1718,17 @@ UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdp UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_pdp_type *pdpType) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_DEF) + 3; char *command; char *response; if (cid > UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_DEF) + 3); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_MESSAGE_PDP_DEF); + snprintf(command, cmdLen, "%s?", UBX_CELL_MESSAGE_PDP_DEF); response = ubx_cell_calloc_char(1024); if (response == nullptr) @@ -1799,12 +1809,14 @@ UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_ UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_SIMPIN) + 2; char *command; char *response; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_SIMPIN) + 2); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_COMMAND_SIMPIN); + snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_SIMPIN); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) { @@ -1843,11 +1855,13 @@ UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) UBX_CELL_error_t UBX_CELL::setSimPin(String pin) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_SIMPIN) + 4 + pin.length(); char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_SIMPIN) + 4 + pin.length()); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_COMMAND_SIMPIN, pin.c_str()); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_COMMAND_SIMPIN, pin.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -1856,12 +1870,13 @@ UBX_CELL_error_t UBX_CELL::setSimPin(String pin) UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_SIM_STATE) + 4; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SIM_STATE) + 4); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_SIM_STATE, mode); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_SIM_STATE, mode); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -1871,15 +1886,16 @@ UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_SIM_STATE) + 3; char *command; char *response; int m; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SIM_STATE) + 3); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_SIM_STATE); + snprintf(command, cmdLen, "%s?", UBX_CELL_SIM_STATE); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -1922,6 +1938,7 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne UBX_CELL::UBX_CELL_l2p_t l2p) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_ENTER_PPP) + 32; char *command; if ((dialing_type_char != 0) && (dialing_type_char != 'T') && (dialing_type_char != 'P')) @@ -1929,17 +1946,17 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne return UBX_CELL_ERROR_UNEXPECTED_PARAM; } - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_ENTER_PPP) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (dialing_type_char != 0) { - sprintf(command, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, dialNumber, PPP_L2P[l2p], + snprintf(command, cmdLen, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, dialNumber, PPP_L2P[l2p], (unsigned int)cid); } else { - sprintf(command, "%s*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialNumber, PPP_L2P[l2p], (unsigned int)cid); + snprintf(command, cmdLen, "%s*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialNumber, PPP_L2P[l2p], (unsigned int)cid); } err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -1951,14 +1968,15 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 3; char *command; char *response; uint8_t opsSeen = 0; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 3); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=?", UBX_CELL_OPERATOR_SELECTION); + snprintf(command, cmdLen, "%s=?", UBX_CELL_OPERATOR_SELECTION); int responseSize = (maxOps + 1) * 48; response = ubx_cell_calloc_char(responseSize); @@ -2035,12 +2053,13 @@ uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 24; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 24); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=1,2,\"%lu\"", UBX_CELL_OPERATOR_SELECTION, oper.numOp); + snprintf(command, cmdLen, "%s=1,2,\"%lu\"", UBX_CELL_OPERATOR_SELECTION, oper.numOp); // AT+COPS maximum response time is 3 minutes (180000 ms) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); @@ -2052,12 +2071,13 @@ UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 6; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 6); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=0,0", UBX_CELL_OPERATOR_SELECTION); + snprintf(command, cmdLen, "%s=0,0", UBX_CELL_OPERATOR_SELECTION); // AT+COPS maximum response time is 3 minutes (180000 ms) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); @@ -2069,15 +2089,16 @@ UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() UBX_CELL_error_t UBX_CELL::getOperator(String *oper) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 3; char *command; char *response; char *searchPtr; char mode; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 3); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_OPERATOR_SELECTION); + snprintf(command, cmdLen, "%s?", UBX_CELL_OPERATOR_SELECTION); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -2135,12 +2156,13 @@ UBX_CELL_error_t UBX_CELL::getOperator(String *oper) UBX_CELL_error_t UBX_CELL::deregisterOperator(void) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 6; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_OPERATOR_SELECTION) + 4); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=2", UBX_CELL_OPERATOR_SELECTION); + snprintf(command, cmdLen, "%s=2", UBX_CELL_OPERATOR_SELECTION); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); @@ -2150,13 +2172,14 @@ UBX_CELL_error_t UBX_CELL::deregisterOperator(void) UBX_CELL_error_t UBX_CELL::setSMSMessageFormat(UBX_CELL_message_format_t textMode) { + size_t cmdLen = strlen(UBX_CELL_MESSAGE_FORMAT) + 4; char *command; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_FORMAT) + 4); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MESSAGE_FORMAT, (textMode == UBX_CELL_MESSAGE_FORMAT_TEXT) ? 1 : 0); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_MESSAGE_FORMAT, (textMode == UBX_CELL_MESSAGE_FORMAT_TEXT) ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -2176,10 +2199,11 @@ UBX_CELL_error_t UBX_CELL::sendSMS(String number, String message) return UBX_CELL_ERROR_OUT_OF_MEMORY; number.toCharArray(numberCStr, number.length() + 1); - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEND_TEXT) + strlen(numberCStr) + 8); + size_t cmdLen = strlen(UBX_CELL_SEND_TEXT) + strlen(numberCStr) + 8; + command = ubx_cell_calloc_char(cmdLen); if (command != nullptr) { - sprintf(command, "%s=\"%s\"", UBX_CELL_SEND_TEXT, numberCStr); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_SEND_TEXT, numberCStr); err = sendCommandWithResponse(command, ">", nullptr, UBX_CELL_10_SEC_TIMEOUT); free(command); @@ -2213,15 +2237,16 @@ UBX_CELL_error_t UBX_CELL::sendSMS(String number, String message) UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, String memory) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_PREF_MESSAGE_STORE) + 32; char *command; char *response; int u; int t; - command = ubx_cell_calloc_char(strlen(UBX_CELL_PREF_MESSAGE_STORE) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_PREF_MESSAGE_STORE, memory.c_str()); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_PREF_MESSAGE_STORE, memory.c_str()); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -2275,13 +2300,14 @@ UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, Str UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_READ_TEXT_MESSAGE) + 5; char *command; char *response; - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_TEXT_MESSAGE) + 5); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_READ_TEXT_MESSAGE, location); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_READ_TEXT_MESSAGE, location); response = ubx_cell_calloc_char(1024); if (response == nullptr) @@ -2379,16 +2405,17 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) { + size_t cmdLen = strlen(UBX_CELL_DELETE_MESSAGE) + 12; char *command; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(strlen(UBX_CELL_DELETE_MESSAGE) + 12); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (deleteFlag == 0) - sprintf(command, "%s=%d", UBX_CELL_DELETE_MESSAGE, location); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_DELETE_MESSAGE, location); else - sprintf(command, "%s=%d,%d", UBX_CELL_DELETE_MESSAGE, location, deleteFlag); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_DELETE_MESSAGE, location, deleteFlag); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_55_SECS_TIMEOUT); @@ -2399,6 +2426,7 @@ UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_BAUD) + 7 + 12; char *command; int b = 0; @@ -2416,10 +2444,10 @@ UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) } // Construct command - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_BAUD) + 7 + 12); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%lu", UBX_CELL_COMMAND_BAUD, baud); + snprintf(command, cmdLen, "%s=%lu", UBX_CELL_COMMAND_BAUD, baud); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_SET_BAUD_TIMEOUT); @@ -2431,12 +2459,13 @@ UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_FLOW_CONTROL) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_FLOW_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s%d", UBX_CELL_FLOW_CONTROL, value); + snprintf(command, cmdLen, "%s%d", UBX_CELL_FLOW_CONTROL, value); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -2448,17 +2477,18 @@ UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_t mode, int value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_GPIO) + 16; char *command; // Example command: AT+UGPIOC=16,2 // Example command: AT+UGPIOC=23,0,1 - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GPIO) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (mode == GPIO_OUTPUT) - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode, value); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode, value); else - sprintf(command, "%s=%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); @@ -2470,16 +2500,18 @@ UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_GPIO) + 2; char *command; char *response; - char gpioChar[4]; + size_t charLen = 4; + char gpioChar[charLen]; char *gpioStart; int gpioMode; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GPIO) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return GPIO_MODE_INVALID; - sprintf(command, "%s?", UBX_CELL_COMMAND_GPIO); + snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_GPIO); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -2497,7 +2529,7 @@ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) return GPIO_MODE_INVALID; } - sprintf(gpioChar, "%d", gpio); // Convert GPIO to char array + snprintf(gpioChar, charLen, "%d", gpio); // Convert GPIO to char array gpioStart = strstr(response, gpioChar); // Find first occurence of GPIO in response free(command); @@ -2513,18 +2545,19 @@ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int localPort) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_CREATE_SOCKET) + 10; char *command; char *response; int sockId = -1; char *responseStart; - command = ubx_cell_calloc_char(strlen(UBX_CELL_CREATE_SOCKET) + 10); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return -1; if (localPort == 0) - sprintf(command, "%s=%d", UBX_CELL_CREATE_SOCKET, (int)protocol); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_CREATE_SOCKET, (int)protocol); else - sprintf(command, "%s=%d,%d", UBX_CELL_CREATE_SOCKET, (int)protocol, localPort); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_CREATE_SOCKET, (int)protocol, localPort); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -2581,10 +2614,11 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_CLOSE_SOCKET) + 10; char *command; char *response; - command = ubx_cell_calloc_char(strlen(UBX_CELL_CLOSE_SOCKET) + 10); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; response = ubx_cell_calloc_char(minimumResponseAllocation); @@ -2596,7 +2630,7 @@ UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) // if timeout is short, close asynchronously and don't wait for socket closure (we will get the URC later) // this will make sure the AT command parser is not confused during init() const char *format = (UBX_CELL_STANDARD_RESPONSE_TIMEOUT == timeout) ? "%s=%d,1" : "%s=%d"; - sprintf(command, format, UBX_CELL_CLOSE_SOCKET, socket); + snprintf(command, cmdLen, format, UBX_CELL_CLOSE_SOCKET, socket); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, timeout); @@ -2615,12 +2649,13 @@ UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, unsigned int port) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_CONNECT_SOCKET) + strlen(address) + 11; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_CONNECT_SOCKET) + strlen(address) + 11); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\",%d", UBX_CELL_CONNECT_SOCKET, socket, address, port); + snprintf(command, cmdLen, "%s=%d,\"%s\",%d", UBX_CELL_CONNECT_SOCKET, socket, address, port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_IP_CONNECT_TIMEOUT); @@ -2631,22 +2666,24 @@ UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, unsign UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, unsigned int port) { - char *charAddress = ubx_cell_calloc_char(16); + size_t charLen = 16; + char *charAddress = ubx_cell_calloc_char(charLen); if (charAddress == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; memset(charAddress, 0, 16); - sprintf(charAddress, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); + snprintf(charAddress, charLen, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); return (socketConnect(socket, (const char *)charAddress, port)); } UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) { + size_t cmdLen = strlen(UBX_CELL_WRITE_SOCKET) + 16; char *command; char *response; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(strlen(UBX_CELL_WRITE_SOCKET) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; response = ubx_cell_calloc_char(minimumResponseAllocation); @@ -2656,7 +2693,7 @@ UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) return UBX_CELL_ERROR_OUT_OF_MEMORY; } int dataLen = len == -1 ? strlen(str) : len; - sprintf(command, "%s=%d,%d", UBX_CELL_WRITE_SOCKET, socket, dataLen); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_WRITE_SOCKET, socket, dataLen); err = sendCommandWithResponse(command, "@", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); @@ -2713,12 +2750,13 @@ UBX_CELL_error_t UBX_CELL::socketWrite(int socket, String str) UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int port, const char *str, int len) { + size_t cmdLen = 64; char *command; char *response; UBX_CELL_error_t err; int dataLen = len == -1 ? strlen(str) : len; - command = ubx_cell_calloc_char(64); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; response = ubx_cell_calloc_char(minimumResponseAllocation); @@ -2728,7 +2766,7 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int p return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s=%d,\"%s\",%d,%d", UBX_CELL_WRITE_UDP_SOCKET, socket, address, port, dataLen); + snprintf(command, cmdLen, "%s=%d,\"%s\",%d,%d", UBX_CELL_WRITE_UDP_SOCKET, socket, address, port, dataLen); err = sendCommandWithResponse(command, "@", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); if (err == UBX_CELL_ERROR_SUCCESS) @@ -2758,11 +2796,12 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int p UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len) { + size_t charLen = 16; char *charAddress = ubx_cell_calloc_char(16); if (charAddress == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; memset(charAddress, 0, 16); - sprintf(charAddress, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); + snprintf(charAddress, charLen, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); return (socketWriteUDP(socket, (const char *)charAddress, port, str, len)); } @@ -2774,6 +2813,7 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, String address, int port, UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, int *bytesRead) { + size_t cmdLen = strlen(UBX_CELL_READ_SOCKET) + 32; char *command; char *response; char *strBegin; @@ -2799,7 +2839,7 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in } // Allocate memory for the command - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_SOCKET) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; @@ -2823,7 +2863,7 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in else bytesToRead = bytesLeftToRead; - sprintf(command, "%s=%d,%d", UBX_CELL_READ_SOCKET, socket, bytesToRead); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_READ_SOCKET, socket, bytesToRead); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, responseLength); @@ -2934,6 +2974,7 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) { + size_t cmdLen = strlen(UBX_CELL_READ_SOCKET) + 32; char *command; char *response; UBX_CELL_error_t err; @@ -2941,10 +2982,10 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) int readLength = 0; int socketStore = 0; - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_SOCKET) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,0", UBX_CELL_READ_SOCKET, socket); + snprintf(command, cmdLen, "%s=%d,0", UBX_CELL_READ_SOCKET, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -2989,6 +3030,7 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress, int *remotePort, int *bytesRead) { + size_t cmdLen = strlen(UBX_CELL_READ_UDP_SOCKET) + 32; char *command; char *response; char *strBegin; @@ -3016,7 +3058,7 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, } // Allocate memory for the command - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_UDP_SOCKET) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; @@ -3040,7 +3082,7 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, else bytesToRead = bytesLeftToRead; - sprintf(command, "%s=%d,%d", UBX_CELL_READ_UDP_SOCKET, socket, bytesToRead); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_READ_UDP_SOCKET, socket, bytesToRead); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, responseLength); @@ -3171,6 +3213,7 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) { + size_t cmdLen = strlen(UBX_CELL_READ_UDP_SOCKET) + 32; char *command; char *response; UBX_CELL_error_t err; @@ -3178,10 +3221,10 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) int readLength = 0; int socketStore = 0; - command = ubx_cell_calloc_char(strlen(UBX_CELL_READ_UDP_SOCKET) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,0", UBX_CELL_READ_UDP_SOCKET, socket); + snprintf(command, cmdLen, "%s=%d,0", UBX_CELL_READ_UDP_SOCKET, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3226,12 +3269,13 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_LISTEN_SOCKET) + 9; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_LISTEN_SOCKET) + 9); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d", UBX_CELL_LISTEN_SOCKET, socket, port); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_LISTEN_SOCKET, socket, port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3242,12 +3286,13 @@ UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) UBX_CELL_error_t UBX_CELL::socketDirectLinkMode(int socket) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_SOCKET_DIRECT_LINK) + 8; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_DIRECT_LINK) + 8); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_SOCKET_DIRECT_LINK, socket); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_SOCKET_DIRECT_LINK, socket); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3262,12 +3307,13 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkTimeTrigger(int socket, unsigned long return UBX_CELL_ERROR_ERROR; UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=5,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, timerTrigger); + snprintf(command, cmdLen, "%s=5,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, timerTrigger); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3282,12 +3328,13 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkDataLengthTrigger(int socket, int dat return UBX_CELL_ERROR_ERROR; UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=6,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, dataLengthTrigger); + snprintf(command, cmdLen, "%s=6,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, dataLengthTrigger); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3302,12 +3349,13 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCharacterTrigger(int socket, int char return UBX_CELL_ERROR_ERROR; UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=7,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, characterTrigger); + snprintf(command, cmdLen, "%s=7,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, characterTrigger); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3322,12 +3370,13 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned return UBX_CELL_ERROR_ERROR; UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_UD_CONFIGURATION) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=8,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, congestionTimer); + snprintf(command, cmdLen, "%s=8,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, congestionTimer); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3337,6 +3386,7 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3344,10 +3394,10 @@ UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_ int socketStore = 0; int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,0", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,0", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3392,6 +3442,7 @@ UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_ UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3399,10 +3450,10 @@ UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) int socketStore = 0; int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,1", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,1", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3446,6 +3497,7 @@ UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3453,10 +3505,10 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total int socketStore = 0; long unsigned int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,2", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,2", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3500,6 +3552,7 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *total) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3507,10 +3560,10 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *t int socketStore = 0; long unsigned int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,3", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,3", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3554,6 +3607,7 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *t UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *address, int *port) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3561,10 +3615,10 @@ UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *add int socketStore = 0; int paramVals[5]; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,4", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,4", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3612,6 +3666,7 @@ UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *add UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3619,10 +3674,10 @@ UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_ int socketStore = 0; int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,10", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,10", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3666,6 +3721,7 @@ UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_ UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) { + size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char *command; char *response; UBX_CELL_error_t err; @@ -3673,10 +3729,10 @@ UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) int socketStore = 0; long unsigned int paramVal; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SOCKET_CONTROL) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,11", UBX_CELL_SOCKET_CONTROL, socket); + snprintf(command, cmdLen, "%s=%d,11", UBX_CELL_SOCKET_CONTROL, socket); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -3722,11 +3778,12 @@ UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) int UBX_CELL::socketGetLastError() { UBX_CELL_error_t err; + size_t cmdLen = 64; char *command; char *response; int errorCode = -1; - command = ubx_cell_calloc_char(64); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; @@ -3737,7 +3794,7 @@ int UBX_CELL::socketGetLastError() return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s", UBX_CELL_GET_ERROR); + snprintf(command, cmdLen, "%s", UBX_CELL_GET_ERROR); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3767,15 +3824,16 @@ IPAddress UBX_CELL::lastRemoteIP(void) UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 16; char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_HTTP_PROFILE, profile); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_HTTP_PROFILE, profile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3786,15 +3844,16 @@ UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 64; char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 64); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_IP, + snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_IP, address[0], address[1], address[2], address[3]); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3806,15 +3865,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + server.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + server.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_NAME, + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_NAME, server.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3826,15 +3886,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + username.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + username.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_USERNAME, + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_USERNAME, username.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3846,15 +3907,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + password.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + password.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_PASSWORD, + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_PASSWORD, password.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3866,15 +3928,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, authenticate); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, authenticate); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3885,15 +3948,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_PORT, port); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_PORT, port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3904,15 +3968,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + header.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 12 + header.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, header.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3924,18 +3989,19 @@ UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofile) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROFILE) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (secprofile == -1) - sprintf(command, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure); else - sprintf(command, "%s=%d,%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure, + snprintf(command, cmdLen, "%s=%d,%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure, secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3947,12 +4013,13 @@ UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofil UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, unsigned long timeout, int ttl) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_PING_COMMAND) + 48 + remote_host.length(); char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_PING_COMMAND) + 48 + remote_host.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\",%d,%d,%ld,%d", UBX_CELL_PING_COMMAND, remote_host.c_str(), retry, p_size, timeout, ttl); + snprintf(command, cmdLen, "%s=\"%s\",%d,%d,%ld,%d", UBX_CELL_PING_COMMAND, remote_host.c_str(), retry, p_size, timeout, ttl); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3963,15 +4030,16 @@ UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, unsig UBX_CELL_error_t UBX_CELL::sendHTTPGET(int profile, String path, String responseFilename) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\",\"%s\"", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_GET, path.c_str(), + snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\"", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_GET, path.c_str(), responseFilename.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3984,16 +4052,17 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String res UBX_CELL_http_content_types_t httpContentType) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + + responseFilename.length() + data.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length() + - data.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, + snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_POST_DATA, path.c_str(), responseFilename.c_str(), data.c_str(), httpContentType); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4006,16 +4075,17 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String res UBX_CELL_http_content_types_t httpContentType) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + + responseFilename.length() + requestFile.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length() + - requestFile.length()); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, + snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_POST_FILE, path.c_str(), responseFilename.c_str(), requestFile.c_str(), httpContentType); @@ -4028,15 +4098,16 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String res UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, int *error_code) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_HTTP_PROTOCOL_ERROR) + 4; char *command; char *response; int rprofile, eclass, ecode; - command = ubx_cell_calloc_char(strlen(UBX_CELL_HTTP_PROTOCOL_ERROR) + 4); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_HTTP_PROTOCOL_ERROR, profile); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_HTTP_PROTOCOL_ERROR, profile); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -4075,11 +4146,13 @@ UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, i UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_NVM) + 10; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_NVM) + 10); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MQTT_NVM, parameter); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_MQTT_NVM, parameter); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4088,11 +4161,13 @@ UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) UBX_CELL_error_t UBX_CELL::setMQTTclientId(const String &clientId) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + clientId.length() + 10; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + clientId.length() + 10); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_CLIENT_ID, clientId.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_CLIENT_ID, clientId.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4101,11 +4176,13 @@ UBX_CELL_error_t UBX_CELL::setMQTTclientId(const String &clientId) UBX_CELL_error_t UBX_CELL::setMQTTserver(const String &serverName, int port) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + serverName.length() + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + serverName.length() + 16); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\",%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SERVERNAME, serverName.c_str(), + snprintf(command, cmdLen, "%s=%d,\"%s\",%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SERVERNAME, serverName.c_str(), port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -4115,13 +4192,15 @@ UBX_CELL_error_t UBX_CELL::setMQTTserver(const String &serverName, int port) UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const String &pwd) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + userName.length() + pwd.length() + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + userName.length() + pwd.length() + 16); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) { return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, userName.c_str(), + snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, userName.c_str(), pwd.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -4131,14 +4210,16 @@ UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const Stri UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_PROFILE) + 16); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (secprofile == -1) - sprintf(command, "%s=%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure); else - sprintf(command, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, secprofile); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4147,11 +4228,13 @@ UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) UBX_CELL_error_t UBX_CELL::connectMQTT(void) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGIN); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGIN); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4160,11 +4243,13 @@ UBX_CELL_error_t UBX_CELL::connectMQTT(void) UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGOUT); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGOUT); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4173,11 +4258,13 @@ UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String &topic) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length(); char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length()); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_SUBSCRIBE, max_Qos, topic.c_str()); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_SUBSCRIBE, max_Qos, topic.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4186,11 +4273,13 @@ UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String &topic) UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String &topic) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length(); char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length()); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_UNSUBSCRIBE, topic.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_UNSUBSCRIBE, topic.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4198,6 +4287,7 @@ UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String &topic) UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest, int readLength, int *bytesRead) { + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; char *command; char *response; UBX_CELL_error_t err; @@ -4209,7 +4299,7 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest *bytesRead = 0; // Allocate memory for the command - command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 10); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; @@ -4225,7 +4315,7 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... // To try and avoid this, look for \"\r\n\r\nOK\r\n there is a extra \r\n beetween " and the the standard \r\nOK\r\n const char mqttReadTerm[] = "\"\r\n\r\nOK\r\n"; - sprintf(command, "%s=%d,%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_READ, 1); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_READ, 1); err = sendCommandWithResponse(command, mqttReadTerm, response, (5 * UBX_CELL_STANDARD_RESPONSE_TIMEOUT), responseLength); @@ -4336,13 +4426,14 @@ UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String &topic, const char *c msg_ptr++; } - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + msg_len); + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + msg_len; + char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) { return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s=%d,%u,%u,0,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISH, qos, + snprintf(command, cmdLen, "%s=%d,%u,%u,0,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISH, qos, (retain ? 1 : 0), topic.c_str(), sanitized_msg); sendCommand(command, true); @@ -4375,13 +4466,14 @@ UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String &topic, const char } UBX_CELL_error_t err; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length()); + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length(); + char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) { return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s=%d,%u,%u,\"%s\",%u", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, qos, + snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",%u", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, qos, (retain ? 1 : 0), topic.c_str(), msg_len); sendCommand(command, true); @@ -4404,13 +4496,14 @@ UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String } UBX_CELL_error_t err; - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + filename.length()); + size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + filename.length(); + char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) { return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, qos, + snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, qos, (retain ? 1 : 0), topic.c_str(), filename.c_str()); sendCommand(command, true); @@ -4462,10 +4555,10 @@ UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code UBX_CELL_error_t UBX_CELL::setFTPserver(const String &serverName) { - constexpr size_t cmd_len = 145; - char command[cmd_len]; // long enough for AT+UFTP=1,<128 bytes> + constexpr size_t cmdLen = 145; + char command[cmdLen]; // long enough for AT+UFTP=1,<128 bytes> - snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_SERVERNAME, + snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_SERVERNAME, serverName.c_str()); return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } @@ -4473,10 +4566,10 @@ UBX_CELL_error_t UBX_CELL::setFTPserver(const String &serverName) UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, const unsigned int data_linger) { - constexpr size_t cmd_len = 64; - char command[cmd_len]; // long enough for AT+UFTP=1,<128 bytes> + constexpr size_t cmdLen = 64; + char command[cmdLen]; // long enough for AT+UFTP=1,<128 bytes> - snprintf(command, cmd_len - 1, "%s=%d,%u,%u,%u", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_TIMEOUT, timeout, + snprintf(command, cmdLen, "%s=%d,%u,%u,%u", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_TIMEOUT, timeout, cmd_linger, data_linger); return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } @@ -4484,10 +4577,10 @@ UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsi UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const String &pwd) { UBX_CELL_error_t err; - constexpr size_t cmd_len = 48; - char command[cmd_len]; // long enough for AT+UFTP=n,<30 bytes> + constexpr size_t cmdLen = 48; + char command[cmdLen]; // long enough for AT+UFTP=n,<30 bytes> - snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_USERNAME, + snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_USERNAME, userName.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) @@ -4495,7 +4588,7 @@ UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const Strin return err; } - snprintf(command, cmd_len - 1, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_PWD, pwd.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_PWD, pwd.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); return err; @@ -4503,31 +4596,32 @@ UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const Strin UBX_CELL_error_t UBX_CELL::connectFTP(void) { - constexpr size_t cmd_len = 16; - char command[cmd_len]; // long enough for AT+UFTPC=n + constexpr size_t cmdLen = 16; + char command[cmdLen]; // long enough for AT+UFTPC=n - snprintf(command, cmd_len - 1, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGIN); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGIN); return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } UBX_CELL_error_t UBX_CELL::disconnectFTP(void) { - constexpr size_t cmd_len = 16; - char command[cmd_len]; // long enough for AT+UFTPC=n + constexpr size_t cmdLen = 16; + char command[cmdLen]; // long enough for AT+UFTPC=n - snprintf(command, cmd_len - 1, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGOUT); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_LOGOUT); return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) { - char *command = ubx_cell_calloc_char(strlen(UBX_CELL_FTP_COMMAND) + (2 * filename.length()) + 16); + size_t cmdLen = strlen(UBX_CELL_FTP_COMMAND) + (2 * filename.length()) + 16; + char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) { return UBX_CELL_ERROR_OUT_OF_MEMORY; } - sprintf(command, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, filename.c_str(), + snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, filename.c_str(), filename.c_str()); // memset(response, 0, sizeof(response)); // sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, response, 8000 /* ms */, response_len); @@ -4586,13 +4680,14 @@ UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2 UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + 6; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + 6); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_SEC_PROFILE, secprofile); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_SEC_PROFILE, secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4603,12 +4698,13 @@ UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) UBX_CELL_error_t UBX_CELL::configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + 10; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + 10); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_SEC_PROFILE, secprofile, parameter, value); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_SEC_PROFILE, secprofile, parameter, value); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4618,11 +4714,13 @@ UBX_CELL_error_t UBX_CELL::configSecurityProfileString(int secprofile, UBX_CELL_ String value) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + value.length() + 10; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_PROFILE) + value.length() + 10); + + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,\"%s\"", UBX_CELL_SEC_PROFILE, secprofile, parameter, value.c_str()); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_SEC_PROFILE, secprofile, parameter, value.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -4631,11 +4729,12 @@ UBX_CELL_error_t UBX_CELL::configSecurityProfileString(int secprofile, UBX_CELL_ UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, UBX_CELL_sec_manager_parameter_t parameter, String name, String data) { + size_t cmdLen = strlen(UBX_CELL_SEC_MANAGER) + name.length() + 20; char *command; char *response; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(strlen(UBX_CELL_SEC_MANAGER) + name.length() + 20); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; response = ubx_cell_calloc_char(minimumResponseAllocation); @@ -4645,7 +4744,7 @@ UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opco return UBX_CELL_ERROR_OUT_OF_MEMORY; } int dataLen = data.length(); - sprintf(command, "%s=%d,%d,\"%s\",%d", UBX_CELL_SEC_MANAGER, opcode, parameter, name.c_str(), dataLen); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\",%d", UBX_CELL_SEC_MANAGER, opcode, parameter, name.c_str(), dataLen); err = sendCommandWithResponse(command, ">", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -4680,18 +4779,19 @@ UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opco UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE) + 32; char *command; if (cid >= UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(strlen(UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE) + 32); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (cid == -1) - sprintf(command, "%s=%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status); else - sprintf(command, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status, cid); + snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status, cid); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4702,14 +4802,15 @@ UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) bool UBX_CELL::isGPSon(void) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_POWER) + 2; char *command; char *response; bool on = false; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_POWER) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_POWER); + snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_POWER); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -4742,6 +4843,7 @@ bool UBX_CELL::isGPSon(void) UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_aiding_mode_t gnss_aiding) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_POWER) + 32; // gnss_sys could be up to three digits char *command; bool gpsState; @@ -4753,16 +4855,16 @@ UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_ai } // GPS power management - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_POWER) + 32); // gnss_sys could be up to three digits + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (enable) { - sprintf(command, "%s=1,%d,%d", UBX_CELL_GNSS_POWER, gnss_aiding, gnss_sys); + snprintf(command, cmdLen, "%s=1,%d,%d", UBX_CELL_GNSS_POWER, gnss_aiding, gnss_sys); } else { - sprintf(command, "%s=0", UBX_CELL_GNSS_POWER); + snprintf(command, cmdLen, "%s=0", UBX_CELL_GNSS_POWER); } err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, 10000); @@ -4833,6 +4935,7 @@ UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) { // AT+UGRMC=<0,1> UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_GPRMC) + 3; char *command; // ** Don't call gpsPower here. It causes problems for +UTIME and the PPS signal ** @@ -4846,10 +4949,10 @@ UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) // } // } - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_GPRMC) + 3); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_GNSS_GPRMC, enable ? 1 : 0); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_GNSS_GPRMC, enable ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); @@ -4861,14 +4964,15 @@ UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData bool *valid) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_GPRMC) + 2; char *command; char *response; char *rmcBegin; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_GPRMC) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_GNSS_GPRMC); + snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_GPRMC); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -4917,6 +5021,7 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b { // AT+ULOC=2,,,, UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_LOCATION) + 24; char *command; // This function will only work if the GPS module is initially turned off. @@ -4930,13 +5035,13 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b if (accuracy > 999999) accuracy = 999999; - command = ubx_cell_calloc_char(strlen(UBX_CELL_GNSS_REQUEST_LOCATION) + 24); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - sprintf(command, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); + snprintf(command, cmdLen, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); #else - sprintf(command, "%s=2,%d,%d,%d,%ld", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); + snprintf(command, cmdLen, "%s=2,%d,%d,%d,%ld", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); #endif err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); @@ -4951,13 +5056,14 @@ UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const unsigned int dataType) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_AIDING_SERVER_CONFIGURATION) + 256; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_AIDING_SERVER_CONFIGURATION) + 256); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, primaryServer, + snprintf(command, cmdLen, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, primaryServer, secondaryServer, authToken, days, period, resolution, gnssTypes, mode, dataType); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4969,11 +5075,12 @@ UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const // OK for text files. But will fail with binary files (containing \0) on some platforms. UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, int len) { + size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10; char *command; char *response; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; response = ubx_cell_calloc_char(minimumResponseAllocation); @@ -4983,7 +5090,7 @@ UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, return UBX_CELL_ERROR_OUT_OF_MEMORY; } int dataLen = len == -1 ? strlen(str) : len; - sprintf(command, "%s=\"%s\",%d", UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE, filename.c_str(), dataLen); + snprintf(command, cmdLen, "%s=\"%s\",%d", UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE, filename.c_str(), dataLen); err = sendCommandWithResponse(command, ">", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 2); @@ -5029,6 +5136,7 @@ UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, String str) UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8; char *command; char *response; @@ -5045,10 +5153,10 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) return err; } - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); response = ubx_cell_calloc_char(fileSize + minimumResponseAllocation); if (response == nullptr) @@ -5151,6 +5259,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8; char *command; char *response; @@ -5167,10 +5276,10 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) return err; } - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_READ_FILE, filename.c_str()); response = ubx_cell_calloc_char(fileSize + minimumResponseAllocation); if (response == nullptr) @@ -5285,9 +5394,9 @@ UBX_CELL_error_t UBX_CELL::getFileBlock(const String &filename, char *buffer, si return UBX_CELL_ERROR_INVALID; } - size_t cmd_len = filename.length() + 32; - char *cmd = ubx_cell_calloc_char(cmd_len); - sprintf(cmd, "at+urdblock=\"%s\",%zu,%zu\r\n", filename.c_str(), offset, requested_length); + size_t cmdLen = filename.length() + 32; + char *cmd = ubx_cell_calloc_char(cmdLen); + snprintf(cmd, cmdLen, "at+urdblock=\"%s\",%zu,%zu\r\n", filename.c_str(), offset, requested_length); sendCommand(cmd, false); int ich; @@ -5338,13 +5447,14 @@ UBX_CELL_error_t UBX_CELL::getFileBlock(const String &filename, char *buffer, si UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_LIST_FILES) + filename.length() + 8; char *command; char *response; - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_LIST_FILES) + filename.length() + 8); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=2,\"%s\"", UBX_CELL_FILE_SYSTEM_LIST_FILES, filename.c_str()); + snprintf(command, cmdLen, "%s=2,\"%s\"", UBX_CELL_FILE_SYSTEM_LIST_FILES, filename.c_str()); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) @@ -5398,12 +5508,13 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) UBX_CELL_error_t UBX_CELL::deleteFile(String filename) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_DELETE_FILE) + filename.length() + 8; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_FILE_SYSTEM_DELETE_FILE) + filename.length() + 8); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_DELETE_FILE, filename.c_str()); + snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_FILE_SYSTEM_DELETE_FILE, filename.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -5423,13 +5534,14 @@ UBX_CELL_error_t UBX_CELL::deleteFile(String filename) UBX_CELL_error_t UBX_CELL::modulePowerOff(void) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_POWER_OFF) + 6; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_POWER_OFF) + 6); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s", UBX_CELL_COMMAND_POWER_OFF); + snprintf(command, cmdLen, "%s", UBX_CELL_COMMAND_POWER_OFF); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_POWER_OFF_TIMEOUT); @@ -5631,12 +5743,13 @@ void UBX_CELL::hwReset(void) UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_FUNC) + 16; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_FUNC) + 16); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_COMMAND_FUNC, function); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_FUNC, function); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); @@ -5648,16 +5761,17 @@ UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_MNO) + 9; char *command; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_MNO) + 9); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; if (mno == MNO_SIM_ICCID) // Only add autoReset and urcNotification if mno is MNO_SIM_ICCID - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno, (uint8_t)autoReset, + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno, (uint8_t)autoReset, (uint8_t)urcNotification); else - sprintf(command, "%s=%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -5669,6 +5783,7 @@ UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool aut UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_MNO) + 2; char *command; char *response; mobile_network_operator_t o; @@ -5677,10 +5792,10 @@ UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) int u; int oStore; - command = ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_MNO) + 2); + command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s?", UBX_CELL_COMMAND_MNO); + snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_MNO); response = ubx_cell_calloc_char(minimumResponseAllocation); if (response == nullptr) diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index 17454eb..98f510b 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -44,12 +44,13 @@ template class UBX_CELL_VOICE return UBX_CELL_ERROR_OUT_OF_MEMORY; number.toCharArray(numberCStr, number.length() + 1); - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_DIAL) + strlen(numberCStr) + 3); + size_t cmdLen = strlen(UBX_CELL_COMMAND_DIAL) + strlen(numberCStr) + 3; + command = static_cast(this)->ubx_cell_calloc_char(cmdLen); if (command != nullptr) { // Heads up! The dial command is one of the only commands that requires a // semicolon at the end of it! - sprintf(command, "%s=%s;", UBX_CELL_COMMAND_DIAL, numberCStr); + snprintf(command, cmdLen, "%s=%s;", UBX_CELL_COMMAND_DIAL, numberCStr); err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, nullptr, UBX_CELL_10_SEC_TIMEOUT); @@ -81,12 +82,13 @@ template class UBX_CELL_VOICE UBX_CELL_error_t playAudioResource(uint8_t audio_resource, uint8_t tone_id = 0, uint8_t nof_repeat = 0) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_PLAY_AUDIO) + 13; char *command; - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_PLAY_AUDIO) + 13); + command = static_cast(this)->ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_PLAY_AUDIO, audio_resource, tone_id, nof_repeat); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_PLAY_AUDIO, audio_resource, tone_id, nof_repeat); err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -97,12 +99,13 @@ template class UBX_CELL_VOICE UBX_CELL_error_t stopAudioResource(uint8_t audio_resource) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_STOP_AUDIO) + 5; char *command; - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_STOP_AUDIO) + 5); + command = static_cast(this)->ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d", UBX_CELL_COMMAND_STOP_AUDIO, audio_resource); + snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_STOP_AUDIO, audio_resource); err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -113,13 +116,14 @@ template class UBX_CELL_VOICE UBX_CELL_error_t generateToneFreq(uint16_t frequency, uint16_t duration, uint8_t volume) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 15; char *command; char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 15); + command = static_cast(this)->ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, frequency, duration, volume); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, frequency, duration, volume); err = static_cast(this)->sendCommandWithResponse(command, response, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -130,13 +134,14 @@ template class UBX_CELL_VOICE UBX_CELL_error_t generateToneDTMF(char dtmf_character, uint16_t duration, uint8_t volume) { UBX_CELL_error_t err; + size_t cmdLen = strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 14; char *command; char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; - command = static_cast(this)->ubx_cell_calloc_char(strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 14); + command = static_cast(this)->ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=\"%c\",%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, dtmf_character, duration, volume); + snprintf(command, cmdLen, "%s=\"%c\",%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, dtmf_character, duration, volume); err = static_cast(this)->sendCommandWithResponse(command, response, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); From 363ec5c2f9ec8f1ab3654f7f277e98c90556a0f8 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 18 Dec 2023 15:58:33 -0700 Subject: [PATCH 4/8] Don't use calloc for fixed length arrays Many command and response arrays are fixed length, so no need to use calloc. This helps prevent the heap from getting fragmented. --- src/sfe_sara_r5.cpp | 109 +--- src/sfe_ublox_cellular.cpp | 1001 +++++--------------------------- src/sfe_ublox_cellular_voice.h | 24 +- 3 files changed, 151 insertions(+), 983 deletions(-) diff --git a/src/sfe_sara_r5.cpp b/src/sfe_sara_r5.cpp index ae66359..b13d056 100644 --- a/src/sfe_sara_r5.cpp +++ b/src/sfe_sara_r5.cpp @@ -10,18 +10,14 @@ UBX_CELL_error_t SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utim { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_TIME) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (mode == UBX_CELL_UTIME_MODE_STOP) // stop UTIME does not require a sensor snprintf(command, cmdLen, "%s=%d", UBX_CELL_GNSS_REQUEST_TIME, mode); else snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_GNSS_REQUEST_TIME, mode, sensor); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - free(command); return err; } @@ -29,24 +25,14 @@ UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_uti { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_TIME) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_utime_mode_t m; UBX_CELL_utime_sensor_t s; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_REQUEST_TIME); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); // Response format: \r\n+UTIME: [,]\r\n\r\nOK\r\n @@ -77,8 +63,6 @@ UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_uti err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); return err; } @@ -86,15 +70,11 @@ UBX_CELL_error_t SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_INDICATION) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_GNSS_TIME_INDICATION, config); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -102,23 +82,13 @@ UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_INDICATION) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_utime_urc_configuration_t c; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_TIME_INDICATION); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); // Response format: \r\n+UTIMEIND: \r\n\r\nOK\r\n @@ -142,8 +112,6 @@ UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); return err; } @@ -151,11 +119,8 @@ UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32 { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 48; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); #else @@ -163,7 +128,6 @@ UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32 #endif err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -171,24 +135,14 @@ UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int3 { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; int32_t ons; int32_t os; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_TIME_CONFIGURATION); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); // Response format: \r\n+UTIMECFG: ,\r\n\r\nOK\r\n @@ -216,8 +170,6 @@ UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int3 err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); return err; } @@ -225,19 +177,15 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 24; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -252,19 +200,15 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -273,20 +217,16 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 64; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value[0], value[1], value[2], value[3]); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -294,45 +234,31 @@ UBX_CELL_error_t SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t a { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_ACTION) + 32; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MESSAGE_PDP_ACTION, profile, action); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *address) { size_t cmdLen = strlen(UBX_CELL_NETWORK_ASSIGNED_DATA) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int profileStore = 0; int paramTag = 0; // 0: IP address: dynamic IP address assigned during PDP context activation int paramVals[4]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_NETWORK_ASSIGNED_DATA, profile, paramTag); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -353,8 +279,6 @@ UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *ad _debugPort->print(F("getNetworkAssignedIPAddress: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -363,9 +287,6 @@ UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *ad *address = tempAddress; } - free(command); - free(response); - return err; } diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index 1238c76..e02bf0f 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -970,13 +970,10 @@ UBX_CELL_error_t UBX_CELL::setRegistrationCallback(void (*registrationCallback)( _registrationCallback = registrationCallback; size_t cmdLen = strlen(UBX_CELL_REGISTRATION_STATUS) + 3; - char *command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char command[cmdLen]; snprintf(command, cmdLen, "%s=%d", UBX_CELL_REGISTRATION_STATUS, 2 /*enable URC with location*/); UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -986,13 +983,10 @@ UBX_CELL_error_t UBX_CELL::setEpsRegistrationCallback( _epsRegistrationCallback = registrationCallback; size_t cmdLen = strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3; - char *command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char command[cmdLen]; snprintf(command, cmdLen, "%s=%d", UBX_CELL_EPSREGISTRATION_STATUS, 2 /*enable URC with location*/); UBX_CELL_error_t err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -1024,25 +1018,18 @@ UBX_CELL_error_t UBX_CELL::enableEcho(bool enable) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_ECHO) + 2; - char *command; - - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char command[cmdLen]; snprintf(command, cmdLen, "%s%d", UBX_CELL_COMMAND_ECHO, enable ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } String UBX_CELL::getManufacturerID(void) { - char *response; + char response[minimumResponseAllocation]; char idResponse[16] = {0x00}; // E.g. u-blox UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_MANU_ID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1052,18 +1039,15 @@ String UBX_CELL::getManufacturerID(void) memset(idResponse, 0, 16); } } - free(response); return String(idResponse); } String UBX_CELL::getModelID(void) { - char *response; + char response[minimumResponseAllocation]; char idResponse[32] = {0x00}; // E.g. SARA-R510M8Q UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_MODEL_ID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1073,18 +1057,15 @@ String UBX_CELL::getModelID(void) memset(idResponse, 0, 16); } } - free(response); return String(idResponse); } String UBX_CELL::getFirmwareVersion(void) { - char *response; + char response[minimumResponseAllocation]; char idResponse[16] = {0x00}; // E.g. 11.40 UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_FW_VER_ID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1094,18 +1075,15 @@ String UBX_CELL::getFirmwareVersion(void) memset(idResponse, 0, 16); } } - free(response); return String(idResponse); } String UBX_CELL::getSerialNo(void) { - char *response; + char response[minimumResponseAllocation]; char idResponse[32] = {0x00}; // E.g. 357520070120767 UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_SERIAL_NO, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1115,18 +1093,15 @@ String UBX_CELL::getSerialNo(void) memset(idResponse, 0, 16); } } - free(response); return String(idResponse); } String UBX_CELL::getIMEI(void) { - char *response; + char response[minimumResponseAllocation]; char imeiResponse[32] = {0x00}; // E.g. 004999010640000 UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_IMEI, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1136,18 +1111,15 @@ String UBX_CELL::getIMEI(void) memset(imeiResponse, 0, 16); } } - free(response); return String(imeiResponse); } String UBX_CELL::getIMSI(void) { - char *response; + char response[minimumResponseAllocation]; char imsiResponse[32] = {0x00}; // E.g. 222107701772423 UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_IMSI, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1157,18 +1129,15 @@ String UBX_CELL::getIMSI(void) memset(imsiResponse, 0, 16); } } - free(response); return String(imsiResponse); } String UBX_CELL::getCCID(void) { - char *response; + char response[minimumResponseAllocation]; char ccidResponse[32] = {0x00}; // E.g. +CCID: 8939107900010087330 UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_CCID, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1185,18 +1154,15 @@ String UBX_CELL::getCCID(void) } } } - free(response); return String(ccidResponse); } String UBX_CELL::getSubscriberNo(void) { - char *response; + char response[minimumResponseAllocation]; char idResponse[128] = {0x00}; // E.g. +CNUM: "ABCD . AAA","123456789012",129 UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_CNUM, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1213,18 +1179,15 @@ String UBX_CELL::getSubscriberNo(void) } } } - free(response); return String(idResponse); } String UBX_CELL::getCapabilities(void) { - char *response; + char response[minimumResponseAllocation]; char idResponse[128] = {0x00}; // E.g. +GCAP: +FCLASS, +CGSM UBX_CELL_error_t err; - response = ubx_cell_calloc_char(minimumResponseAllocation); - err = sendCommandWithResponse(UBX_CELL_COMMAND_REQ_CAP, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1241,7 +1204,6 @@ String UBX_CELL::getCapabilities(void) } } } - free(response); return String(idResponse); } @@ -1271,28 +1233,16 @@ String UBX_CELL::clock(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; char *clockBegin; char *clockEnd; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return ""; snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_CLOCK); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return ""; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) { - free(command); - free(response); return ""; } @@ -1300,25 +1250,18 @@ String UBX_CELL::clock(void) clockBegin = strchr(response, '\"'); // Find first quote if (clockBegin == nullptr) { - free(command); - free(response); return ""; } clockBegin += 1; // Increment pointer to begin at first number clockEnd = strchr(clockBegin, '\"'); // Find last quote if (clockEnd == nullptr) { - free(command); - free(response); return ""; } *(clockEnd) = '\0'; // Set last quote to null char -- end string String clock = String(clockBegin); // Extract the clock as a String _before_ freeing response - free(command); - free(response); - return (clock); } @@ -1326,25 +1269,15 @@ UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; char tzPlusMinus; int scanNum = 0; int iy, imo, id, ih, imin, is, itz; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_CLOCK); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); // Response format (if TZ is negative): \r\n+CCLK: "YY/MM/DD,HH:MM:SS-TZ"\r\n\r\nOK\r\n @@ -1376,8 +1309,6 @@ UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); return err; } @@ -1446,44 +1377,28 @@ UBX_CELL_error_t UBX_CELL::autoTimeZone(bool enable) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_AUTO_TZ) + 3; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_AUTO_TZ, enable ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } int8_t UBX_CELL::rssi(void) { size_t cmdLen = strlen(UBX_CELL_SIGNAL_QUALITY) + 1; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int rssi; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s", UBX_CELL_SIGNAL_QUALITY); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, 10000, minimumResponseAllocation, AT_COMMAND); if (err != UBX_CELL_ERROR_SUCCESS) { - free(command); - free(response); return -1; } @@ -1501,36 +1416,22 @@ int8_t UBX_CELL::rssi(void) rssi = -1; } - free(command); - free(response); return rssi; } UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) { size_t cmdLen = strlen(UBX_CELL_EXT_SIGNAL_QUALITY) + 1; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s", UBX_CELL_EXT_SIGNAL_QUALITY); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, 10000, minimumResponseAllocation, AT_COMMAND); if (err != UBX_CELL_ERROR_SUCCESS) { - free(command); - free(response); return UBX_CELL_ERROR_ERROR; } @@ -1552,38 +1453,24 @@ UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) err = UBX_CELL_ERROR_SUCCESS; } - free(command); - free(response); return err; } UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) { const char *tag = eps ? UBX_CELL_EPSREGISTRATION_STATUS : UBX_CELL_REGISTRATION_STATUS; - size_t cmdLen = strlen(tag) + 3; - char *command; - char *response; + size_t cmdLen = strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int status; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_REGISTRATION_INVALID; snprintf(command, cmdLen, "%s?", tag); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_REGISTRATION_INVALID; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, minimumResponseAllocation, AT_COMMAND); if (err != UBX_CELL_ERROR_SUCCESS) { - free(command); - free(response); return UBX_CELL_REGISTRATION_INVALID; } @@ -1601,8 +1488,6 @@ UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) if (scanned != 1) status = UBX_CELL_REGISTRATION_INVALID; - free(command); - free(response); return (UBX_CELL_registration_status_t)status; } @@ -1719,24 +1604,14 @@ UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_ { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_DEF) + 3; - char *command; - char *response; + char command[cmdLen]; + char response[1024]; if (cid > UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_MESSAGE_PDP_DEF); - response = ubx_cell_calloc_char(1024); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT, 1024); @@ -1800,9 +1675,6 @@ UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_ err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); - return err; } @@ -1810,19 +1682,10 @@ UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_SIMPIN) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_SIMPIN); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1846,9 +1709,6 @@ UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); - return err; } @@ -1871,15 +1731,11 @@ UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SIM_STATE) + 4; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_SIM_STATE, mode); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -1887,23 +1743,13 @@ UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SIM_STATE) + 3; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; int m; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_SIM_STATE); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -1925,8 +1771,6 @@ UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); return err; } @@ -1939,16 +1783,13 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_ENTER_PPP) + 32; - char *command; + char command[cmdLen]; if ((dialing_type_char != 0) && (dialing_type_char != 'T') && (dialing_type_char != 'P')) { return UBX_CELL_ERROR_UNEXPECTED_PARAM; } - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (dialing_type_char != 0) { snprintf(command, cmdLen, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, dialNumber, PPP_L2P[l2p], @@ -1961,7 +1802,6 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -1969,22 +1809,16 @@ uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 3; - char *command; + char command[cmdLen]; char *response; uint8_t opsSeen = 0; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=?", UBX_CELL_OPERATOR_SELECTION); int responseSize = (maxOps + 1) * 48; response = ubx_cell_calloc_char(responseSize); if (response == nullptr) - { - free(command); return UBX_CELL_ERROR_OUT_OF_MEMORY; - } // AT+COPS maximum response time is 3 minutes (180000 ms) err = @@ -2044,7 +1878,6 @@ uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) } } - free(command); free(response); return opsSeen; @@ -2054,17 +1887,13 @@ UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 24; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=1,2,\"%lu\"", UBX_CELL_OPERATOR_SELECTION, oper.numOp); // AT+COPS maximum response time is 3 minutes (180000 ms) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - free(command); return err; } @@ -2072,17 +1901,13 @@ UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 6; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=0,0", UBX_CELL_OPERATOR_SELECTION); // AT+COPS maximum response time is 3 minutes (180000 ms) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - free(command); return err; } @@ -2090,23 +1915,13 @@ UBX_CELL_error_t UBX_CELL::getOperator(String *oper) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 3; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; char *searchPtr; char mode; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_OPERATOR_SELECTION); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - // AT+COPS maximum response time is 3 minutes (180000 ms) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_3_MIN_TIMEOUT); @@ -2148,8 +1963,6 @@ UBX_CELL_error_t UBX_CELL::getOperator(String *oper) } } - free(response); - free(command); return err; } @@ -2157,33 +1970,25 @@ UBX_CELL_error_t UBX_CELL::deregisterOperator(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 6; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=2", UBX_CELL_OPERATOR_SELECTION); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - free(command); return err; } UBX_CELL_error_t UBX_CELL::setSMSMessageFormat(UBX_CELL_message_format_t textMode) { size_t cmdLen = strlen(UBX_CELL_MESSAGE_FORMAT) + 4; - char *command; + char command[cmdLen]; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_MESSAGE_FORMAT, (textMode == UBX_CELL_MESSAGE_FORMAT_TEXT) ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -2238,29 +2043,17 @@ UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, Str { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_PREF_MESSAGE_STORE) + 32; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; int u; int t; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=\"%s\"", UBX_CELL_PREF_MESSAGE_STORE, memory.c_str()); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_3_MIN_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) { - free(command); - free(response); return err; } @@ -2292,8 +2085,6 @@ UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, Str err = UBX_CELL_ERROR_INVALID; } - free(response); - free(command); return err; } @@ -2301,21 +2092,11 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_READ_TEXT_MESSAGE) + 5; - char *command; - char *response; + char command[cmdLen]; + char response[1024]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_READ_TEXT_MESSAGE, location); - response = ubx_cell_calloc_char(1024); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT, 1024); if (err == UBX_CELL_ERROR_SUCCESS) @@ -2337,8 +2118,6 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * } if ((*searchPtr == '\0') || (pointer == 12)) { - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } // Search to the next quote @@ -2351,8 +2130,6 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * } if ((*searchPtr == '\0') || (pointer == 24)) { - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } // Skip two commas @@ -2368,8 +2145,6 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * } if ((*searchPtr == '\0') || (pointer == 24)) { - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } // Search to the next new line @@ -2382,8 +2157,6 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * } if ((*searchPtr == '\0') || (pointer == 512)) { - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } } @@ -2397,21 +2170,15 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) { size_t cmdLen = strlen(UBX_CELL_DELETE_MESSAGE) + 12; - char *command; + char command[cmdLen]; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (deleteFlag == 0) snprintf(command, cmdLen, "%s=%d", UBX_CELL_DELETE_MESSAGE, location); else @@ -2419,7 +2186,6 @@ UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_55_SECS_TIMEOUT); - free(command); return err; } @@ -2427,7 +2193,7 @@ UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_BAUD) + 7 + 12; - char *command; + char command[cmdLen]; int b = 0; // Error check -- ensure supported baud @@ -2444,15 +2210,10 @@ UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) } // Construct command - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%lu", UBX_CELL_COMMAND_BAUD, baud); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_SET_BAUD_TIMEOUT); - free(command); - return err; } @@ -2460,17 +2221,12 @@ UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FLOW_CONTROL) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s%d", UBX_CELL_FLOW_CONTROL, value); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; } @@ -2478,13 +2234,10 @@ UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_ { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_GPIO) + 16; - char *command; + char command[cmdLen]; // Example command: AT+UGPIOC=16,2 // Example command: AT+UGPIOC=23,0,1 - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (mode == GPIO_OUTPUT) snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_GPIO, gpio, mode, value); else @@ -2492,8 +2245,6 @@ UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_ err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - free(command); - return err; } @@ -2501,40 +2252,25 @@ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_GPIO) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; size_t charLen = 4; char gpioChar[charLen]; char *gpioStart; int gpioMode; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return GPIO_MODE_INVALID; snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_GPIO); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return GPIO_MODE_INVALID; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) { - free(command); - free(response); return GPIO_MODE_INVALID; } snprintf(gpioChar, charLen, "%d", gpio); // Convert GPIO to char array gpioStart = strstr(response, gpioChar); // Find first occurence of GPIO in response - free(command); - free(response); - if (gpioStart == nullptr) return GPIO_MODE_INVALID; // If not found return invalid sscanf(gpioStart, "%*d,%d\r\n", &gpioMode); @@ -2546,28 +2282,16 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_CREATE_SOCKET) + 10; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; int sockId = -1; char *responseStart; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return -1; if (localPort == 0) snprintf(command, cmdLen, "%s=%d", UBX_CELL_CREATE_SOCKET, (int)protocol); else snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_CREATE_SOCKET, (int)protocol, localPort); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - if (_printDebug == true) - _debugPort->println(F("socketOpen: Fail: nullptr response")); - free(command); - return -1; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) @@ -2580,8 +2304,6 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local _debugPort->print(response); _debugPort->println(F("}")); } - free(command); - free(response); return -1; } @@ -2594,8 +2316,6 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local _debugPort->print(response); _debugPort->println(F("}")); } - free(command); - free(response); return -1; } @@ -2605,9 +2325,6 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local sscanf(responseStart, "%d", &sockId); _lastSocketProtocol[sockId] = (int)protocol; - free(command); - free(response); - return sockId; } @@ -2615,18 +2332,9 @@ UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_CLOSE_SOCKET) + 10; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } // if timeout is short, close asynchronously and don't wait for socket closure (we will get the URC later) // this will make sure the AT command parser is not confused during init() const char *format = (UBX_CELL_STANDARD_RESPONSE_TIMEOUT == timeout) ? "%s=%d,1" : "%s=%d"; @@ -2640,9 +2348,6 @@ UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) _debugPort->println(socketGetLastError()); } - free(command); - free(response); - return err; } @@ -2667,9 +2372,7 @@ UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, unsign UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, unsigned int port) { size_t charLen = 16; - char *charAddress = ubx_cell_calloc_char(charLen); - if (charAddress == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char charAddress[charLen]; memset(charAddress, 0, 16); snprintf(charAddress, charLen, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); @@ -2679,19 +2382,10 @@ UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, unsigned UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) { size_t cmdLen = strlen(UBX_CELL_WRITE_SOCKET) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } int dataLen = len == -1 ? strlen(str) : len; snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_WRITE_SOCKET, socket, dataLen); @@ -2738,8 +2432,6 @@ UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) } } - free(command); - free(response); return err; } @@ -2751,21 +2443,11 @@ UBX_CELL_error_t UBX_CELL::socketWrite(int socket, String str) UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int port, const char *str, int len) { size_t cmdLen = 64; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int dataLen = len == -1 ? strlen(str) : len; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - snprintf(command, cmdLen, "%s=%d,\"%s\",%d,%d", UBX_CELL_WRITE_UDP_SOCKET, socket, address, port, dataLen); err = sendCommandWithResponse(command, "@", response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT * 5); @@ -2789,17 +2471,13 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int p _debugPort->println(socketGetLastError()); } - free(command); - free(response); return err; } UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len) { size_t charLen = 16; - char *charAddress = ubx_cell_calloc_char(16); - if (charAddress == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char charAddress[16]; memset(charAddress, 0, 16); snprintf(charAddress, charLen, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]); @@ -2814,8 +2492,10 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, String address, int port, UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, int *bytesRead) { size_t cmdLen = strlen(UBX_CELL_READ_SOCKET) + 32; - char *command; - char *response; + char command[cmdLen]; + // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing + int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_SOCKET) + minimumResponseAllocation; + char response[responseLength]; char *strBegin; int readIndexTotal = 0; int readIndexThisRead = 0; @@ -2838,21 +2518,6 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in return UBX_CELL_ERROR_UNEXPECTED_PARAM; } - // Allocate memory for the command - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - // Allocate memory for the response - // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing - int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_SOCKET) + minimumResponseAllocation; - response = ubx_cell_calloc_char(responseLength); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - // If there are more than _saraR5maxSocketRead (1024) bytes to be read, // we need to do multiple reads to get all the data @@ -2875,8 +2540,6 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in _debugPort->print(F("socketRead: sendCommandWithResponse err ")); _debugPort->println(err); } - free(command); - free(response); return err; } @@ -2896,8 +2559,6 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in _debugPort->print(F("socketRead: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -2920,8 +2581,6 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in { _debugPort->println(F("socketRead: zero length!")); } - free(command); - free(response); return UBX_CELL_ERROR_ZERO_READ_LENGTH; } @@ -2930,8 +2589,6 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in if (strBegin == nullptr) { - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -2966,34 +2623,21 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in } } // /while (bytesLeftToRead > 0) - free(command); - free(response); - return UBX_CELL_ERROR_SUCCESS; } UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) { size_t cmdLen = strlen(UBX_CELL_READ_SOCKET) + 32; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int readLength = 0; int socketStore = 0; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,0", UBX_CELL_READ_SOCKET, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3013,17 +2657,12 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) _debugPort->print(F("socketReadAvailable: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *length = readLength; } - free(command); - free(response); - return err; } @@ -3031,8 +2670,10 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, int *remotePort, int *bytesRead) { size_t cmdLen = strlen(UBX_CELL_READ_UDP_SOCKET) + 32; - char *command; - char *response; + char command[cmdLen]; + // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing + int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_UDP_SOCKET) + minimumResponseAllocation; + char response[responseLength]; char *strBegin; int readIndexTotal = 0; int readIndexThisRead = 0; @@ -3057,21 +2698,6 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, return UBX_CELL_ERROR_UNEXPECTED_PARAM; } - // Allocate memory for the command - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - // Allocate memory for the response - // We only need enough to read _saraR5maxSocketRead bytes - not the whole thing - int responseLength = _saraR5maxSocketRead + strlen(UBX_CELL_READ_UDP_SOCKET) + minimumResponseAllocation; - response = ubx_cell_calloc_char(responseLength); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - // If there are more than _saraR5maxSocketRead (1024) bytes to be read, // we need to do multiple reads to get all the data @@ -3094,8 +2720,6 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, _debugPort->print(F("socketReadUDP: sendCommandWithResponse err ")); _debugPort->println(err); } - free(command); - free(response); return err; } @@ -3116,8 +2740,6 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, _debugPort->print(F("socketReadUDP: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -3140,8 +2762,6 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, { _debugPort->println(F("socketRead: zero length!")); } - free(command); - free(response); return UBX_CELL_ERROR_ZERO_READ_LENGTH; } @@ -3152,8 +2772,6 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, if (strBegin == nullptr) { - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -3205,34 +2823,21 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, } } // /while (bytesLeftToRead > 0) - free(command); - free(response); - return UBX_CELL_ERROR_SUCCESS; } UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) { size_t cmdLen = strlen(UBX_CELL_READ_UDP_SOCKET) + 32; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int readLength = 0; int socketStore = 0; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,0", UBX_CELL_READ_UDP_SOCKET, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3252,17 +2857,12 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) _debugPort->print(F("socketReadAvailableUDP: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *length = readLength; } - free(command); - free(response); - return err; } @@ -3270,16 +2870,12 @@ UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_LISTEN_SOCKET) + 9; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_LISTEN_SOCKET, socket, port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3287,16 +2883,12 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkMode(int socket) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SOCKET_DIRECT_LINK) + 8; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_SOCKET_DIRECT_LINK, socket); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3308,16 +2900,12 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkTimeTrigger(int socket, unsigned long UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=5,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, timerTrigger); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3329,16 +2917,12 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkDataLengthTrigger(int socket, int dat UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=6,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, dataLengthTrigger); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3350,16 +2934,12 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCharacterTrigger(int socket, int char UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=7,%d,%d", UBX_CELL_UD_CONFIGURATION, socket, characterTrigger); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3371,41 +2951,27 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_UD_CONFIGURATION) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=8,%d,%ld", UBX_CELL_UD_CONFIGURATION, socket, congestionTimer); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int socketStore = 0; int paramVal; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,0", UBX_CELL_SOCKET_CONTROL, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3425,8 +2991,6 @@ UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_ _debugPort->print(F("querySocketType: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -3434,34 +2998,21 @@ UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_ _lastSocketProtocol[socketStore] = paramVal; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int socketStore = 0; int paramVal; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,1", UBX_CELL_SOCKET_CONTROL, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3481,42 +3032,27 @@ UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) _debugPort->print(F("querySocketLastError: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *error = paramVal; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int socketStore = 0; long unsigned int paramVal; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,2", UBX_CELL_SOCKET_CONTROL, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3536,42 +3072,27 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total _debugPort->print(F("querySocketTotalBytesSent: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *total = (uint32_t)paramVal; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *total) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int socketStore = 0; long unsigned int paramVal; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,3", UBX_CELL_SOCKET_CONTROL, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3591,42 +3112,27 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *t _debugPort->print(F("querySocketTotalBytesReceived: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *total = (uint32_t)paramVal; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *address, int *port) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int socketStore = 0; int paramVals[5]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,4", UBX_CELL_SOCKET_CONTROL, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3647,8 +3153,6 @@ UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *add _debugPort->print(F("querySocketRemoteIPAddress: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -3658,33 +3162,20 @@ UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *add *port = paramVals[4]; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; - int socketStore = 0; - int paramVal; - - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,10", UBX_CELL_SOCKET_CONTROL, socket); - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } + int socketStore = 0; + int paramVal; + + snprintf(command, cmdLen, "%s=%d,10", UBX_CELL_SOCKET_CONTROL, socket); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3705,42 +3196,27 @@ UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_ _debugPort->print(F("querySocketStatusTCP: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *status = (UBX_CELL_tcp_socket_status_t)paramVal; } - free(command); - free(response); - return err; } UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; int scanNum = 0; int socketStore = 0; long unsigned int paramVal; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,11", UBX_CELL_SOCKET_CONTROL, socket); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -3760,17 +3236,12 @@ UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) _debugPort->print(F("querySocketOutUnackData: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } *total = (uint32_t)paramVal; } - free(command); - free(response); - return err; } @@ -3779,21 +3250,10 @@ int UBX_CELL::socketGetLastError() { UBX_CELL_error_t err; size_t cmdLen = 64; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; int errorCode = -1; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - snprintf(command, cmdLen, "%s", UBX_CELL_GET_ERROR); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3810,9 +3270,6 @@ int UBX_CELL::socketGetLastError() } } - free(command); - free(response); - return errorCode; } @@ -3825,19 +3282,15 @@ UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 16; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_HTTP_PROFILE, profile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3845,20 +3298,16 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 64; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_IP, address[0], address[1], address[2], address[3]); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3929,19 +3378,15 @@ UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, authenticate); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3949,19 +3394,15 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_PORT, port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -3990,14 +3431,11 @@ UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofil { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; - char *command; + char command[cmdLen]; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (secprofile == -1) snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure); else @@ -4006,7 +3444,6 @@ UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofil err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4099,23 +3536,13 @@ UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, i { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROTOCOL_ERROR) + 4; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; int rprofile, eclass, ecode; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_HTTP_PROTOCOL_ERROR, profile); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -4138,8 +3565,6 @@ UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, i err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(command); - free(response); return err; } @@ -4147,14 +3572,10 @@ UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_NVM) + 10; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_MQTT_NVM, parameter); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4197,9 +3618,7 @@ UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const Stri command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, userName.c_str(), pwd.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4211,17 +3630,13 @@ UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (secprofile == -1) snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure); else snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4229,14 +3644,10 @@ UBX_CELL_error_t UBX_CELL::connectMQTT(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGIN); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4244,14 +3655,10 @@ UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_LOGOUT); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4288,7 +3695,7 @@ UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String &topic) UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest, int readLength, int *bytesRead) { size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; - char *command; + char command[cmdLen]; char *response; UBX_CELL_error_t err; int scanNum = 0; @@ -4298,19 +3705,11 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest if (bytesRead != nullptr) *bytesRead = 0; - // Allocate memory for the command - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; - // Allocate memory for the response int responseLength = readLength + minimumResponseAllocation; response = ubx_cell_calloc_char(responseLength); if (response == nullptr) - { - free(command); return UBX_CELL_ERROR_OUT_OF_MEMORY; - } // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early... // To try and avoid this, look for \"\r\n\r\nOK\r\n there is a extra \r\n beetween " and the the standard \r\nOK\r\n @@ -4326,7 +3725,6 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest _debugPort->print(F("readMQTT: sendCommandWithResponse err ")); _debugPort->println(err); } - free(command); free(response); return err; } @@ -4349,7 +3747,6 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest _debugPort->print(F("readMQTT: error: scanNum is ")); _debugPort->println(scanNum); } - free(command); free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -4389,7 +3786,6 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } } - free(command); free(response); return err; @@ -4429,9 +3825,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String &topic, const char *c size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + msg_len; char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } snprintf(command, cmdLen, "%s=%d,%u,%u,0,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISH, qos, (retain ? 1 : 0), topic.c_str(), sanitized_msg); @@ -4469,9 +3863,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String &topic, const char size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length(); char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",%u", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, qos, (retain ? 1 : 0), topic.c_str(), msg_len); @@ -4499,9 +3891,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 20 + topic.length() + filename.length(); char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, qos, (retain ? 1 : 0), topic.c_str(), filename.c_str()); @@ -4516,16 +3906,10 @@ UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code2) { UBX_CELL_error_t err; - char *response; + char response[minimumResponseAllocation]; int code, code2; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(UBX_CELL_MQTT_PROTOCOL_ERROR, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4549,7 +3933,6 @@ UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } - free(response); return err; } @@ -4617,9 +4000,7 @@ UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) size_t cmdLen = strlen(UBX_CELL_FTP_COMMAND) + (2 * filename.length()) + 16; char *command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, filename.c_str(), filename.c_str()); @@ -4635,16 +4016,10 @@ UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2) { UBX_CELL_error_t err; - char *response; + char response[minimumResponseAllocation]; int code, code2; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(UBX_CELL_FTP_PROTOCOL_ERROR, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -4673,7 +4048,6 @@ UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2 } } - free(response); return err; } @@ -4681,17 +4055,12 @@ UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + 6; - char *command; - - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char command[cmdLen]; snprintf(command, cmdLen, "%s=%d", UBX_CELL_SEC_PROFILE, secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4699,14 +4068,10 @@ UBX_CELL_error_t UBX_CELL::configSecurityProfile(int secprofile, UBX_CELL_sec_pr { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + 10; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_SEC_PROFILE, secprofile, parameter, value); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4731,18 +4096,12 @@ UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opco { size_t cmdLen = strlen(UBX_CELL_SEC_MANAGER) + name.length() + 20; char *command; - char *response; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } int dataLen = data.length(); snprintf(command, cmdLen, "%s=%d,%d,\"%s\",%d", UBX_CELL_SEC_MANAGER, opcode, parameter, name.c_str(), dataLen); @@ -4772,7 +4131,6 @@ UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opco } free(command); - free(response); return err; } @@ -4780,14 +4138,11 @@ UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE) + 32; - char *command; + char command[cmdLen]; if (cid >= UBX_CELL_NUM_PDP_CONTEXT_IDENTIFIERS) return UBX_CELL_ERROR_ERROR; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (cid == -1) snprintf(command, cmdLen, "%s=%d", UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE, status); else @@ -4795,7 +4150,6 @@ UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -4803,22 +4157,12 @@ bool UBX_CELL::isGPSon(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_POWER) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; bool on = false; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_POWER); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) @@ -4834,9 +4178,6 @@ bool UBX_CELL::isGPSon(void) } } - free(command); - free(response); - return on; } @@ -4844,7 +4185,7 @@ UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_ai { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_POWER) + 32; // gnss_sys could be up to three digits - char *command; + char command[cmdLen]; bool gpsState; // Don't turn GPS on/off if it's already on/off @@ -4855,9 +4196,6 @@ UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_ai } // GPS power management - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (enable) { snprintf(command, cmdLen, "%s=1,%d,%d", UBX_CELL_GNSS_POWER, gnss_aiding, gnss_sys); @@ -4869,7 +4207,6 @@ UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_ai err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, 10000); - free(command); return err; } @@ -4936,7 +4273,7 @@ UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) // AT+UGRMC=<0,1> UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_GPRMC) + 3; - char *command; + char command[cmdLen]; // ** Don't call gpsPower here. It causes problems for +UTIME and the PPS signal ** // ** Call isGPSon and gpsPower externally if required ** @@ -4949,14 +4286,10 @@ UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) // } // } - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_GNSS_GPRMC, enable ? 1 : 0); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - free(command); return err; } @@ -4965,22 +4298,12 @@ UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_GPRMC) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; char *rmcBegin; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_GNSS_GPRMC); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_10_SEC_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) { @@ -4996,8 +4319,6 @@ UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData } } - free(command); - free(response); return err; } @@ -5022,7 +4343,7 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b // AT+ULOC=2,,,, UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_LOCATION) + 24; - char *command; + char command[cmdLen]; // This function will only work if the GPS module is initially turned off. if (isGPSon()) @@ -5035,9 +4356,6 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b if (accuracy > 999999) accuracy = 999999; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) snprintf(command, cmdLen, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); #else @@ -5046,7 +4364,6 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); - free(command); return err; } @@ -5057,18 +4374,13 @@ UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_AIDING_SERVER_CONFIGURATION) + 256; - char *command; - - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char command[cmdLen]; snprintf(command, cmdLen, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, primaryServer, secondaryServer, authToken, days, period, resolution, gnssTypes, mode, dataType); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -5077,18 +4389,12 @@ UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, { size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10; char *command; - char *response; + char response[minimumResponseAllocation]; UBX_CELL_error_t err; command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } int dataLen = len == -1 ? strlen(str) : len; snprintf(command, cmdLen, "%s=\"%s\",%d", UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE, filename.c_str(), dataLen); @@ -5123,7 +4429,6 @@ UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, } free(command); - free(response); return err; } @@ -5396,6 +4701,8 @@ UBX_CELL_error_t UBX_CELL::getFileBlock(const String &filename, char *buffer, si size_t cmdLen = filename.length() + 32; char *cmd = ubx_cell_calloc_char(cmdLen); + if (cmd == nullptr) + return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(cmd, cmdLen, "at+urdblock=\"%s\",%zu,%zu\r\n", filename.c_str(), offset, requested_length); sendCommand(cmd, false); @@ -5449,20 +4756,13 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_LIST_FILES) + filename.length() + 8; char *command; - char *response; + char response[minimumResponseAllocation]; command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=2,\"%s\"", UBX_CELL_FILE_SYSTEM_LIST_FILES, filename.c_str()); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) { @@ -5475,7 +4775,6 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) _debugPort->println(F("}")); } free(command); - free(response); return err; } @@ -5489,7 +4788,6 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) _debugPort->println(F("}")); } free(command); - free(response); return UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -5501,7 +4799,6 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) *size = fileSize; free(command); - free(response); return err; } @@ -5535,17 +4832,12 @@ UBX_CELL_error_t UBX_CELL::modulePowerOff(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_POWER_OFF) + 6; - char *command; - - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; + char command[cmdLen]; snprintf(command, cmdLen, "%s", UBX_CELL_COMMAND_POWER_OFF); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_POWER_OFF_TIMEOUT); - free(command); return err; } @@ -5744,17 +5036,12 @@ UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_FUNC) + 16; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_FUNC, function); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_3_MIN_TIMEOUT); - free(command); - return err; } @@ -5762,11 +5049,8 @@ UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool aut { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_MNO) + 9; - char *command; + char command[cmdLen]; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; if (mno == MNO_SIM_ICCID) // Only add autoReset and urcNotification if mno is MNO_SIM_ICCID snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno, (uint8_t)autoReset, (uint8_t)urcNotification); @@ -5775,8 +5059,6 @@ UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool aut err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; } @@ -5784,33 +5066,19 @@ UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_MNO) + 2; - char *command; - char *response; + char command[cmdLen]; + char response[minimumResponseAllocation]; mobile_network_operator_t o; int d; int r; int u; int oStore; - command = ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s?", UBX_CELL_COMMAND_MNO); - response = ubx_cell_calloc_char(minimumResponseAllocation); - if (response == nullptr) - { - free(command); - return UBX_CELL_ERROR_OUT_OF_MEMORY; - } - err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, response, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) - { - free(command); - free(response); return err; - } int scanned = 0; char *searchPtr = strstr(response, "+UMNOPROF:"); @@ -5837,9 +5105,6 @@ UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) err = UBX_CELL_ERROR_INVALID; } - free(command); - free(response); - return err; } @@ -6195,9 +5460,7 @@ UBX_CELL_error_t UBX_CELL::parseSocketReadIndicationUDP(int socket, int length) readDest = ubx_cell_calloc_char(length + 1); if (readDest == nullptr) - { return UBX_CELL_ERROR_OUT_OF_MEMORY; - } int bytesRead; err = socketReadUDP(socket, length, readDest, &remoteAddress, &remotePort, &bytesRead); diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index 98f510b..fde1e1e 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -83,16 +83,12 @@ template class UBX_CELL_VOICE { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_PLAY_AUDIO) + 13; - char *command; + char command[cmdLen]; - command = static_cast(this)->ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_PLAY_AUDIO, audio_resource, tone_id, nof_repeat); err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -100,16 +96,12 @@ template class UBX_CELL_VOICE { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_STOP_AUDIO) + 5; - char *command; + char command[cmdLen]; - command = static_cast(this)->ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_STOP_AUDIO, audio_resource); err = static_cast(this)->sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -117,17 +109,13 @@ template class UBX_CELL_VOICE { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 15; - char *command; + char command[cmdLen]; char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; - command = static_cast(this)->ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, frequency, duration, volume); err = static_cast(this)->sendCommandWithResponse(command, response, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } @@ -135,17 +123,13 @@ template class UBX_CELL_VOICE { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_GENERATE_TONE) + 14; - char *command; + char command[cmdLen]; char response[] = "\r\nOK\r\n\r\n+UUTGN: 0\r\n"; - command = static_cast(this)->ubx_cell_calloc_char(cmdLen); - if (command == nullptr) - return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=\"%c\",%d,%d", UBX_CELL_COMMAND_GENERATE_TONE, dtmf_character, duration, volume); err = static_cast(this)->sendCommandWithResponse(command, response, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); - free(command); return err; } From 7dc48df6f2e54286fbd40ecbb8e9025f13f643a7 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 18 Dec 2023 16:31:10 -0700 Subject: [PATCH 5/8] Change strstr to strnstr Fixes #12 --- src/sfe_sara_r5.cpp | 10 ++-- src/sfe_ublox_cellular.cpp | 106 ++++++++++++++++----------------- src/sfe_ublox_cellular_voice.h | 2 +- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/sfe_sara_r5.cpp b/src/sfe_sara_r5.cpp index b13d056..d80495d 100644 --- a/src/sfe_sara_r5.cpp +++ b/src/sfe_sara_r5.cpp @@ -39,7 +39,7 @@ UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_uti if (err == UBX_CELL_ERROR_SUCCESS) { int mStore, sStore, scanned = 0; - char *searchPtr = strstr(response, "+UTIME:"); + char *searchPtr = strnstr(response, "+UTIME:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UTIME:"); // Move searchPtr to first character - probably a space @@ -95,7 +95,7 @@ UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t if (err == UBX_CELL_ERROR_SUCCESS) { int cStore, scanned = 0; - char *searchPtr = strstr(response, "+UTIMEIND:"); + char *searchPtr = strnstr(response, "+UTIMEIND:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UTIMEIND:"); // Move searchPtr to first char @@ -149,7 +149,7 @@ UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int3 if (err == UBX_CELL_ERROR_SUCCESS) { int scanned = 0; - char *searchPtr = strstr(response, "+UTIMECFG:"); + char *searchPtr = strnstr(response, "+UTIMECFG:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UTIMECFG:"); // Move searchPtr to first char @@ -263,7 +263,7 @@ UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *ad if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+UPSND:"); + char *searchPtr = strnstr(response, "+UPSND:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UPSND:"); // Move searchPtr to first char @@ -298,7 +298,7 @@ bool SARA_R5::urcHandlerPDPAction(const char *event) int scanNum; int remoteIPstore[4]; - char *searchPtr = strstr(event, UBX_CELL_MESSAGE_PDP_ACTION_URC); + char *searchPtr = strnstr(event, UBX_CELL_MESSAGE_PDP_ACTION_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_MESSAGE_PDP_ACTION_URC); // Move searchPtr to first character - probably a space diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index e02bf0f..e353a9e 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -346,7 +346,7 @@ bool UBX_CELL::urcHandlerReadSocket(const char *event) { // URC: +UUSORD (Read Socket Data) int socket, length; - char *searchPtr = strstr(event, UBX_CELL_READ_SOCKET_URC); + char *searchPtr = strnstr(event, UBX_CELL_READ_SOCKET_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_READ_SOCKET_URC); // Move searchPtr to first character - probably a space @@ -384,7 +384,7 @@ bool UBX_CELL::urcHandlerReadUDPSocket(const char *event) { // URC: +UUSORF (Receive From command (UDP only)) int socket, length; - char *searchPtr = strstr(event, UBX_CELL_READ_UDP_SOCKET_URC); + char *searchPtr = strnstr(event, UBX_CELL_READ_UDP_SOCKET_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_READ_UDP_SOCKET_URC); // Move searchPtr to first character - probably a space @@ -415,7 +415,7 @@ bool UBX_CELL::urcHandlerListeningSocket(const char *event) int remoteIPstore[4] = {0, 0, 0, 0}; int localIPstore[4] = {0, 0, 0, 0}; - char *searchPtr = strstr(event, UBX_CELL_LISTEN_SOCKET_URC); + char *searchPtr = strnstr(event, UBX_CELL_LISTEN_SOCKET_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_LISTEN_SOCKET_URC); // Move searchPtr to first character - probably a space @@ -447,7 +447,7 @@ bool UBX_CELL::urcHandlerCloseSocket(const char *event) { // URC: +UUSOCL (Close Socket) int socket; - char *searchPtr = strstr(event, UBX_CELL_CLOSE_SOCKET_URC); + char *searchPtr = strnstr(event, UBX_CELL_CLOSE_SOCKET_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_CLOSE_SOCKET_URC); // Move searchPtr to first character - probably a space @@ -488,7 +488,7 @@ bool UBX_CELL::urcHandlerGNSSRequestLocation(const char *event) // Maybe we should also scan for +UUGIND and extract the activated gnss system? // This assumes the ULOC response type is "0" or "1" - as selected by gpsRequest detailed - char *searchPtr = strstr(event, UBX_CELL_GNSS_REQUEST_LOCATION_URC); + char *searchPtr = strnstr(event, UBX_CELL_GNSS_REQUEST_LOCATION_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_GNSS_REQUEST_LOCATION_URC); // Move searchPtr to first character - probably a space @@ -559,7 +559,7 @@ bool UBX_CELL::urcHandlerSIMState(const char *event) int scanNum; int stateStore; - char *searchPtr = strstr(event, UBX_CELL_SIM_STATE_URC); + char *searchPtr = strnstr(event, UBX_CELL_SIM_STATE_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_SIM_STATE_URC); // Move searchPtr to first character - probably a space @@ -592,7 +592,7 @@ bool UBX_CELL::urcHandlerHTTPCommand(const char *event) int profile, command, result; int scanNum; - char *searchPtr = strstr(event, UBX_CELL_HTTP_COMMAND_URC); + char *searchPtr = strnstr(event, UBX_CELL_HTTP_COMMAND_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_HTTP_COMMAND_URC); // Move searchPtr to first character - probably a space @@ -628,7 +628,7 @@ bool UBX_CELL::urcHandlerMQTTCommand(const char *event) int qos = -1; String topic; - char *searchPtr = strstr(event, UBX_CELL_MQTT_COMMAND_URC); + char *searchPtr = strnstr(event, UBX_CELL_MQTT_COMMAND_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_MQTT_COMMAND_URC); // Move searchPtr to first character - probably a space @@ -675,7 +675,7 @@ bool UBX_CELL::urcHandlerPingCommand(const char *event) int scanNum; // Try to extract the UUPING retries and payload size - char *searchPtr = strstr(event, UBX_CELL_PING_COMMAND_URC); + char *searchPtr = strnstr(event, UBX_CELL_PING_COMMAND_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_PING_COMMAND_URC); // Move searchPtr to first character - probably a space @@ -747,7 +747,7 @@ bool UBX_CELL::urcHandlerFTPCommand(const char *event) int ftpCmd; int ftpResult; int scanNum; - char *searchPtr = strstr(event, UBX_CELL_FTP_COMMAND_URC); + char *searchPtr = strnstr(event, UBX_CELL_FTP_COMMAND_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_FTP_COMMAND_URC); // Move searchPtr to first character - probably a space @@ -772,7 +772,7 @@ bool UBX_CELL::urcHandlerRegistrationStatus(const char *event) // URC: +CREG int status = 0; unsigned int lac = 0, ci = 0, Act = 0; - char *searchPtr = strstr(event, UBX_CELL_REGISTRATION_STATUS_URC); + char *searchPtr = strnstr(event, UBX_CELL_REGISTRATION_STATUS_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += strlen(UBX_CELL_REGISTRATION_STATUS_URC); // Move searchPtr to first character - probably a space @@ -801,7 +801,7 @@ bool UBX_CELL::urcHandlerEPSRegistrationStatus(const char *event) // URC: +CEREG int status = 0; unsigned int tac = 0, ci = 0, Act = 0; - char *searchPtr = strstr(event, UBX_CELL_EPSREGISTRATION_STATUS_URC); + char *searchPtr = strnstr(event, UBX_CELL_EPSREGISTRATION_STATUS_URC, _RXBuffSize); if (searchPtr != nullptr) { searchPtr += @@ -1142,7 +1142,7 @@ String UBX_CELL::getCCID(void) UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "\r\n+CCID:"); + char *searchPtr = strnstr(response, "\r\n+CCID:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("\r\n+CCID:"); // Move searchPtr to first character - probably a space @@ -1167,7 +1167,7 @@ String UBX_CELL::getSubscriberNo(void) UBX_CELL_10_SEC_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "\r\n+CNUM:"); + char *searchPtr = strnstr(response, "\r\n+CNUM:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("\r\n+CNUM:"); // Move searchPtr to first character - probably a space @@ -1192,7 +1192,7 @@ String UBX_CELL::getCapabilities(void) UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "\r\n+GCAP:"); + char *searchPtr = strnstr(response, "\r\n+GCAP:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("\r\n+GCAP:"); // Move searchPtr to first character - probably a space @@ -1283,7 +1283,7 @@ UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h // Response format (if TZ is negative): \r\n+CCLK: "YY/MM/DD,HH:MM:SS-TZ"\r\n\r\nOK\r\n if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+CCLK:"); + char *searchPtr = strnstr(response, "+CCLK:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+CCLK:"); // Move searchPtr to first char @@ -1403,7 +1403,7 @@ int8_t UBX_CELL::rssi(void) } int scanned = 0; - char *searchPtr = strstr(response, "+CSQ:"); + char *searchPtr = strnstr(response, "+CSQ:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+CSQ:"); // Move searchPtr to first char @@ -1437,7 +1437,7 @@ UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) int scanned = 0; const char *responseStr = "+CESQ:"; - char *searchPtr = strstr(response, responseStr); + char *searchPtr = strnstr(response, responseStr, minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen(responseStr); // Move searchPtr to first char @@ -1476,7 +1476,7 @@ UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) int scanned = 0; const char *startTag = eps ? UBX_CELL_EPSREGISTRATION_STATUS_URC : UBX_CELL_REGISTRATION_STATUS_URC; - char *searchPtr = strstr(response, startTag); + char *searchPtr = strnstr(response, startTag, minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += eps ? strlen(UBX_CELL_EPSREGISTRATION_STATUS_URC) @@ -1628,7 +1628,7 @@ UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_ { int scanned = 0; // Find the first/next occurrence of +CGDCONT: - searchPtr = strstr(searchPtr, "+CGDCONT:"); + searchPtr = strnstr(searchPtr, "+CGDCONT:", 1024 - (searchPtr - response)); if (searchPtr != nullptr) { char strPdpType[10]; @@ -1692,7 +1692,7 @@ UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) { int scanned = 0; char c[16]; - char *searchPtr = strstr(response, "+CPIN:"); + char *searchPtr = strnstr(response, "+CPIN:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+CPIN:"); // Move searchPtr to first char @@ -1755,7 +1755,7 @@ UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) if (err == UBX_CELL_ERROR_SUCCESS) { int scanned = 0; - char *searchPtr = strstr(response, "+USIMSTAT:"); + char *searchPtr = strnstr(response, "+USIMSTAT:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USIMSTAT:"); // Move searchPtr to first char @@ -1927,7 +1927,7 @@ UBX_CELL_error_t UBX_CELL::getOperator(String *oper) if (err == UBX_CELL_ERROR_SUCCESS) { - searchPtr = strstr(response, "+COPS:"); + searchPtr = strnstr(response, "+COPS:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+COPS:"); // Move searchPtr to first char @@ -2058,7 +2058,7 @@ UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, Str } int scanned = 0; - char *searchPtr = strstr(response, "+CPMS:"); + char *searchPtr = strnstr(response, "+CPMS:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+CPMS:"); // Move searchPtr to first char @@ -2104,7 +2104,7 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * char *searchPtr = response; // Find the first occurrence of +CMGR: - searchPtr = strstr(searchPtr, "+CMGR:"); + searchPtr = strnstr(searchPtr, "+CMGR:", 1024 - (searchPtr - response)); if (searchPtr != nullptr) { searchPtr += strlen("+CMGR:"); // Move searchPtr to first char @@ -2269,7 +2269,7 @@ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) } snprintf(gpioChar, charLen, "%d", gpio); // Convert GPIO to char array - gpioStart = strstr(response, gpioChar); // Find first occurence of GPIO in response + gpioStart = strnstr(response, gpioChar, minimumResponseAllocation); // Find first occurence of GPIO in response if (gpioStart == nullptr) return GPIO_MODE_INVALID; // If not found return invalid @@ -2307,7 +2307,7 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local return -1; } - responseStart = strstr(response, "+USOCR:"); + responseStart = strnstr(response, "+USOCR:", minimumResponseAllocation); if (responseStart == nullptr) { if (_printDebug == true) @@ -2544,7 +2544,7 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in } // Extract the data - char *searchPtr = strstr(response, "+USORD:"); + char *searchPtr = strnstr(response, "+USORD:", responseLength); if (searchPtr != nullptr) { searchPtr += strlen("+USORD:"); // Move searchPtr to first char @@ -2642,7 +2642,7 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USORD:"); + char *searchPtr = strnstr(response, "+USORD:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USORD:"); // Move searchPtr to first char @@ -2724,7 +2724,7 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, } // Extract the data - char *searchPtr = strstr(response, "+USORF:"); + char *searchPtr = strnstr(response, "+USORF:", responseLength); if (searchPtr != nullptr) { searchPtr += strlen("+USORF:"); // Move searchPtr to first char @@ -2842,7 +2842,7 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USORF:"); + char *searchPtr = strnstr(response, "+USORF:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USORF:"); // Move searchPtr to first char @@ -2976,7 +2976,7 @@ UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_ if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3017,7 +3017,7 @@ UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3057,7 +3057,7 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3097,7 +3097,7 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *t if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3137,7 +3137,7 @@ UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *add if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3181,7 +3181,7 @@ UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_ if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3221,7 +3221,7 @@ UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOCTL:"); + char *searchPtr = strnstr(response, "+USOCTL:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOCTL:"); // Move searchPtr to first char @@ -3260,7 +3260,7 @@ int UBX_CELL::socketGetLastError() if (err == UBX_CELL_ERROR_SUCCESS) { - char *searchPtr = strstr(response, "+USOER:"); + char *searchPtr = strnstr(response, "+USOER:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+USOER:"); // Move searchPtr to first char @@ -3548,7 +3548,7 @@ UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, i if (err == UBX_CELL_ERROR_SUCCESS) { int scanned = 0; - char *searchPtr = strstr(response, "+UHTTPER:"); + char *searchPtr = strnstr(response, "+UHTTPER:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UHTTPER:"); // Move searchPtr to first char @@ -3730,7 +3730,7 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest } // Extract the data - char *searchPtr = strstr(response, "+UMQTTC:"); + char *searchPtr = strnstr(response, "+UMQTTC:", responseLength); int cmd = 0; if (searchPtr != nullptr) { @@ -3752,7 +3752,7 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest } err = UBX_CELL_ERROR_SUCCESS; - searchPtr = strstr(searchPtr, "\""); + searchPtr = strnstr(searchPtr, "\"", responseLength - (searchPtr - response)); if (searchPtr != nullptr) { if (pTopic) @@ -3761,7 +3761,7 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest *pTopic = searchPtr + 1; searchPtr[topic_length + 1] = '\"'; // restore } - searchPtr = strstr(searchPtr + topic_length + 2, "\""); + searchPtr = strnstr(searchPtr + topic_length + 2, "\"", responseLength - (searchPtr + topic_length + 2 - response)); if (readDest && (searchPtr != nullptr) && (response + responseLength >= searchPtr + data_length + 1) && (searchPtr[data_length + 1] == '"')) { @@ -3916,7 +3916,7 @@ UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code if (err == UBX_CELL_ERROR_SUCCESS) { int scanned = 0; - char *searchPtr = strstr(response, "+UMQTTER:"); + char *searchPtr = strnstr(response, "+UMQTTER:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UMQTTER:"); // Move searchPtr to first char @@ -4026,7 +4026,7 @@ UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2 if (err == UBX_CELL_ERROR_SUCCESS) { int scanned = 0; - char *searchPtr = strstr(response, "+UFTPER:"); + char *searchPtr = strnstr(response, "+UFTPER:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UFTPER:"); // Move searchPtr to first char @@ -4308,7 +4308,7 @@ UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData if (err == UBX_CELL_ERROR_SUCCESS) { // Fast-forward response string to $GPRMC starter - rmcBegin = strstr(response, "$GPRMC"); + rmcBegin = strnstr(response, "$GPRMC", minimumResponseAllocation); if (rmcBegin == nullptr) { err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; @@ -4497,7 +4497,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n int scanned = 0; int readFileSize = 0; - char *searchPtr = strstr(response, "+URDFILE:"); + char *searchPtr = strnstr(response, "+URDFILE:", fileSize + minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr = strchr(searchPtr, '\"'); // Find the first quote @@ -4551,7 +4551,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) else { if (_printDebug == true) - _debugPort->println(F("getFileContents: strstr failed!")); + _debugPort->println(F("getFileContents: strnstr failed!")); err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -4620,7 +4620,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n int scanned = 0; int readFileSize = 0; - char *searchPtr = strstr(response, "+URDFILE:"); + char *searchPtr = strnstr(response, "+URDFILE:", fileSize + minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr = strchr(searchPtr, '\"'); // Find the first quote @@ -4670,7 +4670,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) else { if (_printDebug == true) - _debugPort->println(F("getFileContents: strstr failed!")); + _debugPort->println(F("getFileContents: strnstr failed!")); err = UBX_CELL_ERROR_UNEXPECTED_RESPONSE; } @@ -4778,7 +4778,7 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) return err; } - char *responseStart = strstr(response, "+ULSTFILE:"); + char *responseStart = strnstr(response, "+ULSTFILE:", minimumResponseAllocation); if (responseStart == nullptr) { if (_printDebug == true) @@ -5081,7 +5081,7 @@ UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) return err; int scanned = 0; - char *searchPtr = strstr(response, "+UMNOPROF:"); + char *searchPtr = strnstr(response, "+UMNOPROF:", minimumResponseAllocation); if (searchPtr != nullptr) { searchPtr += strlen("+UMNOPROF:"); // Move searchPtr to first char @@ -5765,7 +5765,7 @@ void UBX_CELL::pruneBacklog() // These are the events we want to keep so they can be processed by poll / bufferedPoll for (auto urcString : _urcStrings) { - if (strstr(event, urcString) != nullptr) + if (strnstr(event, urcString, _RXBuffSize - (event - _saraResponseBacklog)) != nullptr) { strcat(_pruneBuffer, event); // The URCs are all readable text so using strcat is OK strcat(_pruneBuffer, "\r\n"); // strtok blows away delimiter, but we want that for later. diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index fde1e1e..a460de7 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -145,7 +145,7 @@ template class UBX_CELL_VOICE bool urcCheckRing(const char *event) { int socket, length; - char *searchPtr = strstr(event, UBX_CELL_RING_URC); + char *searchPtr = strnstr(event, UBX_CELL_RING_URC, _RXBuffSize); if (searchPtr != nullptr) { if (_ringCallback != nullptr) From 0995691e93858326a4f928eb87212a5a42c341f0 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 18 Dec 2023 16:33:27 -0700 Subject: [PATCH 6/8] Run formatter again clang with Microsoft style --- src/sfe_sara_r5.cpp | 4 +- src/sfe_ublox_cellular.cpp | 98 ++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/src/sfe_sara_r5.cpp b/src/sfe_sara_r5.cpp index d80495d..4bb2574 100644 --- a/src/sfe_sara_r5.cpp +++ b/src/sfe_sara_r5.cpp @@ -222,8 +222,8 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur if (profile >= UBX_CELL_NUM_PSD_PROFILES) return UBX_CELL_ERROR_ERROR; - snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value[0], value[1], - value[2], value[3]); + snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_MESSAGE_PDP_CONFIG, profile, parameter, value[0], + value[1], value[2], value[3]); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index e353a9e..7a07163 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -1792,12 +1792,13 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne if (dialing_type_char != 0) { - snprintf(command, cmdLen, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, dialNumber, PPP_L2P[l2p], - (unsigned int)cid); + snprintf(command, cmdLen, "%s%c*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialing_type_char, dialNumber, + PPP_L2P[l2p], (unsigned int)cid); } else { - snprintf(command, cmdLen, "%s*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialNumber, PPP_L2P[l2p], (unsigned int)cid); + snprintf(command, cmdLen, "%s*%lu**%s*%u#", UBX_CELL_MESSAGE_ENTER_PPP, dialNumber, PPP_L2P[l2p], + (unsigned int)cid); } err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -2268,7 +2269,7 @@ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) return GPIO_MODE_INVALID; } - snprintf(gpioChar, charLen, "%d", gpio); // Convert GPIO to char array + snprintf(gpioChar, charLen, "%d", gpio); // Convert GPIO to char array gpioStart = strnstr(response, gpioChar, minimumResponseAllocation); // Find first occurence of GPIO in response if (gpioStart == nullptr) @@ -3303,8 +3304,8 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_IP, - address[0], address[1], address[2], address[3]); + snprintf(command, cmdLen, "%s=%d,%d,\"%d.%d.%d.%d\"", UBX_CELL_HTTP_PROFILE, profile, + UBX_CELL_HTTP_OP_CODE_SERVER_IP, address[0], address[1], address[2], address[3]); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3324,7 +3325,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SERVER_NAME, - server.c_str()); + server.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3345,7 +3346,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_USERNAME, - username.c_str()); + username.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3366,7 +3367,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_PASSWORD, - password.c_str()); + password.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3383,7 +3384,8 @@ UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) if (profile >= UBX_CELL_NUM_HTTP_PROFILES) return UBX_CELL_ERROR_ERROR; - snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, authenticate); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_AUTHENTICATION, + authenticate); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3418,8 +3420,8 @@ UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, - header.c_str()); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_HTTP_PROFILE, profile, + UBX_CELL_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, header.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3439,8 +3441,8 @@ UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofil if (secprofile == -1) snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure); else - snprintf(command, cmdLen, "%s=%d,%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, secure, - secprofile); + snprintf(command, cmdLen, "%s=%d,%d,%d,%d", UBX_CELL_HTTP_PROFILE, profile, UBX_CELL_HTTP_OP_CODE_SECURE, + secure, secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3456,7 +3458,8 @@ UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, unsig command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=\"%s\",%d,%d,%ld,%d", UBX_CELL_PING_COMMAND, remote_host.c_str(), retry, p_size, timeout, ttl); + snprintf(command, cmdLen, "%s=\"%s\",%d,%d,%ld,%d", UBX_CELL_PING_COMMAND, remote_host.c_str(), retry, p_size, + timeout, ttl); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3476,8 +3479,8 @@ UBX_CELL_error_t UBX_CELL::sendHTTPGET(int profile, String path, String response command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\"", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_GET, path.c_str(), - responseFilename.c_str()); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\"", UBX_CELL_HTTP_COMMAND, profile, UBX_CELL_HTTP_COMMAND_GET, + path.c_str(), responseFilename.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3489,8 +3492,7 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String res UBX_CELL_http_content_types_t httpContentType) { UBX_CELL_error_t err; - size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + - responseFilename.length() + data.length(); + size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length() + data.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) @@ -3500,7 +3502,7 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String res if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, - UBX_CELL_HTTP_COMMAND_POST_DATA, path.c_str(), responseFilename.c_str(), data.c_str(), httpContentType); + UBX_CELL_HTTP_COMMAND_POST_DATA, path.c_str(), responseFilename.c_str(), data.c_str(), httpContentType); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3512,8 +3514,8 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String res UBX_CELL_http_content_types_t httpContentType) { UBX_CELL_error_t err; - size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + - responseFilename.length() + requestFile.length(); + size_t cmdLen = + strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length() + requestFile.length(); char *command; if (profile >= UBX_CELL_NUM_HTTP_PROFILES) @@ -3523,8 +3525,8 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String res if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", UBX_CELL_HTTP_COMMAND, profile, - UBX_CELL_HTTP_COMMAND_POST_FILE, path.c_str(), responseFilename.c_str(), requestFile.c_str(), - httpContentType); + UBX_CELL_HTTP_COMMAND_POST_FILE, path.c_str(), responseFilename.c_str(), requestFile.c_str(), + httpContentType); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3603,8 +3605,8 @@ UBX_CELL_error_t UBX_CELL::setMQTTserver(const String &serverName, int port) command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,\"%s\",%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SERVERNAME, serverName.c_str(), - port); + snprintf(command, cmdLen, "%s=%d,\"%s\",%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SERVERNAME, + serverName.c_str(), port); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -3619,8 +3621,8 @@ UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const Stri command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, userName.c_str(), - pwd.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_USERNAMEPWD, + userName.c_str(), pwd.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -3635,7 +3637,8 @@ UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) if (secprofile == -1) snprintf(command, cmdLen, "%s=%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure); else - snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, secprofile); + snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_MQTT_PROFILE, UBX_CELL_MQTT_PROFILE_SECURE, secure, + secprofile); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); return err; } @@ -3671,7 +3674,8 @@ UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String &topic) command = ubx_cell_calloc_char(cmdLen); if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_SUBSCRIBE, max_Qos, topic.c_str()); + snprintf(command, cmdLen, "%s=%d,%d,\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_SUBSCRIBE, max_Qos, + topic.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -3761,7 +3765,8 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest *pTopic = searchPtr + 1; searchPtr[topic_length + 1] = '\"'; // restore } - searchPtr = strnstr(searchPtr + topic_length + 2, "\"", responseLength - (searchPtr + topic_length + 2 - response)); + searchPtr = + strnstr(searchPtr + topic_length + 2, "\"", responseLength - (searchPtr + topic_length + 2 - response)); if (readDest && (searchPtr != nullptr) && (response + responseLength >= searchPtr + data_length + 1) && (searchPtr[data_length + 1] == '"')) { @@ -3828,7 +3833,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String &topic, const char *c return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%u,%u,0,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISH, qos, - (retain ? 1 : 0), topic.c_str(), sanitized_msg); + (retain ? 1 : 0), topic.c_str(), sanitized_msg); sendCommand(command, true); err = waitForResponse(UBX_CELL_RESPONSE_MORE, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3866,7 +3871,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String &topic, const char return UBX_CELL_ERROR_OUT_OF_MEMORY; snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",%u", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHBINARY, qos, - (retain ? 1 : 0), topic.c_str(), msg_len); + (retain ? 1 : 0), topic.c_str(), msg_len); sendCommand(command, true); err = waitForResponse(UBX_CELL_RESPONSE_MORE, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3893,8 +3898,8 @@ UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, qos, - (retain ? 1 : 0), topic.c_str(), filename.c_str()); + snprintf(command, cmdLen, "%s=%d,%u,%u,\"%s\",\"%s\"", UBX_CELL_MQTT_COMMAND, UBX_CELL_MQTT_COMMAND_PUBLISHFILE, + qos, (retain ? 1 : 0), topic.c_str(), filename.c_str()); sendCommand(command, true); err = waitForResponse(UBX_CELL_RESPONSE_OK, UBX_CELL_RESPONSE_ERROR, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -3952,8 +3957,8 @@ UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsi constexpr size_t cmdLen = 64; char command[cmdLen]; // long enough for AT+UFTP=1,<128 bytes> - snprintf(command, cmdLen, "%s=%d,%u,%u,%u", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_TIMEOUT, timeout, - cmd_linger, data_linger); + snprintf(command, cmdLen, "%s=%d,%u,%u,%u", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_TIMEOUT, timeout, cmd_linger, + data_linger); return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } @@ -3963,8 +3968,7 @@ UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const Strin constexpr size_t cmdLen = 48; char command[cmdLen]; // long enough for AT+UFTP=n,<30 bytes> - snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_USERNAME, - userName.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\"", UBX_CELL_FTP_PROFILE, UBX_CELL_FTP_PROFILE_USERNAME, userName.c_str()); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); if (err != UBX_CELL_ERROR_SUCCESS) { @@ -4002,8 +4006,8 @@ UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) if (command == nullptr) return UBX_CELL_ERROR_OUT_OF_MEMORY; - snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, filename.c_str(), - filename.c_str()); + snprintf(command, cmdLen, "%s=%d,\"%s\",\"%s\"", UBX_CELL_FTP_COMMAND, UBX_CELL_FTP_COMMAND_GET_FILE, + filename.c_str(), filename.c_str()); // memset(response, 0, sizeof(response)); // sendCommandWithResponse(command, UBX_CELL_RESPONSE_CONNECT, response, 8000 /* ms */, response_len); UBX_CELL_error_t err = @@ -4357,9 +4361,11 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b accuracy = 999999; #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - snprintf(command, cmdLen, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); + snprintf(command, cmdLen, "%s=2,%d,%d,%d,%d", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, + accuracy); #else - snprintf(command, cmdLen, "%s=2,%d,%d,%d,%ld", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, accuracy); + snprintf(command, cmdLen, "%s=2,%d,%d,%d,%ld", UBX_CELL_GNSS_REQUEST_LOCATION, sensor, detailed ? 1 : 0, timeout, + accuracy); #endif err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_10_SEC_TIMEOUT); @@ -4376,8 +4382,8 @@ UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const size_t cmdLen = strlen(UBX_CELL_AIDING_SERVER_CONFIGURATION) + 256; char command[cmdLen]; - snprintf(command, cmdLen, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, primaryServer, - secondaryServer, authToken, days, period, resolution, gnssTypes, mode, dataType); + snprintf(command, cmdLen, "%s=\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,%d,%d", UBX_CELL_AIDING_SERVER_CONFIGURATION, + primaryServer, secondaryServer, authToken, days, period, resolution, gnssTypes, mode, dataType); err = sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); @@ -5053,7 +5059,7 @@ UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool aut if (mno == MNO_SIM_ICCID) // Only add autoReset and urcNotification if mno is MNO_SIM_ICCID snprintf(command, cmdLen, "%s=%d,%d,%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno, (uint8_t)autoReset, - (uint8_t)urcNotification); + (uint8_t)urcNotification); else snprintf(command, cmdLen, "%s=%d", UBX_CELL_COMMAND_MNO, (uint8_t)mno); From 92594527ce6444032d35e61f971d045fc9e749f4 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 18 Dec 2023 16:43:24 -0700 Subject: [PATCH 7/8] Rename classes --- .../AudioExample1_PlayTone.ino | 8 +- .../AudioExample2_Loopback.ino | 8 +- .../AudioExample3_CallControl.ino | 8 +- .../Example1_DeviceIdentification.ino | 28 +- .../Example2_NetworkInfo.ino | 28 +- .../Example3_RegisterOperator.ino | 28 +- examples/Example4_Clock/Example4_Clock.ino | 28 +- examples/Example5_Ping/Example5_Ping.ino | 28 +- .../Example6_ReceiveSMS.ino | 28 +- .../Example7_SendSMS/Example7_SendSMS.ino | 28 +- src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 2 + src/sfe_lara_r6.h | 14 +- src/sfe_sara_r5.cpp | 28 +- src/sfe_sara_r5.h | 14 +- src/sfe_ublox_cellular.cpp | 412 +++++++++--------- src/sfe_ublox_cellular.h | 6 +- src/sfe_ublox_cellular_voice.h | 6 +- 17 files changed, 352 insertions(+), 350 deletions(-) diff --git a/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino index c270e19..88b093d 100644 --- a/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino +++ b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino @@ -6,10 +6,10 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modules, so this base class can be used -// LARA_R6001 myModule; -// LARA_R6401 myModule; -// LARA_R6801_00B myModule; +SparkFun_ublox_Cellular_Voice myModule; // This example works with all voice-enabled modules, so this base class can be used +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; void setup() { diff --git a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino index 44aaee0..3adafab 100644 --- a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino +++ b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino @@ -6,10 +6,10 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modules, so this base class can be used -// LARA_R6001 myModule; -// LARA_R6401 myModule; -// LARA_R6801_00B myModule; +SparkFun_ublox_Cellular_Voice myModule; // This example works with all voice-enabled modules, so this base class can be used +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; void setup() { diff --git a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino index 77f8b31..cf6a29a 100644 --- a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino +++ b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino @@ -6,10 +6,10 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modules, so this base class can be used -// LARA_R6001 myModule; -// LARA_R6401 myModule; -// LARA_R6801_00B myModule; +SparkFun_ublox_Cellular_Voice myModule; // This example works with all voice-enabled modules, so this base class can be used +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; bool callInProgress = false; bool incomingCall = false; diff --git a/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino b/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino index fa50999..47089c1 100644 --- a/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino +++ b/examples/Example1_DeviceIdentification/Example1_DeviceIdentification.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; // Map SIM states to more readable strings String simStateString[] = { diff --git a/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino b/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino index cf32155..3a851ba 100644 --- a/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino +++ b/examples/Example2_NetworkInfo/Example2_NetworkInfo.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; // Map registration status messages to more readable strings String registrationString[] = { diff --git a/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino b/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino index 324b2bc..5a459bc 100644 --- a/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino +++ b/examples/Example3_RegisterOperator/Example3_RegisterOperator.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; // Map registration status messages to more readable strings String registrationString[] = { diff --git a/examples/Example4_Clock/Example4_Clock.ino b/examples/Example4_Clock/Example4_Clock.ino index 2e3232b..774f92c 100644 --- a/examples/Example4_Clock/Example4_Clock.ino +++ b/examples/Example4_Clock/Example4_Clock.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; void setup() { diff --git a/examples/Example5_Ping/Example5_Ping.ino b/examples/Example5_Ping/Example5_Ping.ino index 3cc6678..8682cd5 100644 --- a/examples/Example5_Ping/Example5_Ping.ino +++ b/examples/Example5_Ping/Example5_Ping.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; String pingMe = ""; // The name of the server we are going to ping diff --git a/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino b/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino index 416b45f..33dc6ac 100644 --- a/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino +++ b/examples/Example6_ReceiveSMS/Example6_ReceiveSMS.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; void setup() { diff --git a/examples/Example7_SendSMS/Example7_SendSMS.ino b/examples/Example7_SendSMS/Example7_SendSMS.ino index 8e6e11f..5e758cf 100644 --- a/examples/Example7_SendSMS/Example7_SendSMS.ino +++ b/examples/Example7_SendSMS/Example7_SendSMS.ino @@ -6,20 +6,20 @@ // Uncomment the module you're using. If your module is not listed below, then // it's not supported for this example -UBX_CELL myModule; // This example works with all modules, so the base class can be used -// SARA_R5 myModule; // Base SARA-R5 class -// SARA_R500S myModule; -// SARA_R500S_01B myModule; -// SARA_R500S_61B myModule; -// SARA_R510M8S_61B myModule; -// SARA_R510S myModule; -// LARA_R6 myModule; // Base LARA-R6 class -// LARA_R6001 myModule; -// LARA_R6001D myModule; -// LARA_R6401 myModule; -// LARA_R6401D myModule; -// LARA_R6801_00B myModule; -// LARA_R6801D myModule; +SparkFun_ublox_Cellular myModule; // This example works with all modules, so the base class can be used +// SparkFun_ublox_SARA_R5 myModule; // Base SARA-R5 class +// SparkFun_ublox_SARA_R500S myModule; +// SparkFun_ublox_SARA_R500S_01B myModule; +// SparkFun_ublox_SARA_R500S_61B myModule; +// SparkFun_ublox_SARA_R510M8S_61B myModule; +// SparkFun_ublox_SARA_R510S myModule; +// SparkFun_ublox_LARA_R6 myModule; // Base LARA-R6 class +// SparkFun_ublox_LARA_R6001 myModule; +// SparkFun_ublox_LARA_R6001D myModule; +// SparkFun_ublox_LARA_R6401 myModule; +// SparkFun_ublox_LARA_R6401D myModule; +// SparkFun_ublox_LARA_R6801_00B myModule; +// SparkFun_ublox_LARA_R6801D myModule; void setup() { diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index a5fff86..47af564 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -22,6 +22,8 @@ #include "sfe_sara_r5.h" #include "sfe_ublox_cellular.h" +#define SARA_R5 SparkFun_ublox_SARA_R5 + #define SARA_R5_POWER_PIN -1 // Default to no pin #define SARA_R5_RESET_PIN -1 diff --git a/src/sfe_lara_r6.h b/src/sfe_lara_r6.h index 40fc862..e421ae3 100644 --- a/src/sfe_lara_r6.h +++ b/src/sfe_lara_r6.h @@ -5,31 +5,31 @@ #include "sfe_ublox_cellular_voice.h" // Base LARA-R6 class -class LARA_R6 : public UBX_CELL +class SparkFun_ublox_LARA_R6 : public SparkFun_ublox_Cellular { }; -class LARA_R6001 : public LARA_R6, public UBX_CELL_VOICE +class SparkFun_ublox_LARA_R6001 : public SparkFun_ublox_LARA_R6, public SparkFun_ublox_Cellular_Voice_Base { }; -class LARA_R6001D : public LARA_R6 +class SparkFun_ublox_LARA_R6001D : public SparkFun_ublox_LARA_R6 { }; -class LARA_R6401 : public LARA_R6, public UBX_CELL_VOICE +class SparkFun_ublox_LARA_R6401 : public SparkFun_ublox_LARA_R6, public SparkFun_ublox_Cellular_Voice_Base { }; -class LARA_R6401D : public LARA_R6 +class SparkFun_ublox_LARA_R6401D : public SparkFun_ublox_LARA_R6 { }; -class LARA_R6801_00B : public LARA_R6, public UBX_CELL_VOICE +class SparkFun_ublox_LARA_R6801_00B : public SparkFun_ublox_LARA_R6, public SparkFun_ublox_Cellular_Voice_Base { }; -class LARA_R6801D : public LARA_R6 +class SparkFun_ublox_LARA_R6801D : public SparkFun_ublox_LARA_R6 { }; diff --git a/src/sfe_sara_r5.cpp b/src/sfe_sara_r5.cpp index 4bb2574..850b38f 100644 --- a/src/sfe_sara_r5.cpp +++ b/src/sfe_sara_r5.cpp @@ -1,12 +1,12 @@ #include "sfe_sara_r5.h" -SARA_R5::SARA_R5() +SparkFun_ublox_SARA_R5::SparkFun_ublox_SARA_R5() { addURCHandler(UBX_CELL_MESSAGE_PDP_ACTION_URC, [this](const char *event) { return this->urcHandlerPDPAction(event); }); } -UBX_CELL_error_t SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utime_sensor_t sensor) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utime_sensor_t sensor) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_TIME) + 16; @@ -21,7 +21,7 @@ UBX_CELL_error_t SARA_R5::setUtimeMode(UBX_CELL_utime_mode_t mode, UBX_CELL_utim return err; } -UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_utime_sensor_t *sensor) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_utime_sensor_t *sensor) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_REQUEST_TIME) + 2; @@ -66,7 +66,7 @@ UBX_CELL_error_t SARA_R5::getUtimeMode(UBX_CELL_utime_mode_t *mode, UBX_CELL_uti return err; } -UBX_CELL_error_t SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t config) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t config) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_INDICATION) + 16; @@ -78,7 +78,7 @@ UBX_CELL_error_t SARA_R5::setUtimeIndication(UBX_CELL_utime_urc_configuration_t return err; } -UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t *config) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t *config) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_INDICATION) + 2; @@ -115,7 +115,7 @@ UBX_CELL_error_t SARA_R5::getUtimeIndication(UBX_CELL_utime_urc_configuration_t return err; } -UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32_t offsetSeconds) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32_t offsetSeconds) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 48; @@ -131,7 +131,7 @@ UBX_CELL_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32 return err; } -UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_TIME_CONFIGURATION) + 2; @@ -173,7 +173,7 @@ UBX_CELL_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int3 return err; } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, int value) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, int value) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONFIG) + 24; @@ -189,13 +189,13 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur return err; } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, UBX_CELL_pdp_protocol_type_t value) { return (setPDPconfiguration(profile, parameter, (int)value)); } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, String value) { UBX_CELL_error_t err; @@ -212,7 +212,7 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur return err; } -UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, +UBX_CELL_error_t SparkFun_ublox_SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configuration_parameter_t parameter, IPAddress value) { UBX_CELL_error_t err; @@ -230,7 +230,7 @@ UBX_CELL_error_t SARA_R5::setPDPconfiguration(int profile, UBX_CELL_pdp_configur return err; } -UBX_CELL_error_t SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t action) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t action) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_ACTION) + 32; @@ -246,7 +246,7 @@ UBX_CELL_error_t SARA_R5::performPDPaction(int profile, UBX_CELL_pdp_actions_t a return err; } -UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *address) +UBX_CELL_error_t SparkFun_ublox_SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *address) { size_t cmdLen = strlen(UBX_CELL_NETWORK_ASSIGNED_DATA) + 16; char command[cmdLen]; @@ -290,7 +290,7 @@ UBX_CELL_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *ad return err; } -bool SARA_R5::urcHandlerPDPAction(const char *event) +bool SparkFun_ublox_SARA_R5::urcHandlerPDPAction(const char *event) { // URC: +UUPSDA (Packet Switched Data Action) int result; diff --git a/src/sfe_sara_r5.h b/src/sfe_sara_r5.h index a8189c7..f61a67f 100644 --- a/src/sfe_sara_r5.h +++ b/src/sfe_sara_r5.h @@ -13,10 +13,10 @@ const char *const UBX_CELL_GNSS_TIME_CONFIGURATION = "+UTIMECFG"; // Sets time c const char *const UBX_CELL_MESSAGE_PDP_ACTION_URC = "+UUPSDA:"; // Base SARA-R5 class -class SARA_R5 : public UBX_CELL +class SparkFun_ublox_SARA_R5 : public SparkFun_ublox_Cellular { public: - SARA_R5(); + SparkFun_ublox_SARA_R5(); UBX_CELL_error_t setUtimeMode( UBX_CELL_utime_mode_t mode = UBX_CELL_UTIME_MODE_PPS, @@ -50,23 +50,23 @@ class SARA_R5 : public UBX_CELL bool urcHandlerPDPAction(const char *event); }; -class SARA_R500S : public SARA_R5 +class SparkFun_ublox_SARA_R500S : public SparkFun_ublox_SARA_R5 { }; -class SARA_R500S_01B : public SARA_R5 +class SparkFun_ublox_SARA_R500S_01B : public SparkFun_ublox_SARA_R5 { }; -class SARA_R500S_61B : public SARA_R5 +class SparkFun_ublox_SARA_R500S_61B : public SparkFun_ublox_SARA_R5 { }; -class SARA_R510M8S_61B : public SARA_R5 +class SparkFun_ublox_SARA_R510M8S_61B : public SparkFun_ublox_SARA_R5 { }; -class SARA_R510S : public SARA_R5 +class SparkFun_ublox_SARA_R510S : public SparkFun_ublox_SARA_R5 { }; diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index 7a07163..418c024 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -15,7 +15,7 @@ #include "sfe_ublox_cellular.h" -UBX_CELL::UBX_CELL(int powerPin, int resetPin, uint8_t maxInitTries) +SparkFun_ublox_Cellular::SparkFun_ublox_Cellular(int powerPin, int resetPin, uint8_t maxInitTries) { #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED _softSerial = nullptr; @@ -73,7 +73,7 @@ UBX_CELL::UBX_CELL(int powerPin, int resetPin, uint8_t maxInitTries) [this](const char *event) { return this->urcHandlerEPSRegistrationStatus(event); }); } -UBX_CELL::~UBX_CELL(void) +SparkFun_ublox_Cellular::~SparkFun_ublox_Cellular(void) { if (nullptr != _saraRXBuffer) { @@ -93,7 +93,7 @@ UBX_CELL::~UBX_CELL(void) } #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED -bool UBX_CELL::begin(SoftwareSerial &softSerial, unsigned long baud) +bool SparkFun_ublox_Cellular::begin(SoftwareSerial &softSerial, unsigned long baud) { if (nullptr == _saraRXBuffer) { @@ -144,7 +144,7 @@ bool UBX_CELL::begin(SoftwareSerial &softSerial, unsigned long baud) } #endif -bool UBX_CELL::begin(HardwareSerial &hardSerial, unsigned long baud) +bool SparkFun_ublox_Cellular::begin(HardwareSerial &hardSerial, unsigned long baud) { if (nullptr == _saraRXBuffer) { @@ -196,7 +196,7 @@ bool UBX_CELL::begin(HardwareSerial &hardSerial, unsigned long baud) // Calling this function with nothing sets the debug port to Serial // You can also call it with other streams like Serial1, SerialUSB, etc. -void UBX_CELL::enableDebugging(Print &debugPort) +void SparkFun_ublox_Cellular::enableDebugging(Print &debugPort) { _debugPort = &debugPort; _printDebug = true; @@ -204,7 +204,7 @@ void UBX_CELL::enableDebugging(Print &debugPort) // Calling this function with nothing sets the debug port to Serial // You can also call it with other streams like Serial1, SerialUSB, etc. -void UBX_CELL::enableAtDebugging(Print &debugPort) +void SparkFun_ublox_Cellular::enableAtDebugging(Print &debugPort) { _debugAtPort = &debugPort; _printAtDebug = true; @@ -214,7 +214,7 @@ void UBX_CELL::enableAtDebugging(Print &debugPort) // See: https://github.com/sparkfun/SparkFun_LTE_Shield_Arduino_Library/pull/8 // It does the same job as ::poll but also processed any 'old' data stored in the backlog first // It also has a built-in timeout - which ::poll does not -bool UBX_CELL::bufferedPoll(void) +bool SparkFun_ublox_Cellular::bufferedPoll(void) { if (_bufferedPollReentrant == true) // Check for reentry (i.e. bufferedPoll has been called from inside a callback) return false; @@ -342,7 +342,7 @@ bool UBX_CELL::bufferedPoll(void) return handled; } // /bufferedPoll -bool UBX_CELL::urcHandlerReadSocket(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerReadSocket(const char *event) { // URC: +UUSORD (Read Socket Data) int socket, length; @@ -380,7 +380,7 @@ bool UBX_CELL::urcHandlerReadSocket(const char *event) return false; } -bool UBX_CELL::urcHandlerReadUDPSocket(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerReadUDPSocket(const char *event) { // URC: +UUSORF (Receive From command (UDP only)) int socket, length; @@ -403,7 +403,7 @@ bool UBX_CELL::urcHandlerReadUDPSocket(const char *event) return false; } -bool UBX_CELL::urcHandlerListeningSocket(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerListeningSocket(const char *event) { // URC: +UUSOLI (Set Listening Socket) int socket = 0; @@ -443,7 +443,7 @@ bool UBX_CELL::urcHandlerListeningSocket(const char *event) return false; } -bool UBX_CELL::urcHandlerCloseSocket(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerCloseSocket(const char *event) { // URC: +UUSOCL (Close Socket) int socket; @@ -472,7 +472,7 @@ bool UBX_CELL::urcHandlerCloseSocket(const char *event) return false; } -bool UBX_CELL::urcHandlerGNSSRequestLocation(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerGNSSRequestLocation(const char *event) { // URC: +UULOC (Localization information - CellLocate and hybrid positioning) ClockData clck; @@ -552,7 +552,7 @@ bool UBX_CELL::urcHandlerGNSSRequestLocation(const char *event) return false; } -bool UBX_CELL::urcHandlerSIMState(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerSIMState(const char *event) { // URC: +UUSIMSTAT (SIM Status) UBX_CELL_sim_states_t state; @@ -586,7 +586,7 @@ bool UBX_CELL::urcHandlerSIMState(const char *event) return false; } -bool UBX_CELL::urcHandlerHTTPCommand(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerHTTPCommand(const char *event) { // URC: +UUHTTPCR (HTTP Command Result) int profile, command, result; @@ -620,7 +620,7 @@ bool UBX_CELL::urcHandlerHTTPCommand(const char *event) return false; } -bool UBX_CELL::urcHandlerMQTTCommand(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerMQTTCommand(const char *event) { // URC: +UUMQTTC (MQTT Command Result) int command, result; @@ -663,7 +663,7 @@ bool UBX_CELL::urcHandlerMQTTCommand(const char *event) return false; } -bool UBX_CELL::urcHandlerPingCommand(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerPingCommand(const char *event) { // URC: +UUPING (Ping Result) int retry = 0; @@ -741,7 +741,7 @@ bool UBX_CELL::urcHandlerPingCommand(const char *event) return false; } -bool UBX_CELL::urcHandlerFTPCommand(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerFTPCommand(const char *event) { // URC: +UUFTPCR (FTP Command Result) int ftpCmd; @@ -767,7 +767,7 @@ bool UBX_CELL::urcHandlerFTPCommand(const char *event) return false; } -bool UBX_CELL::urcHandlerRegistrationStatus(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerRegistrationStatus(const char *event) { // URC: +CREG int status = 0; @@ -796,7 +796,7 @@ bool UBX_CELL::urcHandlerRegistrationStatus(const char *event) return false; } -bool UBX_CELL::urcHandlerEPSRegistrationStatus(const char *event) +bool SparkFun_ublox_Cellular::urcHandlerEPSRegistrationStatus(const char *event) { // URC: +CEREG int status = 0; @@ -826,14 +826,14 @@ bool UBX_CELL::urcHandlerEPSRegistrationStatus(const char *event) return false; } -void UBX_CELL::addURCHandler(const char *urcString, UBX_CELL_urc_handler_t urcHandler) +void SparkFun_ublox_Cellular::addURCHandler(const char *urcString, UBX_CELL_urc_handler_t urcHandler) { _urcStrings.push_back(urcString); _urcHandlers.push_back(urcHandler); } // Parse incoming URC's - the associated parse functions pass the data to the user via the callbacks (if defined) -bool UBX_CELL::processURCEvent(const char *event) +bool SparkFun_ublox_Cellular::processURCEvent(const char *event) { // Iterate through each URC handler to see if it can handle this message for (auto urcHandler : _urcHandlers) @@ -852,7 +852,7 @@ bool UBX_CELL::processURCEvent(const char *event) // This is the original poll function. // It is 'blocking' - it does not return when serial data is available until it receives a `\n`. // ::bufferedPoll is the new improved version. It processes any data in the backlog and includes a timeout. -bool UBX_CELL::poll(void) +bool SparkFun_ublox_Cellular::poll(void) { if (_pollReentrant == true) // Check for reentry (i.e. poll has been called from inside a callback) return false; @@ -904,66 +904,66 @@ bool UBX_CELL::poll(void) return handled; } -void UBX_CELL::setSocketListenCallback(void (*socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, +void SparkFun_ublox_Cellular::setSocketListenCallback(void (*socketListenCallback)(int, IPAddress, unsigned int, int, IPAddress, unsigned int)) { _socketListenCallback = socketListenCallback; } -void UBX_CELL::setSocketReadCallback(void (*socketReadCallback)(int, String)) +void SparkFun_ublox_Cellular::setSocketReadCallback(void (*socketReadCallback)(int, String)) { _socketReadCallback = socketReadCallback; } -void UBX_CELL::setSocketReadCallbackPlus(void (*socketReadCallbackPlus)( +void SparkFun_ublox_Cellular::setSocketReadCallbackPlus(void (*socketReadCallbackPlus)( int, const char *, int, IPAddress, int)) // socket, data, length, remoteAddress, remotePort { _socketReadCallbackPlus = socketReadCallbackPlus; } -void UBX_CELL::setSocketCloseCallback(void (*socketCloseCallback)(int)) +void SparkFun_ublox_Cellular::setSocketCloseCallback(void (*socketCloseCallback)(int)) { _socketCloseCallback = socketCloseCallback; } -void UBX_CELL::setGpsReadCallback(void (*gpsRequestCallback)(ClockData time, PositionData gps, SpeedData spd, +void SparkFun_ublox_Cellular::setGpsReadCallback(void (*gpsRequestCallback)(ClockData time, PositionData gps, SpeedData spd, unsigned long uncertainty)) { _gpsRequestCallback = gpsRequestCallback; } -void UBX_CELL::setSIMstateReportCallback(void (*simStateReportCallback)(UBX_CELL_sim_states_t state)) +void SparkFun_ublox_Cellular::setSIMstateReportCallback(void (*simStateReportCallback)(UBX_CELL_sim_states_t state)) { _simStateReportCallback = simStateReportCallback; } -void UBX_CELL::setPSDActionCallback(void (*psdActionRequestCallback)(int result, IPAddress ip)) +void SparkFun_ublox_Cellular::setPSDActionCallback(void (*psdActionRequestCallback)(int result, IPAddress ip)) { _psdActionRequestCallback = psdActionRequestCallback; } -void UBX_CELL::setPingCallback(void (*pingRequestCallback)(int retry, int p_size, String remote_hostname, IPAddress ip, +void SparkFun_ublox_Cellular::setPingCallback(void (*pingRequestCallback)(int retry, int p_size, String remote_hostname, IPAddress ip, int ttl, long rtt)) { _pingRequestCallback = pingRequestCallback; } -void UBX_CELL::setHTTPCommandCallback(void (*httpCommandRequestCallback)(int profile, int command, int result)) +void SparkFun_ublox_Cellular::setHTTPCommandCallback(void (*httpCommandRequestCallback)(int profile, int command, int result)) { _httpCommandRequestCallback = httpCommandRequestCallback; } -void UBX_CELL::setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int command, int result)) +void SparkFun_ublox_Cellular::setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int command, int result)) { _mqttCommandRequestCallback = mqttCommandRequestCallback; } -void UBX_CELL::setFTPCommandCallback(void (*ftpCommandRequestCallback)(int command, int result)) +void SparkFun_ublox_Cellular::setFTPCommandCallback(void (*ftpCommandRequestCallback)(int command, int result)) { _ftpCommandRequestCallback = ftpCommandRequestCallback; } -UBX_CELL_error_t UBX_CELL::setRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, +UBX_CELL_error_t SparkFun_ublox_Cellular::setRegistrationCallback(void (*registrationCallback)(UBX_CELL_registration_status_t status, unsigned int lac, unsigned int ci, int Act)) { @@ -977,7 +977,7 @@ UBX_CELL_error_t UBX_CELL::setRegistrationCallback(void (*registrationCallback)( return err; } -UBX_CELL_error_t UBX_CELL::setEpsRegistrationCallback( +UBX_CELL_error_t SparkFun_ublox_Cellular::setEpsRegistrationCallback( void (*registrationCallback)(UBX_CELL_registration_status_t status, unsigned int tac, unsigned int ci, int Act)) { _epsRegistrationCallback = registrationCallback; @@ -990,22 +990,22 @@ UBX_CELL_error_t UBX_CELL::setEpsRegistrationCallback( return err; } -size_t UBX_CELL::write(uint8_t c) +size_t SparkFun_ublox_Cellular::write(uint8_t c) { return hwWrite(c); } -size_t UBX_CELL::write(const char *str) +size_t SparkFun_ublox_Cellular::write(const char *str) { return hwPrint(str); } -size_t UBX_CELL::write(const char *buffer, size_t size) +size_t SparkFun_ublox_Cellular::write(const char *buffer, size_t size) { return hwWriteData(buffer, size); } -UBX_CELL_error_t UBX_CELL::at(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::at(void) { UBX_CELL_error_t err; @@ -1014,7 +1014,7 @@ UBX_CELL_error_t UBX_CELL::at(void) return err; } -UBX_CELL_error_t UBX_CELL::enableEcho(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::enableEcho(bool enable) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_ECHO) + 2; @@ -1024,7 +1024,7 @@ UBX_CELL_error_t UBX_CELL::enableEcho(bool enable) return err; } -String UBX_CELL::getManufacturerID(void) +String SparkFun_ublox_Cellular::getManufacturerID(void) { char response[minimumResponseAllocation]; char idResponse[16] = {0x00}; // E.g. u-blox @@ -1042,7 +1042,7 @@ String UBX_CELL::getManufacturerID(void) return String(idResponse); } -String UBX_CELL::getModelID(void) +String SparkFun_ublox_Cellular::getModelID(void) { char response[minimumResponseAllocation]; char idResponse[32] = {0x00}; // E.g. SARA-R510M8Q @@ -1060,7 +1060,7 @@ String UBX_CELL::getModelID(void) return String(idResponse); } -String UBX_CELL::getFirmwareVersion(void) +String SparkFun_ublox_Cellular::getFirmwareVersion(void) { char response[minimumResponseAllocation]; char idResponse[16] = {0x00}; // E.g. 11.40 @@ -1078,7 +1078,7 @@ String UBX_CELL::getFirmwareVersion(void) return String(idResponse); } -String UBX_CELL::getSerialNo(void) +String SparkFun_ublox_Cellular::getSerialNo(void) { char response[minimumResponseAllocation]; char idResponse[32] = {0x00}; // E.g. 357520070120767 @@ -1096,7 +1096,7 @@ String UBX_CELL::getSerialNo(void) return String(idResponse); } -String UBX_CELL::getIMEI(void) +String SparkFun_ublox_Cellular::getIMEI(void) { char response[minimumResponseAllocation]; char imeiResponse[32] = {0x00}; // E.g. 004999010640000 @@ -1114,7 +1114,7 @@ String UBX_CELL::getIMEI(void) return String(imeiResponse); } -String UBX_CELL::getIMSI(void) +String SparkFun_ublox_Cellular::getIMSI(void) { char response[minimumResponseAllocation]; char imsiResponse[32] = {0x00}; // E.g. 222107701772423 @@ -1132,7 +1132,7 @@ String UBX_CELL::getIMSI(void) return String(imsiResponse); } -String UBX_CELL::getCCID(void) +String SparkFun_ublox_Cellular::getCCID(void) { char response[minimumResponseAllocation]; char ccidResponse[32] = {0x00}; // E.g. +CCID: 8939107900010087330 @@ -1157,7 +1157,7 @@ String UBX_CELL::getCCID(void) return String(ccidResponse); } -String UBX_CELL::getSubscriberNo(void) +String SparkFun_ublox_Cellular::getSubscriberNo(void) { char response[minimumResponseAllocation]; char idResponse[128] = {0x00}; // E.g. +CNUM: "ABCD . AAA","123456789012",129 @@ -1182,7 +1182,7 @@ String UBX_CELL::getSubscriberNo(void) return String(idResponse); } -String UBX_CELL::getCapabilities(void) +String SparkFun_ublox_Cellular::getCapabilities(void) { char response[minimumResponseAllocation]; char idResponse[128] = {0x00}; // E.g. +GCAP: +FCLASS, +CGSM @@ -1207,7 +1207,7 @@ String UBX_CELL::getCapabilities(void) return String(idResponse); } -UBX_CELL_error_t UBX_CELL::reset(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::reset(void) { UBX_CELL_error_t err; @@ -1229,7 +1229,7 @@ UBX_CELL_error_t UBX_CELL::reset(void) return err; } -String UBX_CELL::clock(void) +String SparkFun_ublox_Cellular::clock(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + 2; @@ -1265,7 +1265,7 @@ String UBX_CELL::clock(void) return (clock); } -UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s, int8_t *tz) +UBX_CELL_error_t SparkFun_ublox_Cellular::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s, int8_t *tz) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + 2; @@ -1312,7 +1312,7 @@ UBX_CELL_error_t UBX_CELL::clock(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h return err; } -UBX_CELL_error_t UBX_CELL::setClock(uint8_t y, uint8_t mo, uint8_t d, uint8_t h, uint8_t min, uint8_t s, int8_t tz) +UBX_CELL_error_t SparkFun_ublox_Cellular::setClock(uint8_t y, uint8_t mo, uint8_t d, uint8_t h, uint8_t min, uint8_t s, int8_t tz) { // Convert y,mo,d,h,min,s,tz into a String // Some platforms don't support snprintf correctly (for %02d or %+02d) so we need to build the String manually @@ -1351,7 +1351,7 @@ UBX_CELL_error_t UBX_CELL::setClock(uint8_t y, uint8_t mo, uint8_t d, uint8_t h, return (setClock(theTime)); } -UBX_CELL_error_t UBX_CELL::setClock(String theTime) +UBX_CELL_error_t SparkFun_ublox_Cellular::setClock(String theTime) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_CLOCK) + theTime.length() + 8; @@ -1368,12 +1368,12 @@ UBX_CELL_error_t UBX_CELL::setClock(String theTime) return err; } -void UBX_CELL::autoTimeZoneForBegin(bool tz) +void SparkFun_ublox_Cellular::autoTimeZoneForBegin(bool tz) { _autoTimeZoneForBegin = tz; } -UBX_CELL_error_t UBX_CELL::autoTimeZone(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::autoTimeZone(bool enable) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_AUTO_TZ) + 3; @@ -1385,7 +1385,7 @@ UBX_CELL_error_t UBX_CELL::autoTimeZone(bool enable) return err; } -int8_t UBX_CELL::rssi(void) +int8_t SparkFun_ublox_Cellular::rssi(void) { size_t cmdLen = strlen(UBX_CELL_SIGNAL_QUALITY) + 1; char command[cmdLen]; @@ -1419,7 +1419,7 @@ int8_t UBX_CELL::rssi(void) return rssi; } -UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) +UBX_CELL_error_t SparkFun_ublox_Cellular::getExtSignalQuality(signal_quality &signal_quality) { size_t cmdLen = strlen(UBX_CELL_EXT_SIGNAL_QUALITY) + 1; char command[cmdLen]; @@ -1456,7 +1456,7 @@ UBX_CELL_error_t UBX_CELL::getExtSignalQuality(signal_quality &signal_quality) return err; } -UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) +UBX_CELL_registration_status_t SparkFun_ublox_Cellular::registration(bool eps) { const char *tag = eps ? UBX_CELL_EPSREGISTRATION_STATUS : UBX_CELL_REGISTRATION_STATUS; size_t cmdLen = strlen(UBX_CELL_EPSREGISTRATION_STATUS) + 3; @@ -1491,7 +1491,7 @@ UBX_CELL_registration_status_t UBX_CELL::registration(bool eps) return (UBX_CELL_registration_status_t)status; } -bool UBX_CELL::setNetworkProfile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) +bool SparkFun_ublox_Cellular::setNetworkProfile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) { mobile_network_operator_t currentMno; @@ -1525,7 +1525,7 @@ bool UBX_CELL::setNetworkProfile(mobile_network_operator_t mno, bool autoReset, return true; } -mobile_network_operator_t UBX_CELL::getNetworkProfile(void) +mobile_network_operator_t SparkFun_ublox_Cellular::getNetworkProfile(void) { mobile_network_operator_t mno; UBX_CELL_error_t err; @@ -1538,7 +1538,7 @@ mobile_network_operator_t UBX_CELL::getNetworkProfile(void) return mno; } -UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdpType) +UBX_CELL_error_t SparkFun_ublox_Cellular::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdpType) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_DEF) + strlen(apn.c_str()) + 16; @@ -1600,7 +1600,7 @@ UBX_CELL_error_t UBX_CELL::setAPN(String apn, uint8_t cid, UBX_CELL_pdp_type pdp } // Return the Access Point Name and IP address for the chosen context identifier -UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_pdp_type *pdpType) +UBX_CELL_error_t SparkFun_ublox_Cellular::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_pdp_type *pdpType) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_DEF) + 3; @@ -1678,7 +1678,7 @@ UBX_CELL_error_t UBX_CELL::getAPN(int cid, String *apn, IPAddress *ip, UBX_CELL_ return err; } -UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) +UBX_CELL_error_t SparkFun_ublox_Cellular::getSimStatus(String *code) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_SIMPIN) + 2; @@ -1712,7 +1712,7 @@ UBX_CELL_error_t UBX_CELL::getSimStatus(String *code) return err; } -UBX_CELL_error_t UBX_CELL::setSimPin(String pin) +UBX_CELL_error_t SparkFun_ublox_Cellular::setSimPin(String pin) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_SIMPIN) + 4 + pin.length(); @@ -1727,7 +1727,7 @@ UBX_CELL_error_t UBX_CELL::setSimPin(String pin) return err; } -UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) +UBX_CELL_error_t SparkFun_ublox_Cellular::setSIMstateReportingMode(int mode) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SIM_STATE) + 4; @@ -1739,7 +1739,7 @@ UBX_CELL_error_t UBX_CELL::setSIMstateReportingMode(int mode) return err; } -UBX_CELL_error_t UBX_CELL::getSIMstateReportingMode(int *mode) +UBX_CELL_error_t SparkFun_ublox_Cellular::getSIMstateReportingMode(int *mode) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SIM_STATE) + 3; @@ -1778,8 +1778,8 @@ const char *PPP_L2P[5] = { "", "PPP", "M-HEX", "M-RAW_IP", "M-OPT-PPP", }; -UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigned long dialNumber, - UBX_CELL::UBX_CELL_l2p_t l2p) +UBX_CELL_error_t SparkFun_ublox_Cellular::enterPPP(uint8_t cid, char dialing_type_char, unsigned long dialNumber, + SparkFun_ublox_Cellular::UBX_CELL_l2p_t l2p) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_ENTER_PPP) + 32; @@ -1806,7 +1806,7 @@ UBX_CELL_error_t UBX_CELL::enterPPP(uint8_t cid, char dialing_type_char, unsigne return err; } -uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) +uint8_t SparkFun_ublox_Cellular::getOperators(struct operator_stats *opRet, int maxOps) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 3; @@ -1884,7 +1884,7 @@ uint8_t UBX_CELL::getOperators(struct operator_stats *opRet, int maxOps) return opsSeen; } -UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) +UBX_CELL_error_t SparkFun_ublox_Cellular::registerOperator(struct operator_stats oper) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 24; @@ -1898,7 +1898,7 @@ UBX_CELL_error_t UBX_CELL::registerOperator(struct operator_stats oper) return err; } -UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() +UBX_CELL_error_t SparkFun_ublox_Cellular::automaticOperatorSelection() { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 6; @@ -1912,7 +1912,7 @@ UBX_CELL_error_t UBX_CELL::automaticOperatorSelection() return err; } -UBX_CELL_error_t UBX_CELL::getOperator(String *oper) +UBX_CELL_error_t SparkFun_ublox_Cellular::getOperator(String *oper) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 3; @@ -1967,7 +1967,7 @@ UBX_CELL_error_t UBX_CELL::getOperator(String *oper) return err; } -UBX_CELL_error_t UBX_CELL::deregisterOperator(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::deregisterOperator(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_OPERATOR_SELECTION) + 6; @@ -1980,7 +1980,7 @@ UBX_CELL_error_t UBX_CELL::deregisterOperator(void) return err; } -UBX_CELL_error_t UBX_CELL::setSMSMessageFormat(UBX_CELL_message_format_t textMode) +UBX_CELL_error_t SparkFun_ublox_Cellular::setSMSMessageFormat(UBX_CELL_message_format_t textMode) { size_t cmdLen = strlen(UBX_CELL_MESSAGE_FORMAT) + 4; char command[cmdLen]; @@ -1993,7 +1993,7 @@ UBX_CELL_error_t UBX_CELL::setSMSMessageFormat(UBX_CELL_message_format_t textMod return err; } -UBX_CELL_error_t UBX_CELL::sendSMS(String number, String message) +UBX_CELL_error_t SparkFun_ublox_Cellular::sendSMS(String number, String message) { char *command; char *messageCStr; @@ -2040,7 +2040,7 @@ UBX_CELL_error_t UBX_CELL::sendSMS(String number, String message) return err; } -UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, String memory) +UBX_CELL_error_t SparkFun_ublox_Cellular::getPreferredMessageStorage(int *used, int *total, String memory) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_PREF_MESSAGE_STORE) + 32; @@ -2089,7 +2089,7 @@ UBX_CELL_error_t UBX_CELL::getPreferredMessageStorage(int *used, int *total, Str return err; } -UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message) +UBX_CELL_error_t SparkFun_ublox_Cellular::readSMSmessage(int location, String *unread, String *from, String *dateTime, String *message) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_READ_TEXT_MESSAGE) + 5; @@ -2174,7 +2174,7 @@ UBX_CELL_error_t UBX_CELL::readSMSmessage(int location, String *unread, String * return err; } -UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) +UBX_CELL_error_t SparkFun_ublox_Cellular::deleteSMSmessage(int location, int deleteFlag) { size_t cmdLen = strlen(UBX_CELL_DELETE_MESSAGE) + 12; char command[cmdLen]; @@ -2190,7 +2190,7 @@ UBX_CELL_error_t UBX_CELL::deleteSMSmessage(int location, int deleteFlag) return err; } -UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) +UBX_CELL_error_t SparkFun_ublox_Cellular::setBaud(unsigned long baud) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_BAUD) + 7 + 12; @@ -2218,7 +2218,7 @@ UBX_CELL_error_t UBX_CELL::setBaud(unsigned long baud) return err; } -UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) +UBX_CELL_error_t SparkFun_ublox_Cellular::setFlowControl(UBX_CELL_flow_control_t value) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FLOW_CONTROL) + 16; @@ -2231,7 +2231,7 @@ UBX_CELL_error_t UBX_CELL::setFlowControl(UBX_CELL_flow_control_t value) return err; } -UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_t mode, int value) +UBX_CELL_error_t SparkFun_ublox_Cellular::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_t mode, int value) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_GPIO) + 16; @@ -2249,7 +2249,7 @@ UBX_CELL_error_t UBX_CELL::setGpioMode(UBX_CELL_gpio_t gpio, UBX_CELL_gpio_mode_ return err; } -UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) +SparkFun_ublox_Cellular::UBX_CELL_gpio_mode_t SparkFun_ublox_Cellular::getGpioMode(UBX_CELL_gpio_t gpio) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_GPIO) + 2; @@ -2279,7 +2279,7 @@ UBX_CELL::UBX_CELL_gpio_mode_t UBX_CELL::getGpioMode(UBX_CELL_gpio_t gpio) return (UBX_CELL_gpio_mode_t)gpioMode; } -int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int localPort) +int SparkFun_ublox_Cellular::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int localPort) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_CREATE_SOCKET) + 10; @@ -2329,7 +2329,7 @@ int UBX_CELL::socketOpen(UBX_CELL_socket_protocol_t protocol, unsigned int local return sockId; } -UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketClose(int socket, unsigned long timeout) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_CLOSE_SOCKET) + 10; @@ -2352,7 +2352,7 @@ UBX_CELL_error_t UBX_CELL::socketClose(int socket, unsigned long timeout) return err; } -UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, unsigned int port) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketConnect(int socket, const char *address, unsigned int port) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_CONNECT_SOCKET) + strlen(address) + 11; @@ -2370,7 +2370,7 @@ UBX_CELL_error_t UBX_CELL::socketConnect(int socket, const char *address, unsign return err; } -UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, unsigned int port) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketConnect(int socket, IPAddress address, unsigned int port) { size_t charLen = 16; char charAddress[charLen]; @@ -2380,7 +2380,7 @@ UBX_CELL_error_t UBX_CELL::socketConnect(int socket, IPAddress address, unsigned return (socketConnect(socket, (const char *)charAddress, port)); } -UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketWrite(int socket, const char *str, int len) { size_t cmdLen = strlen(UBX_CELL_WRITE_SOCKET) + 16; char command[cmdLen]; @@ -2436,12 +2436,12 @@ UBX_CELL_error_t UBX_CELL::socketWrite(int socket, const char *str, int len) return err; } -UBX_CELL_error_t UBX_CELL::socketWrite(int socket, String str) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketWrite(int socket, String str) { return socketWrite(socket, str.c_str(), str.length()); } -UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int port, const char *str, int len) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketWriteUDP(int socket, const char *address, int port, const char *str, int len) { size_t cmdLen = 64; char command[cmdLen]; @@ -2475,7 +2475,7 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, const char *address, int p return err; } -UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len) { size_t charLen = 16; char charAddress[16]; @@ -2485,12 +2485,12 @@ UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, IPAddress address, int por return (socketWriteUDP(socket, (const char *)charAddress, port, str, len)); } -UBX_CELL_error_t UBX_CELL::socketWriteUDP(int socket, String address, int port, String str) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketWriteUDP(int socket, String address, int port, String str) { return socketWriteUDP(socket, address.c_str(), port, str.c_str(), str.length()); } -UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, int *bytesRead) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketRead(int socket, int length, char *readDest, int *bytesRead) { size_t cmdLen = strlen(UBX_CELL_READ_SOCKET) + 32; char command[cmdLen]; @@ -2627,7 +2627,7 @@ UBX_CELL_error_t UBX_CELL::socketRead(int socket, int length, char *readDest, in return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketReadAvailable(int socket, int *length) { size_t cmdLen = strlen(UBX_CELL_READ_SOCKET) + 32; char command[cmdLen]; @@ -2667,7 +2667,7 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailable(int socket, int *length) return err; } -UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress, +UBX_CELL_error_t SparkFun_ublox_Cellular::socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress, int *remotePort, int *bytesRead) { size_t cmdLen = strlen(UBX_CELL_READ_UDP_SOCKET) + 32; @@ -2827,7 +2827,7 @@ UBX_CELL_error_t UBX_CELL::socketReadUDP(int socket, int length, char *readDest, return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketReadAvailableUDP(int socket, int *length) { size_t cmdLen = strlen(UBX_CELL_READ_UDP_SOCKET) + 32; char command[cmdLen]; @@ -2867,7 +2867,7 @@ UBX_CELL_error_t UBX_CELL::socketReadAvailableUDP(int socket, int *length) return err; } -UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketListen(int socket, unsigned int port) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_LISTEN_SOCKET) + 9; @@ -2880,7 +2880,7 @@ UBX_CELL_error_t UBX_CELL::socketListen(int socket, unsigned int port) return err; } -UBX_CELL_error_t UBX_CELL::socketDirectLinkMode(int socket) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketDirectLinkMode(int socket) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SOCKET_DIRECT_LINK) + 8; @@ -2893,7 +2893,7 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkMode(int socket) return err; } -UBX_CELL_error_t UBX_CELL::socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger) { // valid range is 0 (trigger disabled), 100-120000 if (!((timerTrigger == 0) || ((timerTrigger >= 100) && (timerTrigger <= 120000)))) @@ -2910,7 +2910,7 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkTimeTrigger(int socket, unsigned long return err; } -UBX_CELL_error_t UBX_CELL::socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger) { // valid range is 0, 3-1472 for UDP if (!((dataLengthTrigger == 0) || ((dataLengthTrigger >= 3) && (dataLengthTrigger <= 1472)))) @@ -2927,7 +2927,7 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkDataLengthTrigger(int socket, int dat return err; } -UBX_CELL_error_t UBX_CELL::socketDirectLinkCharacterTrigger(int socket, int characterTrigger) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketDirectLinkCharacterTrigger(int socket, int characterTrigger) { // The allowed range is -1, 0-255, the factory-programmed value is -1; -1 means trigger disabled. if (!((characterTrigger >= -1) && (characterTrigger <= 255))) @@ -2944,7 +2944,7 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCharacterTrigger(int socket, int char return err; } -UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer) +UBX_CELL_error_t SparkFun_ublox_Cellular::socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer) { // valid range is 0, 1000-72000 if (!((congestionTimer == 0) || ((congestionTimer >= 1000) && (congestionTimer <= 72000)))) @@ -2961,7 +2961,7 @@ UBX_CELL_error_t UBX_CELL::socketDirectLinkCongestionTimer(int socket, unsigned return err; } -UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketType(int socket, UBX_CELL_socket_protocol_t *protocol) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3002,7 +3002,7 @@ UBX_CELL_error_t UBX_CELL::querySocketType(int socket, UBX_CELL_socket_protocol_ return err; } -UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketLastError(int socket, int *error) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3042,7 +3042,7 @@ UBX_CELL_error_t UBX_CELL::querySocketLastError(int socket, int *error) return err; } -UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketTotalBytesSent(int socket, uint32_t *total) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3082,7 +3082,7 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesSent(int socket, uint32_t *total return err; } -UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *total) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketTotalBytesReceived(int socket, uint32_t *total) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3122,7 +3122,7 @@ UBX_CELL_error_t UBX_CELL::querySocketTotalBytesReceived(int socket, uint32_t *t return err; } -UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *address, int *port) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketRemoteIPAddress(int socket, IPAddress *address, int *port) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3166,7 +3166,7 @@ UBX_CELL_error_t UBX_CELL::querySocketRemoteIPAddress(int socket, IPAddress *add return err; } -UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_status_t *status) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3206,7 +3206,7 @@ UBX_CELL_error_t UBX_CELL::querySocketStatusTCP(int socket, UBX_CELL_tcp_socket_ return err; } -UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) +UBX_CELL_error_t SparkFun_ublox_Cellular::querySocketOutUnackData(int socket, uint32_t *total) { size_t cmdLen = strlen(UBX_CELL_SOCKET_CONTROL) + 16; char command[cmdLen]; @@ -3247,7 +3247,7 @@ UBX_CELL_error_t UBX_CELL::querySocketOutUnackData(int socket, uint32_t *total) } // Issues command to get last socket error, then prints to serial. Also updates rx/backlog buffers. -int UBX_CELL::socketGetLastError() +int SparkFun_ublox_Cellular::socketGetLastError() { UBX_CELL_error_t err; size_t cmdLen = 64; @@ -3274,12 +3274,12 @@ int UBX_CELL::socketGetLastError() return errorCode; } -IPAddress UBX_CELL::lastRemoteIP(void) +IPAddress SparkFun_ublox_Cellular::lastRemoteIP(void) { return _lastRemoteIP; } -UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) +UBX_CELL_error_t SparkFun_ublox_Cellular::resetHTTPprofile(int profile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 16; @@ -3295,7 +3295,7 @@ UBX_CELL_error_t UBX_CELL::resetHTTPprofile(int profile) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPserverIPaddress(int profile, IPAddress address) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 64; @@ -3312,7 +3312,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverIPaddress(int profile, IPAddress address return err; } -UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPserverName(int profile, String server) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + server.length(); @@ -3333,7 +3333,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverName(int profile, String server) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPusername(int profile, String username) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + username.length(); @@ -3354,7 +3354,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPusername(int profile, String username) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPpassword(int profile, String password) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + password.length(); @@ -3375,7 +3375,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPpassword(int profile, String password) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPauthentication(int profile, bool authenticate) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; @@ -3392,7 +3392,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPauthentication(int profile, bool authenticate) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPserverPort(int profile, int port) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; @@ -3408,7 +3408,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPserverPort(int profile, int port) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPcustomHeader(int profile, String header) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 12 + header.length(); @@ -3429,7 +3429,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPcustomHeader(int profile, String header) return err; } -UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofile) +UBX_CELL_error_t SparkFun_ublox_Cellular::setHTTPsecure(int profile, bool secure, int secprofile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROFILE) + 32; @@ -3449,7 +3449,7 @@ UBX_CELL_error_t UBX_CELL::setHTTPsecure(int profile, bool secure, int secprofil return err; } -UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, unsigned long timeout, int ttl) +UBX_CELL_error_t SparkFun_ublox_Cellular::ping(String remote_host, int retry, int p_size, unsigned long timeout, int ttl) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_PING_COMMAND) + 48 + remote_host.length(); @@ -3467,7 +3467,7 @@ UBX_CELL_error_t UBX_CELL::ping(String remote_host, int retry, int p_size, unsig return err; } -UBX_CELL_error_t UBX_CELL::sendHTTPGET(int profile, String path, String responseFilename) +UBX_CELL_error_t SparkFun_ublox_Cellular::sendHTTPGET(int profile, String path, String responseFilename) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_COMMAND) + 24 + path.length() + responseFilename.length(); @@ -3488,7 +3488,7 @@ UBX_CELL_error_t UBX_CELL::sendHTTPGET(int profile, String path, String response return err; } -UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String responseFilename, String data, +UBX_CELL_error_t SparkFun_ublox_Cellular::sendHTTPPOSTdata(int profile, String path, String responseFilename, String data, UBX_CELL_http_content_types_t httpContentType) { UBX_CELL_error_t err; @@ -3510,7 +3510,7 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTdata(int profile, String path, String res return err; } -UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String responseFilename, String requestFile, +UBX_CELL_error_t SparkFun_ublox_Cellular::sendHTTPPOSTfile(int profile, String path, String responseFilename, String requestFile, UBX_CELL_http_content_types_t httpContentType) { UBX_CELL_error_t err; @@ -3534,7 +3534,7 @@ UBX_CELL_error_t UBX_CELL::sendHTTPPOSTfile(int profile, String path, String res return err; } -UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, int *error_code) +UBX_CELL_error_t SparkFun_ublox_Cellular::getHTTPprotocolError(int profile, int *error_class, int *error_code) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_HTTP_PROTOCOL_ERROR) + 4; @@ -3570,7 +3570,7 @@ UBX_CELL_error_t UBX_CELL::getHTTPprotocolError(int profile, int *error_class, i return err; } -UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) +UBX_CELL_error_t SparkFun_ublox_Cellular::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_NVM) + 10; @@ -3581,7 +3581,7 @@ UBX_CELL_error_t UBX_CELL::nvMQTT(UBX_CELL_mqtt_nv_parameter_t parameter) return err; } -UBX_CELL_error_t UBX_CELL::setMQTTclientId(const String &clientId) +UBX_CELL_error_t SparkFun_ublox_Cellular::setMQTTclientId(const String &clientId) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + clientId.length() + 10; @@ -3596,7 +3596,7 @@ UBX_CELL_error_t UBX_CELL::setMQTTclientId(const String &clientId) return err; } -UBX_CELL_error_t UBX_CELL::setMQTTserver(const String &serverName, int port) +UBX_CELL_error_t SparkFun_ublox_Cellular::setMQTTserver(const String &serverName, int port) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + serverName.length() + 16; @@ -3612,7 +3612,7 @@ UBX_CELL_error_t UBX_CELL::setMQTTserver(const String &serverName, int port) return err; } -UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const String &pwd) +UBX_CELL_error_t SparkFun_ublox_Cellular::setMQTTcredentials(const String &userName, const String &pwd) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + userName.length() + pwd.length() + 16; @@ -3628,7 +3628,7 @@ UBX_CELL_error_t UBX_CELL::setMQTTcredentials(const String &userName, const Stri return err; } -UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) +UBX_CELL_error_t SparkFun_ublox_Cellular::setMQTTsecure(bool secure, int secprofile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_PROFILE) + 16; @@ -3643,7 +3643,7 @@ UBX_CELL_error_t UBX_CELL::setMQTTsecure(bool secure, int secprofile) return err; } -UBX_CELL_error_t UBX_CELL::connectMQTT(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::connectMQTT(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; @@ -3654,7 +3654,7 @@ UBX_CELL_error_t UBX_CELL::connectMQTT(void) return err; } -UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::disconnectMQTT(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; @@ -3665,7 +3665,7 @@ UBX_CELL_error_t UBX_CELL::disconnectMQTT(void) return err; } -UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String &topic) +UBX_CELL_error_t SparkFun_ublox_Cellular::subscribeMQTTtopic(int max_Qos, const String &topic) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length(); @@ -3681,7 +3681,7 @@ UBX_CELL_error_t UBX_CELL::subscribeMQTTtopic(int max_Qos, const String &topic) return err; } -UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String &topic) +UBX_CELL_error_t SparkFun_ublox_Cellular::unsubscribeMQTTtopic(const String &topic) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 16 + topic.length(); @@ -3696,7 +3696,7 @@ UBX_CELL_error_t UBX_CELL::unsubscribeMQTTtopic(const String &topic) return err; } -UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest, int readLength, int *bytesRead) +UBX_CELL_error_t SparkFun_ublox_Cellular::readMQTT(int *pQos, String *pTopic, uint8_t *readDest, int readLength, int *bytesRead) { size_t cmdLen = strlen(UBX_CELL_MQTT_COMMAND) + 10; char command[cmdLen]; @@ -3796,7 +3796,7 @@ UBX_CELL_error_t UBX_CELL::readMQTT(int *pQos, String *pTopic, uint8_t *readDest return err; } -UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String &topic, const char *const msg, uint8_t qos, bool retain) +UBX_CELL_error_t SparkFun_ublox_Cellular::mqttPublishTextMsg(const String &topic, const char *const msg, uint8_t qos, bool retain) { if (topic.length() < 1 || msg == nullptr) { @@ -3847,7 +3847,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishTextMsg(const String &topic, const char *c return err; } -UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String &topic, const char *const msg, size_t msg_len, uint8_t qos, +UBX_CELL_error_t SparkFun_ublox_Cellular::mqttPublishBinaryMsg(const String &topic, const char *const msg, size_t msg_len, uint8_t qos, bool retain) { /* @@ -3885,7 +3885,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishBinaryMsg(const String &topic, const char return err; } -UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String &filename, uint8_t qos, bool retain) +UBX_CELL_error_t SparkFun_ublox_Cellular::mqttPublishFromFile(const String &topic, const String &filename, uint8_t qos, bool retain) { if (topic.length() < 1 || filename.length() < 1) { @@ -3908,7 +3908,7 @@ UBX_CELL_error_t UBX_CELL::mqttPublishFromFile(const String &topic, const String return err; } -UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code2) +UBX_CELL_error_t SparkFun_ublox_Cellular::getMQTTprotocolError(int *error_code, int *error_code2) { UBX_CELL_error_t err; char response[minimumResponseAllocation]; @@ -3941,7 +3941,7 @@ UBX_CELL_error_t UBX_CELL::getMQTTprotocolError(int *error_code, int *error_code return err; } -UBX_CELL_error_t UBX_CELL::setFTPserver(const String &serverName) +UBX_CELL_error_t SparkFun_ublox_Cellular::setFTPserver(const String &serverName) { constexpr size_t cmdLen = 145; char command[cmdLen]; // long enough for AT+UFTP=1,<128 bytes> @@ -3951,7 +3951,7 @@ UBX_CELL_error_t UBX_CELL::setFTPserver(const String &serverName) return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } -UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, +UBX_CELL_error_t SparkFun_ublox_Cellular::setFTPtimeouts(const unsigned int timeout, const unsigned int cmd_linger, const unsigned int data_linger) { constexpr size_t cmdLen = 64; @@ -3962,7 +3962,7 @@ UBX_CELL_error_t UBX_CELL::setFTPtimeouts(const unsigned int timeout, const unsi return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } -UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const String &pwd) +UBX_CELL_error_t SparkFun_ublox_Cellular::setFTPcredentials(const String &userName, const String &pwd) { UBX_CELL_error_t err; constexpr size_t cmdLen = 48; @@ -3981,7 +3981,7 @@ UBX_CELL_error_t UBX_CELL::setFTPcredentials(const String &userName, const Strin return err; } -UBX_CELL_error_t UBX_CELL::connectFTP(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::connectFTP(void) { constexpr size_t cmdLen = 16; char command[cmdLen]; // long enough for AT+UFTPC=n @@ -3990,7 +3990,7 @@ UBX_CELL_error_t UBX_CELL::connectFTP(void) return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } -UBX_CELL_error_t UBX_CELL::disconnectFTP(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::disconnectFTP(void) { constexpr size_t cmdLen = 16; char command[cmdLen]; // long enough for AT+UFTPC=n @@ -3999,7 +3999,7 @@ UBX_CELL_error_t UBX_CELL::disconnectFTP(void) return sendCommandWithResponse(command, UBX_CELL_RESPONSE_OK_OR_ERROR, nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } -UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) +UBX_CELL_error_t SparkFun_ublox_Cellular::ftpGetFile(const String &filename) { size_t cmdLen = strlen(UBX_CELL_FTP_COMMAND) + (2 * filename.length()) + 16; char *command = ubx_cell_calloc_char(cmdLen); @@ -4017,7 +4017,7 @@ UBX_CELL_error_t UBX_CELL::ftpGetFile(const String &filename) return err; } -UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2) +UBX_CELL_error_t SparkFun_ublox_Cellular::getFTPprotocolError(int *error_code, int *error_code2) { UBX_CELL_error_t err; char response[minimumResponseAllocation]; @@ -4055,7 +4055,7 @@ UBX_CELL_error_t UBX_CELL::getFTPprotocolError(int *error_code, int *error_code2 return err; } -UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) +UBX_CELL_error_t SparkFun_ublox_Cellular::resetSecurityProfile(int secprofile) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + 6; @@ -4068,7 +4068,7 @@ UBX_CELL_error_t UBX_CELL::resetSecurityProfile(int secprofile) return err; } -UBX_CELL_error_t UBX_CELL::configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value) +UBX_CELL_error_t SparkFun_ublox_Cellular::configSecurityProfile(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, int value) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_SEC_PROFILE) + 10; @@ -4079,7 +4079,7 @@ UBX_CELL_error_t UBX_CELL::configSecurityProfile(int secprofile, UBX_CELL_sec_pr return err; } -UBX_CELL_error_t UBX_CELL::configSecurityProfileString(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, +UBX_CELL_error_t SparkFun_ublox_Cellular::configSecurityProfileString(int secprofile, UBX_CELL_sec_profile_parameter_t parameter, String value) { UBX_CELL_error_t err; @@ -4095,7 +4095,7 @@ UBX_CELL_error_t UBX_CELL::configSecurityProfileString(int secprofile, UBX_CELL_ return err; } -UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, +UBX_CELL_error_t SparkFun_ublox_Cellular::setSecurityManager(UBX_CELL_sec_manager_opcode_t opcode, UBX_CELL_sec_manager_parameter_t parameter, String name, String data) { size_t cmdLen = strlen(UBX_CELL_SEC_MANAGER) + name.length() + 20; @@ -4138,7 +4138,7 @@ UBX_CELL_error_t UBX_CELL::setSecurityManager(UBX_CELL_sec_manager_opcode_t opco return err; } -UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) +UBX_CELL_error_t SparkFun_ublox_Cellular::activatePDPcontext(bool status, int cid) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_MESSAGE_PDP_CONTEXT_ACTIVATE) + 32; @@ -4157,7 +4157,7 @@ UBX_CELL_error_t UBX_CELL::activatePDPcontext(bool status, int cid) return err; } -bool UBX_CELL::isGPSon(void) +bool SparkFun_ublox_Cellular::isGPSon(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_POWER) + 2; @@ -4185,7 +4185,7 @@ bool UBX_CELL::isGPSon(void) return on; } -UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_aiding_mode_t gnss_aiding) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_aiding_mode_t gnss_aiding) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_GNSS_POWER) + 32; // gnss_sys could be up to three digits @@ -4215,56 +4215,56 @@ UBX_CELL_error_t UBX_CELL::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_ai } /* -UBX_CELL_error_t UBX_CELL::gpsEnableClock(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsEnableClock(bool enable) { // AT+UGZDA=<0,1> UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsGetClock(struct ClockData *clock) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsGetClock(struct ClockData *clock) { // AT+UGZDA? UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsEnableFix(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsEnableFix(bool enable) { // AT+UGGGA=<0,1> UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsGetFix(struct PositionData *pos) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsGetFix(struct PositionData *pos) { // AT+UGGGA? UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsEnablePos(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsEnablePos(bool enable) { // AT+UGGLL=<0,1> UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsGetPos(struct PositionData *pos) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsGetPos(struct PositionData *pos) { // AT+UGGLL? UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsEnableSat(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsEnableSat(bool enable) { // AT+UGGSV=<0,1> UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsGetSat(uint8_t *sats) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsGetSat(uint8_t *sats) { // AT+UGGSV? UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; @@ -4272,7 +4272,7 @@ UBX_CELL_error_t UBX_CELL::gpsGetSat(uint8_t *sats) } */ -UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsEnableRmc(bool enable) { // AT+UGRMC=<0,1> UBX_CELL_error_t err; @@ -4297,7 +4297,7 @@ UBX_CELL_error_t UBX_CELL::gpsEnableRmc(bool enable) return err; } -UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData *spd, struct ClockData *clk, +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsGetRmc(struct PositionData *pos, struct SpeedData *spd, struct ClockData *clk, bool *valid) { UBX_CELL_error_t err; @@ -4327,14 +4327,14 @@ UBX_CELL_error_t UBX_CELL::gpsGetRmc(struct PositionData *pos, struct SpeedData } /* -UBX_CELL_error_t UBX_CELL::gpsEnableSpeed(bool enable) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsEnableSpeed(bool enable) { // AT+UGVTG=<0,1> UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; return err; } -UBX_CELL_error_t UBX_CELL::gpsGetSpeed(struct SpeedData *speed) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsGetSpeed(struct SpeedData *speed) { // AT+UGVTG? UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; @@ -4342,7 +4342,7 @@ UBX_CELL_error_t UBX_CELL::gpsGetSpeed(struct SpeedData *speed) } */ -UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, bool detailed, unsigned int sensor) +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsRequest(unsigned int timeout, uint32_t accuracy, bool detailed, unsigned int sensor) { // AT+ULOC=2,,,, UBX_CELL_error_t err; @@ -4373,7 +4373,7 @@ UBX_CELL_error_t UBX_CELL::gpsRequest(unsigned int timeout, uint32_t accuracy, b return err; } -UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const char *secondaryServer, +UBX_CELL_error_t SparkFun_ublox_Cellular::gpsAidingServerConf(const char *primaryServer, const char *secondaryServer, const char *authToken, unsigned int days, unsigned int period, unsigned int resolution, unsigned int gnssTypes, unsigned int mode, unsigned int dataType) @@ -4391,7 +4391,7 @@ UBX_CELL_error_t UBX_CELL::gpsAidingServerConf(const char *primaryServer, const } // OK for text files. But will fail with binary files (containing \0) on some platforms. -UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, int len) +UBX_CELL_error_t SparkFun_ublox_Cellular::appendFileContents(String filename, const char *str, int len) { size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10; char *command; @@ -4438,13 +4438,13 @@ UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, const char *str, return err; } -UBX_CELL_error_t UBX_CELL::appendFileContents(String filename, String str) +UBX_CELL_error_t SparkFun_ublox_Cellular::appendFileContents(String filename, String str) { return appendFileContents(filename, str.c_str(), str.length()); } // OK for text files. But will fail with binary files (containing \0) on some platforms. -UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) +UBX_CELL_error_t SparkFun_ublox_Cellular::getFileContents(String filename, String *contents) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8; @@ -4567,7 +4567,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, String *contents) } // OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize. -UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) +UBX_CELL_error_t SparkFun_ublox_Cellular::getFileContents(String filename, char *contents) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_READ_FILE) + filename.length() + 8; @@ -4685,7 +4685,7 @@ UBX_CELL_error_t UBX_CELL::getFileContents(String filename, char *contents) return err; } -UBX_CELL_error_t UBX_CELL::getFileBlock(const String &filename, char *buffer, size_t offset, size_t requested_length, +UBX_CELL_error_t SparkFun_ublox_Cellular::getFileBlock(const String &filename, char *buffer, size_t offset, size_t requested_length, size_t &bytes_read) { bytes_read = 0; @@ -4757,7 +4757,7 @@ UBX_CELL_error_t UBX_CELL::getFileBlock(const String &filename, char *buffer, si return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) +UBX_CELL_error_t SparkFun_ublox_Cellular::getFileSize(String filename, int *size) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_LIST_FILES) + filename.length() + 8; @@ -4808,7 +4808,7 @@ UBX_CELL_error_t UBX_CELL::getFileSize(String filename, int *size) return err; } -UBX_CELL_error_t UBX_CELL::deleteFile(String filename) +UBX_CELL_error_t SparkFun_ublox_Cellular::deleteFile(String filename) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_FILE_SYSTEM_DELETE_FILE) + filename.length() + 8; @@ -4834,7 +4834,7 @@ UBX_CELL_error_t UBX_CELL::deleteFile(String filename) return err; } -UBX_CELL_error_t UBX_CELL::modulePowerOff(void) +UBX_CELL_error_t SparkFun_ublox_Cellular::modulePowerOff(void) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_POWER_OFF) + 6; @@ -4847,7 +4847,7 @@ UBX_CELL_error_t UBX_CELL::modulePowerOff(void) return err; } -void UBX_CELL::modulePowerOn(void) +void SparkFun_ublox_Cellular::modulePowerOn(void) { if (_powerPin >= 0) { @@ -4864,7 +4864,7 @@ void UBX_CELL::modulePowerOn(void) // Private // ///////////// -UBX_CELL_error_t UBX_CELL::init(unsigned long baud, UBX_CELL::UBX_CELL_init_type_t initType) +UBX_CELL_error_t SparkFun_ublox_Cellular::init(unsigned long baud, SparkFun_ublox_Cellular::UBX_CELL_init_type_t initType) { int retries = _maxInitTries; UBX_CELL_error_t err = UBX_CELL_ERROR_SUCCESS; @@ -4942,14 +4942,14 @@ UBX_CELL_error_t UBX_CELL::init(unsigned long baud, UBX_CELL::UBX_CELL_init_type return UBX_CELL_ERROR_SUCCESS; } -void UBX_CELL::invertPowerPin(bool invert) +void SparkFun_ublox_Cellular::invertPowerPin(bool invert) { _invertPowerPin = invert; } // Do a graceful power off. Hold the PWR_ON pin low for UBX_CELL_POWER_OFF_PULSE_PERIOD // Note: +CPWROFF () is preferred to this. -void UBX_CELL::powerOff(void) +void SparkFun_ublox_Cellular::powerOff(void) { if (_powerPin >= 0) { @@ -4969,7 +4969,7 @@ void UBX_CELL::powerOff(void) } } -void UBX_CELL::powerOn(void) +void SparkFun_ublox_Cellular::powerOn(void) { if (_powerPin >= 0) { @@ -4993,7 +4993,7 @@ void UBX_CELL::powerOn(void) // This does an abrupt emergency hardware shutdown of the SARA-R5 series modules. // It only works if you have access to both the RESET_N and PWR_ON pins. // You cannot use this function on the SparkFun Asset Tracker and RESET_N is tied to the MicroMod processor !RESET!... -void UBX_CELL::hwReset(void) +void SparkFun_ublox_Cellular::hwReset(void) { if ((_resetPin >= 0) && (_powerPin >= 0)) { @@ -5038,7 +5038,7 @@ void UBX_CELL::hwReset(void) } } -UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) +UBX_CELL_error_t SparkFun_ublox_Cellular::functionality(UBX_CELL_functionality_t function) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_FUNC) + 16; @@ -5051,7 +5051,7 @@ UBX_CELL_error_t UBX_CELL::functionality(UBX_CELL_functionality_t function) return err; } -UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) +UBX_CELL_error_t SparkFun_ublox_Cellular::setMNOprofile(mobile_network_operator_t mno, bool autoReset, bool urcNotification) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_MNO) + 9; @@ -5068,7 +5068,7 @@ UBX_CELL_error_t UBX_CELL::setMNOprofile(mobile_network_operator_t mno, bool aut return err; } -UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) +UBX_CELL_error_t SparkFun_ublox_Cellular::getMNOprofile(mobile_network_operator_t *mno) { UBX_CELL_error_t err; size_t cmdLen = strlen(UBX_CELL_COMMAND_MNO) + 2; @@ -5114,7 +5114,7 @@ UBX_CELL_error_t UBX_CELL::getMNOprofile(mobile_network_operator_t *mno) return err; } -UBX_CELL_error_t UBX_CELL::waitForResponse(const char *expectedResponse, const char *expectedError, uint16_t timeout) +UBX_CELL_error_t SparkFun_ublox_Cellular::waitForResponse(const char *expectedResponse, const char *expectedError, uint16_t timeout) { unsigned long timeIn; bool found = false; @@ -5201,7 +5201,7 @@ UBX_CELL_error_t UBX_CELL::waitForResponse(const char *expectedResponse, const c return UBX_CELL_ERROR_NO_RESPONSE; } -UBX_CELL_error_t UBX_CELL::sendCommandWithResponse(const char *command, const char *expectedResponse, +UBX_CELL_error_t SparkFun_ublox_Cellular::sendCommandWithResponse(const char *command, const char *expectedResponse, char *responseDest, unsigned long commandTimeout, int destSize, bool at) { @@ -5341,14 +5341,14 @@ UBX_CELL_error_t UBX_CELL::sendCommandWithResponse(const char *command, const ch } // Send a custom command with an expected (potentially partial) response, store entire response -UBX_CELL_error_t UBX_CELL::sendCustomCommandWithResponse(const char *command, const char *expectedResponse, +UBX_CELL_error_t SparkFun_ublox_Cellular::sendCustomCommandWithResponse(const char *command, const char *expectedResponse, char *responseDest, unsigned long commandTimeout, bool at) { // Assume the user has allocated enough storage for any response. Set destSize to 32766. return sendCommandWithResponse(command, expectedResponse, responseDest, commandTimeout, 32766, at); } -void UBX_CELL::sendCommand(const char *command, bool at) +void SparkFun_ublox_Cellular::sendCommand(const char *command, bool at) { // Check for incoming serial data. Copy it into the backlog @@ -5399,7 +5399,7 @@ void UBX_CELL::sendCommand(const char *command, bool at) } } -UBX_CELL_error_t UBX_CELL::parseSocketReadIndication(int socket, int length) +UBX_CELL_error_t SparkFun_ublox_Cellular::parseSocketReadIndication(int socket, int length) { UBX_CELL_error_t err; char *readDest; @@ -5448,7 +5448,7 @@ UBX_CELL_error_t UBX_CELL::parseSocketReadIndication(int socket, int length) return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::parseSocketReadIndicationUDP(int socket, int length) +UBX_CELL_error_t SparkFun_ublox_Cellular::parseSocketReadIndicationUDP(int socket, int length) { UBX_CELL_error_t err; char *readDest; @@ -5496,7 +5496,7 @@ UBX_CELL_error_t UBX_CELL::parseSocketReadIndicationUDP(int socket, int length) return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::parseSocketListenIndication(int listeningSocket, IPAddress localIP, +UBX_CELL_error_t SparkFun_ublox_Cellular::parseSocketListenIndication(int listeningSocket, IPAddress localIP, unsigned int listeningPort, int socket, IPAddress remoteIP, unsigned int port) { @@ -5511,7 +5511,7 @@ UBX_CELL_error_t UBX_CELL::parseSocketListenIndication(int listeningSocket, IPAd return UBX_CELL_ERROR_SUCCESS; } -UBX_CELL_error_t UBX_CELL::parseSocketCloseIndication(String *closeIndication) +UBX_CELL_error_t SparkFun_ublox_Cellular::parseSocketCloseIndication(String *closeIndication) { int search; int socket; @@ -5532,7 +5532,7 @@ UBX_CELL_error_t UBX_CELL::parseSocketCloseIndication(String *closeIndication) return UBX_CELL_ERROR_SUCCESS; } -size_t UBX_CELL::hwPrint(const char *s) +size_t SparkFun_ublox_Cellular::hwPrint(const char *s) { if ((true == _printAtDebug) && (nullptr != s)) { @@ -5552,7 +5552,7 @@ size_t UBX_CELL::hwPrint(const char *s) return (size_t)0; } -size_t UBX_CELL::hwWriteData(const char *buff, int len) +size_t SparkFun_ublox_Cellular::hwWriteData(const char *buff, int len) { if ((true == _printAtDebug) && (nullptr != buff) && (0 < len)) { @@ -5571,7 +5571,7 @@ size_t UBX_CELL::hwWriteData(const char *buff, int len) return (size_t)0; } -size_t UBX_CELL::hwWrite(const char c) +size_t SparkFun_ublox_Cellular::hwWrite(const char c) { if (true == _printAtDebug) { @@ -5591,7 +5591,7 @@ size_t UBX_CELL::hwWrite(const char c) return (size_t)0; } -int UBX_CELL::readAvailable(char *inString) +int SparkFun_ublox_Cellular::readAvailable(char *inString) { int len = 0; @@ -5633,7 +5633,7 @@ int UBX_CELL::readAvailable(char *inString) return len; } -char UBX_CELL::readChar(void) +char SparkFun_ublox_Cellular::readChar(void) { char ret = 0; @@ -5651,7 +5651,7 @@ char UBX_CELL::readChar(void) return ret; } -int UBX_CELL::hwAvailable(void) +int SparkFun_ublox_Cellular::hwAvailable(void) { if (_hardSerial != nullptr) { @@ -5667,7 +5667,7 @@ int UBX_CELL::hwAvailable(void) return -1; } -void UBX_CELL::beginSerial(unsigned long baud) +void SparkFun_ublox_Cellular::beginSerial(unsigned long baud) { delay(100); if (_hardSerial != nullptr) @@ -5685,7 +5685,7 @@ void UBX_CELL::beginSerial(unsigned long baud) delay(100); } -void UBX_CELL::setTimeout(unsigned long timeout) +void SparkFun_ublox_Cellular::setTimeout(unsigned long timeout) { if (_hardSerial != nullptr) { @@ -5699,7 +5699,7 @@ void UBX_CELL::setTimeout(unsigned long timeout) #endif } -bool UBX_CELL::find(char *target) +bool SparkFun_ublox_Cellular::find(char *target) { bool found = false; if (_hardSerial != nullptr) @@ -5715,7 +5715,7 @@ bool UBX_CELL::find(char *target) return found; } -UBX_CELL_error_t UBX_CELL::autobaud(unsigned long desiredBaud) +UBX_CELL_error_t SparkFun_ublox_Cellular::autobaud(unsigned long desiredBaud) { UBX_CELL_error_t err = UBX_CELL_ERROR_INVALID; int b = 0; @@ -5734,14 +5734,14 @@ UBX_CELL_error_t UBX_CELL::autobaud(unsigned long desiredBaud) return err; } -char *UBX_CELL::ubx_cell_calloc_char(size_t num) +char *SparkFun_ublox_Cellular::ubx_cell_calloc_char(size_t num) { return (char *)calloc(num, sizeof(char)); } // This prunes the backlog of non-actionable events. If new actionable events are added, you must modify the if // statement. -void UBX_CELL::pruneBacklog() +void SparkFun_ublox_Cellular::pruneBacklog() { char *event; @@ -5806,7 +5806,7 @@ void UBX_CELL::pruneBacklog() // GPS Helper Functions: // Read a source string until a delimiter is hit, store the result in destination -char *UBX_CELL::readDataUntil(char *destination, unsigned int destSize, char *source, char delimiter) +char *SparkFun_ublox_Cellular::readDataUntil(char *destination, unsigned int destSize, char *source, char delimiter) { char *strEnd; @@ -5824,7 +5824,7 @@ char *UBX_CELL::readDataUntil(char *destination, unsigned int destSize, char *so return strEnd; } -bool UBX_CELL::parseGPRMCString(char *rmcString, PositionData *pos, ClockData *clk, SpeedData *spd) +bool SparkFun_ublox_Cellular::parseGPRMCString(char *rmcString, PositionData *pos, ClockData *clk, SpeedData *spd) { char *ptr, *search; unsigned long tTemp; diff --git a/src/sfe_ublox_cellular.h b/src/sfe_ublox_cellular.h index f0a21a5..9e391d6 100644 --- a/src/sfe_ublox_cellular.h +++ b/src/sfe_ublox_cellular.h @@ -629,15 +629,15 @@ typedef enum // DEEP_LOW_POWER_STATE = 127 // Not supported on SARA-R5 } UBX_CELL_functionality_t; -class UBX_CELL : public Print +class SparkFun_ublox_Cellular : public Print { public: // Constructor // The library will use the powerPin and resetPin (if provided) to power the module off/on and perform an emergency // reset maxInitTries sets the maximum number of initialization attempts. .init is called by .begin. - UBX_CELL(int powerPin = UBX_CELL_POWER_PIN, int resetPin = UBX_CELL_RESET_PIN, uint8_t maxInitTries = 9); + SparkFun_ublox_Cellular(int powerPin = UBX_CELL_POWER_PIN, int resetPin = UBX_CELL_RESET_PIN, uint8_t maxInitTries = 9); - ~UBX_CELL(); + ~SparkFun_ublox_Cellular(); // Begin -- initialize module and ensure it's connected #ifdef UBX_CELL_SOFTWARE_SERIAL_ENABLED bool begin(SoftwareSerial &softSerial, unsigned long baud = UBX_CELL_DEFAULT_BAUD_RATE); diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index a460de7..c824d02 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -20,10 +20,10 @@ typedef enum } UBX_CELL_audio_resource_t; // Base class for any modules supporting voice calls -template class UBX_CELL_VOICE +template class SparkFun_ublox_Cellular_Voice_Base { public: - UBX_CELL_VOICE(void) + SparkFun_ublox_Cellular_Voice_Base(void) { // Set ring URC callback to nullptr _ringCallback = nullptr; @@ -159,7 +159,7 @@ template class UBX_CELL_VOICE } }; -class UBX_CELL_VOICE_BASE : public UBX_CELL, public UBX_CELL_VOICE +class SparkFun_ublox_Cellular_Voice : public SparkFun_ublox_Cellular, public SparkFun_ublox_Cellular_Voice_Base { }; From 5de76b7efe959bfb717d2f190d7ced56cd68f4fe Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Tue, 2 Jan 2024 15:23:06 -0700 Subject: [PATCH 8/8] Remove empty else block --- src/sfe_ublox_cellular.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sfe_ublox_cellular.cpp b/src/sfe_ublox_cellular.cpp index 418c024..1e7e2db 100644 --- a/src/sfe_ublox_cellular.cpp +++ b/src/sfe_ublox_cellular.cpp @@ -894,9 +894,6 @@ bool SparkFun_ublox_Cellular::poll(void) _debugPort->println(_saraRXBuffer); } } - else - { - } } _pollReentrant = false;