diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index ff8b3839..9bcd8314 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -35,7 +35,6 @@ jobs: - name: MKRNB - name: MKRWAN - name: Arduino_Cellular - - name: Blues Wireless Notecard SKETCH_PATHS: | - examples/ConnectionHandlerDemo - examples/CheckInternetAvailabilityDemo @@ -113,8 +112,6 @@ jobs: platforms: | # Install Arduino SAMD Boards via Boards Manager - name: arduino:samd - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - board: platform-name: arduino:mbed platforms: | @@ -123,53 +120,21 @@ jobs: # Overwrite the Arduino mbed-Enabled Boards release version with version from the tip of the default branch (located in local path because of the need to first install ArduinoCore-API) - source-path: extras/ArduinoCore-mbed name: arduino:mbed - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - - board: - platform-name: arduino:mbed_portenta - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - - board: - platform-name: arduino:mbed_nano - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - - board: - platform-name: arduino:mbed_nicla - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - - board: - platform-name: arduino:mbed_opta - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - - board: - platform-name: arduino:mbed_giga - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - - board: - platform-name: arduino:mbed_edge - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - board: platform-name: arduino:renesas_portenta platforms: | # Install Arduino Renesas portenta Boards via Boards Manager - name: arduino:renesas_portenta - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - board: platform-name: arduino:renesas_uno platforms: | # Install Arduino Renesas uno Boards via Boards Manager - name: arduino:renesas_uno - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - board: platform-name: arduino:esp32 platforms: | # Install Arduino ESP32 Boards via Boards Manager - name: arduino:esp32 - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - board: platform-name: esp8266:esp8266 platforms: | @@ -183,16 +148,12 @@ jobs: # Install ESP32 platform via Boards Manager - name: esp32:esp32 source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard - board: platform-name: rp2040:rp2040 platforms: | # Install rp2040 platform via Boards Manager - name: rp2040:rp2040 source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json - sketch-paths: | - - examples/ConnectionHandlerDemo-Notecard steps: - uses: actions/checkout@v5 diff --git a/README.md b/README.md index 139db7f9..40f9ee09 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,13 @@ Library for handling and managing network connections by providing keep-alive fu * **5G**: [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413) * **LoRa**: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) * **Ethernet**: [`Portenta H7`](https://store.arduino.cc/products/portenta-h7) + [`Vision Shield Ethernet`](https://store.arduino.cc/products/arduino-portenta-vision-shield-ethernet), [`Max Carrier`](https://store.arduino.cc/products/portenta-max-carrier), [`Breakout`](https://store.arduino.cc/products/arduino-portenta-breakout), [`Portenta Machine Control`](https://store.arduino.cc/products/arduino-portenta-machine-control), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`Portenta C33`](https://store.arduino.cc/products/portenta-c33) + [`Vision Shield Ethernet`](https://store.arduino.cc/products/arduino-portenta-vision-shield-ethernet) -* **Notecard**: [Provides Cellular/LoRa/Satellite/Wi-Fi to any modern board/architecture](examples/ConnectionHandlerDemo-Notecard/README.md) ### How-to-use ```C++ #include /* ... */ -#if defined(BOARD_HAS_NOTECARD) -NotecardConnectionHandler conMan("com.domain.you:product"); -#elif defined(BOARD_HAS_ETHERNET) +#if defined(BOARD_HAS_ETHERNET) EthernetConnectionHandler conMan; #elif defined(BOARD_HAS_WIFI) WiFiConnectionHandler conMan("SECRET_WIFI_SSID", "SECRET_WIFI_PASS"); diff --git a/examples/ConnectionHandlerDemo-Notecard/ConnectionHandlerDemo-Notecard.ino b/examples/ConnectionHandlerDemo-Notecard/ConnectionHandlerDemo-Notecard.ino deleted file mode 100644 index e4183618..00000000 --- a/examples/ConnectionHandlerDemo-Notecard/ConnectionHandlerDemo-Notecard.ino +++ /dev/null @@ -1,144 +0,0 @@ -/* SECRET_ fields are in `arduino_secrets.h` (included below) - * - * If using a Host + Notecard connected over I2C you'll need a - * NotecardConnectionHandler object as follows: - * - * NotecardConnectionHandler conMan(NOTECARD_PRODUCT_UID); - * - * If using a Host + Notecard connected over Serial you'll need a - * NotecardConnectionHandler object as follows: - * - * NotecardConnectionHandler conMan(NOTECARD_PRODUCT_UID, UART_INTERFACE); - */ - -#include // MUST include this first to enable Notecard support -#include - -#include "arduino_secrets.h" - -/* Uncomment the following line to use this example in a manner that is more - * compatible with LoRa. - */ -// #define USE_NOTE_LORA - -#ifndef USE_NOTE_LORA -#define CONN_TOGGLE_MS 60000 -#else -#define CONN_TOGGLE_MS 300000 -#endif - -/* The Notecard can provide connectivity to almost any board via ESLOV (I2C) - * or UART. An empty string (or the default value provided below) will not - * override the Notecard's existing configuration. - * Learn more at: https://dev.blues.io */ -#define NOTECARD_PRODUCT_UID "com.domain.you:product" - -/* Uncomment the following line to use the Notecard over UART */ -// #define UART_INTERFACE Serial1 - -#ifndef UART_INTERFACE -NotecardConnectionHandler conMan(NOTECARD_PRODUCT_UID); -#else -NotecardConnectionHandler conMan(NOTECARD_PRODUCT_UID, UART_INTERFACE); -#endif - -bool attemptConnect = false; -uint32_t lastConnToggleMs = 0; - -void setup() { - /* Initialize serial debug port and wait up to 5 seconds for port to open */ - Serial.begin(9600); - for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } - - /* Set the debug message level: - * - DBG_ERROR: Only show error messages - * - DBG_WARNING: Show warning and error messages - * - DBG_INFO: Show info, warning, and error messages - * - DBG_DEBUG: Show debug, info, warning, and error messages - * - DBG_VERBOSE: Show all messages - */ - setDebugMessageLevel(DBG_INFO); - - /* Add callbacks to the ConnectionHandler object to get notified of network - * connection events. */ - conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect); - conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect); - conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError); - - /* First call to `check()` initializes the connection to the Notecard. While - * not strictly necessary, it cleans up the logging from this application. - */ - conMan.check(); - -#ifndef USE_NOTE_LORA - /* Set the Wi-Fi credentials for the Notecard */ - String ssid = SECRET_WIFI_SSID; - if (ssid.length() > 0 && ssid != "NETWORK NAME") { - conMan.setWiFiCredentials(SECRET_WIFI_SSID, SECRET_WIFI_PASS); - } -#else - conMan.setNotehubPollingInterval(720); // poll twice per day -#endif - - /* Confirm Interface */ - Serial.print("Network Adapter Interface: "); - if (NetworkAdapter::NOTECARD == conMan.getInterface()) { - Serial.print("Notecard "); - Serial.print(conMan.getNotecardUid()); -#ifndef UART_INTERFACE - Serial.println(" (via I2C)"); -#else - Serial.println(" (via UART)"); -#endif - } else { - Serial.println("ERROR: Unexpected Interface"); - while(1); - } - - /* Display the Arduino IoT Cloud Device ID */ - displayCachedDeviceId(); -} - -void loop() { - /* Toggle the connection every `CONN_TOGGLE_MS` milliseconds */ - if ((millis() - lastConnToggleMs) > CONN_TOGGLE_MS) { - Serial.println("Toggling connection..."); - if (attemptConnect) { - displayCachedDeviceId(); - conMan.connect(); - } else { - // Flush any queued Notecard requests before disconnecting - conMan.initiateNotehubSync(NotecardConnectionHandler::SyncType::Outbound); - conMan.disconnect(); - } - attemptConnect = !attemptConnect; - lastConnToggleMs = millis(); - } - - /* The following code keeps on running connection workflows on our - * ConnectionHandler object, hence allowing reconnection in case of failure - * and notification of connect/disconnect event if enabled (see - * addConnectCallback/addDisconnectCallback) NOTE: any use of delay() within - * the loop or methods called from it will delay the execution of .update(), - * which might not guarantee the correct functioning of the ConnectionHandler - * object. - */ - conMan.check(); -} - -void displayCachedDeviceId() { - Serial.print("Cached Arduino IoT Cloud Device ID: "); - Serial.println(conMan.getDeviceId()); -} - -void onNetworkConnect() { - Serial.println(">>>> CONNECTED to network"); -} - -void onNetworkDisconnect() { - Serial.println(">>>> DISCONNECTED from network"); -} - -void onNetworkError() { - Serial.println(">>>> ERROR"); -} diff --git a/examples/ConnectionHandlerDemo-Notecard/README.md b/examples/ConnectionHandlerDemo-Notecard/README.md deleted file mode 100644 index 7f90a7cf..00000000 --- a/examples/ConnectionHandlerDemo-Notecard/README.md +++ /dev/null @@ -1,71 +0,0 @@ -Notecard Connectivity -===================== - -The Notecard is a wireless, secure abstraction for device connectivity, that can -be used to enable _ANY*_ device with I2C, or UART, to connect to the Arduino IoT -Cloud via cellular, LoRa, satellite or Wi-Fi! - -As a result, your existing device architecture can now have first class support -in the Arduino IoT Cloud, by using a Notecard as a secure communication channel. - -> \*_While any device with I2C/UART may use the Notecard, the Arduino IoT Cloud -> library is not supported by the AVR toolchain. Therefore, devices based on the -> AVR architecture cannot access the Arduino IoT Cloud via the Notecard._ -> -> _However, any device (including AVR), may use the Notecard library to send data -> to Notehub, then that data may be routed to any endpoint of your choosing. See the -> [Notecard Routing Guide](https://dev.blues.io/guides-and-tutorials/routing-data-to-cloud) -> for more information..._ - -Wireless Connectivity Options ------------------------------ - -- [Cellular](https://shop.blues.com/collections/notecard/products/notecard-cellular) -- [Cellular + Wi-Fi](https://shop.blues.com/collections/notecard/products/notecard-cell-wifi) -- [Wi-Fi](https://shop.blues.com/collections/notecard/products/wifi-notecard) -- [LoRa](https://shop.blues.com/collections/notecard/products/notecard-lora) -- [Satellite](https://shop.blues.com/products/starnote) - -How it Works ------------- - -**Architecture Diagram:** - -``` --------- ------------ ----------- ----------- -| | | | | | | | -| Host | | | Secure | | | Arduino | -| MCU |------| Notecard | ( ( Wireless ) ) | Notehub |------| IoT | -| | | | Protocol | | | Cloud | -|______| |__________| |_________| |_________| -``` - -Getting Started ---------------- - -### Setup a Notehub Account - -Using the Notecard only requires a couple of easy steps: - -1. [Purchase a Notecard](https://shop.blues.com/collections/notecard) (and -[Notecarrier](https://shop.blues.com/collections/notecarrier)) that fits the -needs of your device. - > _**NOTE:** We recommend starting with our [Dev Kit](https://shop.blues.com/products/blues-global-starter-kit) - > if you are unsure._ -1. [Setup a Notehub account](https://dev.blues.io/quickstart/notecard-quickstart/notecard-and-notecarrier-f/#set-up-notehub). - > _**NOTE:** Notehub accounts are free (no credit card required)._ -1. [Create a project on your Notehub account](https://dev.blues.io/quickstart/notecard-quickstart/notecard-and-notecarrier-f/#create-a-notehub-project). -1. In `ConnectionHandlerDemo-Notecard`, replace "com.domain.you:product" (from -`NOTECARD_PRODUCT_UID`) with the ProductUID of your new Notehub project. - -### Power-up the Device - -1. [Connect the Notecard to your Host MCU](https://dev.blues.io/quickstart/notecard-quickstart/notecard-and-notecarrier-f/#connect-your-notecard-and-notecarrier) -1. Flash the `ConnectionHanderDemo-Notecard` example sketch to your device. You -should see the device reporting itself as online in your [Notehub Project](https://notehub.io). - -### More Information - -For more information about the Notecard and Notehub in general, please see our -[Quickstart Guide](https://dev.blues.io/quickstart/) for a general overview of -how the Notecard and Notehub are designed to work. diff --git a/examples/ConnectionHandlerDemo-Notecard/arduino_secrets.h b/examples/ConnectionHandlerDemo-Notecard/arduino_secrets.h deleted file mode 100644 index bd2a9d58..00000000 --- a/examples/ConnectionHandlerDemo-Notecard/arduino_secrets.h +++ /dev/null @@ -1,5 +0,0 @@ -/* If provided, the Wi-Fi Credentials will be passed along to the Notecard. If - * the Notecard supports Wi-Fi, it will attempt to connect to the network using - * these credentials, if not, the Notecard will safely ignore these values. */ -const char SECRET_WIFI_SSID[] = "NETWORK NAME"; -const char SECRET_WIFI_PASS[] = "NETWORK PASSWORD"; diff --git a/keywords.txt b/keywords.txt index 68e2be2d..f2176d69 100644 --- a/keywords.txt +++ b/keywords.txt @@ -12,7 +12,6 @@ NBConnectionHandler KEYWORD1 LoRaConnectionHandler KEYWORD1 EthernetConnectionHandler KEYWORD1 CatM1ConnectionHandler KEYWORD1 -NotecardConnectionHandler KEYWORD1 #################################################### # Methods and Functions (KEYWORD2) @@ -30,10 +29,6 @@ getTime KEYWORD2 getClient KEYWORD2 getUDP KEYWORD2 -# NotecardConnectionHandler.h -initiateNotehubSync KEYWORD2 -setWiFiCredentials KEYWORD2 - #################################################### # Constants (LITERAL1) #################################################### diff --git a/library.properties b/library.properties index 9ad0dc11..48f42491 100644 --- a/library.properties +++ b/library.properties @@ -2,9 +2,9 @@ name=Arduino_ConnectionHandler version=1.2.0 author=Ubi de Feo, Cristian Maglie, Andrea Catozzi, Alexander Entinger et al. maintainer=Arduino -sentence=Arduino Library for network connection management (WiFi, GSM, NB, [Ethernet], Notecard) +sentence=Arduino Library for network connection management (WiFi, GSM, NB, [Ethernet]) paragraph=Originally part of ArduinoIoTCloud category=Communication url=https://github.com/arduino-libraries/Arduino_ConnectionHandler architectures=samd,esp32,esp8266,mbed,megaavr,mbed_nano,mbed_portenta,mbed_nicla,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge,stm32,rp2040 -depends=Arduino_DebugUtils, WiFi101, WiFiNINA, MKRGSM, MKRNB, MKRWAN, Blues Wireless Notecard (>=1.6.3) +depends=Arduino_DebugUtils, WiFi101, WiFiNINA, MKRGSM, MKRNB, MKRWAN diff --git a/src/Arduino_ConnectionHandler.h b/src/Arduino_ConnectionHandler.h index c7a2dcf4..8153c45e 100644 --- a/src/Arduino_ConnectionHandler.h +++ b/src/Arduino_ConnectionHandler.h @@ -22,10 +22,6 @@ #include #include "ConnectionHandlerDefinitions.h" -#if defined(BOARD_HAS_NOTECARD) - #include "NotecardConnectionHandler.h" -#else - #if defined(BOARD_HAS_WIFI) #include "WiFiConnectionHandler.h" #endif @@ -54,6 +50,4 @@ #include "CellularConnectionHandler.h" #endif -#endif // BOARD_HAS_NOTECARD - #endif /* CONNECTION_HANDLER_H_ */ diff --git a/src/ConnectionHandlerDefinitions.h b/src/ConnectionHandlerDefinitions.h index 1534e473..969ecd19 100644 --- a/src/ConnectionHandlerDefinitions.h +++ b/src/ConnectionHandlerDefinitions.h @@ -14,16 +14,8 @@ INCLUDES ******************************************************************************/ -#if defined __has_include - #if __has_include () - #define BOARD_HAS_NOTECARD - #endif -#endif - #include -#ifndef BOARD_HAS_NOTECARD - #ifdef ARDUINO_SAMD_MKR1000 #define BOARD_HAS_WIFI #define NETWORK_HARDWARE_ERROR WL_NO_SHIELD @@ -144,8 +136,6 @@ #define NETWORK_CONNECTED WL_CONNECTED #endif -#endif // BOARD_HAS_NOTECARD - /****************************************************************************** TYPEDEFS ******************************************************************************/ @@ -174,8 +164,7 @@ enum class NetworkAdapter { GSM, LORA, CATM1, - CELL, - NOTECARD + CELL }; union TimeoutTable { @@ -198,7 +187,7 @@ union TimeoutTable { ******************************************************************************/ constexpr TimeoutTable DefaultTimeoutTable { -#if defined(BOARD_HAS_NOTECARD) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) 4000, // init #else 500, // init diff --git a/src/NotecardConnectionHandler.cpp b/src/NotecardConnectionHandler.cpp deleted file mode 100644 index 80cd0145..00000000 --- a/src/NotecardConnectionHandler.cpp +++ /dev/null @@ -1,795 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright 2024 Blues (http://www.blues.com/) - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include "ConnectionHandlerDefinitions.h" - -#if defined(BOARD_HAS_NOTECARD) // Only compile if the Notecard is present - -#include "NotecardConnectionHandler.h" - -#include -#include -#include - -/****************************************************************************** - DEFINES - ******************************************************************************/ - -#define NO_INBOUND_POLLING -1 - -#define NOTEFILE_BASE_NAME "arduino_iot_cloud" - -// Notecard LoRa requires us to choose an arbitrary port between 1-99 -#define NOTEFILE_INBOUND_LORA_PORT 2 -#define NOTEFILE_OUTBOUND_LORA_PORT 3 - -// Note that we use "s" versions of the Notefile extensions to ensure that -// traffic always happens on a secure transport -#define NOTEFILE_SECURE_INBOUND NOTEFILE_BASE_NAME ".qis" -#define NOTEFILE_SECURE_OUTBOUND NOTEFILE_BASE_NAME ".qos" - -/****************************************************************************** - STLINK DEBUG OUTPUT - ******************************************************************************/ - -// Provide Notehub debug output via STLINK serial port when available -#if defined(ARDUINO_SWAN_R5) || defined(ARDUINO_CYGNET) - #define STLINK_DEBUG - HardwareSerial stlinkSerial(PIN_VCP_RX, PIN_VCP_TX); -#endif - -/****************************************************************************** - TYPEDEF - ******************************************************************************/ - -struct NotecardConnectionStatus -{ - NotecardConnectionStatus(void) : transport_connected(0), connected_to_notehub(0), notecard_error(0), host_error(0), reserved(0) { } - NotecardConnectionStatus(uint_fast8_t x) : transport_connected(x & 0x01), connected_to_notehub(x & 0x02), notecard_error(x & 0x04), host_error(x & 0x08), reserved(x & 0xF0) { } - NotecardConnectionStatus & operator=(uint_fast8_t x) { - transport_connected = (x & 0x01); - connected_to_notehub = (x & 0x02); - notecard_error = (x & 0x04); - host_error = (x & 0x08); - reserved = (x & 0xF0); - return *this; - } - operator uint_fast8_t () const { - return ((reserved << 4) | (host_error << 3) | (notecard_error << 2) | (connected_to_notehub << 1) | (transport_connected)); - } - - bool transport_connected : 1; - bool connected_to_notehub : 1; - bool notecard_error : 1; - bool host_error : 1; - uint_fast8_t reserved : 4; -}; -static_assert(sizeof(NotecardConnectionStatus) == sizeof(uint_fast8_t)); - -/****************************************************************************** - CTOR/DTOR - ******************************************************************************/ - -NotecardConnectionHandler::NotecardConnectionHandler( - const String & project_uid_, - uint32_t i2c_address_, - uint32_t i2c_max_, - TwoWire & wire_, - bool keep_alive_ -) : - ConnectionHandler{keep_alive_, NetworkAdapter::NOTECARD}, - _notecard{}, - _device_id{}, - _notecard_uid{}, - _project_uid(project_uid_), - _serial(nullptr), - _wire(&wire_), - _inbound_buffer(nullptr), - _conn_start_ms(0), - _i2c_address(i2c_address_), - _i2c_max(i2c_max_), - _inbound_buffer_index(0), - _inbound_buffer_size(0), - _inbound_polling_interval_min(NO_INBOUND_POLLING), - _uart_baud(0), - _en_hw_int(false), - _topic_type{TopicType::Invalid} -{ } - -NotecardConnectionHandler::NotecardConnectionHandler( - const String & project_uid_, - HardwareSerial & serial_, - uint32_t baud_, - bool keep_alive_ -) : - ConnectionHandler{keep_alive_, NetworkAdapter::NOTECARD}, - _notecard{}, - _device_id{}, - _notecard_uid{}, - _project_uid(project_uid_), - _serial(&serial_), - _wire(nullptr), - _inbound_buffer(nullptr), - _conn_start_ms(0), - _i2c_address(0), - _i2c_max(0), - _inbound_buffer_index(0), - _inbound_buffer_size(0), - _inbound_polling_interval_min(NO_INBOUND_POLLING), - _uart_baud(baud_), - _en_hw_int(false), - _topic_type{TopicType::Invalid} -{ } - -/****************************************************************************** - PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -int NotecardConnectionHandler::initiateNotehubSync (SyncType type_) const -{ - int result; - - DEBUG_DEBUG(F("NotecardConnectionHandler::%s initiating Notehub sync..."), __FUNCTION__); - if (J *req = _notecard.newRequest("hub.sync")) { - if (type_ == SyncType::Inbound) { - JAddBoolToObject(req, "in", true); - } else if (type_ == SyncType::Outbound) { - JAddBoolToObject(req, "out", true); - } - if (J *rsp = _notecard.requestAndResponse(req)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"), err); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } else { - DEBUG_DEBUG(F("NotecardConnectionHandler::%s successfully initiated Notehub sync."), __FUNCTION__); - result = NotecardCommunicationError::NOTECARD_ERROR_NONE; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } - } else { - DEBUG_ERROR("Failed to allocate request: hub.sync"); - result = NotecardCommunicationError::HOST_ERROR_OUT_OF_MEMORY; - } - - return result; -} - -int NotecardConnectionHandler::setWiFiCredentials (const String & ssid_, const String & password_) -{ - int result; - - // Validate the connection state is not in an initialization state - const NetworkConnectionState current_net_connection_state = check(); - if (NetworkConnectionState::INIT == current_net_connection_state) - { - DEBUG_ERROR(F("Unable to set Wi-Fi credentials. Connection to Notecard uninitialized.")); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } else if (J *req = _notecard.newRequest("card.wifi")) { - JAddStringToObject(req, "ssid", ssid_.c_str()); - JAddStringToObject(req, "password", password_.c_str()); - if (J *rsp = _notecard.requestAndResponse(req)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"), err); - DEBUG_ERROR(F("Failed to set Wi-Fi credentials.")); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } else { - DEBUG_INFO(F("Wi-Fi credentials updated. ssid: \"%s\" password: \"%s\"."), ssid_.c_str(), password_.length() ? "**********" : ""); - result = NotecardCommunicationError::NOTECARD_ERROR_NONE; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } - } else { - DEBUG_ERROR(F("Failed to allocate request: wifi.set")); - result = NotecardCommunicationError::HOST_ERROR_OUT_OF_MEMORY; - } - - return result; -} - -/****************************************************************************** - PUBLIC INTERFACE MEMBER FUNCTIONS - ******************************************************************************/ - -bool NotecardConnectionHandler::available() -{ - bool buffered_data = (_inbound_buffer_index < _inbound_buffer_size); - bool flush_required = !buffered_data && _inbound_buffer_size; - - // When the buffer is empty, look for a Note in the - // NOTEFILE_SECURE_INBOUND file to reload the buffer. - if (!buffered_data) { - // Reset the buffer - free(_inbound_buffer); - _inbound_buffer = nullptr; - _inbound_buffer_index = 0; - _inbound_buffer_size = 0; - - // Do NOT attempt to buffer the next Note immediately after buffer - // exhaustion (a.k.a. flush required). Returning `false` between Notes, - // will break the read loop, force the CBOR buffer to be parsed, and the - // property containers to be updated. - if (!flush_required) { - // Reload the buffer - J *note = getNote(true); - if (note) { - if (J *body = JGetObject(note, "body")) { - _topic_type = static_cast(JGetInt(body, "topic")); - if (_topic_type == TopicType::Invalid) { - DEBUG_WARNING(F("Note does not contain a topic")); - } else { - buffered_data = JGetBinaryFromObject(note, "payload", &_inbound_buffer, &_inbound_buffer_size); - if (!buffered_data) { - DEBUG_WARNING(F("Note does not contain payload data")); - } else { - DEBUG_DEBUG(F("NotecardConnectionHandler::%s buffered payload with size: %d"), __FUNCTION__, _inbound_buffer_size); - } - } - } else { - _topic_type = TopicType::Invalid; - } - JDelete(note); - } - } - } - - return buffered_data; -} - -unsigned long NotecardConnectionHandler::getTime() -{ - unsigned long result; - - if (J *rsp = _notecard.requestAndResponse(_notecard.newRequest("card.time"))) { - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s\n"), err); - result = 0; - } else { - result = JGetInt(rsp, "time"); - } - JDelete(rsp); - } else { - result = 0; - } - - return result; -} - -int NotecardConnectionHandler::read() -{ - int result; - - if (_inbound_buffer_index < _inbound_buffer_size) { - result = _inbound_buffer[_inbound_buffer_index++]; - } else { - result = NotecardCommunicationError::NOTECARD_ERROR_NO_DATA_AVAILABLE; - } - - return result; -} - -int NotecardConnectionHandler::write(const uint8_t * buf_, size_t size_) -{ - int result; - - // Validate the connection state is not uninitialized or in error state - const NetworkConnectionState current_net_connection_state = check(); - if ((NetworkConnectionState::INIT == current_net_connection_state) - || (NetworkConnectionState::ERROR == current_net_connection_state)) - { - DEBUG_ERROR(F("Unable to write message. Connection to Notecard uninitialized or in error state.")); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } else if (J * req = _notecard.newRequest("note.add")) { - JAddStringToObject(req, "file", NOTEFILE_SECURE_OUTBOUND); - if (buf_) { - JAddBinaryToObject(req, "payload", buf_, size_); - } - // Queue the Note when `_keep_alive` is disabled or not connected to Notehub - if (_keep_alive && (NetworkConnectionState::CONNECTED == current_net_connection_state)) { - JAddBoolToObject(req, "live", true); - JAddBoolToObject(req, "sync", true); - } - if (J *body = JAddObjectToObject(req, "body")) { - JAddIntToObject(body, "topic", static_cast(_topic_type)); - J * rsp = _notecard.requestAndResponse(req); - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - if (NoteErrorContains(err, "{hub-not-connected}")) { - // _current_net_connection_state = NetworkConnectionState::DISCONNECTED; - } - DEBUG_ERROR(F("%s\n"), err); - result = NotecardCommunicationError::NOTECARD_ERROR_GENERIC; - } else { - result = NotecardCommunicationError::NOTECARD_ERROR_NONE; - DEBUG_INFO(F("Message sent correctly!")); - } - JDelete(rsp); - } else { - JFree(req); - result = NotecardCommunicationError::HOST_ERROR_OUT_OF_MEMORY; - } - } else { - result = NotecardCommunicationError::HOST_ERROR_OUT_OF_MEMORY; - } - - return result; -} - -/****************************************************************************** - PROTECTED STATE MACHINE FUNCTIONS - ******************************************************************************/ - -NetworkConnectionState NotecardConnectionHandler::update_handleInit() -{ - NetworkConnectionState result = NetworkConnectionState::INIT; - - // Configure Hardware - /////////////////////// - -#if defined(STLINK_DEBUG) - // Output Notecard logs to the STLINK serial port - stlinkSerial.end(); // necessary to handle multiple initializations (e.g. reconnections) - stlinkSerial.begin(115200); - const size_t usb_timeout_ms = 3000; - for (const size_t start_ms = millis(); !stlinkSerial && (millis() - start_ms) < usb_timeout_ms;); - _notecard.setDebugOutputStream(stlinkSerial); -#endif - - // Initialize the Notecard based on the configuration - if (_serial) { - _notecard.begin(*_serial, _uart_baud); - } else { - _notecard.begin(_i2c_address, _i2c_max, *_wire); - } - - // Configure `note-c` - /////////////////////// - - // Set the user agent - NoteSetUserAgent((char *) ("arduino-iot-cloud " NOTECARD_CONNECTION_HANDLER_VERSION)); - - // Configure the ATTN pin to be used as an interrupt to indicate when a Note - // is available to read. `getNote()` will only arm the interrupt if no old - // Notes are available. If `ATTN` remains unarmed, it signals the user - // application that outstanding Notes are queued and need to be processed. - if (J *note = getNote(false)) { - JDelete(note); - } - - // Configure the Notecard - /////////////////////////// - - // Set the project UID - if (NetworkConnectionState::INIT == result) { - if (configureConnection(true)) { - result = NetworkConnectionState::INIT; - } else { - result = NetworkConnectionState::ERROR; - } - } - -#if defined(ARDUINO_OPTA) - // The Opta Extension has an onboard Li-Ion capacitor, that can be utilized - // to monitor the power state of the device and automatically report loss of - // power to Notehub. The following command enables that detection by default - // for the Opta Wirelss Extension. - if (NetworkConnectionState::INIT == result) { - if (J *req = _notecard.newRequest("card.voltage")) { - JAddStringToObject(req, "mode", "lic"); - JAddBoolToObject(req, "alert", true); - JAddBoolToObject(req, "sync", true); - JAddBoolToObject(req, "usb", true); - if (J *rsp = _notecard.requestAndResponse(req)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"), err); - result = NetworkConnectionState::ERROR; - } else { - result = NetworkConnectionState::INIT; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } else { - DEBUG_ERROR("Failed to allocate request: card.voltage"); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } -#endif - - // Set inbound template to support LoRa/Satellite Notecard - if (NetworkConnectionState::INIT == result) { - if (J *req = _notecard.newRequest("note.template")) { - JAddStringToObject(req, "file", NOTEFILE_SECURE_INBOUND); - JAddStringToObject(req, "format", "compact"); // Support LoRa/Satellite Notecards - JAddIntToObject(req, "port", NOTEFILE_INBOUND_LORA_PORT); // Support LoRa/Satellite Notecards - if (J *body = JAddObjectToObject(req, "body")) { - JAddIntToObject(body, "topic", TUINT8); - if (J *rsp = _notecard.requestAndResponse(req)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"), err); - result = NetworkConnectionState::ERROR; - } else { - result = NetworkConnectionState::INIT; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } else { - DEBUG_ERROR("Failed to allocate request: note.template:body"); - JFree(req); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } else { - DEBUG_ERROR("Failed to allocate request: note.template"); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } - - // Set outbound template to remove payload size restrictions - if (NetworkConnectionState::INIT == result) { - if (J *req = _notecard.newRequest("note.template")) { - JAddStringToObject(req, "file", NOTEFILE_SECURE_OUTBOUND); - JAddStringToObject(req, "format", "compact"); // Support LoRa/Satellite Notecards - JAddIntToObject(req, "port", NOTEFILE_OUTBOUND_LORA_PORT); // Support LoRa/Satellite Notecards - if (J *body = JAddObjectToObject(req, "body")) { - JAddIntToObject(body, "topic", TUINT8); - if (J *rsp = _notecard.requestAndResponse(req)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"), err); - result = NetworkConnectionState::ERROR; - } else { - result = NetworkConnectionState::INIT; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } else { - DEBUG_ERROR("Failed to allocate request: note.template:body"); - JFree(req); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } else { - DEBUG_ERROR("Failed to allocate request: note.template"); - result = NetworkConnectionState::ERROR; // Assume the worst - } - } - - // Get the device UID - if (NetworkConnectionState::INIT == result) { - if (!updateUidCache()) { - result = NetworkConnectionState::ERROR; - } else { - DEBUG_INFO(F("Notecard has been initialized.")); - if (_keep_alive) { - _conn_start_ms = ::millis(); - DEBUG_INFO(F("Starting network connection...")); - result = NetworkConnectionState::CONNECTING; - } else { - DEBUG_INFO(F("Network is disconnected.")); - result = NetworkConnectionState::DISCONNECTED; - } - } - } - - return result; -} - -NetworkConnectionState NotecardConnectionHandler::update_handleConnecting() -{ - NetworkConnectionState result; - - // Check the connection status - const NotecardConnectionStatus conn_status = connected(); - - // Update the connection state - if (!conn_status.connected_to_notehub) { - if ((::millis() - _conn_start_ms) > NOTEHUB_CONN_TIMEOUT_MS) { - DEBUG_ERROR(F("Timeout exceeded, connection to the network failed.")); - DEBUG_INFO(F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); - result = NetworkConnectionState::INIT; - } else { - // Continue awaiting the connection to Notehub - if (conn_status.transport_connected) { - DEBUG_INFO(F("Establishing connection to Notehub...")); - } else { - DEBUG_INFO(F("Connecting to the network...")); - } - result = NetworkConnectionState::CONNECTING; - } - } else { - DEBUG_INFO(F("Connected to Notehub!")); - result = NetworkConnectionState::CONNECTED; - if (initiateNotehubSync()) { - DEBUG_ERROR(F("Failed to initiate Notehub sync.")); - } - } - - return result; -} - -NetworkConnectionState NotecardConnectionHandler::update_handleConnected() -{ - NetworkConnectionState result; - - const NotecardConnectionStatus conn_status = connected(); - if (!conn_status.connected_to_notehub) { - if (!conn_status.transport_connected) { - DEBUG_ERROR(F("Connection to the network lost.")); - } else { - DEBUG_ERROR(F("Connection to Notehub lost.")); - } - result = NetworkConnectionState::DISCONNECTED; - } else { - result = NetworkConnectionState::CONNECTED; - } - - return result; -} - -NetworkConnectionState NotecardConnectionHandler::update_handleDisconnecting() -{ - NetworkConnectionState result; - - DEBUG_ERROR(F("Connection to the network lost.")); - result = NetworkConnectionState::DISCONNECTED; - - return result; -} - -NetworkConnectionState NotecardConnectionHandler::update_handleDisconnected() -{ - NetworkConnectionState result; - - if (_keep_alive) - { - DEBUG_ERROR(F("Attempting reconnection...")); - result = NetworkConnectionState::INIT; - } - else - { - if (configureConnection(false)) { - result = NetworkConnectionState::CLOSED; - DEBUG_INFO(F("Closing connection...")); - } else { - result = NetworkConnectionState::ERROR; - DEBUG_INFO(F("Error closing connection...")); - } - } - - return result; -} - -/****************************************************************************** - PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - -bool NotecardConnectionHandler::armInterrupt (void) const -{ - bool result; - - if (J *req = _notecard.newRequest("card.attn")) { - JAddStringToObject(req, "mode","rearm,files"); - if (J *files = JAddArrayToObject(req, "files")) { - JAddItemToArray(files, JCreateString(NOTEFILE_SECURE_INBOUND)); - if (J *rsp = _notecard.requestAndResponse(req)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s\n"), err); - result = false; - } else { - result = true; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = false; - } - } else { - DEBUG_ERROR("Failed to allocate request: card.attn:files"); - JFree(req); - result = false; - } - } else { - DEBUG_ERROR("Failed to allocate request: card.attn"); - result = false; - } - - return result; -} - -bool NotecardConnectionHandler::configureConnection (bool connect_) const -{ - bool result; - - if (J *req = _notecard.newRequest("hub.set")) { - // Only update the product if it is not empty or the default value - if (_project_uid.length() > 0 && _project_uid != "com.domain.you:product") { - JAddStringToObject(req, "product", _project_uid.c_str()); - } - - // Configure the connection mode based on the `connect_` parameter - if (connect_) { - JAddStringToObject(req, "mode", "continuous"); - JAddIntToObject(req, "inbound", _inbound_polling_interval_min); - JAddBoolToObject(req, "sync", true); - } else { - JAddStringToObject(req, "mode", "periodic"); - JAddIntToObject(req, "inbound", NO_INBOUND_POLLING); - JAddIntToObject(req, "outbound", -1); - JAddStringToObject(req, "vinbound", "-"); - JAddStringToObject(req, "voutbound", "-"); - } - - // Send the request to the Notecard - if (J *rsp = _notecard.requestAndResponseWithRetry(req, 30)) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"), err); - result = false; - } else { - result = true; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = false; // Assume the worst - } - } else { - DEBUG_ERROR("Failed to allocate request: hub.set"); - result = false; // Assume the worst - } - - return result; -} - -uint_fast8_t NotecardConnectionHandler::connected (void) const -{ - NotecardConnectionStatus result; - - // Query the connection status from the Notecard - if (J *rsp = _notecard.requestAndResponse(_notecard.newRequest("hub.status"))) { - // Ensure the transaction doesn't return an error - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("%s"),err); - result.notecard_error = true; - } else { - // Parse the transport connection status - result.transport_connected = (strstr(JGetString(rsp,"status"),"{connected}") != nullptr); - - // Parse the status of the connection to Notehub - result.connected_to_notehub = JGetBool(rsp,"connected"); - - // Set the Notecard error status - result.notecard_error = false; - result.host_error = false; - } - - // Free the response - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to acquire Notecard connection status.")); - result.transport_connected = false; - result.connected_to_notehub = false; - result.notecard_error = false; - result.host_error = true; - } - - return result; -} - -J * NotecardConnectionHandler::getNote (bool pop_) const -{ - J * result; - - // Look for a Note in the NOTEFILE_SECURE_INBOUND file - if (J *req = _notecard.newRequest("note.get")) { - JAddStringToObject(req, "file", NOTEFILE_SECURE_INBOUND); - if (pop_) { - JAddBoolToObject(req, "delete", true); - } - if (J *note = _notecard.requestAndResponse(req)) { - // Ensure the transaction doesn't return an error - if (NoteResponseError(note)) { - const char *jErr = JGetString(note, "err"); - if (NoteErrorContains(jErr, "{note-noexist}")) { - // The Notefile is empty, thus no Note is available. - if (_en_hw_int) { - armInterrupt(); - } - } else { - // Any other error indicates that we were unable to - // retrieve a Note, therefore no Note is available. - } - result = nullptr; - JDelete(note); - } else { - // The Note was successfully retrieved, and it now - // becomes the callers responsibility to free it. - result = note; - } - } else { - DEBUG_ERROR(F("Failed to receive response from Notecard.")); - result = nullptr; - } - } else { - DEBUG_ERROR("Failed to allocate request: note.get"); - // Failed to retrieve a Note, therefore no Note is available. - result = nullptr; - } - - return result; -} - -bool NotecardConnectionHandler::updateUidCache (void) -{ - bool result; - - // This operation is safe to perform before a sync has occurred, because the - // Notecard UID is static and the cloud value of Serial Number is strictly - // informational with regard to the host firmware operations. - - // Read the Notecard UID from the Notehub configuration - if (J *rsp = _notecard.requestAndResponse(_notecard.newRequest("hub.get"))) { - // Check the response for errors - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - DEBUG_ERROR(F("Failed to read Notecard UID")); - DEBUG_ERROR(F("Error: %s"), err); - result = false; - } else { - _notecard_uid = JGetString(rsp, "device"); - char device_id[] = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; - if (NoteGetEnv("_arduino_device_id", device_id, device_id, sizeof(device_id))) { - _device_id = device_id; - } else { - DEBUG_DEBUG(F("NotecardConnectionHandler::%s Arduino Device ID not cached on Notecard, using default value: <%s>"), __FUNCTION__, _device_id.c_str()); - } - DEBUG_DEBUG(F("NotecardConnectionHandler::%s updated local cache with Notecard UID: <%s> and Arduino Device ID: <%s>"), __FUNCTION__, _notecard_uid.c_str(), _device_id.c_str()); - result = true; - } - JDelete(rsp); - } else { - DEBUG_ERROR(F("Failed to read Notecard UID")); - result = false; - } - - return result; -} - -#endif /* BOARD_HAS_NOTECARD */ diff --git a/src/NotecardConnectionHandler.h b/src/NotecardConnectionHandler.h deleted file mode 100644 index 7e84fc51..00000000 --- a/src/NotecardConnectionHandler.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright 2024 Blues (http://www.blues.com/) - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#ifndef ARDUINO_NOTECARD_CONNECTION_HANDLER_H_ -#define ARDUINO_NOTECARD_CONNECTION_HANDLER_H_ - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include - -#include -#include -#include - -#include "ConnectionHandlerInterface.h" - -/****************************************************************************** - DEFINES - ******************************************************************************/ - -#define NOTECARD_CONNECTION_HANDLER_VERSION_MAJOR 1 -#define NOTECARD_CONNECTION_HANDLER_VERSION_MINOR 1 -#define NOTECARD_CONNECTION_HANDLER_VERSION_PATCH 1 - -#define NOTECARD_CONNECTION_HANDLER_VERSION NOTE_C_STRINGIZE(NOTECARD_CONNECTION_HANDLER_VERSION_MAJOR) "." NOTE_C_STRINGIZE(NOTECARD_CONNECTION_HANDLER_VERSION_MINOR) "." NOTE_C_STRINGIZE(NOTECARD_CONNECTION_HANDLER_VERSION_PATCH) - -/****************************************************************************** - CLASS DECLARATION - ******************************************************************************/ - -/** - * @brief The NotecardConnectionHandler class - * - * The NotecardConnectionHandler class is a concrete implementation of the - * ConnectionHandler interface that provides connectivity to the Arduino IoT - * Cloud using a Notecard. - */ -class NotecardConnectionHandler final : public ConnectionHandler -{ - public: - /** - * @brief The manner in which the Notecard is synchronized with Notehub - * - * The SyncType enum defines the valid types of synchronization operations - * that can be performed by the NotecardConnectionHandler class. - * - * @par - * - Full - synchronize both the inbound and outbound queues. - * - Inbound - synchronize only the inbound queues. - * - Outbound - synchronize only the outbound queues. - */ - enum class SyncType : uint8_t { - Full, - Inbound, - Outbound, - }; - - /** - * @brief The type of topic to be used for R/W operations - * - * The Notecard uses topics to identify the target of a read or write - * operation. The TopicType enum defines the valid types of topics. - * - * @par - * - Command - used to interact with the Arduino IoT Cloud. - * - Thing - used to send application data to the Arduino IoT Cloud. - */ - enum class TopicType : uint8_t { - Invalid = 0, - Command, - Thing, - }; - - /** - * @brief The error codes for communicating with the Notecard - * - * The NotecardCommunicationError enum defines the error codes that can be - * returned by the NotecardConnectionHandler class. - * - * @par - * - NOTECARD_ERROR_NONE - No error occurred. - * - NOTECARD_ERROR_NO_DATA_AVAILABLE - No data is available. - * - NOTECARD_ERROR_GENERIC - A generic error occurred. - * - HOST_ERROR_OUT_OF_MEMORY - The host is out of memory. - */ - typedef enum { - NOTECARD_ERROR_NONE = 0, - NOTECARD_ERROR_NO_DATA_AVAILABLE = -1, - NOTECARD_ERROR_GENERIC = -2, - HOST_ERROR_OUT_OF_MEMORY = -3, - } NotecardCommunicationError; - - /** - * @brief The default timeout for the Notecard to connect to Notehub - */ - static const uint32_t NOTEHUB_CONN_TIMEOUT_MS = 185000; - - /** - * @brief The I2C constructor for the Notecard - * - * @param project_uid[in] The project UID of the related Notehub account - * @param i2c_address[in] The I2C address of the Notecard - * @param i2c_max[in] The maximum I2C transaction size (MTU) - * @param wire[in] The I2C bus to use - * @param keep_alive[in] Keep the connection alive if connection to Notehub drops - */ - NotecardConnectionHandler( - const String & project_uid, - uint32_t i2c_address = NOTE_I2C_ADDR_DEFAULT, - uint32_t i2c_max = NOTE_I2C_MAX_DEFAULT, - TwoWire & wire = Wire, - bool keep_alive = true - ); - - /** - * @brief The UART constructor for the Notecard - * - * @param project_uid[in] The project UID of the related Notehub account - * @param serial[in] The serial port to use - * @param baud[in] The baud rate of the serial port - * @param keep_alive[in] Keep the connection alive if connection to Notehub drops - */ - NotecardConnectionHandler( - const String & project_uid, - HardwareSerial & serial, - uint32_t baud = 9600, - bool keep_alive = true - ); - - /** - * @brief Disable hardware interrupts - * - * When hardware interrupts are disabled, the `NotecardConnectionHandler` - * must be polled for incoming data. This is necessary when the host - * microcontroller is unable to use the ATTN pin of the Notecard. - */ - inline void disableHardwareInterrupts (void) { - _en_hw_int = false; - } - - /** - * @brief Enable hardware interrupts - * - * Hardware interrupts allow the `NotecardConnectionHandler` to leverage the - * ATTN pin of the Notecard. This improves the responsiveness of the - * `NotecardConnectionHandler` by eliminating the need for the host - * microcontroller to poll the Notecard for incoming data. - */ - inline void enableHardwareInterrupts (void) { - _en_hw_int = true; - } - - /** - * @brief Get the Arduino IoT Cloud Device ID - * - * The Arduino IoT Cloud Device ID is set as the serial number of the - * Notecard when the device is provisioned in Notehub. The serial number is - * updated on each sync between the Notecard and Notehub and cached by the - * Notecard. As a result, this value can lag behind the actual value of the - * Arduino IoT Cloud Device ID used by the Notehub. However, this value is - * typically unchanged during the life of the Notecard, so this is rarely, - * if ever, an issue. - * - * @return The Arduino IoT Cloud Device ID - */ - inline const String & getDeviceId (void) { - check(); // Ensure the connection to the Notecard is initialized - return _device_id; - } - - /** - * @brief Get the Notecard object - * - * The Notecard object is used to interact with the Notecard. This object - * provides methods to read and write data to the Notecard, as well as - * methods to configure the Notecard. - * - * @return The Notecard object - */ - inline const Notecard & getNotecard (void) { - return _notecard; - } - - /** - * @brief Get the Notecard Device ID - * - * The Notecard Device ID is the unique identifier of the Notecard. This - * value is set at time of manufacture, and is used to identify the Notecard - * in Notehub. - * - * @return The Notecard Device ID - */ - inline const String & getNotecardUid (void) { - check(); // Ensure the connection to the Notecard is initialized - return _notecard_uid; - } - - /** - * @brief Get the topic type of the most recent R/W operations - * - * @return The current topic type - * - * @see TopicType - */ - TopicType getTopicType (void) const { - return _topic_type; - } - - /** - * @brief Initiate a synchronization operation with Notehub - * - * The Notecard maintains two queues: an inbound queue and an outbound - * queue. The inbound queue is used to receive data from Notehub, while the - * outbound queue is used to send data to Notehub. This method initiates a - * synchronization operation between the Notecard and Notehub. - * - * As the name implies, this method is asynchronous and will only initiate - * the synchronization operation. The actual synchronization operation will - * be performed by the Notecard in the background. - * - * @param type[in] The type of synchronization operation to perform - * @par - * - SyncType::Full - synchronize both the inbound and outbound queues (default) - * - SyncType::Inbound - synchronize only the inbound queues. - * - SyncType::Outbound - synchronize only the outbound queues. - * - * @return 0 if successful, otherwise an error code - * - * @see SyncType - * @see NotecardCommunicationError - */ - int initiateNotehubSync (SyncType type = SyncType::Full) const; - - /** - * @brief Set the inbound polling interval (in minutes) - * - * A cellular Notecard will receive inbound traffic from the Arduino IoT - * Cloud in real-time. As such, the polling interval is used as a fail-safe - * to ensure the Notecard is guaranteed to receive inbound traffic at the - * interval specified by this method. - * - * Alternatively, a LoRa (or Satellite) Notecard does not maintain a - * continuous connection, and therefore must rely on the polling interval to - * establish the maximum acceptable delay before receiving any unsolicited, - * inbound traffic from the Arduino IoT Cloud. The polling interval must - * balance the needs of the application against the regulatory limitations - * of LoRa (or bandwidth limitations and cost of Satellite). - * - * LoRaWAN Fair Use Policy: - * https://www.thethingsnetwork.org/forum/t/fair-use-policy-explained/1300 - * - * @param interval_min[in] The inbound polling interval (in minutes) - * - * @note Set the interval to 0 to disable inbound polling. - * @note Must be set prior to initializing the connection to the Notecard. - */ - inline void setNotehubPollingInterval (int32_t interval_min) { - _inbound_polling_interval_min = (interval_min ? interval_min : -1); - } - - /** - * @brief Set the topic type for R/W operations - * - * @param topic[in] The topic type - * @par - * - TopicType::Command - used to interact with the Arduino IoT Cloud. - * - TopicType::Thing - used to send application data to the Arduino IoT Cloud. - * - * @see TopicType - */ - void setTopicType (TopicType topic) { - _topic_type = topic; - } - - /** - * @brief Set the WiFi credentials to be used by the Notecard - * - * @param ssid[in] The SSID of the WiFi network - * @param pass[in] The password of the WiFi network - * - * @return 0 if successful, otherwise an error code - * - * @note This method is only applicable when using a Wi-Fi capable Notecard, - * and is unnecessary when using a Notecard with cellular connectivity. - * If the Notecard is not Wi-Fi capable, this method will be a no-op. - * - * @see NotecardCommunicationError - */ - int setWiFiCredentials (const String & ssid, const String & pass); - - // ConnectionHandler interface - virtual bool available() override; - virtual unsigned long getTime() override; - virtual int read() override; - virtual int write(const uint8_t *buf, size_t size) override; - - protected: - - virtual NetworkConnectionState update_handleInit () override; - virtual NetworkConnectionState update_handleConnecting () override; - virtual NetworkConnectionState update_handleConnected () override; - virtual NetworkConnectionState update_handleDisconnecting() override; - virtual NetworkConnectionState update_handleDisconnected () override; - - private: - - // Private members - Notecard _notecard; - String _device_id; - String _notecard_uid; - String _project_uid; - HardwareSerial * _serial; - TwoWire * _wire; - uint8_t * _inbound_buffer; - uint32_t _conn_start_ms; - uint32_t _i2c_address; - uint32_t _i2c_max; - uint32_t _inbound_buffer_index; - uint32_t _inbound_buffer_size; - int32_t _inbound_polling_interval_min; - uint32_t _uart_baud; - bool _en_hw_int; - TopicType _topic_type; - - // Private methods - bool armInterrupt (void) const; - bool configureConnection (bool connect) const; - uint_fast8_t connected (void) const; - J * getNote (bool pop = false) const; - bool updateUidCache (void); -}; - -#endif /* ARDUINO_NOTECARD_CONNECTION_HANDLER_H_ */