diff --git a/.github/workflows/compile-sketch.yml b/.github/workflows/compile-sketch.yml new file mode 100644 index 0000000..b3b9163 --- /dev/null +++ b/.github/workflows/compile-sketch.yml @@ -0,0 +1,109 @@ +name: Compile Sketch + +on: + # - push + - pull_request + + +jobs: + compile-sketch: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + board: + # ATmega2560 + # https://github.com/arduino/ArduinoCore-avr/blob/master/boards.txt + - fqbn: arduino:avr:mega + platforms: | + - name: arduino:avr + source-url: https://downloads.arduino.cc/packages/package_index.json + + # ESP32 + # https://github.com/espressif/arduino-esp32/blob/master/boards.txt + - fqbn: esp32:esp32:esp32 + platforms: | + - name: esp32:esp32 + source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + + # ESP32-S2 + # https://github.com/espressif/arduino-esp32/blob/master/boards.txt + - fqbn: esp32:esp32:esp32s2 + platforms: | + - name: esp32:esp32 + source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + + # ESP32-C3 + # https://github.com/espressif/arduino-esp32/blob/master/boards.txt + - fqbn: esp32:esp32:esp32c3 + platforms: | + - name: esp32:esp32 + source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + + # Artemis / Apollo3 + # https://github.com/sparkfun/Arduino_Apollo3/blob/main/boards.txt + - fqbn: SparkFun:apollo3:sfe_artemis_atp + platforms: | + - name: SparkFun:apollo3 + source-url: https://raw.githubusercontent.com/sparkfun/Arduino_Apollo3/master/package_sparkfun_apollo3_index.json + + # ESP8266 + # https://github.com/esp8266/Arduino/blob/master/boards.txt + - fqbn: esp8266:esp8266:thingdev + platforms: | + - name: esp8266:esp8266 + source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json + + # SAMD21 + # https://github.com/arduino/ArduinoCore-samd/blob/master/boards.txt + - fqbn: arduino:samd:mkr1000 + platforms: | + - name: arduino:samd + # source-url: https://downloads.arduino.cc/packages/package_index.json + + # Nano BLE 33 / nRF52840 + # https://github.com/arduino/ArduinoCore-mbed/blob/master/boards.txt + - fqbn: arduino:mbed:nano33ble + platforms: | + - name: arduino:mbed + # source-url: https://downloads.arduino.cc/packages/package_index.json + + # RP2040 + # https://github.com/arduino/ArduinoCore-mbed/blob/master/boards.txt + - fqbn: rp2040:rp2040:sparkfun_promicrorp2040 + platforms: | + - name: rp2040:rp2040 + source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + + # STM32 + # https://github.com/arduino/ArduinoCore-mbed/blob/master/boards.txt + - fqbn: STMicroelectronics:stm32:GenF4 + platforms: | + - name: STMicroelectronics:stm32 + source-url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Branch name + run: echo running on branch ${GITHUB_REF##*/} + + - name: Compile Sketch + uses: arduino/compile-sketches@v1 + with: + platforms: ${{ matrix.board.platforms }} + fqbn: ${{ matrix.board.fqbn }} + libraries: | + - source-path: ./ + sketch-paths: | + - examples/SARA-R5_Example10_SocketPingPong + enable-warnings-report: true + enable-deltas-report: true + # verbose: true + + # outputs: + # report-artifact-name: ${{ steps.report-artifact-name.outputs.report-artifact-name }} + diff --git a/library.properties b/library.properties index 922f7bb..49ad7bb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox SARA-R5 Arduino Library -version=1.1.1 +version=1.1.2 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud

diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp index 68ff5f2..077e7a3 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp @@ -174,7 +174,7 @@ bool SARA_R5::begin(HardwareSerial &hardSerial, unsigned long baud) //Calling this function with nothing sets the debug port to Serial //You can also call it with other streams like Serial1, SerialUSB, etc. -void SARA_R5::enableDebugging(Stream &debugPort) +void SARA_R5::enableDebugging(Print &debugPort) { _debugPort = &debugPort; _printDebug = true; @@ -182,7 +182,7 @@ void SARA_R5::enableDebugging(Stream &debugPort) //Calling this function with nothing sets the debug port to Serial //You can also call it with other streams like Serial1, SerialUSB, etc. -void SARA_R5::enableAtDebugging(Stream &debugPort) +void SARA_R5::enableAtDebugging(Print &debugPort) { _debugAtPort = &debugPort; _printAtDebug = true; @@ -246,6 +246,8 @@ bool SARA_R5::bufferedPoll(void) c = '0'; // Convert any NULLs to ASCII Zeros _saraRXBuffer[avail++] = c; timeIn = millis(); + } else { + yield(); } } @@ -546,10 +548,15 @@ bool SARA_R5::processURCEvent(const char *event) { // URC: +UUMQTTC (HTTP Command Result) int command, result; int scanNum; - + int qos = -1; + String topic; scanNum = sscanf(event, "+UUMQTTC: %d,%d", &command, &result); - - if (scanNum == 2) + if ((scanNum == 2) && (command == SARA_R5_MQTT_COMMAND_SUBSCRIBE)) { + char topicC[100] = ""; + scanNum = sscanf(event, "+UUMQTTC: %*d,%*d,%d,\"%[^\"]\"", &qos, topicC); + topic = topicC; + } + if ((scanNum == 2) || (scanNum == 4)) { if (_printDebug == true) _debugPort->println(F("processReadEvent: MQTT command result")); @@ -673,6 +680,8 @@ bool SARA_R5::poll(void) { c = readChar(); _saraRXBuffer[avail++] = c; + } else { + yield(); } } @@ -1615,14 +1624,12 @@ SARA_R5_error_t SARA_R5::setAPN(String apn, uint8_t cid, SARA_R5_pdp_type pdpTyp } // Return the Access Point Name and IP address for the chosen context identifier -SARA_R5_error_t SARA_R5::getAPN(int cid, String *apn, IPAddress *ip) +SARA_R5_error_t SARA_R5::getAPN(int cid, String *apn, IPAddress *ip, SARA_R5_pdp_type* pdpType) { SARA_R5_error_t err; char *command; char *response; - int ipOctets[4]; - int rcid = -1; - + if (cid > SARA_R5_NUM_PDP_CONTEXT_IDENTIFIERS) return SARA_R5_ERROR_ERROR; @@ -1646,72 +1653,47 @@ SARA_R5_error_t SARA_R5::getAPN(int cid, String *apn, IPAddress *ip) // Example: // +CGDCONT: 0,"IP","payandgo.o2.co.uk","0.0.0.0",0,0,0,0,0,0,0,0,0,0 // +CGDCONT: 1,"IP","payandgo.o2.co.uk.mnc010.mcc234.gprs","10.160.182.234",0,0,0,2,0,0,0,0,0,0 - + int rcid = -1; char *searchPtr = response; bool keepGoing = true; while (keepGoing == true) { - int apnLen = 0; int scanned = 0; // Find the first/next occurrence of +CGDCONT: searchPtr = strstr(searchPtr, "+CGDCONT: "); if (searchPtr != NULL) { + char strPdpType[10]; + char strApn[128]; + int ipOct[4]; + searchPtr += strlen("+CGDCONT: "); // Point to the cid - rcid = (*searchPtr) - '0'; // Get the first/only digit of cid - searchPtr++; - if (*searchPtr != ',') // Get the second digit of cid - if there is one - { - rcid *= 10; - rcid += (*searchPtr) - '0'; - } - if (_printDebug == true) - { - _debugPort->print(F("getAPN: cid is ")); - _debugPort->println(rcid); - } - if (rcid == cid) // If we have a match - { - // Search to the third double-quote - for (int i = 0; i < 3; i++) + scanned = sscanf(searchPtr, "%d,\"%[^\"]\",\"%[^\"]\",\"%d.%d.%d.%d", + &rcid, strPdpType, strApn, + &ipOct[0], &ipOct[1], &ipOct[2], &ipOct[3]); + if ((scanned == 7) && (rcid == cid)) { + if (apn) *apn = strApn; + for (int o = 0; ip && (o < 4); o++) { - searchPtr = strchr(++searchPtr, '\"'); + (*ip)[o] = (uint8_t)ipOct[o]; } - if (searchPtr != NULL) - { - // Fill in the APN: - //searchPtr = strchr(searchPtr, '\"'); // Move to first quote - while ((*(++searchPtr) != '\"') && (*searchPtr != '\0')) - { - apn->concat(*(searchPtr)); - apnLen++; - } - // Now get the IP: - if (searchPtr != NULL) - { - scanned = sscanf(searchPtr, "\",\"%d.%d.%d.%d\"", - &ipOctets[0], &ipOctets[1], &ipOctets[2], &ipOctets[3]); - if (scanned == 4) - { - for (int octet = 0; octet < 4; octet++) - { - (*ip)[octet] = (uint8_t)ipOctets[octet]; - } - } - } + if (pdpType) { + *pdpType = (0 == strcmp(strPdpType, "IPV4V6")) ? PDP_TYPE_IPV4V6 : + (0 == strcmp(strPdpType, "IPV6")) ? PDP_TYPE_IPV6 : + (0 == strcmp(strPdpType, "IP")) ? PDP_TYPE_IP : + PDP_TYPE_INVALID; } - } - else // We don't have a match so let's clear the APN and IP address - { - *apn = ""; - *ip = {0, 0, 0, 0}; + keepGoing = false; } } - if ((rcid == cid) || (searchPtr == NULL) || (*searchPtr == '\0')) // Stop searching + else // We don't have a match so let's clear the APN and IP address { - keepGoing = false; - } + if (apn) *apn = ""; + if (pdpType) *pdpType = PDP_TYPE_INVALID; + if (ip) *ip = {0, 0, 0, 0}; + keepGoing = false; + } } } else @@ -1752,7 +1734,8 @@ SARA_R5_error_t SARA_R5::getSimStatus(String* code) scanned = sscanf(searchPtr, "+CPIN: %s\r\n", c); if (scanned == 1) { - *code = c; + if(code) + *code = c; } else err = SARA_R5_ERROR_UNEXPECTED_RESPONSE; @@ -4076,7 +4059,7 @@ 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); + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + 16 + topic.length()); 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()); @@ -4090,7 +4073,7 @@ 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); + command = sara_r5_calloc_char(strlen(SARA_R5_MQTT_COMMAND) + 16 + topic.length()); 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()); @@ -4099,8 +4082,8 @@ SARA_R5_error_t SARA_R5::unsubscribeMQTTtopic(String topic) free(command); return err; } - -SARA_R5_error_t SARA_R5::readMQTT(int* pQos, char* pTopic, uint8_t *readDest, int readLength, int *bytesRead) + +SARA_R5_error_t SARA_R5::readMQTT(int* pQos, String* pTopic, uint8_t *readDest, int readLength, int *bytesRead) { char *command; char *response; @@ -4148,8 +4131,8 @@ SARA_R5_error_t SARA_R5::readMQTT(int* pQos, char* pTopic, uint8_t *readDest, in // 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) + scanNum = sscanf(searchPtr, "+UMQTTC: 6,%d,%d,%d,\"%*[^\"]\",%d,\"", pQos, &total_length, &topic_length, &data_length); + if (scanNum != 4) { if (_printDebug == true) { @@ -4160,13 +4143,17 @@ SARA_R5_error_t SARA_R5::readMQTT(int* pQos, char* pTopic, uint8_t *readDest, in 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); - + if (pTopic) { + searchPtr[topic_length+1] = '\0'; // zero terminate + *pTopic = searchPtr+1; + searchPtr[topic_length+1] = '\"'; // restore + } + searchPtr = strstr(searchPtr + topic_length + 2, "\""); + if (readDest) { + *bytesRead = (data_length > readLength) ? readLength : data_length; + memcpy(readDest, searchPtr+1, *bytesRead); + } free(command); free(response); @@ -5495,6 +5482,8 @@ SARA_R5_error_t SARA_R5::waitForResponse(const char *expectedResponse, const cha else _saraResponseBacklog[_saraResponseBacklogLength++] = c; } + } else { + yield(); } } @@ -5616,6 +5605,8 @@ SARA_R5_error_t SARA_R5::sendCommandWithResponse( else _saraResponseBacklog[_saraResponseBacklogLength++] = c; } + } else { + yield(); } } @@ -5681,6 +5672,8 @@ void SARA_R5::sendCommand(const char *command, bool at) c = '0'; _saraResponseBacklog[_saraResponseBacklogLength++] = c; timeIn = millis(); + } else { + yield(); } } } @@ -6068,6 +6061,9 @@ void SARA_R5::pruneBacklog() || (strstr(event, "+UUSIMSTAT:") != NULL) || (strstr(event, "+UUPSDA:") != NULL) || (strstr(event, "+UUPING:") != NULL) + || (strstr(event, "+UUMQTTC:") != NULL) + || (strstr(event, "+UUCREG:") != NULL) + || (strstr(event, "+UUCEREG:") != NULL) || (strstr(event, "+UUHTTPCR:") != NULL)) { strcat(_pruneBuffer, event); // The URCs are all readable text so using strcat is OK diff --git a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h index d4ccbdc..8ac323d 100644 --- a/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h +++ b/src/SparkFun_u-blox_SARA-R5_Arduino_Library.h @@ -585,8 +585,8 @@ class SARA_R5 : public Print bool begin(HardwareSerial &hardSerial, unsigned long baud = 9600); // 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. + void enableDebugging(Print &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. + void enableAtDebugging(Print &debugPort = Serial); //Turn on AT debug printing. If user doesn't specify then Serial will be used. // Invert the polarity of the power pin - if required // Normally the SARA's power pin is pulled low and released to toggle the power @@ -681,7 +681,7 @@ class SARA_R5 : public Print PDP_TYPE_IPV6 = 3 } SARA_R5_pdp_type; 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 getAPN(int cid, String *apn, IPAddress *ip, SARA_R5_pdp_type* pdpType = NULL); // 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); @@ -859,7 +859,7 @@ class SARA_R5 : public Print 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 readMQTT(int* pQos, String* pTopic, uint8_t *readDest, int readLength, int *bytesRead); SARA_R5_error_t getMQTTprotocolError(int *error_code, int *error_code2); // Configure security profiles @@ -945,9 +945,9 @@ class SARA_R5 : public Print SoftwareSerial *_softSerial; #endif - Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial. + Print *_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. + Print *_debugAtPort; //The stream to send debug messages to if enabled. Usually Serial. bool _printAtDebug = false; //Flag to print debugging variables int _powerPin;