From 5d158438da8956dbf0c5b43fb5fdd245ada9e02a Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Sun, 3 Apr 2022 14:31:38 +0200 Subject: [PATCH 1/8] Security, MQTT, FILE write and improvements - Security APIs - MQTT APIs - File download - improved ERROR parsing - debug capability to see raw AT commands and responses --- ...parkFun_u-blox_SARA-R5_Arduino_Library.cpp | 792 ++++++++++++++---- src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 144 +++- 2 files changed, 777 insertions(+), 159 deletions(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 819c8af..4badf65 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -36,6 +36,10 @@ SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitDepth) _psdActionRequestCallback = NULL; _pingRequestCallback = NULL; _httpCommandRequestCallback = NULL; + _mqttCommandRequestCallback = NULL; + _debugAtPort = NULL; + _debugPort = NULL; + _printDebug = false; _lastRemoteIP = {0, 0, 0, 0}; _lastLocalIP = {0, 0, 0, 0}; for (int i = 0; i < SARA_R5_NUM_SOCKETS; i++) @@ -139,6 +143,14 @@ void SARA_R5::enableDebugging(Stream &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. +void SARA_R5::enableAtDebugging(Stream &debugPort) +{ + _debugAtPort = &debugPort; + _printAtDebug = true; +} + // 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 processed any 'old' data stored in the backlog first @@ -220,9 +232,12 @@ bool SARA_R5::bufferedPoll(void) //Process the event bool latestHandled = processURCEvent((const char *)event); - if (latestHandled) + if (latestHandled) { + if ((true == _printAtDebug) && (NULL != 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) @@ -484,6 +499,25 @@ bool SARA_R5::processURCEvent(const char *event) return true; } } + { // URC: +UUMQTTC (HTTP Command Result) + int command, result; + int scanNum; + + scanNum = sscanf(event, "+UUMQTTC: %d,%d", &command, &result); + + if (scanNum == 2) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: MQTT command result")); + + if (_mqttCommandRequestCallback != NULL) + { + _mqttCommandRequestCallback(command, result); + } + + return true; + } + } { // URC: +UUPING (Ping Result) int retry = 0; int p_size = 0; @@ -565,7 +599,9 @@ bool SARA_R5::poll(void) // 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) @@ -630,56 +666,32 @@ void SARA_R5::setHTTPCommandCallback(void (*httpCommandRequestCallback)(int prof _httpCommandRequestCallback = httpCommandRequestCallback; } +void SARA_R5::setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int command, int result)) +{ + _mqttCommandRequestCallback = mqttCommandRequestCallback; +} + + size_t SARA_R5::write(uint8_t c) { - if (_hardSerial != NULL) - { - return _hardSerial->write(c); - } -#ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != NULL) - { - return _softSerial->write(c); - } -#endif - return (size_t)0; + return hwWrite(c); } size_t SARA_R5::write(const char *str) { - if (_hardSerial != NULL) - { - return _hardSerial->print(str); - } -#ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != NULL) - { - return _softSerial->print(str); - } -#endif - return (size_t)0; + return hwPrint(str); } size_t SARA_R5::write(const char *buffer, size_t size) { - if (_hardSerial != NULL) - { - return _hardSerial->write((const uint8_t *)buffer, (int)size); - } -#ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED - else if (_softSerial != NULL) - { - return _softSerial->write((const uint8_t *)buffer, (int)size); - } -#endif - return (size_t)0; + return hwWriteData(buffer, size); } SARA_R5_error_t SARA_R5::at(void) { SARA_R5_error_t err; - err = sendCommandWithResponse(NULL, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(NULL, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); return err; @@ -701,7 +713,7 @@ SARA_R5_error_t SARA_R5::enableEcho(bool enable) { sprintf(command, "%s0", SARA_R5_COMMAND_ECHO); } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -718,7 +730,7 @@ String SARA_R5::getManufacturerID(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_MANU_ID, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n%s\r\n", idResponse) != 1) @@ -739,7 +751,7 @@ String SARA_R5::getModelID(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_MODEL_ID, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n%s\r\n", idResponse) != 1) @@ -760,7 +772,7 @@ String SARA_R5::getFirmwareVersion(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_FW_VER_ID, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n%s\r\n", idResponse) != 1) @@ -781,7 +793,7 @@ String SARA_R5::getSerialNo(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_SERIAL_NO, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n%s\r\n", idResponse) != 1) @@ -802,7 +814,7 @@ String SARA_R5::getIMEI(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_IMEI, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n%s\r\n", imeiResponse) != 1) @@ -823,7 +835,7 @@ String SARA_R5::getIMSI(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_IMSI, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n%s\r\n", imsiResponse) != 1) @@ -844,7 +856,7 @@ String SARA_R5::getCCID(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_CCID, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n+CCID: %s", ccidResponse) != 1) @@ -865,7 +877,7 @@ String SARA_R5::getSubscriberNo(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_CNUM, - SARA_R5_RESPONSE_OK, response, SARA_R5_10_SEC_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_10_SEC_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n+CNUM: %s", idResponse) != 1) @@ -886,7 +898,7 @@ String SARA_R5::getCapabilities(void) response = sara_r5_calloc_char(minimumResponseAllocation); err = sendCommandWithResponse(SARA_R5_COMMAND_REQ_CAP, - SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { if (sscanf(response, "\r\n+GCAP: %s", idResponse) != 1) @@ -942,7 +954,7 @@ String SARA_R5::clock(void) return ""; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) { @@ -1000,7 +1012,7 @@ SARA_R5_error_t SARA_R5::clock(uint8_t *y, uint8_t *mo, uint8_t *d, return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_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 @@ -1082,7 +1094,7 @@ SARA_R5_error_t SARA_R5::setClock(String theTime) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=\"%s\"", SARA_R5_COMMAND_CLOCK, theTime.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -1107,7 +1119,7 @@ SARA_R5_error_t SARA_R5::setUtimeMode(SARA_R5_utime_mode_t mode, SARA_R5_utime_s else sprintf(command, "%s=%d,%d", SARA_R5_GNSS_REQUEST_TIME, mode, sensor); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_10_SEC_TIMEOUT); free(command); return err; @@ -1134,7 +1146,7 @@ SARA_R5_error_t SARA_R5::getUtimeMode(SARA_R5_utime_mode_t *mode, SARA_R5_utime_ return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_10_SEC_TIMEOUT); // Response format: \r\n+UTIME: [,]\r\n\r\nOK\r\n @@ -1175,7 +1187,7 @@ SARA_R5_error_t SARA_R5::setUtimeIndication(SARA_R5_utime_urc_configuration_t co return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d", SARA_R5_GNSS_TIME_INDICATION, config); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -1201,7 +1213,7 @@ SARA_R5_error_t SARA_R5::getUtimeIndication(SARA_R5_utime_urc_configuration_t *c return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); // Response format: \r\n+UTIMEIND: \r\n\r\nOK\r\n @@ -1239,7 +1251,7 @@ SARA_R5_error_t SARA_R5::setUtimeConfiguration(int32_t offsetNanoseconds, int32_ sprintf(command, "%s=%ld,%ld", SARA_R5_GNSS_TIME_CONFIGURATION, offsetNanoseconds, offsetSeconds); #endif - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -1266,7 +1278,7 @@ SARA_R5_error_t SARA_R5::getUtimeConfiguration(int32_t *offsetNanoseconds, int32 return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); // Response format: \r\n+UTIMECFG: ,\r\n\r\nOK\r\n @@ -1304,7 +1316,7 @@ SARA_R5_error_t SARA_R5::autoTimeZone(bool enable) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d", SARA_R5_COMMAND_AUTO_TZ, enable ? 1 : 0); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -1330,7 +1342,7 @@ int8_t SARA_R5::rssi(void) } err = sendCommandWithResponse(command, - SARA_R5_RESPONSE_OK, response, 10000, + SARA_R5_RESPONSE_OK_OR_ERROR, response, 10000, minimumResponseAllocation, AT_COMMAND); if (err != SARA_R5_ERROR_SUCCESS) { @@ -1372,7 +1384,7 @@ SARA_R5_registration_status_t SARA_R5::registration(void) return SARA_R5_REGISTRATION_INVALID; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT, minimumResponseAllocation, AT_COMMAND); if (err != SARA_R5_ERROR_SUCCESS) @@ -1496,7 +1508,7 @@ SARA_R5_error_t SARA_R5::setAPN(String apn, uint8_t cid, SARA_R5_pdp_type pdpTyp cid, pdpStr, apn.c_str()); } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -1528,7 +1540,7 @@ SARA_R5_error_t SARA_R5::getAPN(int cid, String *apn, IPAddress *ip) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT, 1024); if (err == SARA_R5_ERROR_SUCCESS) @@ -1615,6 +1627,20 @@ SARA_R5_error_t SARA_R5::getAPN(int cid, String *apn, IPAddress *ip) return err; } +SARA_R5_error_t SARA_R5::setSimPin(String pin) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_COMMAND_SIMPIN) + 4 + pin.length()); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=\"%s\"", SARA_R5_COMMAND_SIMPIN, pin.c_str()); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, + NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + SARA_R5_error_t SARA_R5::setSIMstateReportingMode(int mode) { SARA_R5_error_t err; @@ -1625,7 +1651,7 @@ SARA_R5_error_t SARA_R5::setSIMstateReportingMode(int mode) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d", SARA_R5_SIM_STATE, mode); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); return err; @@ -1651,7 +1677,7 @@ SARA_R5_error_t SARA_R5::getSIMstateReportingMode(int *mode) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -1735,7 +1761,7 @@ uint8_t SARA_R5::getOperators(struct operator_stats *opRet, int maxOps) } // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_3_MIN_TIMEOUT, responseSize); // Sample responses: @@ -1808,7 +1834,7 @@ SARA_R5_error_t SARA_R5::registerOperator(struct operator_stats oper) sprintf(command, "%s=1,2,\"%lu\"", SARA_R5_OPERATOR_SELECTION, oper.numOp); // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_3_MIN_TIMEOUT); free(command); @@ -1826,7 +1852,7 @@ SARA_R5_error_t SARA_R5::automaticOperatorSelection() sprintf(command, "%s=0,0", SARA_R5_OPERATOR_SELECTION); // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_3_MIN_TIMEOUT); free(command); @@ -1854,7 +1880,7 @@ SARA_R5_error_t SARA_R5::getOperator(String *oper) } // AT+COPS maximum response time is 3 minutes (180000 ms) - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_3_MIN_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -1908,7 +1934,7 @@ SARA_R5_error_t SARA_R5::deregisterOperator(void) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=2", SARA_R5_OPERATOR_SELECTION); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_3_MIN_TIMEOUT); free(command); @@ -1926,7 +1952,7 @@ SARA_R5_error_t SARA_R5::setSMSMessageFormat(SARA_R5_message_format_t textMode) sprintf(command, "%s=%d", SARA_R5_MESSAGE_FORMAT, (textMode == SARA_R5_MESSAGE_FORMAT_TEXT) ? 1 : 0); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -1966,7 +1992,7 @@ SARA_R5_error_t SARA_R5::sendSMS(String number, String message) message.toCharArray(messageCStr, message.length() + 1); messageCStr[message.length()] = ASCII_CTRL_Z; - err = sendCommandWithResponse(messageCStr, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(messageCStr, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_3_MIN_TIMEOUT, minimumResponseAllocation, NOT_AT_COMMAND); free(messageCStr); @@ -2000,7 +2026,7 @@ SARA_R5_error_t SARA_R5::getPreferredMessageStorage(int *used, int *total, Strin return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_3_MIN_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) @@ -2056,7 +2082,7 @@ SARA_R5_error_t SARA_R5::readSMSmessage(int location, String *unread, String *fr return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_10_SEC_TIMEOUT, 1024); if (err == SARA_R5_ERROR_SUCCESS) @@ -2155,7 +2181,7 @@ SARA_R5_error_t SARA_R5::deleteSMSmessage(int location, int deleteFlag) else sprintf(command, "%s=%d,%d", SARA_R5_DELETE_MESSAGE, location, deleteFlag); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, SARA_R5_55_SECS_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_55_SECS_TIMEOUT); free(command); return err; @@ -2186,7 +2212,7 @@ SARA_R5_error_t SARA_R5::setBaud(unsigned long baud) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%lu", SARA_R5_COMMAND_BAUD, baud); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_SET_BAUD_TIMEOUT); free(command); @@ -2204,7 +2230,7 @@ SARA_R5_error_t SARA_R5::setFlowControl(SARA_R5_flow_control_t value) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s%d", SARA_R5_FLOW_CONTROL, value); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -2228,7 +2254,7 @@ SARA_R5_error_t SARA_R5::setGpioMode(SARA_R5_gpio_t gpio, else sprintf(command, "%s=%d,%d", SARA_R5_COMMAND_GPIO, gpio, mode); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_10_SEC_TIMEOUT); free(command); @@ -2257,7 +2283,7 @@ SARA_R5::SARA_R5_gpio_mode_t SARA_R5::getGpioMode(SARA_R5_gpio_t gpio) return GPIO_MODE_INVALID; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) @@ -2305,7 +2331,7 @@ int SARA_R5::socketOpen(SARA_R5_socket_protocol_t protocol, unsigned int localPo return -1; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) @@ -2363,7 +2389,7 @@ SARA_R5_error_t SARA_R5::socketClose(int socket, unsigned long timeout) } sprintf(command, "%s=%d", SARA_R5_CLOSE_SOCKET, socket); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, timeout); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, timeout); if ((err != SARA_R5_ERROR_SUCCESS) && (_printDebug == true)) { @@ -2388,7 +2414,7 @@ SARA_R5_error_t SARA_R5::socketConnect(int socket, const char *address, return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d,\"%s\",%d", SARA_R5_CONNECT_SOCKET, socket, address, port); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, SARA_R5_IP_CONNECT_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_IP_CONNECT_TIMEOUT); free(command); @@ -2594,7 +2620,7 @@ SARA_R5_error_t SARA_R5::socketRead(int socket, int length, char *readDest, int sprintf(command, "%s=%d,%d", SARA_R5_READ_SOCKET, socket, bytesToRead); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT, responseLength); if (err != SARA_R5_ERROR_SUCCESS) @@ -2718,7 +2744,7 @@ SARA_R5_error_t SARA_R5::socketReadAvailable(int socket, int *length) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -2804,7 +2830,7 @@ SARA_R5_error_t SARA_R5::socketReadUDP(int socket, int length, char *readDest, sprintf(command, "%s=%d,%d", SARA_R5_READ_UDP_SOCKET, socket, bytesToRead); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT, responseLength); if (err != SARA_R5_ERROR_SUCCESS) @@ -2948,7 +2974,7 @@ SARA_R5_error_t SARA_R5::socketReadAvailableUDP(int socket, int *length) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -2988,7 +3014,7 @@ SARA_R5_error_t SARA_R5::socketListen(int socket, unsigned int port) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d,%d", SARA_R5_LISTEN_SOCKET, socket, port); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3026,7 +3052,7 @@ SARA_R5_error_t SARA_R5::socketDirectLinkTimeTrigger(int socket, unsigned long t return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=5,%d,%ld", SARA_R5_UD_CONFIGURATION, socket, timerTrigger); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3047,7 +3073,7 @@ SARA_R5_error_t SARA_R5::socketDirectLinkDataLengthTrigger(int socket, int dataL return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=6,%d,%d", SARA_R5_UD_CONFIGURATION, socket, dataLengthTrigger); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3068,7 +3094,7 @@ SARA_R5_error_t SARA_R5::socketDirectLinkCharacterTrigger(int socket, int charac return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=7,%d,%d", SARA_R5_UD_CONFIGURATION, socket, characterTrigger); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3089,7 +3115,7 @@ SARA_R5_error_t SARA_R5::socketDirectLinkCongestionTimer(int socket, unsigned lo return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=8,%d,%ld", SARA_R5_UD_CONFIGURATION, socket, congestionTimer); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3117,7 +3143,7 @@ SARA_R5_error_t SARA_R5::querySocketType(int socket, SARA_R5_socket_protocol_t * return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3169,7 +3195,7 @@ SARA_R5_error_t SARA_R5::querySocketLastError(int socket, int *error) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3220,7 +3246,7 @@ SARA_R5_error_t SARA_R5::querySocketTotalBytesSent(int socket, uint32_t *total) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3271,7 +3297,7 @@ SARA_R5_error_t SARA_R5::querySocketTotalBytesReceived(int socket, uint32_t *tot return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3322,7 +3348,7 @@ SARA_R5_error_t SARA_R5::querySocketRemoteIPAddress(int socket, IPAddress *addre return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3378,7 +3404,7 @@ SARA_R5_error_t SARA_R5::querySocketStatusTCP(int socket, SARA_R5_tcp_socket_sta return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3429,7 +3455,7 @@ SARA_R5_error_t SARA_R5::querySocketOutUnackData(int socket, uint32_t *total) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3480,7 +3506,7 @@ int SARA_R5::socketGetLastError() sprintf(command, "%s", SARA_R5_GET_ERROR); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3514,7 +3540,7 @@ SARA_R5_error_t SARA_R5::resetHTTPprofile(int profile) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d", SARA_R5_HTTP_PROFILE, profile); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3535,7 +3561,7 @@ SARA_R5_error_t SARA_R5::setHTTPserverIPaddress(int profile, IPAddress address) sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_SERVER_IP, address[0], address[1], address[2], address[3]); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3556,7 +3582,7 @@ SARA_R5_error_t SARA_R5::setHTTPserverName(int profile, String server) sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_SERVER_NAME, server.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3577,7 +3603,7 @@ SARA_R5_error_t SARA_R5::setHTTPusername(int profile, String username) sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_USERNAME, username.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3598,7 +3624,7 @@ SARA_R5_error_t SARA_R5::setHTTPpassword(int profile, String password) sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_PASSWORD, password.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3619,7 +3645,7 @@ SARA_R5_error_t SARA_R5::setHTTPauthentication(int profile, bool authenticate) sprintf(command, "%s=%d,%d,%d", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_AUTHENTICATION, authenticate); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3640,14 +3666,35 @@ SARA_R5_error_t SARA_R5::setHTTPserverPort(int profile, int port) sprintf(command, "%s=%d,%d,%d", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_SERVER_PORT, port); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::setHTTPcustomHeader(int profile, String header) +{ + SARA_R5_error_t err; + char *command; + + if (profile >= SARA_R5_NUM_HTTP_PROFILES) + return SARA_R5_ERROR_ERROR; + + command = sara_r5_calloc_char(strlen(SARA_R5_HTTP_PROFILE) + 12 + header.length()); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_ADD_CUSTOM_HEADERS, + header.c_str()); + + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); return err; } -SARA_R5_error_t SARA_R5::setHTTPsecure(int profile, bool secure) +SARA_R5_error_t SARA_R5::setHTTPsecure(int profile, bool secure, int secprofile) { SARA_R5_error_t err; char *command; @@ -3658,10 +3705,13 @@ SARA_R5_error_t SARA_R5::setHTTPsecure(int profile, bool secure) command = sara_r5_calloc_char(strlen(SARA_R5_HTTP_PROFILE) + 32); if (command == NULL) return SARA_R5_ERROR_OUT_OF_MEMORY; - sprintf(command, "%s=%d,%d,%d", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_SECURE, + if (secprofile == -1) + sprintf(command, "%s=%d,%d,%d", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_SECURE, secure); + else sprintf(command, "%s=%d,%d,%d,%d", SARA_R5_HTTP_PROFILE, profile, SARA_R5_HTTP_OP_CODE_SECURE, + secure, secprofile); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3681,7 +3731,7 @@ SARA_R5_error_t SARA_R5::ping(String remote_host, int retry, int p_size, sprintf(command, "%s=\"%s\",%d,%d,%ld,%d", SARA_R5_PING_COMMAND, remote_host.c_str(), retry, p_size, timeout, ttl); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3703,7 +3753,7 @@ SARA_R5_error_t SARA_R5::sendHTTPGET(int profile, String path, String responseFi sprintf(command, "%s=%d,%d,\"%s\",\"%s\"", SARA_R5_HTTP_COMMAND, profile, SARA_R5_HTTP_COMMAND_GET, path.c_str(), responseFilename.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3726,7 +3776,30 @@ SARA_R5_error_t SARA_R5::sendHTTPPOSTdata(int profile, String path, String respo sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", SARA_R5_HTTP_COMMAND, profile, SARA_R5_HTTP_COMMAND_POST_DATA, path.c_str(), responseFilename.c_str(), data.c_str(), httpContentType); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::sendHTTPPOSTfile(int profile, String path, String responseFilename, + String requestFile, SARA_R5_http_content_types_t httpContentType) +{ + SARA_R5_error_t err; + char *command; + + if (profile >= SARA_R5_NUM_HTTP_PROFILES) + return SARA_R5_ERROR_ERROR; + + command = sara_r5_calloc_char(strlen(SARA_R5_HTTP_COMMAND) + 24 + + path.length() + responseFilename.length() + requestFile.length()); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\",\"%s\",\"%s\",%d", SARA_R5_HTTP_COMMAND, profile, SARA_R5_HTTP_COMMAND_POST_FILE, + path.c_str(), responseFilename.c_str(), requestFile.c_str(), httpContentType); + + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3753,7 +3826,7 @@ SARA_R5_error_t SARA_R5::getHTTPprotocolError(int profile, int *error_class, int return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3777,6 +3850,324 @@ SARA_R5_error_t SARA_R5::getHTTPprotocolError(int profile, int *error_class, int return err; } +SARA_R5_error_t SARA_R5::nvMQTT(SARA_R5_mqtt_nv_parameter_t parameter) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_NVM) + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", SARA_R5_MQTT_NVM, parameter); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::setMQTTclientId(String clientId) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_PROFILE) + clientId.length() + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\"", SARA_R5_MQTT_PROFILE, SARA_R5_MQTT_PROFILE_CLIENT_ID, clientId.c_str()); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::setMQTTserver(String serverName, int port) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_PROFILE) + serverName.length() + 16); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\",%d", SARA_R5_MQTT_PROFILE, SARA_R5_MQTT_PROFILE_SERVERNAME, serverName.c_str(), port); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::setMQTTsecure(bool secure, int secprofile) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_PROFILE) + 16); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + if (secprofile == -1) sprintf(command, "%s=%d,%d", SARA_R5_MQTT_PROFILE, SARA_R5_MQTT_PROFILE_SECURE, secure); + else sprintf(command, "%s=%d,%d,%d", SARA_R5_MQTT_PROFILE, SARA_R5_MQTT_PROFILE_SECURE, secure, secprofile); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::connectMQTT(void) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", SARA_R5_MQTT_COMMAND, SARA_R5_MQTT_COMMAND_LOGIN); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::disconnectMQTT(void) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", SARA_R5_MQTT_COMMAND, SARA_R5_MQTT_COMMAND_LOGOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::subscribeMQTTtopic(int max_Qos, String topic) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + topic.length() + 16); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_MQTT_COMMAND, SARA_R5_MQTT_COMMAND_SUBSCRIBE, max_Qos, topic.c_str()); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::unsubscribeMQTTtopic(String topic) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + topic.length() + 16); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,\"%s\"", SARA_R5_MQTT_COMMAND, SARA_R5_MQTT_COMMAND_UNSUBSCRIBE, topic.c_str()); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::readMQTT(int* pQos, char* pTopic, uint8_t *readDest, int readLength, int *bytesRead) +{ + char *command; + char *response; + SARA_R5_error_t err; + int scanNum = 0; + int total_length, topic_length, data_length; + + // Set *bytesRead to zero + if (bytesRead != NULL) + *bytesRead = 0; + + // Allocate memory for the command + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + + // Allocate memory for the response + int responseLength = readLength + minimumResponseAllocation; + response = sara_r5_calloc_char(responseLength); + if (response == NULL) + { + free(command); + return SARA_R5_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", SARA_R5_MQTT_COMMAND, SARA_R5_MQTT_COMMAND_READ, 1); + err = sendCommandWithResponse(command, mqttReadTerm, response, + (5 * SARA_R5_STANDARD_RESPONSE_TIMEOUT), responseLength); + + if (err != SARA_R5_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: 6"); + if (searchPtr != NULL) + scanNum = sscanf(searchPtr, "+UMQTTC: 6,%d,%d,%d,\"%[^\"]\",%d\"", pQos, &total_length, &topic_length, pTopic, &data_length); + if (scanNum != 5) + { + if (_printDebug == true) + { + _debugPort->print(F("readMQTT: error: scanNum is ")); + _debugPort->println(scanNum); + } + free(command); + free(response); + return SARA_R5_ERROR_UNEXPECTED_RESPONSE; + } + + searchPtr = strstr(searchPtr, "\""); + searchPtr = strstr(searchPtr+1, "\""); + searchPtr = strstr(searchPtr+1, "\""); + *bytesRead = (data_length > readLength) ? readLength : data_length; + memcpy(readDest, searchPtr, *bytesRead); + + free(command); + free(response); + + return (data_length > readLength) ? SARA_R5_ERROR_OUT_OF_MEMORY : SARA_R5_ERROR_SUCCESS; +} + +SARA_R5_error_t SARA_R5::getMQTTprotocolError(int *error_code, int *error_code2) +{ + SARA_R5_error_t err; + char *response; + + int code, code2; + + response = sara_r5_calloc_char(minimumResponseAllocation); + if (response == NULL) + { + return SARA_R5_ERROR_OUT_OF_MEMORY; + } + + err = sendCommandWithResponse(SARA_R5_MQTT_PROTOCOL_ERROR, SARA_R5_RESPONSE_OK_OR_ERROR, + response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + + if (err == SARA_R5_ERROR_SUCCESS) + { + int scanned = 0; + char *searchPtr = strstr(response, "+UMQTTER: "); + if (searchPtr != NULL) + scanned = sscanf(searchPtr, "+UMQTTER:%d,%d\r\n", + &code, &code2); + if (scanned == 2) + { + *error_code = code; + *error_code2 = code2; + } + else + err = SARA_R5_ERROR_UNEXPECTED_RESPONSE; + } + + free(response); + return err; +} + +SARA_R5_error_t SARA_R5::resetSecurityProfile(int secprofile) +{ + SARA_R5_error_t err; + char *command; + + command = sara_r5_calloc_char(strlen(SARA_R5_SEC_PROFILE) + 6); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + + sprintf(command, "%s=%d", SARA_R5_SEC_PROFILE, secprofile); + + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::configSecurityProfile(int secprofile, SARA_R5_sec_profile_parameter_t parameter, int value) +{ + SARA_R5_error_t err; + char *command; + + command = sara_r5_calloc_char(strlen(SARA_R5_SEC_PROFILE) + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,%d", SARA_R5_SEC_PROFILE, secprofile,parameter,value); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::configSecurityProfileString(int secprofile, SARA_R5_sec_profile_parameter_t parameter, String value) +{ + SARA_R5_error_t err; + char *command; + command = sara_r5_calloc_char(strlen(SARA_R5_SEC_PROFILE) + value.length() + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_SEC_PROFILE, secprofile,parameter,value.c_str()); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::setSecurityManager(SARA_R5_sec_manager_opcode_t opcode, SARA_R5_sec_manager_parameter_t parameter, String name, String data) +{ + char *command; + char *response; + SARA_R5_error_t err; + + command = sara_r5_calloc_char(strlen(SARA_R5_SEC_MANAGER) + name.length() + 20); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + response = sara_r5_calloc_char(minimumResponseAllocation); + if (response == NULL) + { + free(command); + return SARA_R5_ERROR_OUT_OF_MEMORY; + } + int dataLen = data.length(); + sprintf(command, "%s=%d,%d,\"%s\",%d", SARA_R5_SEC_MANAGER, opcode, parameter, name.c_str(), dataLen); + + err = sendCommandWithResponse(command, ">", response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + if (err == SARA_R5_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("dataDownload: writing ")); + _debugPort->print(dataLen); + _debugPort->println(F(" bytes")); + } + hwWriteData(data.c_str(), dataLen); + err = waitForResponse(SARA_R5_RESPONSE_OK, SARA_R5_RESPONSE_ERROR, SARA_R5_STANDARD_RESPONSE_TIMEOUT*3); + } + + + if (err != SARA_R5_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; +} + SARA_R5_error_t SARA_R5::setPDPconfiguration(int profile, SARA_R5_pdp_configuration_parameter_t parameter, int value) { SARA_R5_error_t err; @@ -3791,7 +4182,7 @@ SARA_R5_error_t SARA_R5::setPDPconfiguration(int profile, SARA_R5_pdp_configurat sprintf(command, "%s=%d,%d,%d", SARA_R5_MESSAGE_PDP_CONFIG, profile, parameter, value); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3817,7 +4208,7 @@ SARA_R5_error_t SARA_R5::setPDPconfiguration(int profile, SARA_R5_pdp_configurat sprintf(command, "%s=%d,%d,\"%s\"", SARA_R5_MESSAGE_PDP_CONFIG, profile, parameter, value.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3838,7 +4229,7 @@ SARA_R5_error_t SARA_R5::setPDPconfiguration(int profile, SARA_R5_pdp_configurat sprintf(command, "%s=%d,%d,\"%d.%d.%d.%d\"", SARA_R5_MESSAGE_PDP_CONFIG, profile, parameter, value[0], value[1], value[2], value[3]); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3858,7 +4249,7 @@ SARA_R5_error_t SARA_R5::performPDPaction(int profile, SARA_R5_pdp_actions_t act return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d,%d", SARA_R5_MESSAGE_PDP_ACTION, profile, action); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3881,7 +4272,7 @@ SARA_R5_error_t SARA_R5::activatePDPcontext(bool status, int cid) else sprintf(command, "%s=%d,%d", SARA_R5_MESSAGE_PDP_CONTEXT_ACTIVATE, status, cid); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -3910,7 +4301,7 @@ SARA_R5_error_t SARA_R5::getNetworkAssignedIPAddress(int profile, IPAddress *add return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -3962,7 +4353,7 @@ bool SARA_R5::isGPSon(void) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_10_SEC_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) @@ -4010,7 +4401,7 @@ SARA_R5_error_t SARA_R5::gpsPower(bool enable, gnss_system_t gnss_sys, gnss_aidi sprintf(command, "%s=0", SARA_R5_GNSS_POWER); } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, 10000); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, 10000); free(command); return err; @@ -4096,7 +4487,7 @@ SARA_R5_error_t SARA_R5::gpsEnableRmc(bool enable) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d", SARA_R5_GNSS_GPRMC, enable ? 1 : 0); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, SARA_R5_10_SEC_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_10_SEC_TIMEOUT); free(command); return err; @@ -4122,7 +4513,7 @@ SARA_R5_error_t SARA_R5::gpsGetRmc(struct PositionData *pos, struct SpeedData *s return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, SARA_R5_10_SEC_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_10_SEC_TIMEOUT); if (err == SARA_R5_ERROR_SUCCESS) { // Fast-forward response string to $GPRMC starter @@ -4187,7 +4578,7 @@ SARA_R5_error_t SARA_R5::gpsRequest(unsigned int timeout, uint32_t accuracy, sensor, detailed ? 1 : 0, timeout, accuracy); #endif - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, SARA_R5_10_SEC_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_10_SEC_TIMEOUT); free(command); return err; @@ -4208,13 +4599,71 @@ SARA_R5_error_t SARA_R5::gpsAidingServerConf(const char *primaryServer, const ch primaryServer, secondaryServer, authToken, days, period, resolution, gnssTypes, mode, dataType); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); return err; } + +// OK for text files. But will fail with binary files (containing \0) on some platforms. +SARA_R5_error_t SARA_R5::appendFileContents(String filename, const char *str, int len) +{ + char *command; + char *response; + SARA_R5_error_t err; + + command = sara_r5_calloc_char(strlen(SARA_R5_FILE_SYSTEM_DOWNLOAD_FILE) + filename.length() + 10); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + response = sara_r5_calloc_char(minimumResponseAllocation); + if (response == NULL) + { + free(command); + return SARA_R5_ERROR_OUT_OF_MEMORY; + } + int dataLen = len == -1 ? strlen(str) : len; + sprintf(command, "%s=\"%s\",%d", SARA_R5_FILE_SYSTEM_DOWNLOAD_FILE, filename.c_str(), dataLen); + + err = sendCommandWithResponse(command, ">", response, + SARA_R5_STANDARD_RESPONSE_TIMEOUT*2); + delay(50); + if (err == SARA_R5_ERROR_SUCCESS) + { + if (_printDebug == true) + { + _debugPort->print(F("fileDownload: writing ")); + _debugPort->print(dataLen); + _debugPort->println(F(" bytes")); + } + hwWriteData(str, dataLen); + + err = waitForResponse(SARA_R5_RESPONSE_OK, SARA_R5_RESPONSE_ERROR, SARA_R5_STANDARD_RESPONSE_TIMEOUT*5); + } + if (err != SARA_R5_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; +} + +SARA_R5_error_t SARA_R5::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. SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents) { @@ -4234,7 +4683,7 @@ SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents) } return err; } - + command = sara_r5_calloc_char(strlen(SARA_R5_FILE_SYSTEM_READ_FILE) + filename.length() + 8); if (command == NULL) return SARA_R5_ERROR_OUT_OF_MEMORY; @@ -4474,7 +4923,7 @@ SARA_R5_error_t SARA_R5::getFileSize(String filename, int *size) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) { if (_printDebug == true) @@ -4523,7 +4972,7 @@ SARA_R5_error_t SARA_R5::deleteFile(String filename) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=\"%s\"", SARA_R5_FILE_SYSTEM_DELETE_FILE, filename.c_str()); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) { @@ -4549,7 +4998,7 @@ SARA_R5_error_t SARA_R5::modulePowerOff(void) sprintf(command, "%s", SARA_R5_COMMAND_POWER_OFF); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_POWER_OFF_TIMEOUT); free(command); @@ -4641,7 +5090,7 @@ SARA_R5_error_t SARA_R5::init(unsigned long baud, autoTimeZone(_autoTimeZoneForBegin); for (int i = 0; i < SARA_R5_NUM_SOCKETS; i++) { - socketClose(i, 100); + socketClose(i, SARA_R5_STANDARD_RESPONSE_TIMEOUT); } return SARA_R5_ERROR_SUCCESS; @@ -4753,7 +5202,7 @@ SARA_R5_error_t SARA_R5::functionality(SARA_R5_functionality_t function) return SARA_R5_ERROR_OUT_OF_MEMORY; sprintf(command, "%s=%d", SARA_R5_COMMAND_FUNC, function); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_3_MIN_TIMEOUT); free(command); @@ -4774,7 +5223,7 @@ SARA_R5_error_t SARA_R5::setMNOprofile(mobile_network_operator_t mno, bool autoR else sprintf(command, "%s=%d", SARA_R5_COMMAND_MNO, (uint8_t)mno); - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); free(command); @@ -4805,7 +5254,7 @@ SARA_R5_error_t SARA_R5::getMNOprofile(mobile_network_operator_t *mno) return SARA_R5_ERROR_OUT_OF_MEMORY; } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); if (err != SARA_R5_ERROR_SUCCESS) { @@ -4844,11 +5293,15 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha { 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 NULL @@ -4861,9 +5314,9 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha // _debugPort->write(c); // printedSomething = true; // } - if (c == expectedResponse[responseIndex]) + if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) { - if (++responseIndex == (int)strlen(expectedResponse)) + if (++responseIndex == responseLen) { found = true; } @@ -4872,10 +5325,11 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha { responseIndex = 0; } - if (c == expectedError[errorIndex]) + if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) { - if (++errorIndex == (int)strlen(expectedError)) + if (++errorIndex == errorLen) { + error = true; found = true; } } @@ -4907,14 +5361,12 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha if (found == true) { - if (responseIndex > 0) // Let success have priority - { - return SARA_R5_ERROR_SUCCESS; - } - else if (errorIndex > 0) - { - return SARA_R5_ERROR_ERROR; + if (true == _printAtDebug) { + _debugAtPort->print("\r\n"); + _debugAtPort->print((error == true) ? expectedError : expectedResponse); } + + return (error == true) ? SARA_R5_ERROR_ERROR : SARA_R5_ERROR_SUCCESS; } return SARA_R5_ERROR_NO_RESPONSE; @@ -4925,9 +5377,14 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( unsigned long commandTimeout, int destSize, bool at) { bool found = false; - int index = 0; + 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= NULL; //bool printedSomething = false; if (_printDebug == true) @@ -4935,10 +5392,18 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( _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 (SARA_R5_RESPONSE_OK_OR_ERROR == expectedResponse) { + expectedResponse = SARA_R5_RESPONSE_OK; + expectedError = SARA_R5_RESPONSE_ERROR; + responseLen = sizeof(SARA_R5_RESPONSE_OK)-1; + errorLen = sizeof(SARA_R5_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 NULL @@ -4971,16 +5436,28 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( } } charsRead++; - if (c == expectedResponse[index]) + if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) + { + if (++errorIndex == errorLen) + { + error = true; + found = true; + } + } + else + { + errorIndex = 0; + } + if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) { - if (++index == (int)strlen(expectedResponse)) + if (++responseIndex == responseLen) { found = true; } } else { - index = 0; + responseIndex = 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(). @@ -5006,7 +5483,10 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( if (found) { - return SARA_R5_ERROR_SUCCESS; + if ((true == _printAtDebug) && ((NULL != responseDest) || (NULL != expectedResponse))) { + _debugAtPort->print((NULL != responseDest) ? responseDest : expectedResponse); + } + return error ? SARA_R5_ERROR_ERROR : SARA_R5_ERROR_SUCCESS; } else if (charsRead == 0) { @@ -5014,6 +5494,9 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( } else { + if ((true == _printAtDebug) && (NULL != responseDest)) { + _debugAtPort->print(responseDest); + } return SARA_R5_ERROR_UNEXPECTED_RESPONSE; } } @@ -5056,7 +5539,7 @@ void SARA_R5::sendCommand(const char *command, bool at) { hwPrint(SARA_R5_COMMAND_AT); hwPrint(command); - hwPrint("\r"); + hwPrint("\r\n"); } else { @@ -5196,6 +5679,9 @@ SARA_R5_error_t SARA_R5::parseSocketCloseIndication(String *closeIndication) size_t SARA_R5::hwPrint(const char *s) { + if ((true == _printAtDebug) && (NULL != s)) { + _debugAtPort->print(s); + } if (_hardSerial != NULL) { return _hardSerial->print(s); @@ -5212,6 +5698,9 @@ size_t SARA_R5::hwPrint(const char *s) size_t SARA_R5::hwWriteData(const char *buff, int len) { + if ((true == _printAtDebug) && (NULL != buff) && (0 < len) ) { + _debugAtPort->write(buff,len); + } if (_hardSerial != NULL) { return _hardSerial->write((const uint8_t *)buff, len); @@ -5227,6 +5716,9 @@ size_t SARA_R5::hwWriteData(const char *buff, int len) size_t SARA_R5::hwWrite(const char c) { + if (true == _printAtDebug) { + _debugAtPort->write(c); + } if (_hardSerial != NULL) { return _hardSerial->write(c); diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index 66b4d0a..9915cee 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -102,13 +102,13 @@ const char SARA_R5_COMMAND_IMEI[] = "+CSN"; // IMEI identification const char SARA_R5_COMMAND_IMSI[] = "+CIMI"; // IMSI identification const char SARA_R5_COMMAND_CCID[] = "+CCID"; // SIM CCID const char SARA_R5_COMMAND_REQ_CAP[] = "+GCAP"; // Request capabilities list -// ### Control and status +/// ### Control and status const char SARA_R5_COMMAND_POWER_OFF[] = "+CPWROFF"; // Module switch off const char SARA_R5_COMMAND_FUNC[] = "+CFUN"; // Functionality (reset, etc.) const char SARA_R5_COMMAND_CLOCK[] = "+CCLK"; // Real-time clock const char SARA_R5_COMMAND_AUTO_TZ[] = "+CTZU"; // Automatic time zone update const char SARA_R5_COMMAND_TZ_REPORT[] = "+CTZR"; // Time zone reporting -// ### Network service +/// ### Network service const char SARA_R5_COMMAND_CNUM[] = "+CNUM"; // Subscriber number const char SARA_R5_SIGNAL_QUALITY[] = "+CSQ"; const char SARA_R5_OPERATOR_SELECTION[] = "+COPS"; @@ -117,6 +117,7 @@ const char SARA_R5_READ_OPERATOR_NAMES[] = "+COPN"; const char SARA_R5_COMMAND_MNO[] = "+UMNOPROF"; // MNO (mobile network operator) Profile // ### SIM const char SARA_R5_SIM_STATE[] = "+USIMSTAT"; +const char SARA_R5_COMMAND_SIMPIN[] = "+CPIN"; // SIM PIN // ### SMS const char SARA_R5_MESSAGE_FORMAT[] = "+CMGF"; // Set SMS message format const char SARA_R5_SEND_TEXT[] = "+CMGS"; // Send SMS message @@ -155,6 +156,12 @@ const char SARA_R5_PING_COMMAND[] = "+UPING"; // Ping const char SARA_R5_HTTP_PROFILE[] = "+UHTTP"; // Configure the HTTP profile. Up to 4 different profiles can be defined const char SARA_R5_HTTP_COMMAND[] = "+UHTTPC"; // Trigger the specified HTTP command const char SARA_R5_HTTP_PROTOCOL_ERROR[] = "+UHTTPER"; // Retrieves the error class and code of the latest HTTP operation on the specified HTTP profile. + +const char SARA_R5_MQTT_NVM[] = "+UMQTTNV"; +const char SARA_R5_MQTT_PROFILE[] = "+UMQTT"; +const char SARA_R5_MQTT_COMMAND[] = "+UMQTTC"; +const char SARA_R5_MQTT_PROTOCOL_ERROR[] = "+UMQTTER"; + // ### GNSS const char SARA_R5_GNSS_POWER[] = "+UGPS"; // GNSS power management configuration const char SARA_R5_GNSS_ASSISTED_IND[] = "+UGIND"; // Assisted GNSS unsolicited indication @@ -169,12 +176,19 @@ const char SARA_R5_AIDING_SERVER_CONFIGURATION[] = "+UGSRV"; // Configure aiding // ### File System // TO DO: Add support for file tags. Default tag to USER const char SARA_R5_FILE_SYSTEM_READ_FILE[] = "+URDFILE"; // Read a file +const char SARA_R5_FILE_SYSTEM_DOWNLOAD_FILE[] = "+UDWNFILE"; // Download a file into the module const char SARA_R5_FILE_SYSTEM_LIST_FILES[] = "+ULSTFILE"; // List of files, size of file, etc. const char SARA_R5_FILE_SYSTEM_DELETE_FILE[] = "+UDELFILE"; // Delete a file +// ### File System +// TO DO: Add support for file tags. Default tag to USER +const char SARA_R5_SEC_PROFILE[] = "+USECPRF"; +const char SARA_R5_SEC_MANAGER[] = "+USECMNG"; + // ### Response const char SARA_R5_RESPONSE_OK[] = "OK\r\n"; const char SARA_R5_RESPONSE_ERROR[] = "ERROR\r\n"; const char SARA_R5_RESPONSE_CONNECT[] = "CONNECT\r\n"; +#define SARA_R5_RESPONSE_OK_OR_ERROR NULL // CTRL+Z and ESC ASCII codes for SMS message sends const char ASCII_CTRL_Z = 0x1A; @@ -423,6 +437,40 @@ typedef enum SARA_R5_HTTP_CONTENT_USER_DEFINED } SARA_R5_http_content_types_t; +typedef enum +{ + SARA_R5_MQTT_NV_RESTORE = 0, + SARA_R5_MQTT_NV_SET, + SARA_R5_MQTT_NV_STORE, +} SARA_R5_mqtt_nv_parameter_t; + +typedef enum +{ + SARA_R5_MQTT_PROFILE_CLIENT_ID = 0, + SARA_R5_MQTT_PROFILE_SERVERNAME = 2, + SARA_R5_MQTT_PROFILE_IPADDRESS, + SARA_R5_MQTT_PROFILE_USERNAMEPWD, + SARA_R5_MQTT_PROFILE_QOS = 6, + SARA_R5_MQTT_PROFILE_RETAIN, + SARA_R5_MQTT_PROFILE_TOPIC, + SARA_R5_MQTT_PROFILE_MESSAGE, + SARA_R5_MQTT_PROFILE_INACTIVITYTIMEOUT, + SARA_R5_MQTT_PROFILE_SECURE, +} SARA_R5_mqtt_profile_opcode_t; + +typedef enum +{ + SARA_R5_MQTT_COMMAND_LOGOUT = 0, + SARA_R5_MQTT_COMMAND_LOGIN, + SARA_R5_MQTT_COMMAND_PUBLISH, + SARA_R5_MQTT_COMMAND_PUBLISHFILE, + SARA_R5_MQTT_COMMAND_SUBSCRIBE, + SARA_R5_MQTT_COMMAND_UNSUBSCRIBE, + SARA_R5_MQTT_COMMAND_READ, + SARA_R5_MQTT_COMMAND_PING, + SARA_R5_MQTT_COMMAND_PUBLISHBINARY, +} SARA_R5_mqtt_command_opcode_t; + typedef enum { SARA_R5_PSD_CONFIG_PARAM_PROTOCOL = 0, @@ -455,6 +503,56 @@ typedef enum SARA_R5_PSD_ACTION_DEACTIVATE } SARA_R5_pdp_actions_t; +typedef enum +{ + SARA_R5_SEC_PROFILE_PARAM_CERT_VAL_LEVEL = 0, + SARA_R5_SEC_PROFILE_PARAM_TLS_VER, + SARA_R5_SEC_PROFILE_PARAM_CYPHER_SUITE, + SARA_R5_SEC_PROFILE_PARAM_ROOT_CA, + SARA_R5_SEC_PROFILE_PARAM_HOSTNAME, + SARA_R5_SEC_PROFILE_PARAM_CLIENT_CERT, + SARA_R5_SEC_PROFILE_PARAM_CLIENT_KEY, + SARA_R5_SEC_PROFILE_PARAM_CLIENT_KEY_PWD, + SARA_R5_SEC_PROFILE_PARAM_PSK, + SARA_R5_SEC_PROFILE_PARAM_PSK_IDENT, + SARA_R5_SEC_PROFILE_PARAM_SNI, +} SARA_R5_sec_profile_parameter_t; + +typedef enum +{ + SARA_R5_SEC_PROFILE_CERTVAL_OPCODE_NO = 0, + SARA_R5_SEC_PROFILE_CERTVAL_OPCODE_YESNOURL, + SARA_R5_SEC_PROFILE_CERVTAL_OPCODE_YESURL, + SARA_R5_SEC_PROFILE_CERTVAL_OPCODE_YESURLDATE, +} SARA_R5_sec_profile_certval_op_code_t; + +typedef enum +{ + SARA_R5_SEC_PROFILE_TLS_OPCODE_ANYVER = 0, + SARA_R5_SEC_PROFILE_TLS_OPCODE_VER1_0, + SARA_R5_SEC_PROFILE_TLS_OPCODE_VER1_1, + SARA_R5_SEC_PROFILE_TLS_OPCODE_VER1_2, + SARA_R5_SEC_PROFILE_TLS_OPCODE_VER1_3, +} SARA_R5_sec_profile_tls_op_code_t; + +typedef enum +{ + SARA_R5_SEC_PROFILE_SUITE_OPCODE_PROPOSEDDEFAULT = 0, +} SARA_R5_sec_profile_suite_op_code_t; + +typedef enum +{ + SARA_R5_SEC_MANAGER_OPCODE_IMPORT = 0, +} SARA_R5_sec_manager_opcode_t; + +typedef enum +{ + SARA_R5_SEC_MANAGER_ROOTCA = 0, + SARA_R5_SEC_MANAGER_CLIENT_CERT, + SARA_R5_SEC_MANAGER_CLIENT_KEY, + SARA_R5_SEC_MANAGER_SERVER_CERT +} SARA_R5_sec_manager_parameter_t; + typedef enum { MINIMUM_FUNCTIONALITY = 0, // (disable both transmit and receive RF circuits by deactivating both CS and PS services) @@ -486,7 +584,8 @@ class SARA_R5 : public Print // Debug prints void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. - + void enableAtDebugging(Stream &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 @@ -524,7 +623,8 @@ class SARA_R5 : public Print 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)); + // Direct write/print to cell serial port virtual size_t write(uint8_t c); virtual size_t write(const char *str); @@ -560,7 +660,7 @@ class SARA_R5 : public Print SARA_R5_error_t getUtimeIndication(SARA_R5_utime_urc_configuration_t *config); SARA_R5_error_t setUtimeConfiguration(int32_t offsetNanoseconds = 0, int32_t offsetSeconds = 0); // +UTIMECFG SARA_R5_error_t getUtimeConfiguration(int32_t *offsetNanoseconds, int32_t *offsetSeconds); - + // Network service AT commands int8_t rssi(void); // Receive signal strength SARA_R5_registration_status_t registration(void); @@ -577,6 +677,7 @@ class SARA_R5 : public Print SARA_R5_error_t setAPN(String apn, uint8_t cid = 1, SARA_R5_pdp_type pdpType = PDP_TYPE_IP); // Set the Access Point Name SARA_R5_error_t getAPN(int cid, String *apn, IPAddress *ip); // Return the apn and IP address for the chosen context identifier + SARA_R5_error_t setSimPin(String pin); // SIM // Status report Mode: // Bit States reported @@ -734,12 +835,31 @@ class SARA_R5 : public Print SARA_R5_error_t setHTTPpassword(int profile, String password); // Default: empty string SARA_R5_error_t setHTTPauthentication(int profile, bool authenticate); // Default: no authentication SARA_R5_error_t setHTTPserverPort(int profile, int port); // Default: 80 - SARA_R5_error_t setHTTPsecure(int profile, bool secure); // Default: disabled (HTTP on port 80). Set to true for HTTPS on port 443 + SARA_R5_error_t setHTTPcustomHeader(int profile, String header); // Default: format 0:Content-Type:application/json" + SARA_R5_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 SARA_R5_error_t getHTTPprotocolError(int profile, int *error_class, int *error_code); // Read the most recent HTTP protocol error for this profile SARA_R5_error_t sendHTTPGET(int profile, String path, String responseFilename); SARA_R5_error_t sendHTTPPOSTdata(int profile, String path, String responseFilename, String data, SARA_R5_http_content_types_t httpContentType); - + SARA_R5_error_t sendHTTPPOSTfile(int profile, String path, String responseFilename, String requestFile, SARA_R5_http_content_types_t httpContentType); + + SARA_R5_error_t nvMQTT(SARA_R5_mqtt_nv_parameter_t parameter); + SARA_R5_error_t setMQTTclientId(String clientId); + SARA_R5_error_t setMQTTserver(String serverName, int port); + SARA_R5_error_t setMQTTsecure(bool secure, int secprofile = -1); + SARA_R5_error_t connectMQTT(void); + SARA_R5_error_t disconnectMQTT(void); + SARA_R5_error_t subscribeMQTTtopic(int max_Qos, String topic); + SARA_R5_error_t unsubscribeMQTTtopic(String topic); + SARA_R5_error_t readMQTT(int* pQos, char* pTopic, uint8_t *readDest, int readLength, int *bytesRead); + SARA_R5_error_t getMQTTprotocolError(int *error_code, int *error_code2); + + // Configure security profiles + SARA_R5_error_t resetSecurityProfile(int secprofile); + SARA_R5_error_t configSecurityProfileString(int secprofile, SARA_R5_sec_profile_parameter_t parameter, String value); + SARA_R5_error_t configSecurityProfile(int secprofile, SARA_R5_sec_profile_parameter_t parameter, int value); + SARA_R5_error_t setSecurityManager(SARA_R5_sec_manager_opcode_t opcode, SARA_R5_sec_manager_parameter_t parameter, String name, String data); + // Packet Switched Data // Configure the PDP using +UPSD. See SARA_R5_pdp_configuration_parameter_t for the list of parameters: protocol, APN, username, DNS, etc. SARA_R5_error_t setPDPconfiguration(int profile, SARA_R5_pdp_configuration_parameter_t parameter, int value); // Set parameters in the chosen PSD profile @@ -798,9 +918,12 @@ class SARA_R5 : public Print // TO DO: add full support for file tags. Default tag to USER SARA_R5_error_t getFileContents(String filename, String *contents); // OK for text files. But will fail with binary files (containing \0) on some platforms. SARA_R5_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. + // Append data to a file, delete file first to not appends the data. + SARA_R5_error_t appendFileContents(String filename, String str); + SARA_R5_error_t appendFileContents(String filename, const char *str, int len); SARA_R5_error_t getFileSize(String filename, int *size); SARA_R5_error_t deleteFile(String filename); - + // Functionality SARA_R5_error_t functionality(SARA_R5_functionality_t function = FULL_FUNCTIONALITY); @@ -816,7 +939,9 @@ class SARA_R5 : public Print Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial. bool _printDebug = false; //Flag to print debugging variables - + Stream *_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; @@ -846,6 +971,7 @@ class SARA_R5 : public Print void (*_psdActionRequestCallback)(int, IPAddress); void (*_pingRequestCallback)(int, int, String, IPAddress, int, long); void (*_httpCommandRequestCallback)(int, int, int); + void (*_mqttCommandRequestCallback)(int, int); int _lastSocketProtocol[SARA_R5_NUM_SOCKETS]; // Record the protocol for each socket to avoid having to call querySocketType in parseSocketReadIndication From 4d70bc72634e30954ab6ffef14676f91adedc07a Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Sun, 3 Apr 2022 14:36:58 +0200 Subject: [PATCH 2/8] Add files via upload --- src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index 9915cee..a6f9858 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -102,13 +102,13 @@ const char SARA_R5_COMMAND_IMEI[] = "+CSN"; // IMEI identification const char SARA_R5_COMMAND_IMSI[] = "+CIMI"; // IMSI identification const char SARA_R5_COMMAND_CCID[] = "+CCID"; // SIM CCID const char SARA_R5_COMMAND_REQ_CAP[] = "+GCAP"; // Request capabilities list -/// ### Control and status +// ### Control and status const char SARA_R5_COMMAND_POWER_OFF[] = "+CPWROFF"; // Module switch off const char SARA_R5_COMMAND_FUNC[] = "+CFUN"; // Functionality (reset, etc.) const char SARA_R5_COMMAND_CLOCK[] = "+CCLK"; // Real-time clock const char SARA_R5_COMMAND_AUTO_TZ[] = "+CTZU"; // Automatic time zone update const char SARA_R5_COMMAND_TZ_REPORT[] = "+CTZR"; // Time zone reporting -/// ### Network service +// ### Network service const char SARA_R5_COMMAND_CNUM[] = "+CNUM"; // Subscriber number const char SARA_R5_SIGNAL_QUALITY[] = "+CSQ"; const char SARA_R5_OPERATOR_SELECTION[] = "+COPS"; From ea91e5dd421cf4f98124c51aa87d4f0709531fc6 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Sun, 3 Apr 2022 16:43:36 +0200 Subject: [PATCH 3/8] Avoid recession to allow working in a task. - Avoid nasty recursion in init just use a do - while loop. recursion is almost always a bad thing. - switch the parser to more sticks end tags \r\nXX\r\n - fix an issue in the waiting for response to break a special case where a spurious duplicate first character e.g. \r\r\nXX\r\n would not be detected as successful expected response. this happens e.g. if ATE0\r is sent while echo is enabled you will get ATE0\r\r\nXX\r\n --- ...parkFun_u-blox_SARA-R5_Arduino_Library.cpp | 125 +++++++++--------- src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 13 +- 2 files changed, 66 insertions(+), 72 deletions(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 4badf65..0d11ee5 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -16,7 +16,7 @@ #include -SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitDepth) +SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitTries) { #ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED _softSerial = NULL; @@ -26,7 +26,7 @@ SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitDepth) _resetPin = resetPin; _powerPin = powerPin; _invertPowerPin = false; - _maxInitDepth = maxInitDepth; + _maxInitTries = maxInitTries; _socketListenCallback = NULL; _socketReadCallback = NULL; _socketReadCallbackPlus = NULL; @@ -47,7 +47,6 @@ SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitDepth) _autoTimeZoneForBegin = true; _bufferedPollReentrant = false; _pollReentrant = false; - _currentInitDepth = 0; _saraResponseBacklogLength = 0; } @@ -690,8 +689,8 @@ size_t SARA_R5::write(const char *buffer, size_t size) SARA_R5_error_t SARA_R5::at(void) { SARA_R5_error_t err; - - err = sendCommandWithResponse(NULL, SARA_R5_RESPONSE_OK_OR_ERROR, NULL, + + err = sendCommandWithResponse(NULL, SARA_R5_RESPONSE_OK, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); return err; @@ -705,19 +704,10 @@ SARA_R5_error_t SARA_R5::enableEcho(bool enable) command = sara_r5_calloc_char(strlen(SARA_R5_COMMAND_ECHO) + 2); if (command == NULL) return SARA_R5_ERROR_OUT_OF_MEMORY; - if (enable) - { - sprintf(command, "%s1", SARA_R5_COMMAND_ECHO); - } - else - { - sprintf(command, "%s0", SARA_R5_COMMAND_ECHO); - } - err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, + sprintf(command, "%s%d", SARA_R5_COMMAND_ECHO, enable ? 1 : 0); + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK, NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); - free(command); - return err; } @@ -4628,7 +4618,11 @@ SARA_R5_error_t SARA_R5::appendFileContents(String filename, const char *str, in err = sendCommandWithResponse(command, ">", response, SARA_R5_STANDARD_RESPONSE_TIMEOUT*2); - delay(50); + + unsigned long writeDelay = millis(); + while (millis() < (writeDelay + 50)) + delay(1); //uBlox specification says to wait 50ms after receiving "@" to write data. + if (err == SARA_R5_ERROR_SUCCESS) { if (_printDebug == true) @@ -5025,58 +5019,60 @@ void SARA_R5::modulePowerOn(void) SARA_R5_error_t SARA_R5::init(unsigned long baud, SARA_R5::SARA_R5_init_type_t initType) { - SARA_R5_error_t err; - - //If we have recursively called init too many times, bail - _currentInitDepth++; - if (_currentInitDepth == _maxInitDepth) + int retries = _maxInitTries; + SARA_R5_error_t err = SARA_R5_ERROR_SUCCESS; + + do { if (_printDebug == true) - _debugPort->println(F("init: Module failed to init. Exiting.")); - return (SARA_R5_ERROR_NO_RESPONSE); - } - - if (_printDebug == true) - _debugPort->println(F("init: Begin module init.")); + _debugPort->println(F("init: Begin module init.")); - // There's no 'easy' way to tell if the serial port has already been begun for us. - // We have to assume it has not been begun and so do it here. - // For special cases like Software Serial on ESP32, we need to begin _and_ end the port externally - // _before_ calling the SARA_R5 .begin. - // See SARA-R5_Example2_Identification_ESPSoftwareSerial for more details. - beginSerial(baud); + beginSerial(baud); - if (initType == SARA_R5_INIT_AUTOBAUD) - { - if (_printDebug == true) - _debugPort->println(F("init: Attempting autobaud connection to module.")); - if (autobaud(baud) != SARA_R5_ERROR_SUCCESS) + if (initType == SARA_R5_INIT_AUTOBAUD) + { + if (_printDebug == true) + _debugPort->println(F("init: Attempting autobaud connection to module.")); + + err = autobaud(baud); + if (err != SARA_R5_ERROR_SUCCESS) { + initType = SARA_R5_INIT_RESET; + } + } + else if (initType == SARA_R5_INIT_RESET) { - return init(baud, SARA_R5_INIT_RESET); + if (_printDebug == true) + _debugPort->println(F("init: Power cycling module.")); + + powerOff(); + delay(SARA_R5_POWER_OFF_PULSE_PERIOD); + powerOn(); + delay(2000); + + err = at(); + if (err != SARA_R5_ERROR_SUCCESS) + { + initType = SARA_R5_INIT_AUTOBAUD; + } } - } - else if (initType == SARA_R5_INIT_RESET) - { - if (_printDebug == true) - _debugPort->println(F("init: Power cycling module.")); - powerOff(); - delay(SARA_R5_POWER_OFF_PULSE_PERIOD); - powerOn(); - delay(2000); - if (at() != SARA_R5_ERROR_SUCCESS) + if (err == SARA_R5_ERROR_SUCCESS) { - return init(baud, SARA_R5_INIT_AUTOBAUD); + err = enableEcho(false); // = disableEcho + if (err != SARA_R5_ERROR_SUCCESS) + { + if (_printDebug == true) + _debugPort->println(F("init: Module failed echo test.")); + initType = SARA_R5_INIT_AUTOBAUD; + } } } - - // Use disable echo to test response - err = enableEcho(false); - - if (err != SARA_R5_ERROR_SUCCESS) - { + while ((retries --) && (err != SARA_R5_ERROR_SUCCESS)); + + // we tried but seems failed + if (err != SARA_R5_ERROR_SUCCESS) { if (_printDebug == true) - _debugPort->println(F("init: Module failed echo test.")); - return init(baud, SARA_R5_INIT_AUTOBAUD); + _debugPort->println(F("init: Module failed to init. Exiting.")); + return (SARA_R5_ERROR_NO_RESPONSE); } if (_printDebug == true) @@ -5323,7 +5319,7 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha } else { - responseIndex = 0; + responseIndex = ((responseIndex < responseLen) && (c == expectedResponse[0])) ? 1 : 0; } if ((errorIndex < errorLen) && (c == expectedError[errorIndex])) { @@ -5335,7 +5331,7 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha } else { - errorIndex = 0; + 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(). @@ -5362,7 +5358,6 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha if (found == true) { if (true == _printAtDebug) { - _debugAtPort->print("\r\n"); _debugAtPort->print((error == true) ? expectedError : expectedResponse); } @@ -5446,7 +5441,7 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( } else { - errorIndex = 0; + errorIndex = ((errorIndex < errorLen) && (c == expectedError[0])) ? 1 : 0; } if ((responseIndex < responseLen) && (c == expectedResponse[responseIndex])) { @@ -5457,7 +5452,7 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( } else { - responseIndex = 0; + 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(). @@ -5474,7 +5469,7 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( } } } - + // if (_printDebug == true) // if (printedSomething) // _debugPort->println(); diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index a6f9858..c8996f3 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -185,9 +185,9 @@ const char SARA_R5_SEC_PROFILE[] = "+USECPRF"; const char SARA_R5_SEC_MANAGER[] = "+USECMNG"; // ### Response -const char SARA_R5_RESPONSE_OK[] = "OK\r\n"; -const char SARA_R5_RESPONSE_ERROR[] = "ERROR\r\n"; -const char SARA_R5_RESPONSE_CONNECT[] = "CONNECT\r\n"; +const char SARA_R5_RESPONSE_OK[] = "\r\nOK\r\n"; +const char SARA_R5_RESPONSE_ERROR[] = "\r\nERROR\r\n"; +const char SARA_R5_RESPONSE_CONNECT[] = "\r\nCONNECT\r\n"; #define SARA_R5_RESPONSE_OK_OR_ERROR NULL // CTRL+Z and ESC ASCII codes for SMS message sends @@ -573,8 +573,8 @@ class SARA_R5 : 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 - // maxInitDepth sets the maximum number of initialization attempts (recursive). .init is called by .begin. - SARA_R5(int powerPin = SARA_R5_POWER_PIN, int resetPin = SARA_R5_RESET_PIN, uint8_t maxInitDepth = 9); + // maxInitTries sets the maximum number of initialization attempts. .init is called by .begin. + SARA_R5(int powerPin = SARA_R5_POWER_PIN, int resetPin = SARA_R5_RESET_PIN, uint8_t maxInitTries = 9); // Begin -- initialize module and ensure it's connected #ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED @@ -949,8 +949,7 @@ class SARA_R5 : public Print unsigned long _baud; IPAddress _lastRemoteIP; IPAddress _lastLocalIP; - uint8_t _maxInitDepth; - uint8_t _currentInitDepth = 0; + 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 From f06ae26c6299525c4cf678810845c3300e179785 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Sun, 3 Apr 2022 18:37:59 +0200 Subject: [PATCH 4/8] optimize baud rate handling - optimise times - avoid issues when ruining from from task and with concurrent access when changing baud rate --- src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 0d11ee5..56a9a41 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -914,10 +914,8 @@ SARA_R5_error_t SARA_R5::reset(void) { beginSerial(SARA_R5_DEFAULT_BAUD_RATE); setBaud(_baud); - delay(200); beginSerial(_baud); err = at(); - delay(500); } return init(_baud); } @@ -5022,19 +5020,20 @@ SARA_R5_error_t SARA_R5::init(unsigned long baud, int retries = _maxInitTries; SARA_R5_error_t err = SARA_R5_ERROR_SUCCESS; + beginSerial(baud); + do { if (_printDebug == true) _debugPort->println(F("init: Begin module init.")); - beginSerial(baud); - if (initType == SARA_R5_INIT_AUTOBAUD) { if (_printDebug == true) _debugPort->println(F("init: Attempting autobaud connection to module.")); err = autobaud(baud); + if (err != SARA_R5_ERROR_SUCCESS) { initType = SARA_R5_INIT_RESET; } @@ -5047,6 +5046,7 @@ SARA_R5_error_t SARA_R5::init(unsigned long baud, powerOff(); delay(SARA_R5_POWER_OFF_PULSE_PERIOD); powerOn(); + beginSerial(baud); delay(2000); err = at(); @@ -5806,6 +5806,7 @@ int SARA_R5::hwAvailable(void) void SARA_R5::beginSerial(unsigned long baud) { + delay(100); if (_hardSerial != NULL) { _hardSerial->begin(baud); @@ -5859,7 +5860,6 @@ SARA_R5_error_t SARA_R5::autobaud(unsigned long desiredBaud) { beginSerial(SARA_R5_SUPPORTED_BAUD[b++]); setBaud(desiredBaud); - delay(200); beginSerial(desiredBaud); err = at(); } From 883beab67b50cbbd79fdbf96609999080f3d8b3e Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Sun, 3 Apr 2022 22:20:29 +0200 Subject: [PATCH 5/8] Add files via upload --- ...parkFun_u-blox_SARA-R5_Arduino_Library.cpp | 39 +++++++++++++++++++ src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 2 + 2 files changed, 41 insertions(+) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 56a9a41..08f6fc5 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -1615,6 +1615,45 @@ SARA_R5_error_t SARA_R5::getAPN(int cid, String *apn, IPAddress *ip) return err; } +SARA_R5_error_t SARA_R5::getSimStatus(String* code) +{ + SARA_R5_error_t err; + char *command; + char *response; + command = sara_r5_calloc_char(strlen(SARA_R5_COMMAND_SIMPIN) + 2); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s?", SARA_R5_COMMAND_SIMPIN); + response = sara_r5_calloc_char(minimumResponseAllocation); + if (response == NULL) + { + free(command); + return SARA_R5_ERROR_OUT_OF_MEMORY; + } + err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, + response, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + + if (err == SARA_R5_ERROR_SUCCESS) + { + int scanned = 0; + char c[16]; + char *searchPtr = strstr(response, "+CPIN: "); + if (searchPtr != NULL) + scanned = sscanf(searchPtr, "+CPIN: %s\r\n", c); + if (scanned == 1) + { + *code = c; + } + else + err = SARA_R5_ERROR_UNEXPECTED_RESPONSE; + } + + free(command); + free(response); + + return err; +} + SARA_R5_error_t SARA_R5::setSimPin(String pin) { SARA_R5_error_t err; diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index c8996f3..ca758e3 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -677,7 +677,9 @@ class SARA_R5 : public Print SARA_R5_error_t setAPN(String apn, uint8_t cid = 1, SARA_R5_pdp_type pdpType = PDP_TYPE_IP); // Set the Access Point Name SARA_R5_error_t getAPN(int cid, String *apn, IPAddress *ip); // Return the apn and IP address for the chosen context identifier + SARA_R5_error_t getSimStatus(String* code); SARA_R5_error_t setSimPin(String pin); + // SIM // Status report Mode: // Bit States reported From 0b589449da6f853a92c9d7136de60f3b7b05a1c9 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Mon, 4 Apr 2022 22:53:20 +0200 Subject: [PATCH 6/8] Add files via upload registration callbacks and EPS status --- ...parkFun_u-blox_SARA-R5_Arduino_Library.cpp | 83 +++++++++++++++++-- src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 14 +++- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 08f6fc5..7dc6cf9 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -37,6 +37,8 @@ SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitTries) _pingRequestCallback = NULL; _httpCommandRequestCallback = NULL; _mqttCommandRequestCallback = NULL; + _registrationCallback = NULL; + _epsRegistrationCallback = NULL; _debugAtPort = NULL; _debugPort = NULL; _printDebug = false; @@ -566,6 +568,41 @@ bool SARA_R5::processURCEvent(const char *event) return true; } } + { // URC: +A + int status = 0; + unsigned int lac = 0, ci = 0, Act = 0; + int scanNum = sscanf(event, "+CREG: %d,\"%4x\",\"%4x\",%d", &status, &lac, &ci, &Act); + if (scanNum == 4) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: CREG")); + + if (_registrationCallback != NULL) + { + _registrationCallback((SARA_R5_registration_status_t)status, lac, ci, Act); + } + + return true; + } + } + { // URC: +CEREG + int status = 0; + unsigned int tac = 0, ci = 0, Act = 0; + int scanNum = sscanf(event, "+CEREG: %d,\"%4x\",\"%4x\",%d", &status, &tac, &ci, &Act); + if (scanNum == 4) + { + if (_printDebug == true) + _debugPort->println(F("processReadEvent: CEREG")); + + if (_epsRegistrationCallback != NULL) + { + _epsRegistrationCallback((SARA_R5_registration_status_t)status, tac, ci, Act); + } + + return true; + } + } + return false; } @@ -670,6 +707,33 @@ void SARA_R5::setMQTTCommandCallback(void (*mqttCommandRequestCallback)(int comm _mqttCommandRequestCallback = mqttCommandRequestCallback; } +SARA_R5_error_t SARA_R5::setRegistrationCallback(void (*registrationCallback)(SARA_R5_registration_status_t status, unsigned int lac, unsigned int ci, int Act)) +{ + _registrationCallback = registrationCallback; + + char *command = sara_r5_calloc_char(strlen(SARA_R5_REGISTRATION_STATUS) + 3); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", SARA_R5_REGISTRATION_STATUS, 2/*enable URC with location*/); + SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, + NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} + +SARA_R5_error_t SARA_R5::setEpsRegistrationCallback(void (*registrationCallback)(SARA_R5_registration_status_t status, unsigned int tac, unsigned int ci, int Act)) +{ + _epsRegistrationCallback = registrationCallback; + + char *command = sara_r5_calloc_char(strlen(SARA_R5_EPSREGISTRATION_STATUS) + 3); + if (command == NULL) + return SARA_R5_ERROR_OUT_OF_MEMORY; + sprintf(command, "%s=%d", SARA_R5_EPSREGISTRATION_STATUS, 2/*enable URC with location*/); + SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, + NULL, SARA_R5_STANDARD_RESPONSE_TIMEOUT); + free(command); + return err; +} size_t SARA_R5::write(uint8_t c) { @@ -1353,17 +1417,17 @@ int8_t SARA_R5::rssi(void) return rssi; } -SARA_R5_registration_status_t SARA_R5::registration(void) +SARA_R5_registration_status_t SARA_R5::registration(bool eps) { char *command; char *response; SARA_R5_error_t err; int status; - - command = sara_r5_calloc_char(strlen(SARA_R5_REGISTRATION_STATUS) + 2); + const char* tag = eps ? SARA_R5_EPSREGISTRATION_STATUS : SARA_R5_REGISTRATION_STATUS; + command = sara_r5_calloc_char(strlen(tag) + 3); if (command == NULL) return SARA_R5_REGISTRATION_INVALID; - sprintf(command, "%s?", SARA_R5_REGISTRATION_STATUS); + sprintf(command, "%s?", tag); response = sara_r5_calloc_char(minimumResponseAllocation); if (response == NULL) @@ -1381,11 +1445,14 @@ SARA_R5_registration_status_t SARA_R5::registration(void) free(response); return SARA_R5_REGISTRATION_INVALID; } - + int scanned = 0; - char *searchPtr = strstr(response, "+CREG: "); - if (searchPtr != NULL) - scanned = sscanf(searchPtr, "+CREG: %*d,%d", &status); + const char *startTag = eps ? "+CEREG: " : "+CREG: "; + char *searchPtr = strstr(response, startTag); + if (searchPtr != NULL) { + const char *format = eps ? "+CEREG: %*d,%d" : "+CREG: %*d,%d"; + scanned = sscanf(searchPtr, format, &status); + } if (scanned != 1) status = SARA_R5_REGISTRATION_INVALID; diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index ca758e3..3463ea9 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -113,6 +113,7 @@ const char SARA_R5_COMMAND_CNUM[] = "+CNUM"; // Subscriber number const char SARA_R5_SIGNAL_QUALITY[] = "+CSQ"; const char SARA_R5_OPERATOR_SELECTION[] = "+COPS"; const char SARA_R5_REGISTRATION_STATUS[] = "+CREG"; +const char SARA_R5_EPSREGISTRATION_STATUS[] = "+CEREG"; const char SARA_R5_READ_OPERATOR_NAMES[] = "+COPN"; const char SARA_R5_COMMAND_MNO[] = "+UMNOPROF"; // MNO (mobile network operator) Profile // ### SIM @@ -185,8 +186,8 @@ const char SARA_R5_SEC_PROFILE[] = "+USECPRF"; const char SARA_R5_SEC_MANAGER[] = "+USECMNG"; // ### Response -const char SARA_R5_RESPONSE_OK[] = "\r\nOK\r\n"; -const char SARA_R5_RESPONSE_ERROR[] = "\r\nERROR\r\n"; +const char SARA_R5_RESPONSE_OK[] = "\nOK\r\n"; +const char SARA_R5_RESPONSE_ERROR[] = "\nERROR\r\n"; const char SARA_R5_RESPONSE_CONNECT[] = "\r\nCONNECT\r\n"; #define SARA_R5_RESPONSE_OK_OR_ERROR NULL @@ -624,6 +625,10 @@ class SARA_R5 : public Print 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)); + SARA_R5_error_t setRegistrationCallback(void (*registrationCallback)(SARA_R5_registration_status_t status, + unsigned int lac, unsigned int ci, int Act)); + SARA_R5_error_t setEpsRegistrationCallback(void (*epsRegistrationCallback)(SARA_R5_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); @@ -663,7 +668,7 @@ class SARA_R5 : public Print // Network service AT commands int8_t rssi(void); // Receive signal strength - SARA_R5_registration_status_t registration(void); + SARA_R5_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 @@ -973,6 +978,9 @@ class SARA_R5 : public Print void (*_pingRequestCallback)(int, int, String, IPAddress, int, long); void (*_httpCommandRequestCallback)(int, int, int); void (*_mqttCommandRequestCallback)(int, int); + void (*_registrationCallback)(SARA_R5_registration_status_t status, unsigned int lac, unsigned int ci, int Act); + void (*_epsRegistrationCallback)(SARA_R5_registration_status_t status, unsigned int tac, unsigned int ci, int Act); + int _lastSocketProtocol[SARA_R5_NUM_SOCKETS]; // Record the protocol for each socket to avoid having to call querySocketType in parseSocketReadIndication From f3be6e0bf01ca9e28eb401e02e5b529b66b0ac30 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Tue, 5 Apr 2022 18:26:31 +0200 Subject: [PATCH 7/8] Add files via upload --- ...parkFun_u-blox_SARA-R5_Arduino_Library.cpp | 63 +++++++++++++------ src/SparkFun_u-blox_SARA-R5_Arduino_Library.h | 1 + 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 7dc6cf9..9dbcf36 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -50,36 +50,59 @@ SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitTries) _bufferedPollReentrant = false; _pollReentrant = false; _saraResponseBacklogLength = 0; + _saraRXBuffer = NULL; + _pruneBuffer = NULL; + _saraResponseBacklog = NULL; +} + +~SARA_R5() { + if (NULL != _saraRXBuffer) { + delete [] _saraRXBuffer; + _saraRXBuffer = NULL; + } + if (NULL != _pruneBuffer) { + delete [] _pruneBuffer; + _pruneBuffer = NULL; + } + if (NULL != _saraResponseBacklog) { + delete [] _saraResponseBacklog; + _saraResponseBacklog = NULL; + } } #ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED bool SARA_R5::begin(SoftwareSerial &softSerial, unsigned long baud) { - _saraRXBuffer = new char[_RXBuffSize]; - if (_saraRXBuffer == NULL) - { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _saraRXBuffer!")); - return false; + if (NULL == _saraRXBuffer) + _saraRXBuffer = new char[_RXBuffSize]; + if (NULL == _saraRXBuffer) + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _saraRXBuffer!")); + return false; + } } memset(_saraRXBuffer, 0, _RXBuffSize); - _pruneBuffer = new char[_RXBuffSize]; - if (_pruneBuffer == NULL) - { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _pruneBuffer!")); - return false; + if (NULL == _pruneBuffer) { + _pruneBuffer = new char[_RXBuffSize]; + if (NULL == _pruneBuffer) { + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _pruneBuffer!")); + return false; + } } memset(_pruneBuffer, 0, _RXBuffSize); - - _saraResponseBacklog = new char[_RXBuffSize]; - if (_saraResponseBacklog == NULL) - { - if (_printDebug == true) - _debugPort->println(F("begin: not enough memory for _saraResponseBacklog!")); - return false; - } + + if (NULL == _saraResponseBacklog) { + saraResponseBacklog = new char[_RXBuffSize]; + if (NULL == _saraResponseBacklog) { + { + if (_printDebug == true) + _debugPort->println(F("begin: not enough memory for _saraResponseBacklog!")); + return false; + } memset(_saraResponseBacklog, 0, _RXBuffSize); SARA_R5_error_t err; diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index 3463ea9..ab2cd05 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -577,6 +577,7 @@ class SARA_R5 : public Print // maxInitTries sets the maximum number of initialization attempts. .init is called by .begin. SARA_R5(int powerPin = SARA_R5_POWER_PIN, int resetPin = SARA_R5_RESET_PIN, uint8_t maxInitTries = 9); + ~SARA_R5(); // Begin -- initialize module and ensure it's connected #ifdef SARA_R5_SOFTWARE_SERIAL_ENABLED bool begin(SoftwareSerial &softSerial, unsigned long baud = 9600); From f37e0db2d7ab0c91b0d4bce4b5e0fb227a5ac161 Mon Sep 17 00:00:00 2001 From: Michael Ammann Date: Tue, 5 Apr 2022 18:32:20 +0200 Subject: [PATCH 8/8] avoid leak do not reallocate buffers in begin, but delete them in the destructor. --- src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 9dbcf36..784f4b9 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -55,7 +55,7 @@ SARA_R5::SARA_R5(int powerPin, int resetPin, uint8_t maxInitTries) _saraResponseBacklog = NULL; } -~SARA_R5() { +SARA_R5::~SARA_R5(void) { if (NULL != _saraRXBuffer) { delete [] _saraRXBuffer; _saraRXBuffer = NULL;