From 9e2680336b3be343fbbe78164041b90ae4ba6886 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 03:07:39 -0300 Subject: [PATCH 01/25] feat(OThread): Add Library --- CMakeLists.txt | 7 +- .../examples/COAP/coap_lamp/ci.json | 10 + .../examples/COAP/coap_lamp/coap_lamp.ino | 133 ++++++ .../examples/COAP/coap_switch/ci.json | 10 + .../examples/COAP/coap_switch/coap_switch.ino | 158 +++++++ .../examples/SimpleCLI/SimpleCLI.ino | 21 + .../OpenThread/examples/SimpleCLI/ci.json | 10 + .../examples/SimpleNode/SimpleNode.ino | 31 ++ .../OpenThread/examples/SimpleNode/ci.json | 10 + .../LeaderNode/LeaderNode.ino | 37 ++ .../SimpleThreadNetwork/LeaderNode/ci.json | 10 + .../RouterNode/RouterNode.ino | 37 ++ .../SimpleThreadNetwork/RouterNode/ci.json | 10 + libraries/OpenThread/keywords.txt | 44 ++ libraries/OpenThread/library.properties | 9 + libraries/OpenThread/src/OThreadCLI.cpp | 424 ++++++++++++++++++ libraries/OpenThread/src/OThreadCLI.h | 53 +++ libraries/OpenThread/src/OThreadCLI_Util.cpp | 74 +++ libraries/OpenThread/src/OThreadCLI_Util.h | 22 + 19 files changed, 1109 insertions(+), 1 deletion(-) create mode 100644 libraries/OpenThread/examples/COAP/coap_lamp/ci.json create mode 100644 libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino create mode 100644 libraries/OpenThread/examples/COAP/coap_switch/ci.json create mode 100644 libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino create mode 100644 libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino create mode 100644 libraries/OpenThread/examples/SimpleCLI/ci.json create mode 100644 libraries/OpenThread/examples/SimpleNode/SimpleNode.ino create mode 100644 libraries/OpenThread/examples/SimpleNode/ci.json create mode 100644 libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino create mode 100644 libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json create mode 100644 libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino create mode 100644 libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json create mode 100644 libraries/OpenThread/keywords.txt create mode 100644 libraries/OpenThread/library.properties create mode 100644 libraries/OpenThread/src/OThreadCLI.cpp create mode 100644 libraries/OpenThread/src/OThreadCLI.h create mode 100644 libraries/OpenThread/src/OThreadCLI_Util.cpp create mode 100644 libraries/OpenThread/src/OThreadCLI_Util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cad3c3a079d..47cdfda906a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ set(ARDUINO_ALL_LIBRARIES LittleFS NetBIOS Network + OpenThread PPP Preferences RainMaker @@ -158,7 +159,11 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) -set(ARDUINO_LIBRARY_PPP_SRCS +set(ARDUINO_LIBRARY_OpenThread_SRCS + libraries/OpenThread/src/OThreadCLI.cpp + libraries/OpenThread/src/OThreadCLI_Util.c) + + set(ARDUINO_LIBRARY_PPP_SRCS libraries/PPP/src/PPP.cpp libraries/PPP/src/ppp.c) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json new file mode 100644 index 00000000000..742d0567b8e --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json @@ -0,0 +1,10 @@ +{ + "targets": { + "esp32": false + "esp32c2": false + "esp32c3": false + "esp32s2": false + "esp32s3": false + } + } + \ No newline at end of file diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino new file mode 100644 index 00000000000..ff782d73c5c --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -0,0 +1,133 @@ +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define OT_CHANNEL "24" +#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" + +const char *otSetupLeader[] = { + // clear/disable all + "coap", "stop", + "thread", "stop", + "ifconfig", "down", + "dataset", "clear", + // set dataset + "dataset", "init new", + "dataset channel", OT_CHANNEL, + "dataset networkkey", OT_NETWORK_KEY, + "dataset", "commit active", + // network start + "ifconfig", "up", + "thread", "start" +}; + +const char *otCoapLamp[] = { + // create a multicast IPv6 Address for this device + "ipmaddr add", "ff05::abcd", + // start and create a CoAP resource + "coap", "start", + "coap resource", "Lamp", + "coap set", "0" +}; + +bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole) { + Serial.println("Starting OpenThread."); + Serial.println("Running as Lamp (RGB LED) - use the other C6/H2 as a Switch"); + uint8_t i; + for (i = 0; i < nCmds1; i++) { + if (!otExecCommand(otSetupCmds[i * 2], otSetupCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds1) { + log_e("Sorry, OpenThread Network setup failed!"); + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); + // wait for the expected Device Role to start + uint8_t tries = 24; // 24 x 2.5 sec = 1 min + while (tries && getOtDeviceRole() != expectedRole) { + Serial.print("."); + delay(2500); + tries--; + } + Serial.println(); + if (!tries) { + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", getStringOtDeviceRole()); + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.printf("Device is %s.\r\n", getStringOtDeviceRole()); + for (i = 0; i < nCmds2; i++) { + if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds2) { + log_e("Sorry, OpenThread CoAP setup failed!"); + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread setup done. Node is ready."); + // all fine! LED goes Green + neopixelWrite(RGB_BUILTIN, 0, 64, 8); // GREEN ... Lamp is ready! + return true; +} + +void setupNode() { + // tries to set the Thread Network node and only returns when succeded + bool startedCorrectly = false; + while (!startedCorrectly) { + startedCorrectly |= otDeviceSetup(otSetupLeader, sizeof(otSetupLeader) / sizeof(char *) / 2, + otCoapLamp, sizeof(otCoapLamp) / sizeof(char *) / 2, + OT_ROLE_LEADER); + if (!startedCorrectly) { + Serial.println("Setup Failed...\r\nTrying again..."); + } + } + +} + +// this function is used by the Lamp mode to listen for CoAP frames from the Switch Node +void otCOAPListen() { + // waits for the client to send a CoAP request + char cliResp[256]; + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + cliResp[len] = '\0'; + if (strlen(cliResp)) { + String sResp(cliResp); + log_d("Msg[%s]", cliResp); + if (sResp.startsWith("coap request from") && sResp.indexOf("PUT") > 0) { + uint16_t payloadIdx = sResp.indexOf("payload: ") + 10; // 0x30 | 0x31 + char payload = sResp.charAt(payloadIdx); + log_i("CoAP PUT [%s]\r\n", payload == '0' ? "OFF" : "ON"); + if (payload == '0') { + for (int16_t c = 248; c > 16; c -= 8) { + neopixelWrite(RGB_BUILTIN, c, c, c); // ramp down + delay(5); + } + neopixelWrite(RGB_BUILTIN, 0, 0, 0); // Lamp Off + } else { + for (int16_t c = 16; c < 248; c += 8) { + neopixelWrite(RGB_BUILTIN, c, c, c); // ramp up + delay(5); + } + neopixelWrite(RGB_BUILTIN, 255, 255, 255); // Lamp On + } + } + } +} + +void setup() { + Serial.begin(115200); + // LED starts RED, indicating not connected to Thread network. + neopixelWrite(RGB_BUILTIN, 64, 0, 0); + OThreadCLI.begin(false); // No AutoStart is necessary + OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response + setupNode(); +} + +void loop() { + otCOAPListen(); + delay(10); +} diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json new file mode 100644 index 00000000000..742d0567b8e --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -0,0 +1,10 @@ +{ + "targets": { + "esp32": false + "esp32c2": false + "esp32c3": false + "esp32s2": false + "esp32s3": false + } + } + \ No newline at end of file diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino new file mode 100644 index 00000000000..60545cdb681 --- /dev/null +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -0,0 +1,158 @@ +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define USER_BUTTON 9 // C6/H2 Boot button +#define OT_CHANNEL "24" +#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" + +const char *otSetupChild[] = { + // clear/disable all + "coap", "stop", + "thread", "stop", + "ifconfig", "down", + "dataset", "clear", + // set dataset + "dataset channel", OT_CHANNEL, + "dataset networkkey", OT_NETWORK_KEY, + "dataset", "commit active", + // network start + "ifconfig", "up", + "thread", "start" +}; + +const char *otCoapSwitch[] = { + // start and create a CoAP resource + "coap", "start", +}; + +bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole1, ot_device_role_t expectedRole2) { + Serial.println("Starting OpenThread."); + Serial.println("Running as Switch - use the BOOT button to toggle the other C6/H2 as a Lamp"); + uint8_t i; + for (i = 0; i < nCmds1; i++) { + if (!otExecCommand(otSetupCmds[i * 2], otSetupCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds1) { + log_e("Sorry, OpenThread Network setup failed!"); + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); + // wait for the expected Device Role to start + uint8_t tries = 24; // 24 x 2.5 sec = 1 min + while (tries && getOtDeviceRole() != expectedRole1 && getOtDeviceRole() != expectedRole2) { + Serial.print("."); + delay(2500); + tries--; + } + Serial.println(); + if (!tries) { + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", getStringOtDeviceRole()); + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.printf("Device is %s.\r\n", getStringOtDeviceRole()); + for (i = 0; i < nCmds2; i++) { + if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { + break; + } + } + if (i != nCmds2) { + log_e("Sorry, OpenThread CoAP setup failed!"); + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! + return false; + } + Serial.println("OpenThread setup done. Node is ready."); + // all fine! LED goes Blue + neopixelWrite(RGB_BUILTIN, 0, 0, 64); // BLUE ... Swtich is ready! + return true; +} + + +void setupNode() { + // tries to set the Thread Network node and only returns when succeded + bool startedCorrectly = false; + while (!startedCorrectly) { + startedCorrectly |= otDeviceSetup(otSetupChild, sizeof(otSetupChild) / sizeof(char *) / 2, + otCoapSwitch, sizeof(otCoapSwitch) / sizeof(char *) / 2, + OT_ROLE_CHILD, OT_ROLE_ROUTER); + if (!startedCorrectly) { + Serial.println("Setup Failed...\r\nTrying again..."); + } + } + +} + +// Sends the CoAP frame to the Lamp node +bool otCoapPUT(bool lampState) { + bool gotDone = false, gotConfirmation = false; + char coapMsg[] = "coap put ff05::abcd Lamp con 0"; + + if (lampState) { + coapMsg[strlen(coapMsg) - 1] = '1'; + } + OThreadCLI.println(coapMsg); + log_d("Send CLI CMD:[%s]", coapMsg); + + char cliResp[256]; + // waits for the CoAP confirmation and Done message for about 5 seconds + // timeout is based on Stream::setTimeout() + uint8_t tries = 5; + *cliResp = '\0'; + while (tries && !(gotDone && gotConfirmation)) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + cliResp[len] = '\0'; + log_d("Try[%d]::MSG[%s]", tries, cliResp); + if (strlen(cliResp)) { + log_d("%s", cliResp); + if (!strncmp(cliResp, "coap response from", 18)) { + gotConfirmation = true; + } + if (!strncmp(cliResp, "Done", 4)) { + gotDone = true; + } + } + tries--; + } + if (gotDone && gotConfirmation) { + return true; + } + return false; +} + +// this fucntion is used by the Switch mode to check the BOOT Button and send the user action to the Lamp node +void checkUserButton() { + static long unsigned int lastPress = 0; + const long unsigned int debounceTime = 500; + static bool lastLampState = false; + + pinMode(USER_BUTTON, INPUT_PULLUP); // C6/H2 User Button + if (millis() > lastPress + debounceTime && digitalRead(USER_BUTTON) == LOW) { + if (otCoapPUT(!lastLampState)) { + lastLampState = !lastLampState; + } else { + // timeout from the CoAP PUT message... restart the node. + neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... something failed! + Serial.println("Reseting the Node as Switch... wait."); + // start over... + setupNode(); + } + lastPress = millis(); + } +} + +void setup() { + Serial.begin(115200); + // LED starts RED, indicating not connected to Thread network. + neopixelWrite(RGB_BUILTIN, 64, 0, 0); + OThreadCLI.begin(false); // No AutoStart is necessary + OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response + setupNode(); +} + +void loop() { + checkUserButton(); + delay(10); +} diff --git a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino new file mode 100644 index 00000000000..311788d7969 --- /dev/null +++ b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino @@ -0,0 +1,21 @@ +/* + * OpenThread.begin(false) will not start a node in a Thread Network + * You will need to start it manually using the OpenThread CLI commands + * Use the Serial Monitor to interact with the OpenThread CLI + * + * Type 'help' for a list of commands. + * Documentation: https://openthread.io/reference/cli/commands + * + */ + +#include "OThreadCLI.h" + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println("OpenThread CLI started - type 'help' for a list of commands."); + OThreadCLI.startOpenThreadConsole(Serial); +} + +void loop() { +} \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json new file mode 100644 index 00000000000..742d0567b8e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -0,0 +1,10 @@ +{ + "targets": { + "esp32": false + "esp32c2": false + "esp32c3": false + "esp32s2": false + "esp32s3": false + } + } + \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino new file mode 100644 index 00000000000..a0a240f5598 --- /dev/null +++ b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino @@ -0,0 +1,31 @@ +/* + * OpenThread.begin() will automatically start a node in a Thread Network + * If NVS is empty, default configuration will be as follow: + * + * NETWORK_NAME "OpenThread-ESP" + * MESH_LOCAL_PREFIX "fd00:db8:a0:0::/64" + * NETWORK_CHANNEL 15 + * NETWORK_PANID 0x1234 + * NETWORK_EXTPANID "dead00beef00cafe" + * NETWORK_KEY "00112233445566778899aabbccddeeff" + * NETWORK_PSKC "104810e2315100afd6bc9215a6bfac53" + * + * If NVS has already a dataset information, it will load it from there. + */ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +// The first device to start Thread will be the Leader +// Next devices will be Router or Child + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(); // AutoStart using Thread default settings +} + +void loop() { + Serial.print("Thread Node State: "); + Serial.println(getStringOtDeviceRole()); + delay(5000); +} diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json new file mode 100644 index 00000000000..742d0567b8e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -0,0 +1,10 @@ +{ + "targets": { + "esp32": false + "esp32c2": false + "esp32c3": false + "esp32s2": false + "esp32s3": false + } + } + \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino new file mode 100644 index 00000000000..e11e9b7c9f6 --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -0,0 +1,37 @@ +/* + * OpenThread.begin(false) will not start a node in a Thread Network + * A Leader node is the first device to start Thread that has a complete dataset + * This is achieved by using the OpenThread CLI command "dataset init new" + * + * In order to allow other node to join the network, + * all of them shall use the same network master key + * The network master key is a 16-byte key that is used to secure the network + * + * Using the same channel will make the process faster + * + */ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" +#define CLI_NETWORK_CHANEL "dataset channel 24" + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println("Setting up OpenThread Node as Leader"); + + OThreadCLI.println("dataset init new"); + OThreadCLI.println(CLI_NETWORK_KEY); + OThreadCLI.println(CLI_NETWORK_CHANEL); + OThreadCLI.println("dataset commit active"); + OThreadCLI.println("ifconfig up"); + OThreadCLI.println("thread start"); +} + +void loop() { + Serial.print("Thread Node State: "); + Serial.println(getStringOtDeviceRole()); + delay(5000); +} \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json new file mode 100644 index 00000000000..742d0567b8e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json @@ -0,0 +1,10 @@ +{ + "targets": { + "esp32": false + "esp32c2": false + "esp32c3": false + "esp32s2": false + "esp32s3": false + } + } + \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino new file mode 100644 index 00000000000..f1bad7a9a16 --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -0,0 +1,37 @@ +/* + * OpenThread.begin(false) will not start a node in a Thread Network + * A Router/Child node is the device that will join an existent Thread Network + * + * In order to allow this node to join the network, + * it shall use the same network master key as used by the Leader Node + * The network master key is a 16-byte key that is used to secure the network + * + * Using the same channel will make the process faster + * + */ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" +#define CLI_NETWORK_CHANEL "dataset channel 24" + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(false); // No AutoStart - fresh start + Serial.println("Setting up OpenThread Node as Router/Child"); + Serial.println("Make sure the Leader Node is already running"); + + OThreadCLI.println("dataset clear"); + OThreadCLI.println(CLI_NETWORK_KEY); + OThreadCLI.println(CLI_NETWORK_CHANEL); + OThreadCLI.println("dataset commit active"); + OThreadCLI.println("ifconfig up"); + OThreadCLI.println("thread start"); +} + +void loop() { + Serial.print("Thread Node State: "); + Serial.println(getStringOtDeviceRole()); + delay(5000); +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json new file mode 100644 index 00000000000..742d0567b8e --- /dev/null +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json @@ -0,0 +1,10 @@ +{ + "targets": { + "esp32": false + "esp32c2": false + "esp32c3": false + "esp32s2": false + "esp32s3": false + } + } + \ No newline at end of file diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt new file mode 100644 index 00000000000..a7a1cdc5c34 --- /dev/null +++ b/libraries/OpenThread/keywords.txt @@ -0,0 +1,44 @@ +####################################### +# Syntax Coloring Map For OpenThread +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +OThreadCLI KEYWORD1 +OpenThreadCLI KEYWORD1 +ot_cmd_return_t KEYWORD1 +ot_device_role_t KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +startOpenThreadConsole KEYWORD2 +stopOpenThreadConsole KEYWORD2 +setPrompt KEYWORD2 +setEchoBack KEYWORD2 +setStream KEYWORD2 +onReceive KEYWORD2 +begin KEYWORD2 +setTxBufferSize KEYWORD2 +setRxBufferSize KEYWORD2 +write KEYWORD2 +available KEYWORD2 +read KEYWORD2 +peek KEYWORD2 +flush KEYWORD2 +getOtDeviceRole KEYWORD2 +getStringOtDeviceRole KEYWORD2 +otExecCommand KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +OT_ROLE_DISABLED LITERAL1 +OT_ROLE_DETACHED LITERAL1 +OT_ROLE_CHILD LITERAL1 +OT_ROLE_ROUTER LITERAL1 +OT_ROLE_LEADER LITERAL1 diff --git a/libraries/OpenThread/library.properties b/libraries/OpenThread/library.properties new file mode 100644 index 00000000000..1091f154b53 --- /dev/null +++ b/libraries/OpenThread/library.properties @@ -0,0 +1,9 @@ +name=OpenThread +version=1.0.0 +author=Rodrigo Garcia | GitHub @SuGlider +maintainer=Rodrigo Garcia +sentence=Library for OpenThread Network on ESP32. +paragraph=This library is a wrapper for OpenThread CLI. It provides a simple way to interact with OpenThread Network. +category=Sensor +url=https://github.com/espressif/arduino-esp32/ +architectures=esp32 diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp new file mode 100644 index 00000000000..83fb38231b2 --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -0,0 +1,424 @@ +#include "OThreadCLI.h" +#if SOC_IEEE802154_SUPPORTED + +#include "Arduino.h" +#include "OThreadCLI.h" + +#include "esp_err.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_netif_types.h" +#include "esp_vfs_eventfd.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" + +#include "esp_netif.h" +#include "esp_netif_types.h" + +static TaskHandle_t s_cli_task = NULL; +static TaskHandle_t s_console_cli_task = NULL; +static xQueueHandle rx_queue = NULL; +static xQueueHandle tx_queue = NULL; + +static esp_openthread_platform_config_t ot_native_config; +static TaskHandle_t s_ot_task = NULL; +static esp_netif_t *openthread_netif = NULL; + +#define OT_CLI_MAX_LINE_LENGTH 512 + +typedef struct { + Stream *cliStream; + bool echoback; + String prompt; + OnReceiveCb_t responseCallBack; +} ot_cli_console_t; +static ot_cli_console_t otConsole = {NULL, false, (const char *) NULL, NULL}; + +// process the CLI commands sent to the OpenThread stack +static void ot_cli_loop(void *context) { + String sTxString(""); + + while (true) { + if (tx_queue != NULL) { + uint8_t c; + if (xQueueReceive(tx_queue, &c, portMAX_DELAY)) { + // avoids sending a empty command, specially when the terminal send "\r\n" together + if (sTxString.length() > 0 && (c == '\r' || c == '\n')) { + esp_openthread_cli_input(sTxString.c_str()); + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + sTxString = ""; + } else { + if (c == '\b' || c == 127) { + if (sTxString.length() > 0) { + sTxString.remove(sTxString.length() - 1); + } + } else { + // only allow printable characters + if (c > 31 && c < 127) { + sTxString += (char)c; + } + } + } + } + } + } +} + +// process the CLI responses received from the OpenThread stack +static int OTcli_output_callback(void *context, const char *format, va_list args) +{ + char prompt_check[3]; + int ret = 0; + + vsnprintf(prompt_check, sizeof(prompt_check), format, args); + if (!strncmp(prompt_check, "> ", sizeof(prompt_check))) { + if (s_cli_task) { + xTaskNotifyGive(s_cli_task); + } + if (s_console_cli_task) { + xTaskNotifyGive(s_console_cli_task); + } + } else { + char buf[OT_CLI_MAX_LINE_LENGTH]; + ret = vsnprintf(buf, sizeof(buf), format, args); + if (ret) { + // store received data in the RX buffer + if (rx_queue != NULL) { + size_t freeSpace = uxQueueSpacesAvailable(rx_queue); + if (freeSpace < ret) { + // Drop the oldest data to make room for the new data + for (int i = 0; i < (ret - freeSpace); i++) { + uint8_t c; + xQueueReceive(rx_queue, &c, 0); + } + } + for (int i = 0; i < ret; i++) { + xQueueSend(rx_queue, &buf[i], 0); + } + } + } + } + return ret; +} + +// helper task to process CLI from a Stream (e.g. Serial) +static void ot_cli_console_worker(void *context) { + ot_cli_console_t *cli = (ot_cli_console_t *)context; + + // prints the prompt as first action + if (cli->prompt && cli->echoback) { + cli->cliStream->print(cli->prompt.c_str()); + } + // manages and synchronizes the Stream flow with OpenThread CLI response + char lastReadChar; + char c = '\n'; + while (true) { + if (cli->cliStream->available() > 0) { + lastReadChar = c; + c = cli->cliStream->read(); + // if EOL is received, it may contain a combination of '\n' + // and/or '\r' depending on the Host OS and Terminal used. + // remove all leading '\r' '\n' + if (c == '\r') { + c = '\n'; // just mark it as New Line + } + if (c == '\n' && lastReadChar == '\n') { + continue; + } + + // echo it back to the console + if (cli->echoback) { + if (c == '\n') { + cli->cliStream->println(); // follows whatever is defined as EOL in Arduino + } else { + cli->cliStream->write(c); + } + } + // send it to be processed by Open Thread CLI + OThreadCLI.write(c); + // if EOL, it shall wait for the command to be processed in background + if (c == '\n' && lastReadChar != '\n') { + // wait for the OpenThread CLI to finish processing the command + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + // if there is a user callback function in place, it shall have the priority + // to process/consume the Stream data received from OpenThread CLI, which is available in its RX Buffer + if (cli->responseCallBack != NULL) { + cli->responseCallBack(); + } + // read response from OpenThread CLI and send it to the Stream + while (OThreadCLI.available()) { + char c = OThreadCLI.read(); + // echo it back to the console + if (cli->echoback) { + if (c == '\n') { + cli->cliStream->println(); // follows whatever is defined as EOL in Arduino + } else { + cli->cliStream->write(c); + } + } + } + // print the prompt + if (cli->prompt && cli->echoback) { + cli->cliStream->printf(cli->prompt.c_str()); + } + } + } + } +} + +void OpenThreadCLI::setEchoBack(bool echoback) { + otConsole.echoback = echoback; +} + +void OpenThreadCLI::setPrompt(char *prompt) { + otConsole.prompt = prompt; // NULL will make the prompt not visible +} + +void OpenThreadCLI::setStream(Stream& otStream) { + otConsole.cliStream = &otStream; +} + +void onReceive(OnReceiveCb_t func) { + otConsole.responseCallBack = func; // NULL will set it off +} + +// Stream object shall be already started and configured before calling this function +void OpenThreadCLI::startOpenThreadConsole(Stream& otStream, bool echoback, const char *prompt) { + if (s_console_cli_task == NULL) { + otConsole.cliStream = &otStream; + otConsole.echoback = echoback; + otConsole.prompt = prompt; // NULL will invalidate the String + // it will run in the same priority (1) as the Arduino setup()/loop() task + xTaskCreate(ot_cli_console_worker, "ot_cli_console", 4096, &otConsole, 1, &s_console_cli_task); + } else { + log_w("A console is already running. Please stop it before starting a new one."); + } +} + +void OpenThreadCLI::stopOpenThreadConsole() { + if (s_console_cli_task) { + vTaskDelete(s_console_cli_task); + s_console_cli_task = NULL; + } +} + +OpenThreadCLI::OpenThreadCLI() { + memset(&ot_native_config, 0, sizeof(esp_openthread_platform_config_t)); + ot_native_config.radio_config.radio_mode = RADIO_MODE_NATIVE; + ot_native_config.host_config.host_connection_mode = HOST_CONNECTION_MODE_NONE; + ot_native_config.port_config.storage_partition_name = "nvs"; + ot_native_config.port_config.netif_queue_size = 10; + ot_native_config.port_config.task_queue_size = 10; + //sTxString = ""; +} + +OpenThreadCLI::~OpenThreadCLI() { + end(); +} + +static void ot_task_worker(void *aContext) { + esp_vfs_eventfd_config_t eventfd_config = { + .max_fds = 3, + }; + bool err = false; + if (ESP_OK != esp_event_loop_create_default()) { + log_e("Failed to create OpentThread event loop"); + err = true; + } + if (!err && ESP_OK != esp_netif_init()) { + log_e("Failed to initialize OpentThread netif"); + err = true; + } + if (!err && ESP_OK != esp_vfs_eventfd_register(&eventfd_config)) { + log_e("Failed to register OpentThread eventfd"); + err = true; + } + + // Initialize the OpenThread stack + if (!err && ESP_OK != esp_openthread_init(&ot_native_config)) { + log_e("Failed to initialize OpenThread stack"); + err = true; + } + if (!err) { + // Initialize the OpenThread cli + otCliInit(esp_openthread_get_instance(), OTcli_output_callback, NULL); + + // Initialize the esp_netif bindings + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); + openthread_netif = esp_netif_new(&cfg); + } + if (!err && openthread_netif == NULL) { + log_e("Failed to create OpenThread esp_netif"); + err = true; + } + if (!err && ESP_OK != esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&ot_native_config))) { + log_e("Failed to attach OpenThread esp_netif"); + err = true; + } + if (!err && ESP_OK != esp_netif_set_default_netif(openthread_netif)) { + log_e("Failed to set default OpenThread esp_netif"); + err = true; + } + if (!err) { + // only returns in case there is an OpenThread Stack failure... + esp_openthread_launch_mainloop(); + } + // Clean up + esp_openthread_netif_glue_deinit(); + esp_netif_destroy(openthread_netif); + esp_vfs_eventfd_unregister(); + vTaskDelete(NULL); +} + +void OpenThreadCLI::begin(bool OThreadAutoStart) { + xTaskCreate(ot_task_worker, "ot_main_loop", 10240, NULL, 20, &s_ot_task); + + //RX Buffer default has 1024 bytes if not preset + if (rx_queue == NULL) { + if (!setRxBufferSize(1024)) { + log_e("HW CDC RX Buffer error"); + } + } + //TX Buffer default has 256 bytes if not preset + if (tx_queue == NULL) { + if (!setTxBufferSize(256)) { + log_e("HW CDC RX Buffer error"); + } + } + xTaskCreate(ot_cli_loop, "ot_cli", 4096, xTaskGetCurrentTaskHandle(), 2, &s_cli_task); + + // starts Thread with default dataset from NVS or from IDF default settings + if (OThreadAutoStart) { + otOperationalDatasetTlvs dataset; + otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); + // error = OT_ERROR_FAILED; // teste para forçar NULL dataset + if (error != OT_ERROR_NONE) { + log_i("Failed to get active NVS dataset from OpenThread"); + } else { + log_i("Got active NVS dataset from OpenThread"); + } +#if 1 + esp_err_t err = esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL); + if (err != ESP_OK) { + log_i("Failed to AUTO start OpenThread"); + } else { + log_i("AUTO start OpenThread done"); + } + +#else + if (dataset.mLength > 0) { + Serial.println("There is a dataset in NVS. Trying to start OpenThread..."); + log_i("There is a dataset in NVS. Trying to start OpenThread..."); + if (IDFesp_openthread_auto_start(&dataset) != ESP_OK) { + Serial.println("Failed to start OpenThread using NVS dataset. Trying a new one..."); + log_i("Failed to start OpenThread using NVS dataset. Trying a new one..."); + if (IDFesp_openthread_auto_start(NULL) != ESP_OK) { + Serial.println("Failed to start OpenThread using a new dataset"); + log_i("Failed to start OpenThread using a new dataset"); + } + } + } else { + Serial.println("There is no dataset in NVS. Trying a new one..."); + log_i("There is no dataset in NVS. Trying a new one..."); + if (IDFesp_openthread_auto_start(NULL) != ESP_OK) { + Serial.println("Failed to start OpenThread using a new dataset"); + log_i("Failed to start OpenThread using a new dataset"); + } + } +#endif + } + return; +} + +void OpenThreadCLI::end() { + if (s_ot_task != NULL) { + vTaskDelete(s_ot_task); + // Clean up + esp_openthread_netif_glue_deinit(); + esp_netif_destroy(openthread_netif); + esp_vfs_eventfd_unregister(); + } + if (s_cli_task != NULL) { + vTaskDelete(s_cli_task); + } + if (s_console_cli_task != NULL) { + vTaskDelete(s_console_cli_task); + } + setRxBufferSize(0); + setTxBufferSize(0); +} + + +size_t OpenThreadCLI::write(uint8_t c) { + if (rx_queue == NULL) { + return 0; + } + if (xQueueSend(tx_queue, &c, 0) != pdPASS) { + return 0; + } + return 1; +} + +size_t OpenThreadCLI::setBuffer(xQueueHandle & queue, size_t queue_len) { + if (queue) { + vQueueDelete(queue); + queue = NULL; + } + if (!queue_len) { + return 0; + } + queue = xQueueCreate(queue_len, sizeof(uint8_t)); + if (!queue) { + return 0; + } + return queue_len; +} + +size_t OpenThreadCLI::setTxBufferSize(size_t tx_queue_len) { + return setBuffer(tx_queue, tx_queue_len); +} + +size_t OpenThreadCLI::setRxBufferSize(size_t rx_queue_len) { + return setBuffer(rx_queue, rx_queue_len); +} + +int OpenThreadCLI::available(void) { + if (rx_queue == NULL) { + return -1; + } + return uxQueueMessagesWaiting(rx_queue); +} + +int OpenThreadCLI::peek(void) { + if (rx_queue == NULL) { + return -1; + } + uint8_t c; + if (xQueuePeek(rx_queue, &c, 0)) { + return c; + } + return -1; +} + +int OpenThreadCLI::read(void) { + if (rx_queue == NULL) { + return -1; + } + uint8_t c = 0; + if (xQueueReceive(rx_queue, &c, 0) == pdTRUE) { + return c; + } + return -1; +} + +void OpenThreadCLI::flush() { + // wait for the TX Queue to be empty + while (uxQueueMessagesWaiting(tx_queue)); +} + + +OpenThreadCLI OThreadCLI; +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h new file mode 100644 index 00000000000..3db3cf75d8d --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -0,0 +1,53 @@ +#pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + +#include "esp_openthread.h" +#include "esp_openthread_cli.h" +#include "esp_openthread_lock.h" +#include "esp_openthread_netif_glue.h" +#include "esp_openthread_types.h" + +#include "openthread/cli.h" +#include "openthread/instance.h" +#include "openthread/logging.h" +#include "openthread/tasklet.h" +#include "openthread/dataset_ftd.h" + +#include "Arduino.h" + +typedef std::function OnReceiveCb_t; + +class OpenThreadCLI : public Stream { +private: + static size_t setBuffer(xQueueHandle &queue, size_t len); +public: + OpenThreadCLI(); + ~OpenThreadCLI(); + + // starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. + void startOpenThreadConsole(Stream& otStream, bool echoback = true, const char *prompt = "ot> "); + void stopOpenThreadConsole(); + void setPrompt(char *prompt); // changes the console prompt. NULL is an empty prompt. + void setEchoBack(bool echoback); // changes the console echoback option + void setStream(Stream& otStream); // changes the console Stream object + void onReceive(OnReceiveCb_t func); // called on a complete line of output from OT CLI, as OT Response + + void begin(bool OThreadAutoStart = true); + void end(); + + // default size is 256 bytes + size_t setTxBufferSize(size_t tx_queue_len); + // default size is 1024 bytes + size_t setRxBufferSize(size_t rx_queue_len); + + size_t write(uint8_t); + int available(); + int read(); + int peek(); + void flush(); +}; + +extern OpenThreadCLI OThreadCLI; + +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp new file mode 100644 index 00000000000..50d8b696174 --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -0,0 +1,74 @@ +#include "OThreadCLI.h" +#if SOC_IEEE802154_SUPPORTED +#include "OThreadCLI_Util.h" + +static const char *otRoleString[] = { + "Disabled", ///< The Thread stack is disabled. + "Detached", ///< Not currently participating in a Thread network/partition. + "Child", ///< The Thread Child role. + "Router", ///< The Thread Router role. + "Leader", ///< The Thread Leader role. +}; + +ot_device_role_t getOtDeviceRole() { + otInstance *instance = esp_openthread_get_instance(); + return (ot_device_role_t) otThreadGetDeviceRole(instance); +} + +const char* getStringOtDeviceRole() { + return otRoleString[getOtDeviceRole()]; +} + +bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode) { + char cliResp[256]; + if (arg == NULL) { + OThreadCLI.println(cmd); + } else { + OThreadCLI.print(cmd); + OThreadCLI.print(" "); + OThreadCLI.println(arg); + } + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + log_d("CMD[%s %s] Resp[%s]", cmd, arg, cliResp); + // initial returnCode is success values + if (returnCode) { + returnCode->errorCode = 0; + returnCode->errorMessage = "Done"; + } + if (!strncmp(cliResp, "Done", 4)) { + return true; + } else { + if (returnCode) { + // initial setting is a bad error message or it is something else... + // return -1 and the full returned message + returnCode->errorCode = -1; + returnCode->errorMessage = cliResp; + // parse cliResp looking for errorCode and errorMessage + // OT CLI error message format is "Error ##: msg\n" - Example: + //Error 35: InvalidCommand + //Error 7: InvalidArgs + char *i = cliResp; + char *m = cliResp; + while (*i && *i != ':') i++; + if (*i) { + *i = '\0'; + m = i + 2; // message is 2 characters after ':' + while (i > cliResp && *i != ' ') i--; // search for ' ' before ":' + if (*i == ' ') { + i++; // move it forward to the number begining + returnCode->errorCode = atoi(i); + returnCode->errorMessage = m; + } // otherwise, it will keep the "bad error message" information + } // otherwise, it will keep the "bad error message" information + } // returnCode is NULL pointer + return false; + } +} + +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h new file mode 100644 index 00000000000..293a4cb20ea --- /dev/null +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -0,0 +1,22 @@ +#pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + +typedef enum { + OT_ROLE_DISABLED = 0, ///< The Thread stack is disabled. + OT_ROLE_DETACHED = 1, ///< Not currently participating in a Thread network/partition. + OT_ROLE_CHILD = 2, ///< The Thread Child role. + OT_ROLE_ROUTER = 3, ///< The Thread Router role. + OT_ROLE_LEADER = 4, ///< The Thread Leader role. +} ot_device_role_t; + +typedef struct { + int errorCode; + String errorMessage; +} ot_cmd_return_t; + +ot_device_role_t getOtDeviceRole(); +const char* getStringOtDeviceRole(); +bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); + +#endif \ No newline at end of file From 1a66bc186429b6ccfa6ffea7879d9e2a89ec95fc Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 03:15:32 -0300 Subject: [PATCH 02/25] fix(OpenThread): fixes file list in CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47cdfda906a..88495b7018d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,7 +161,7 @@ set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) set(ARDUINO_LIBRARY_OpenThread_SRCS libraries/OpenThread/src/OThreadCLI.cpp - libraries/OpenThread/src/OThreadCLI_Util.c) + libraries/OpenThread/src/OThreadCLI_Util.cpp) set(ARDUINO_LIBRARY_PPP_SRCS libraries/PPP/src/PPP.cpp From 54f043aebafa060f1e26f1cf9d710c95fc46a4aa Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 08:43:08 -0300 Subject: [PATCH 03/25] fix(openthread): Fixes JSON CI Files --- libraries/OpenThread/examples/COAP/coap_lamp/ci.json | 8 ++++---- libraries/OpenThread/examples/COAP/coap_switch/ci.json | 8 ++++---- libraries/OpenThread/examples/SimpleCLI/ci.json | 8 ++++---- libraries/OpenThread/examples/SimpleNode/ci.json | 8 ++++---- .../examples/SimpleThreadNetwork/LeaderNode/ci.json | 8 ++++---- .../examples/SimpleThreadNetwork/RouterNode/ci.json | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json index 742d0567b8e..6bcf9bff49b 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false - "esp32c2": false - "esp32c3": false - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, "esp32s3": false } } diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json index 742d0567b8e..6bcf9bff49b 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false - "esp32c2": false - "esp32c3": false - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json index 742d0567b8e..6bcf9bff49b 100644 --- a/libraries/OpenThread/examples/SimpleCLI/ci.json +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false - "esp32c2": false - "esp32c3": false - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json index 742d0567b8e..6bcf9bff49b 100644 --- a/libraries/OpenThread/examples/SimpleNode/ci.json +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false - "esp32c2": false - "esp32c3": false - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json index 742d0567b8e..6bcf9bff49b 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false - "esp32c2": false - "esp32c3": false - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, "esp32s3": false } } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json index 742d0567b8e..6bcf9bff49b 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json @@ -1,9 +1,9 @@ { "targets": { - "esp32": false - "esp32c2": false - "esp32c3": false - "esp32s2": false + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, "esp32s3": false } } From 3e1134326e85ef67bfbfd1c8cbec0282390f49b8 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 09:19:26 -0300 Subject: [PATCH 04/25] fix(openthread): Fixes JSON CI Files --- libraries/OpenThread/examples/COAP/coap_lamp/ci.json | 3 +-- libraries/OpenThread/examples/COAP/coap_switch/ci.json | 3 +-- libraries/OpenThread/examples/SimpleCLI/ci.json | 3 +-- libraries/OpenThread/examples/SimpleNode/ci.json | 3 +-- .../OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json | 3 +-- .../OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json index 6bcf9bff49b..68806c42a07 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json @@ -6,5 +6,4 @@ "esp32s2": false, "esp32s3": false } - } - \ No newline at end of file + } \ No newline at end of file diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json index 6bcf9bff49b..68806c42a07 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -6,5 +6,4 @@ "esp32s2": false, "esp32s3": false } - } - \ No newline at end of file + } \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json index 6bcf9bff49b..68806c42a07 100644 --- a/libraries/OpenThread/examples/SimpleCLI/ci.json +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -6,5 +6,4 @@ "esp32s2": false, "esp32s3": false } - } - \ No newline at end of file + } \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json index 6bcf9bff49b..68806c42a07 100644 --- a/libraries/OpenThread/examples/SimpleNode/ci.json +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -6,5 +6,4 @@ "esp32s2": false, "esp32s3": false } - } - \ No newline at end of file + } \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json index 6bcf9bff49b..68806c42a07 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json @@ -6,5 +6,4 @@ "esp32s2": false, "esp32s3": false } - } - \ No newline at end of file + } \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json index 6bcf9bff49b..68806c42a07 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json @@ -6,5 +6,4 @@ "esp32s2": false, "esp32s3": false } - } - \ No newline at end of file + } \ No newline at end of file From 1b2530daef96fa026c779bc8760dfc99c32d4b57 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 09:33:40 -0300 Subject: [PATCH 05/25] fix(openthread): Include Openthread guarding --- libraries/OpenThread/src/OThreadCLI.cpp | 3 ++- libraries/OpenThread/src/OThreadCLI.h | 7 +++++-- libraries/OpenThread/src/OThreadCLI_Util.cpp | 3 +-- libraries/OpenThread/src/OThreadCLI_Util.h | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 83fb38231b2..0bb9b2252ea 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -421,4 +421,5 @@ void OpenThreadCLI::flush() { OpenThreadCLI OThreadCLI; -#endif // SOC_IEEE802154_SUPPORTED + +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index 3db3cf75d8d..e4c697fbd9f 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -8,6 +8,9 @@ #include "esp_openthread_netif_glue.h" #include "esp_openthread_types.h" +#include "sdkconfig.h" +#if CONFIG_OPENTHREAD_ENABLED + #include "openthread/cli.h" #include "openthread/instance.h" #include "openthread/logging.h" @@ -49,5 +52,5 @@ class OpenThreadCLI : public Stream { }; extern OpenThreadCLI OThreadCLI; - -#endif // SOC_IEEE802154_SUPPORTED +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index 50d8b696174..edc56fd948b 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -70,5 +70,4 @@ bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode return false; } } - -#endif // SOC_IEEE802154_SUPPORTED +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h index 293a4cb20ea..8fb2e667bb1 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.h +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -19,4 +19,4 @@ ot_device_role_t getOtDeviceRole(); const char* getStringOtDeviceRole(); bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); -#endif \ No newline at end of file +#endif /* SOC_IEEE802154_SUPPORTED */ \ No newline at end of file From 739b77c2cb3f45ffbec9dcb2cec11be233db0fa0 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 09:54:03 -0300 Subject: [PATCH 06/25] fix(openthread): COAP parametrization --- .../examples/COAP/coap_lamp/coap_lamp.ino | 6 ++++-- .../examples/COAP/coap_switch/coap_switch.ino | 14 ++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino index ff782d73c5c..b21ebb5c7ce 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -3,6 +3,8 @@ #define OT_CHANNEL "24" #define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define OT_MCAST_ADDR "ff05::abcd" +#define OT_COAP_RESOURCE_NAME "Lamp" const char *otSetupLeader[] = { // clear/disable all @@ -22,10 +24,10 @@ const char *otSetupLeader[] = { const char *otCoapLamp[] = { // create a multicast IPv6 Address for this device - "ipmaddr add", "ff05::abcd", + "ipmaddr add", OT_MCAST_ADDR, // start and create a CoAP resource "coap", "start", - "coap resource", "Lamp", + "coap resource", OT_COAP_RESOURCE_NAME, "coap set", "0" }; diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino index 60545cdb681..d4a2ed76e9a 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -4,6 +4,8 @@ #define USER_BUTTON 9 // C6/H2 Boot button #define OT_CHANNEL "24" #define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define OT_MCAST_ADDR "ff05::abcd" +#define OT_COAP_RESOURCE_NAME "Lamp" const char *otSetupChild[] = { // clear/disable all @@ -88,13 +90,17 @@ void setupNode() { // Sends the CoAP frame to the Lamp node bool otCoapPUT(bool lampState) { bool gotDone = false, gotConfirmation = false; - char coapMsg[] = "coap put ff05::abcd Lamp con 0"; + String coapMsg = "coap put "; + coapMsg += OT_MCAST_ADDR; + coapMsg += " "; + coapMsg += OT_COAP_RESOURCE_NAME; + coapMsg += " con 0"; if (lampState) { - coapMsg[strlen(coapMsg) - 1] = '1'; + coapMsg[coapMsg.length() - 1] = '1'; } - OThreadCLI.println(coapMsg); - log_d("Send CLI CMD:[%s]", coapMsg); + OThreadCLI.println(coapMsg.c_str()); + log_d("Send CLI CMD:[%s]", coapMsg.c_str()); char cliResp[256]; // waits for the CoAP confirmation and Done message for about 5 seconds From 3687c5fbcbc3a03527aa2e4f566f455f5ef49c02 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 10:16:48 -0300 Subject: [PATCH 07/25] fix(openthread): Include Openthread guarding --- libraries/OpenThread/src/OThreadCLI.cpp | 2 ++ libraries/OpenThread/src/OThreadCLI.h | 6 +++--- libraries/OpenThread/src/OThreadCLI_Util.cpp | 4 ++++ libraries/OpenThread/src/OThreadCLI_Util.h | 3 +++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 0bb9b2252ea..322482ec514 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -1,5 +1,6 @@ #include "OThreadCLI.h" #if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED #include "Arduino.h" #include "OThreadCLI.h" @@ -422,4 +423,5 @@ void OpenThreadCLI::flush() { OpenThreadCLI OThreadCLI; +#endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index e4c697fbd9f..148fb7eeb61 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -1,6 +1,8 @@ #pragma once #include "soc/soc_caps.h" +#include "sdkconfig.h" #if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED #include "esp_openthread.h" #include "esp_openthread_cli.h" @@ -8,9 +10,6 @@ #include "esp_openthread_netif_glue.h" #include "esp_openthread_types.h" -#include "sdkconfig.h" -#if CONFIG_OPENTHREAD_ENABLED - #include "openthread/cli.h" #include "openthread/instance.h" #include "openthread/logging.h" @@ -52,5 +51,6 @@ class OpenThreadCLI : public Stream { }; extern OpenThreadCLI OThreadCLI; + #endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index edc56fd948b..be901b0764d 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -1,5 +1,7 @@ #include "OThreadCLI.h" #if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + #include "OThreadCLI_Util.h" static const char *otRoleString[] = { @@ -70,4 +72,6 @@ bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode return false; } } + +#endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h index 8fb2e667bb1..9dc4f1dbb87 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.h +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -1,6 +1,8 @@ #pragma once #include "soc/soc_caps.h" +#include "sdkconfig.h" #if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED typedef enum { OT_ROLE_DISABLED = 0, ///< The Thread stack is disabled. @@ -19,4 +21,5 @@ ot_device_role_t getOtDeviceRole(); const char* getStringOtDeviceRole(); bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); +#endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ \ No newline at end of file From bbece1c509809b41a2d1155a69ee50f3f59e2ddd Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 11:46:08 -0300 Subject: [PATCH 08/25] fix(openthread): Improves commentaries and code --- .../examples/COAP/coap_lamp/coap_lamp.ino | 11 +++++++---- .../examples/COAP/coap_switch/coap_switch.ino | 17 +++++++++-------- .../OpenThread/examples/SimpleCLI/SimpleCLI.ino | 4 ++-- .../LeaderNode/LeaderNode.ino | 6 +++--- .../RouterNode/RouterNode.ino | 4 ++-- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino index b21ebb5c7ce..2a8f847a347 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -93,15 +93,17 @@ void setupNode() { // this function is used by the Lamp mode to listen for CoAP frames from the Switch Node void otCOAPListen() { // waits for the client to send a CoAP request - char cliResp[256]; + char cliResp[256] = {0}; size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); - cliResp[len] = '\0'; + cliResp[len - 1] = '\0'; if (strlen(cliResp)) { String sResp(cliResp); + // cliResp shall be something like: + // "coap request from fd0c:94df:f1ae:b39a:ec47:ec6d:15e8:804a PUT with payload: 30" + // payload may be 30 or 31 (HEX) '0' or '1' (ASCII) log_d("Msg[%s]", cliResp); if (sResp.startsWith("coap request from") && sResp.indexOf("PUT") > 0) { - uint16_t payloadIdx = sResp.indexOf("payload: ") + 10; // 0x30 | 0x31 - char payload = sResp.charAt(payloadIdx); + char payload = sResp.charAt(sResp.length() - 1); // last character in the payload log_i("CoAP PUT [%s]\r\n", payload == '0' ? "OFF" : "ON"); if (payload == '0') { for (int16_t c = 248; c > 16; c -= 8) { @@ -127,6 +129,7 @@ void setup() { OThreadCLI.begin(false); // No AutoStart is necessary OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response setupNode(); + // LED goes Green when all is ready and Red when failed. } void loop() { diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino index d4a2ed76e9a..23cb4c64df4 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -67,7 +67,7 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap return false; } Serial.println("OpenThread setup done. Node is ready."); - // all fine! LED goes Blue + // all fine! LED goes and stays Blue neopixelWrite(RGB_BUILTIN, 0, 0, 64); // BLUE ... Swtich is ready! return true; } @@ -96,6 +96,7 @@ bool otCoapPUT(bool lampState) { coapMsg += OT_COAP_RESOURCE_NAME; coapMsg += " con 0"; + // final command is "coap put ff05::abcd Lamp con 1" or "coap put ff05::abcd Lamp con 0" if (lampState) { coapMsg[coapMsg.length() - 1] = '1'; } @@ -103,16 +104,16 @@ bool otCoapPUT(bool lampState) { log_d("Send CLI CMD:[%s]", coapMsg.c_str()); char cliResp[256]; - // waits for the CoAP confirmation and Done message for about 5 seconds + // waits for the CoAP confirmation and Done message for about 1.25 seconds // timeout is based on Stream::setTimeout() + // Example of the expected confirmation response: "coap response from fdae:3289:1783:5c3f:fd84:c714:7e83:6122" uint8_t tries = 5; *cliResp = '\0'; while (tries && !(gotDone && gotConfirmation)) { size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); - cliResp[len] = '\0'; + cliResp[len - 1] = '\0'; log_d("Try[%d]::MSG[%s]", tries, cliResp); if (strlen(cliResp)) { - log_d("%s", cliResp); if (!strncmp(cliResp, "coap response from", 18)) { gotConfirmation = true; } @@ -132,13 +133,12 @@ bool otCoapPUT(bool lampState) { void checkUserButton() { static long unsigned int lastPress = 0; const long unsigned int debounceTime = 500; - static bool lastLampState = false; + static bool lastLampState = true; // first button press will turn the Lamp OFF from inital Green pinMode(USER_BUTTON, INPUT_PULLUP); // C6/H2 User Button if (millis() > lastPress + debounceTime && digitalRead(USER_BUTTON) == LOW) { - if (otCoapPUT(!lastLampState)) { - lastLampState = !lastLampState; - } else { + lastLampState = !lastLampState; + if (!otCoapPUT(lastLampState)) { // failed: Lamp Node is not responding due to be off or unreachable // timeout from the CoAP PUT message... restart the node. neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... something failed! Serial.println("Reseting the Node as Switch... wait."); @@ -156,6 +156,7 @@ void setup() { OThreadCLI.begin(false); // No AutoStart is necessary OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response setupNode(); + // LED goes and keeps Blue when all is ready and Red when failed. } void loop() { diff --git a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino index 311788d7969..b21a431b68a 100644 --- a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino +++ b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino @@ -1,6 +1,6 @@ /* - * OpenThread.begin(false) will not start a node in a Thread Network - * You will need to start it manually using the OpenThread CLI commands + * OpenThread.begin(false) will not automatically start a node in a Thread Network + * The user will need to start it manually using the OpenThread CLI commands * Use the Serial Monitor to interact with the OpenThread CLI * * Type 'help' for a list of commands. diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino index e11e9b7c9f6..abbc3f08525 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -1,7 +1,7 @@ /* - * OpenThread.begin(false) will not start a node in a Thread Network - * A Leader node is the first device to start Thread that has a complete dataset - * This is achieved by using the OpenThread CLI command "dataset init new" + * OpenThread.begin(false) will not automatically start a node in a Thread Network + * A Leader node is the first device, that has a complete dataset, to start Thread + * A complete dataset is easily achieved by using the OpenThread CLI command "dataset init new" * * In order to allow other node to join the network, * all of them shall use the same network master key diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino index f1bad7a9a16..c5c6b1ad05f 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -1,6 +1,6 @@ /* - * OpenThread.begin(false) will not start a node in a Thread Network - * A Router/Child node is the device that will join an existent Thread Network + * OpenThread.begin(false) will not automatically start a node in a Thread Network + * A Router/Child node is the device that will join an existing Thread Network * * In order to allow this node to join the network, * it shall use the same network master key as used by the Leader Node From 5c677bec68d837f81799b9e56df03543b248ec03 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 14:24:58 -0300 Subject: [PATCH 09/25] fix(openthread): Improves code --- .../examples/COAP/coap_lamp/coap_lamp.ino | 6 +- .../examples/COAP/coap_switch/coap_switch.ino | 6 +- .../examples/SimpleNode/SimpleNode.ino | 3 +- .../LeaderNode/LeaderNode.ino | 2 +- .../RouterNode/RouterNode.ino | 2 +- libraries/OpenThread/keywords.txt | 6 +- libraries/OpenThread/src/OThreadCLI.cpp | 28 ++---- libraries/OpenThread/src/OThreadCLI.h | 2 + libraries/OpenThread/src/OThreadCLI_Util.cpp | 92 ++++++++++++++++++- libraries/OpenThread/src/OThreadCLI_Util.h | 6 +- 10 files changed, 114 insertions(+), 39 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino index 2a8f847a347..68b2865bb71 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -48,18 +48,18 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); // wait for the expected Device Role to start uint8_t tries = 24; // 24 x 2.5 sec = 1 min - while (tries && getOtDeviceRole() != expectedRole) { + while (tries && otGetDeviceRole() != expectedRole) { Serial.print("."); delay(2500); tries--; } Serial.println(); if (!tries) { - log_e("Sorry, Device Role failed by timeout! Current Role: %s.", getStringOtDeviceRole()); + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", otGetStringDeviceRole()); neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! return false; } - Serial.printf("Device is %s.\r\n", getStringOtDeviceRole()); + Serial.printf("Device is %s.\r\n", otGetStringDeviceRole()); for (i = 0; i < nCmds2; i++) { if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { break; diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino index 23cb4c64df4..de1ea6d1cd7 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -44,18 +44,18 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); // wait for the expected Device Role to start uint8_t tries = 24; // 24 x 2.5 sec = 1 min - while (tries && getOtDeviceRole() != expectedRole1 && getOtDeviceRole() != expectedRole2) { + while (tries && otGetDeviceRole() != expectedRole1 && otGetDeviceRole() != expectedRole2) { Serial.print("."); delay(2500); tries--; } Serial.println(); if (!tries) { - log_e("Sorry, Device Role failed by timeout! Current Role: %s.", getStringOtDeviceRole()); + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", otGetStringDeviceRole()); neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! return false; } - Serial.printf("Device is %s.\r\n", getStringOtDeviceRole()); + Serial.printf("Device is %s.\r\n", otGetStringDeviceRole()); for (i = 0; i < nCmds2; i++) { if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { break; diff --git a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino index a0a240f5598..e895153e43a 100644 --- a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino +++ b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino @@ -22,10 +22,11 @@ void setup() { Serial.begin(115200); OThreadCLI.begin(); // AutoStart using Thread default settings + otPrintNetworkInformation(Serial); // Print Current Thread Network Information } void loop() { Serial.print("Thread Node State: "); - Serial.println(getStringOtDeviceRole()); + Serial.println(otGetStringDeviceRole()); delay(5000); } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino index abbc3f08525..59d597b6bba 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -32,6 +32,6 @@ void setup() { void loop() { Serial.print("Thread Node State: "); - Serial.println(getStringOtDeviceRole()); + Serial.println(otGetStringDeviceRole()); delay(5000); } \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino index c5c6b1ad05f..129b6217d79 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -32,6 +32,6 @@ void setup() { void loop() { Serial.print("Thread Node State: "); - Serial.println(getStringOtDeviceRole()); + Serial.println(otGetStringDeviceRole()); delay(5000); } diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt index a7a1cdc5c34..c1a8b5410c6 100644 --- a/libraries/OpenThread/keywords.txt +++ b/libraries/OpenThread/keywords.txt @@ -29,9 +29,11 @@ available KEYWORD2 read KEYWORD2 peek KEYWORD2 flush KEYWORD2 -getOtDeviceRole KEYWORD2 -getStringOtDeviceRole KEYWORD2 +otGetDeviceRole KEYWORD2 +otGetStringDeviceRole KEYWORD2 +otGetRespCmd KEYWORD2 otExecCommand KEYWORD2 +otPrintNetworkInformation KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 322482ec514..c0d3c297208 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -220,6 +220,10 @@ OpenThreadCLI::~OpenThreadCLI() { end(); } +OpenThreadCLI::operator bool() const { + return otStarted; +} + static void ot_task_worker(void *aContext) { esp_vfs_eventfd_config_t eventfd_config = { .max_fds = 3, @@ -301,7 +305,6 @@ void OpenThreadCLI::begin(bool OThreadAutoStart) { } else { log_i("Got active NVS dataset from OpenThread"); } -#if 1 esp_err_t err = esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL); if (err != ESP_OK) { log_i("Failed to AUTO start OpenThread"); @@ -309,28 +312,8 @@ void OpenThreadCLI::begin(bool OThreadAutoStart) { log_i("AUTO start OpenThread done"); } -#else - if (dataset.mLength > 0) { - Serial.println("There is a dataset in NVS. Trying to start OpenThread..."); - log_i("There is a dataset in NVS. Trying to start OpenThread..."); - if (IDFesp_openthread_auto_start(&dataset) != ESP_OK) { - Serial.println("Failed to start OpenThread using NVS dataset. Trying a new one..."); - log_i("Failed to start OpenThread using NVS dataset. Trying a new one..."); - if (IDFesp_openthread_auto_start(NULL) != ESP_OK) { - Serial.println("Failed to start OpenThread using a new dataset"); - log_i("Failed to start OpenThread using a new dataset"); - } - } - } else { - Serial.println("There is no dataset in NVS. Trying a new one..."); - log_i("There is no dataset in NVS. Trying a new one..."); - if (IDFesp_openthread_auto_start(NULL) != ESP_OK) { - Serial.println("Failed to start OpenThread using a new dataset"); - log_i("Failed to start OpenThread using a new dataset"); - } - } -#endif } + otStarted = true; return; } @@ -350,6 +333,7 @@ void OpenThreadCLI::end() { } setRxBufferSize(0); setTxBufferSize(0); + otStarted = false; } diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index 148fb7eeb61..e4b9a503e34 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -23,9 +23,11 @@ typedef std::function OnReceiveCb_t; class OpenThreadCLI : public Stream { private: static size_t setBuffer(xQueueHandle &queue, size_t len); + bool otStarted = false; public: OpenThreadCLI(); ~OpenThreadCLI(); + operator bool() const; // starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. void startOpenThreadConsole(Stream& otStream, bool echoback = true, const char *prompt = "ot> "); diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index be901b0764d..06f53def0c4 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -12,17 +12,66 @@ static const char *otRoleString[] = { "Leader", ///< The Thread Leader role. }; -ot_device_role_t getOtDeviceRole() { +ot_device_role_t otGetDeviceRole() { + if (!OThreadCLI) { + return OT_ROLE_DISABLED; + } otInstance *instance = esp_openthread_get_instance(); return (ot_device_role_t) otThreadGetDeviceRole(instance); } -const char* getStringOtDeviceRole() { - return otRoleString[getOtDeviceRole()]; +const char* otGetStringDeviceRole() { + return otRoleString[otGetDeviceRole()]; +} + +bool otGetRespCmd(const char *cmd, char *resp, uint32_t respTimeout) { + if (!OThreadCLI) { + return false; + } + StreamString cliRespAllLines; + char cliResp[256] = {0}; + if (resp != NULL) { + *resp = '\0'; + } + if (cmd == NULL) { + return true; + } + OThreadCLI.println(cmd); + log_d("CMD[%s]", cmd); + uint32_t timeout = millis() + respTimeout; + while(millis() < timeout) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + log_d("Resp[%s]", cliResp); + if (strncmp(cliResp, "Done", 4) && strncmp(cliResp, "Error", 4)) { + cliRespAllLines += cliResp; + cliRespAllLines.println(); // Adds whatever EOL is for the OS + } else { + break; + } + } + if (!strncmp(cliResp, "Error", 4) || millis() > timeout) { + return false; + } + if (resp != NULL) { + strcpy(resp, cliRespAllLines.c_str()); + } + return true; } bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode) { - char cliResp[256]; + if (!OThreadCLI) { + return false; + } + char cliResp[256] = {0}; + if (cmd == NULL) { + return true; + } if (arg == NULL) { OThreadCLI.println(cmd); } else { @@ -73,5 +122,40 @@ bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode } } +void otPrintNetworkInformation(Stream &output) { + if (!OThreadCLI) { + return; + } + char resp[512]; + output.println("Thread Setup:"); + if (otGetRespCmd("state", resp)) { + output.printf("Node State: \t%s", resp); + } + if (otGetRespCmd("networkname", resp)) { + output.printf("Network Name: \t%s", resp); + } + if (otGetRespCmd("channel", resp)) { + output.printf("Channel: \t%s", resp); + } + if (otGetRespCmd("panid", resp)) { + output.printf("Pan ID: \t%s", resp); + } + if (otGetRespCmd("extpanid", resp)) { + output.printf("Ext Pan ID: \t%s", resp); + } + if (otGetRespCmd("networkkey", resp)) { + output.printf("Network Key: \t%s", resp); + } + if (otGetRespCmd("ipaddr", resp)) { + output.println("Node IP Addresses are:"); + output.printf("%s", resp); + } + if (otGetRespCmd("ipmaddr", resp)) { + output.println("Node Multicast Addresses are:"); + output.printf("%s", resp); + } +} + + #endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h index 9dc4f1dbb87..b691b83f078 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.h +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -17,9 +17,11 @@ typedef struct { String errorMessage; } ot_cmd_return_t; -ot_device_role_t getOtDeviceRole(); -const char* getStringOtDeviceRole(); +ot_device_role_t otGetDeviceRole(); +const char* otGetStringDeviceRole(); +bool otGetRespCmd(const char *cmd, char *resp = NULL, uint32_t respTimeout = 5000); bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); +void otPrintNetworkInformation(Stream &output); #endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ \ No newline at end of file From 436a7ffb89a0e19cc2a2c57dad3cd87e68ecc3fe Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 14:30:07 -0300 Subject: [PATCH 10/25] fix(openthread): Includes StreamString.h --- libraries/OpenThread/src/OThreadCLI_Util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index 06f53def0c4..bb9fb463700 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -3,6 +3,7 @@ #if CONFIG_OPENTHREAD_ENABLED #include "OThreadCLI_Util.h" +#include static const char *otRoleString[] = { "Disabled", ///< The Thread stack is disabled. From ce46f4a66d37f364306584b663680e02022b74cc Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 18:52:21 -0300 Subject: [PATCH 11/25] feat(openthread): New Scan Example --- .../examples/ThreadScan/ThreadScan.ino | 68 +++++++++++++++++++ .../OpenThread/examples/ThreadScan/ci.json | 9 +++ 2 files changed, 77 insertions(+) create mode 100644 libraries/OpenThread/examples/ThreadScan/ThreadScan.ino create mode 100644 libraries/OpenThread/examples/ThreadScan/ci.json diff --git a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino new file mode 100644 index 00000000000..2eedfc732f0 --- /dev/null +++ b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino @@ -0,0 +1,68 @@ +/* + OpenThread.begin(true) will automatically start a node in a Thread Network + Full scanning requires the thread node to be at least in Child state. + + This will scan the IEEE 802.14.5 devices in the local area using CLI "scan" command + As soon as this device turns into a Child, Router or Leader, it will be able to + scan for Local Thread Networks as well. + +*/ + +#include "OThreadCLI.h" +#include "OThreadCLI_Util.h" + +bool otPrintRespCLI(const char *cmd, Stream &output) { + char cliResp[256]; + if (cmd == NULL) { + return true; + } + OThreadCLI.println(cmd); + while (1) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + if (len == 0) { + return false; // timeout for reading a response from CLI + } + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + if (!strncmp(cliResp, "Done", 4)) { + return true; // finished with success + } + if (!strncmp(cliResp, "Error", 4)) { + return false; // the CLI command or its arguments are not valid + } + output.println(cliResp); + } +} + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(true); // For scanning, AutoStart must be active, any setup + OThreadCLI.setTimeout(10000); // 10 seconds for reading a line from CLI - scanning takes time + Serial.println(); + Serial.println("This sketch will continuosly scan the Thread Local Network and all devices IEEE 802.15.4 compatible"); +} + +void loop() { + Serial.println(); + Serial.println("Scanning for near by IEEE 802.15.4 devices:"); + // 802.15.4 Scan just need a previous OThreadCLI.begin() to tun on the 802.15.4 stack + if (!otPrintRespCLI("scan", Serial)) { + Serial.println("802.15.4 Scan Failed..."); + } + delay(5000); + if (otGetDeviceRole() < OT_ROLE_CHILD) { + Serial.println(); + Serial.println("This device has not started Thread yet, bypassing Discovery Scan"); + return; + } + Serial.println(); + Serial.println("Scanning - MLE Discover:"); + if (!otPrintRespCLI("discover", Serial)) { + Serial.println("MLE Discover Failed..."); + } + delay(5000); +} diff --git a/libraries/OpenThread/examples/ThreadScan/ci.json b/libraries/OpenThread/examples/ThreadScan/ci.json new file mode 100644 index 00000000000..68806c42a07 --- /dev/null +++ b/libraries/OpenThread/examples/ThreadScan/ci.json @@ -0,0 +1,9 @@ +{ + "targets": { + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + } + } \ No newline at end of file From 7fece86fbebc889ffad9d05b5d3b0ca487a0bcdb Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 19:09:11 -0300 Subject: [PATCH 12/25] feat(openthread): Improved Scan Example --- .../examples/ThreadScan/ThreadScan.ino | 45 ++++--------------- libraries/OpenThread/keywords.txt | 1 + libraries/OpenThread/src/OThreadCLI_Util.cpp | 33 ++++++++++++++ libraries/OpenThread/src/OThreadCLI_Util.h | 1 + 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino index 2eedfc732f0..905faa8a132 100644 --- a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino +++ b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino @@ -11,47 +11,20 @@ #include "OThreadCLI.h" #include "OThreadCLI_Util.h" -bool otPrintRespCLI(const char *cmd, Stream &output) { - char cliResp[256]; - if (cmd == NULL) { - return true; - } - OThreadCLI.println(cmd); - while (1) { - size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); - if (len == 0) { - return false; // timeout for reading a response from CLI - } - // clip it on EOL - for (int i = 0; i < len; i++) { - if (cliResp[i] == '\r' || cliResp[i] == '\n') { - cliResp[i] = '\0'; - } - } - if (!strncmp(cliResp, "Done", 4)) { - return true; // finished with success - } - if (!strncmp(cliResp, "Error", 4)) { - return false; // the CLI command or its arguments are not valid - } - output.println(cliResp); - } -} - void setup() { Serial.begin(115200); OThreadCLI.begin(true); // For scanning, AutoStart must be active, any setup - OThreadCLI.setTimeout(10000); // 10 seconds for reading a line from CLI - scanning takes time + OThreadCLI.setTimeout(100); // Set a timeout for the CLI response Serial.println(); - Serial.println("This sketch will continuosly scan the Thread Local Network and all devices IEEE 802.15.4 compatible"); + Serial.println("This sketch will continuously scan the Thread Local Network and all devices IEEE 802.15.4 compatible"); } void loop() { Serial.println(); - Serial.println("Scanning for near by IEEE 802.15.4 devices:"); - // 802.15.4 Scan just need a previous OThreadCLI.begin() to tun on the 802.15.4 stack - if (!otPrintRespCLI("scan", Serial)) { - Serial.println("802.15.4 Scan Failed..."); + Serial.println("Scanning for nearby IEEE 802.15.4 devices:"); + // 802.15.4 Scan just needs a previous OThreadCLI.begin() + if (!otPrintRespCLI("scan", Serial, 3000)) { + Serial.println("Scan Failed..."); } delay(5000); if (otGetDeviceRole() < OT_ROLE_CHILD) { @@ -60,9 +33,9 @@ void loop() { return; } Serial.println(); - Serial.println("Scanning - MLE Discover:"); - if (!otPrintRespCLI("discover", Serial)) { - Serial.println("MLE Discover Failed..."); + Serial.println("Scanning MLE Discover:"); + if (!otPrintRespCLI("discover", Serial, 3000)) { + Serial.println("Discover Failed..."); } delay(5000); } diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt index c1a8b5410c6..68963e354cd 100644 --- a/libraries/OpenThread/keywords.txt +++ b/libraries/OpenThread/keywords.txt @@ -33,6 +33,7 @@ otGetDeviceRole KEYWORD2 otGetStringDeviceRole KEYWORD2 otGetRespCmd KEYWORD2 otExecCommand KEYWORD2 +otPrintRespCLI KEYWORD2 otPrintNetworkInformation KEYWORD2 ####################################### diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index bb9fb463700..16629a20c5c 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -123,6 +123,39 @@ bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode } } +bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout) { + char cliResp[256] = {0}; + if (cmd == NULL) { + return true; + } + OThreadCLI.println(cmd); + uint32_t timeout = millis() + respTimeout; + while (millis() < timeout) { + size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); + if (cliResp[0] == '\0') { + // Straem has timed out and it should try again using parameter respTimeout + continue; + } + // clip it on EOL + for (int i = 0; i < len; i++) { + if (cliResp[i] == '\r' || cliResp[i] == '\n') { + cliResp[i] = '\0'; + } + } + if (strncmp(cliResp, "Done", 4) && strncmp(cliResp, "Error", 4)) { + output.println(cliResp); + memset(cliResp, 0, sizeof(cliResp)); + timeout = millis() + respTimeout; // renew timeout, line per line + } else { + break; + } + } + if (!strncmp(cliResp, "Error", 4) || millis() > timeout) { + return false; + } + return true; +} + void otPrintNetworkInformation(Stream &output) { if (!OThreadCLI) { return; diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h index b691b83f078..02a05c30b5f 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.h +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -21,6 +21,7 @@ ot_device_role_t otGetDeviceRole(); const char* otGetStringDeviceRole(); bool otGetRespCmd(const char *cmd, char *resp = NULL, uint32_t respTimeout = 5000); bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); +bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout); void otPrintNetworkInformation(Stream &output); #endif /* CONFIG_OPENTHREAD_ENABLED */ From 001ae42f5284d0f0cb09be5ad63caea87a07c248 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 21 Jun 2024 15:19:45 -0300 Subject: [PATCH 13/25] feat(openthread): README.md Initial documentation for ESP3 Arduino OpenThread CLI API. --- libraries/OpenThread/README.md | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 libraries/OpenThread/README.md diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md new file mode 100644 index 00000000000..9968c79870b --- /dev/null +++ b/libraries/OpenThread/README.md @@ -0,0 +1,68 @@ +# ESP32 Arduino OpenThreadCLI + +The `OpenThreadCLI` class is an Arduino API for interacting with the OpenThread Command Line Interface (CLI). It allows you to manage and configure the Thread stack using a command-line interface. Below are the details of the class: +The available OpenThread Commands are documented in the [OpenThread CLI Reference Page](https://openthread.io/reference/cli/commands) + +There is one main class called `OpenThreadCLI` and a global object used to operate OpenThread CLI, called `OThreadCLI` +Some [helper functions](helper_functions.md) were made available for working with the OpenThread CLI environment. + +It is important to note that the current implementation can only be used with Espressif SoC that has support to IEEE 802.15.4, such as **ESP32-C6** and **ESP32-H2**. + +## Class Definition + +```cpp +class OpenThreadCLI : public Stream { +private: + static size_t setBuffer(xQueueHandle &queue, size_t len); + bool otStarted = false; + +public: + OpenThreadCLI(); + ~OpenThreadCLI(); + operator bool() const; + + // Starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. + void startOpenThreadConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> "); + void stopOpenThreadConsole(); + void setPrompt(char* prompt); // Changes the console prompt. NULL is an empty prompt. + void setEchoBack(bool echoback); // Changes the console echoback option + void setStream(Stream& otStream); // Changes the console Stream object + void onReceive(OnReceiveCb_t func); // Called on a complete line of output from OT CLI, as OT Response + + void begin(bool OThreadAutoStart = true); + void end(); + + // Default size is 256 bytes + size_t setTxBufferSize(size_t tx_queue_len); + // Default size is 1024 bytes + size_t setRxBufferSize(size_t rx_queue_len); + + size_t write(uint8_t); + int available(); + int read(); + int peek(); + void flush(); +}; + +extern OpenThreadCLI OThreadCLI; +``` + +## Class Overview +- The `OpenThreadCLI` class inherits from the `Stream` class, making it compatible with Arduino's standard I/O functions. +- It provides methods for managing the OpenThread CLI, including starting and stopping the console, setting prompts, and handling received data. +- You can customize the console behavior by adjusting parameters such as echoback and buffer sizes. + +## Public Methods +- `startOpenThreadConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> ")`: Starts the OpenThread console with the specified stream, echoback option, and prompt. +- `stopOpenThreadConsole()`: Stops the OpenThread console. +- `setPrompt(char* prompt)`: Changes the console prompt (set to NULL for an empty prompt). +- `setEchoBack(bool echoback)`: Changes the console echoback option. +- `setStream(Stream& otStream)`: Changes the console Stream object. +- `onReceive(OnReceiveCb_t func)`: Sets a callback function to handle complete lines of output from the OT CLI. +- `begin(bool OThreadAutoStart = true)`: Initializes the OpenThread stack (optional auto-start). +- `end()`: Deinitializes the OpenThread stack. +- `setTxBufferSize(size_t tx_queue_len)`: Sets the transmit buffer size (default is 256 bytes). +- `setRxBufferSize(size_t rx_queue_len)`: Sets the receive buffer size (default is 1024 bytes). +- `write(uint8_t)`, `available()`, `read()`, `peek()`, `flush()`: Standard Stream methods implementation for OpenThread CLI object. + + From 198e6e8d3e1ee177e279aeced405c74645d8c6d0 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 21 Jun 2024 15:21:58 -0300 Subject: [PATCH 14/25] feat(openthread): helper functions documentation Create helper_functions.md for ESP32 Arduino OpenThread API --- libraries/OpenThread/helper_functions.md | 58 ++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 libraries/OpenThread/helper_functions.md diff --git a/libraries/OpenThread/helper_functions.md b/libraries/OpenThread/helper_functions.md new file mode 100644 index 00000000000..a3c4a2692e8 --- /dev/null +++ b/libraries/OpenThread/helper_functions.md @@ -0,0 +1,58 @@ +# OpenThread Helper Functions and Types + +The following helper functions and types are designed to simplify writing Arduino sketches for OpenThread. They provide useful utilities for managing OpenThread stack behavior and interacting with the Thread network. + +## Enumerated Type: `ot_device_role_t` + +This enumeration defines the possible roles of a Thread device within the network: + +- `OT_ROLE_DISABLED`: The Thread stack is disabled. +- `OT_ROLE_DETACHED`: The device is not currently participating in a Thread network/partition. +- `OT_ROLE_CHILD`: The device operates as a Thread Child. +- `OT_ROLE_ROUTER`: The device operates as a Thread Router. +- `OT_ROLE_LEADER`: The device operates as a Thread Leader. + +## Struct: `ot_cmd_return_t` + +This structure represents the return status of an OpenThread CLI command: + +- `errorCode`: An integer representing the error code (if any). +- `errorMessage`: A string containing an error message (if applicable). + +## Function: `otGetDeviceRole()` + +- Returns the current role of the device as an `ot_device_role_t` value. + +## Function: `otGetStringDeviceRole()` + +- Returns a human-readable string representation of the device role (e.g., "Child," "Router," etc.). + +## Function: `otGetRespCmd(const char* cmd, char* resp = NULL, uint32_t respTimeout = 5000)` + +- Executes an OpenThread CLI command and retrieves the response. +- Parameters: + - `cmd`: The OpenThread CLI command to execute. + - `resp`: Optional buffer to store the response (if provided). + - `respTimeout`: Timeout (in milliseconds) for waiting for the response. + +## Function: `otExecCommand(const char* cmd, const char* arg, ot_cmd_return_t* returnCode = NULL)` + +- Executes an OpenThread CLI command with an argument. +- Parameters: + - `cmd`: The OpenThread CLI command to execute. + - `arg`: The argument for the command. + - `returnCode`: Optional pointer to an `ot_cmd_return_t` structure to store the return status. + +## Function: `otPrintRespCLI(const char* cmd, Stream& output, uint32_t respTimeout)` + +- Executes an OpenThread CLI command and prints the response to the specified output stream. +- Parameters: + - `cmd`: The OpenThread CLI command to execute. + - `output`: The output stream (e.g., Serial) to print the response. + - `respTimeout`: Timeout (in milliseconds) for waiting for the response. + +## Function: `otPrintNetworkInformation(Stream& output)` + +- Prints information about the current Thread network to the specified output stream. +- Parameters: + - `output`: The output stream (e.g., Serial) to print the network information. From 28d7c44db017d599e062e6b571ebd4a0d2206e25 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sat, 22 Jun 2024 18:22:16 -0300 Subject: [PATCH 15/25] fix(openthread): begin end --- libraries/OpenThread/src/OThreadCLI.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index c0d3c297208..07bcf490f62 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -69,7 +69,7 @@ static void ot_cli_loop(void *context) { } // process the CLI responses received from the OpenThread stack -static int OTcli_output_callback(void *context, const char *format, va_list args) +static int ot_cli_output_callback(void *context, const char *format, va_list args) { char prompt_check[3]; int ret = 0; @@ -188,6 +188,11 @@ void onReceive(OnReceiveCb_t func) { // Stream object shall be already started and configured before calling this function void OpenThreadCLI::startOpenThreadConsole(Stream& otStream, bool echoback, const char *prompt) { + if (!otStarted) { + log_e("OpenThread CLI has not started. Please begin() it before starting the console."); + return; + } + if (s_console_cli_task == NULL) { otConsole.cliStream = &otStream; otConsole.echoback = echoback; @@ -249,7 +254,7 @@ static void ot_task_worker(void *aContext) { } if (!err) { // Initialize the OpenThread cli - otCliInit(esp_openthread_get_instance(), OTcli_output_callback, NULL); + otCliInit(esp_openthread_get_instance(), ot_cli_output_callback, NULL); // Initialize the esp_netif bindings esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); @@ -279,6 +284,11 @@ static void ot_task_worker(void *aContext) { } void OpenThreadCLI::begin(bool OThreadAutoStart) { + if (otStarted) { + log_w("OpenThread CLI already started. Please end() it before starting again."); + return; + } + xTaskCreate(ot_task_worker, "ot_main_loop", 10240, NULL, 20, &s_ot_task); //RX Buffer default has 1024 bytes if not preset @@ -318,9 +328,14 @@ void OpenThreadCLI::begin(bool OThreadAutoStart) { } void OpenThreadCLI::end() { + if (!otStarted) { + log_w("OpenThread CLI already stopped. Please begin() it before stopping again."); + return; + } if (s_ot_task != NULL) { vTaskDelete(s_ot_task); // Clean up + esp_openthread_deinit(); esp_openthread_netif_glue_deinit(); esp_netif_destroy(openthread_netif); esp_vfs_eventfd_unregister(); @@ -331,6 +346,7 @@ void OpenThreadCLI::end() { if (s_console_cli_task != NULL) { vTaskDelete(s_console_cli_task); } + esp_event_loop_delete_default(); setRxBufferSize(0); setTxBufferSize(0); otStarted = false; From 3507a9d888a5e65d7ca22941009a740fa78d3ce5 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 23 Jun 2024 13:46:43 -0300 Subject: [PATCH 16/25] feat(openthread): onReceice example --- .../OpenThread/examples/onReceive/ci.json | 9 +++++ .../examples/onReceive/onReceive.ino | 37 +++++++++++++++++++ libraries/OpenThread/src/OThreadCLI.cpp | 14 +++---- 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 libraries/OpenThread/examples/onReceive/ci.json create mode 100644 libraries/OpenThread/examples/onReceive/onReceive.ino diff --git a/libraries/OpenThread/examples/onReceive/ci.json b/libraries/OpenThread/examples/onReceive/ci.json new file mode 100644 index 00000000000..68806c42a07 --- /dev/null +++ b/libraries/OpenThread/examples/onReceive/ci.json @@ -0,0 +1,9 @@ +{ + "targets": { + "esp32": false, + "esp32c2": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + } + } \ No newline at end of file diff --git a/libraries/OpenThread/examples/onReceive/onReceive.ino b/libraries/OpenThread/examples/onReceive/onReceive.ino new file mode 100644 index 00000000000..dde182f1f1c --- /dev/null +++ b/libraries/OpenThread/examples/onReceive/onReceive.ino @@ -0,0 +1,37 @@ +/* + OpenThread.begin() will automatically start a node in a Thread Network + This will demonstrate how to capture the CLI response in a callback function + The device state shall change from "disabled" to valid Thread states along time +*/ + +#include "OThreadCLI.h" + +// reads all the lines sent by CLI, one by one +// ignores some lines that are just a sequence of \r\n +void otReceivedLine() { + String line = ""; + while (OThreadCLI.available() > 0) { + char ch = OThreadCLI.read(); + if (ch != '\r' && ch != '\n') { + line += ch; + } + } + // ignores empty lines, usually EOL sequence + if (line.length() > 0) { + Serial.print("OpenThread CLI RESP===> "); + Serial.println(line.c_str()); + } +} + +void setup() { + Serial.begin(115200); + OThreadCLI.begin(); // AutoStart + OThreadCLI.onReceive(otReceivedLine); +} + +void loop() { + // sends the "state" command to the CLI every second + // the onReceive() Callback Function will read and process the response + OThreadCLI.println("state"); + delay(1000); +} diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 07bcf490f62..60f6385375a 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -99,6 +99,11 @@ static int ot_cli_output_callback(void *context, const char *format, va_list arg for (int i = 0; i < ret; i++) { xQueueSend(rx_queue, &buf[i], 0); } + // if there is a user callback function in place, it shall have the priority + // to process/consume the Stream data received from OpenThread CLI, which is available in its RX Buffer + if (otConsole.responseCallBack != NULL) { + otConsole.responseCallBack(); + } } } } @@ -144,13 +149,8 @@ static void ot_cli_console_worker(void *context) { if (c == '\n' && lastReadChar != '\n') { // wait for the OpenThread CLI to finish processing the command xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); - // if there is a user callback function in place, it shall have the priority - // to process/consume the Stream data received from OpenThread CLI, which is available in its RX Buffer - if (cli->responseCallBack != NULL) { - cli->responseCallBack(); - } // read response from OpenThread CLI and send it to the Stream - while (OThreadCLI.available()) { + while (OThreadCLI.available() > 0) { char c = OThreadCLI.read(); // echo it back to the console if (cli->echoback) { @@ -182,7 +182,7 @@ void OpenThreadCLI::setStream(Stream& otStream) { otConsole.cliStream = &otStream; } -void onReceive(OnReceiveCb_t func) { +void OpenThreadCLI::onReceive(OnReceiveCb_t func) { otConsole.responseCallBack = func; // NULL will set it off } From 176f92bb945c44da4062e767b5ff03bfb4e2122a Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 23 Jun 2024 13:56:07 -0300 Subject: [PATCH 17/25] fix(openthread): tx queue error --- libraries/OpenThread/src/OThreadCLI.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 60f6385375a..5f77d850aee 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -354,7 +354,7 @@ void OpenThreadCLI::end() { size_t OpenThreadCLI::write(uint8_t c) { - if (rx_queue == NULL) { + if (tx_queue == NULL) { return 0; } if (xQueueSend(tx_queue, &c, 0) != pdPASS) { @@ -416,6 +416,9 @@ int OpenThreadCLI::read(void) { } void OpenThreadCLI::flush() { + if (tx_queue == NULL) { + return; + } // wait for the TX Queue to be empty while (uxQueueMessagesWaiting(tx_queue)); } From 6b0b9afb09b007dfbfd750b0aafd870fc4003bd2 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 23 Jun 2024 20:29:07 -0300 Subject: [PATCH 18/25] fix(doc): fixing documentation apresentation Fixes the documentation first paragraph in order to make it easier fore reading. It also displays in the very top which SoC are supported by the library. --- libraries/OpenThread/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md index 9968c79870b..974be9c73cb 100644 --- a/libraries/OpenThread/README.md +++ b/libraries/OpenThread/README.md @@ -1,13 +1,19 @@ +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + # ESP32 Arduino OpenThreadCLI -The `OpenThreadCLI` class is an Arduino API for interacting with the OpenThread Command Line Interface (CLI). It allows you to manage and configure the Thread stack using a command-line interface. Below are the details of the class: -The available OpenThread Commands are documented in the [OpenThread CLI Reference Page](https://openthread.io/reference/cli/commands) +The `OpenThreadCLI` class is an Arduino API for interacting with the OpenThread Command Line Interface (CLI). It allows you to manage and configure the Thread stack using a command-line interface. -There is one main class called `OpenThreadCLI` and a global object used to operate OpenThread CLI, called `OThreadCLI` +There is one main class called `OpenThreadCLI` and a global object used to operate OpenThread CLI, called `OThreadCLI`.\ Some [helper functions](helper_functions.md) were made available for working with the OpenThread CLI environment. +The available OpenThread Commands are documented in the [OpenThread CLI Reference Page](https://openthread.io/reference/cli/commands) + It is important to note that the current implementation can only be used with Espressif SoC that has support to IEEE 802.15.4, such as **ESP32-C6** and **ESP32-H2**. +Below are the details of the class: + ## Class Definition ```cpp From 4ec13979462d7206de339aac152ad18e1e8bccb4 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 23 Jun 2024 22:06:34 -0300 Subject: [PATCH 19/25] fix(doc): documentation format --- libraries/OpenThread/helper_functions.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libraries/OpenThread/helper_functions.md b/libraries/OpenThread/helper_functions.md index a3c4a2692e8..db8b7db29e9 100644 --- a/libraries/OpenThread/helper_functions.md +++ b/libraries/OpenThread/helper_functions.md @@ -1,8 +1,9 @@ # OpenThread Helper Functions and Types -The following helper functions and types are designed to simplify writing Arduino sketches for OpenThread. They provide useful utilities for managing OpenThread stack behavior and interacting with the Thread network. +The following helper functions and types are designed to simplify writing Arduino sketches for OpenThread.\ +They provide useful utilities for managing OpenThread stack behavior and interacting with the Thread network. -## Enumerated Type: `ot_device_role_t` +### Enumerated Type: `ot_device_role_t` This enumeration defines the possible roles of a Thread device within the network: @@ -12,22 +13,22 @@ This enumeration defines the possible roles of a Thread device within the networ - `OT_ROLE_ROUTER`: The device operates as a Thread Router. - `OT_ROLE_LEADER`: The device operates as a Thread Leader. -## Struct: `ot_cmd_return_t` +### Struct: `ot_cmd_return_t` This structure represents the return status of an OpenThread CLI command: - `errorCode`: An integer representing the error code (if any). - `errorMessage`: A string containing an error message (if applicable). -## Function: `otGetDeviceRole()` +### Function: `otGetDeviceRole()` - Returns the current role of the device as an `ot_device_role_t` value. -## Function: `otGetStringDeviceRole()` +### Function: `otGetStringDeviceRole()` - Returns a human-readable string representation of the device role (e.g., "Child," "Router," etc.). -## Function: `otGetRespCmd(const char* cmd, char* resp = NULL, uint32_t respTimeout = 5000)` +### Function: `otGetRespCmd(const char* cmd, char* resp = NULL, uint32_t respTimeout = 5000)` - Executes an OpenThread CLI command and retrieves the response. - Parameters: @@ -35,7 +36,7 @@ This structure represents the return status of an OpenThread CLI command: - `resp`: Optional buffer to store the response (if provided). - `respTimeout`: Timeout (in milliseconds) for waiting for the response. -## Function: `otExecCommand(const char* cmd, const char* arg, ot_cmd_return_t* returnCode = NULL)` +### Function: `otExecCommand(const char* cmd, const char* arg, ot_cmd_return_t* returnCode = NULL)` - Executes an OpenThread CLI command with an argument. - Parameters: @@ -43,7 +44,7 @@ This structure represents the return status of an OpenThread CLI command: - `arg`: The argument for the command. - `returnCode`: Optional pointer to an `ot_cmd_return_t` structure to store the return status. -## Function: `otPrintRespCLI(const char* cmd, Stream& output, uint32_t respTimeout)` +### Function: `otPrintRespCLI(const char* cmd, Stream& output, uint32_t respTimeout)` - Executes an OpenThread CLI command and prints the response to the specified output stream. - Parameters: @@ -51,7 +52,7 @@ This structure represents the return status of an OpenThread CLI command: - `output`: The output stream (e.g., Serial) to print the response. - `respTimeout`: Timeout (in milliseconds) for waiting for the response. -## Function: `otPrintNetworkInformation(Stream& output)` +### Function: `otPrintNetworkInformation(Stream& output)` - Prints information about the current Thread network to the specified output stream. - Parameters: From 2aaa575e2c830b64abbf856a0ab2746435d03d8d Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 23 Jun 2024 23:46:32 -0300 Subject: [PATCH 20/25] feat(openthread): commentary --- libraries/OpenThread/src/OThreadCLI.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index e4b9a503e34..9f13532c985 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -27,6 +27,7 @@ class OpenThreadCLI : public Stream { public: OpenThreadCLI(); ~OpenThreadCLI(); + // returns true if OpenThread CLI is running operator bool() const; // starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. From eb7b0191b183f7e7f4d4514770633ebeda97923c Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 24 Jun 2024 08:50:45 -0300 Subject: [PATCH 21/25] fix(openthread): Typo, start/stop console --- CMakeLists.txt | 2 +- libraries/OpenThread/README.md | 8 ++++---- libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino | 2 +- libraries/OpenThread/keywords.txt | 4 ++-- libraries/OpenThread/src/OThreadCLI.cpp | 4 ++-- libraries/OpenThread/src/OThreadCLI.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88495b7018d..9be41fe8d5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,7 +163,7 @@ set(ARDUINO_LIBRARY_OpenThread_SRCS libraries/OpenThread/src/OThreadCLI.cpp libraries/OpenThread/src/OThreadCLI_Util.cpp) - set(ARDUINO_LIBRARY_PPP_SRCS +set(ARDUINO_LIBRARY_PPP_SRCS libraries/PPP/src/PPP.cpp libraries/PPP/src/ppp.c) diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md index 974be9c73cb..a0b80658a8e 100644 --- a/libraries/OpenThread/README.md +++ b/libraries/OpenThread/README.md @@ -28,8 +28,8 @@ public: operator bool() const; // Starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. - void startOpenThreadConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> "); - void stopOpenThreadConsole(); + void startConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> "); + void stopConsole(); void setPrompt(char* prompt); // Changes the console prompt. NULL is an empty prompt. void setEchoBack(bool echoback); // Changes the console echoback option void setStream(Stream& otStream); // Changes the console Stream object @@ -59,8 +59,8 @@ extern OpenThreadCLI OThreadCLI; - You can customize the console behavior by adjusting parameters such as echoback and buffer sizes. ## Public Methods -- `startOpenThreadConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> ")`: Starts the OpenThread console with the specified stream, echoback option, and prompt. -- `stopOpenThreadConsole()`: Stops the OpenThread console. +- `startConsole(Stream& otStream, bool echoback = true, const char* prompt = "ot> ")`: Starts the OpenThread console with the specified stream, echoback option, and prompt. +- `stopConsole()`: Stops the OpenThread console. - `setPrompt(char* prompt)`: Changes the console prompt (set to NULL for an empty prompt). - `setEchoBack(bool echoback)`: Changes the console echoback option. - `setStream(Stream& otStream)`: Changes the console Stream object. diff --git a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino index b21a431b68a..732e1946499 100644 --- a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino +++ b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino @@ -14,7 +14,7 @@ void setup() { Serial.begin(115200); OThreadCLI.begin(false); // No AutoStart - fresh start Serial.println("OpenThread CLI started - type 'help' for a list of commands."); - OThreadCLI.startOpenThreadConsole(Serial); + OThreadCLI.startConsole(Serial); } void loop() { diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt index 68963e354cd..b7135522d05 100644 --- a/libraries/OpenThread/keywords.txt +++ b/libraries/OpenThread/keywords.txt @@ -15,8 +15,8 @@ ot_device_role_t KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### -startOpenThreadConsole KEYWORD2 -stopOpenThreadConsole KEYWORD2 +startConsole KEYWORD2 +stopConsole KEYWORD2 setPrompt KEYWORD2 setEchoBack KEYWORD2 setStream KEYWORD2 diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 5f77d850aee..045ee405f4a 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -187,7 +187,7 @@ void OpenThreadCLI::onReceive(OnReceiveCb_t func) { } // Stream object shall be already started and configured before calling this function -void OpenThreadCLI::startOpenThreadConsole(Stream& otStream, bool echoback, const char *prompt) { +void OpenThreadCLI::startConsole(Stream& otStream, bool echoback, const char *prompt) { if (!otStarted) { log_e("OpenThread CLI has not started. Please begin() it before starting the console."); return; @@ -204,7 +204,7 @@ void OpenThreadCLI::startOpenThreadConsole(Stream& otStream, bool echoback, cons } } -void OpenThreadCLI::stopOpenThreadConsole() { +void OpenThreadCLI::stopConsole() { if (s_console_cli_task) { vTaskDelete(s_console_cli_task); s_console_cli_task = NULL; diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index 9f13532c985..9185124e840 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -31,8 +31,8 @@ class OpenThreadCLI : public Stream { operator bool() const; // starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. - void startOpenThreadConsole(Stream& otStream, bool echoback = true, const char *prompt = "ot> "); - void stopOpenThreadConsole(); + void startConsole(Stream& otStream, bool echoback = true, const char *prompt = "ot> "); + void stopConsole(); void setPrompt(char *prompt); // changes the console prompt. NULL is an empty prompt. void setEchoBack(bool echoback); // changes the console echoback option void setStream(Stream& otStream); // changes the console Stream object From b60a35488daed217c670a608b1733ce8c08eb069 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 24 Jun 2024 09:39:06 -0300 Subject: [PATCH 22/25] fix(openthread): library properties --- libraries/OpenThread/library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/OpenThread/library.properties b/libraries/OpenThread/library.properties index 1091f154b53..e789000f766 100644 --- a/libraries/OpenThread/library.properties +++ b/libraries/OpenThread/library.properties @@ -4,6 +4,6 @@ author=Rodrigo Garcia | GitHub @SuGlider maintainer=Rodrigo Garcia sentence=Library for OpenThread Network on ESP32. paragraph=This library is a wrapper for OpenThread CLI. It provides a simple way to interact with OpenThread Network. -category=Sensor +category=Communication url=https://github.com/espressif/arduino-esp32/ architectures=esp32 From 11ec1d1c1848e5de2d71596902eb7926e1643f50 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:51:32 -0300 Subject: [PATCH 23/25] ci(pre-commit): Apply automatic fixes --- libraries/OpenThread/README.md | 2 - .../examples/COAP/coap_lamp/ci.json | 2 +- .../examples/COAP/coap_lamp/coap_lamp.ino | 45 ++++++---------- .../examples/COAP/coap_switch/ci.json | 2 +- .../examples/COAP/coap_switch/coap_switch.ino | 49 ++++++++--------- .../examples/SimpleCLI/SimpleCLI.ino | 9 ++-- .../OpenThread/examples/SimpleCLI/ci.json | 2 +- .../examples/SimpleNode/SimpleNode.ino | 6 +-- .../OpenThread/examples/SimpleNode/ci.json | 2 +- .../LeaderNode/LeaderNode.ino | 16 +++--- .../SimpleThreadNetwork/LeaderNode/ci.json | 2 +- .../RouterNode/RouterNode.ino | 14 ++--- .../SimpleThreadNetwork/RouterNode/ci.json | 2 +- .../examples/ThreadScan/ThreadScan.ino | 4 +- .../OpenThread/examples/ThreadScan/ci.json | 2 +- .../OpenThread/examples/onReceive/ci.json | 2 +- .../examples/onReceive/onReceive.ino | 4 +- libraries/OpenThread/src/OThreadCLI.cpp | 36 ++++++------- libraries/OpenThread/src/OThreadCLI.h | 13 ++--- libraries/OpenThread/src/OThreadCLI_Util.cpp | 53 ++++++++++--------- libraries/OpenThread/src/OThreadCLI_Util.h | 14 ++--- 21 files changed, 131 insertions(+), 150 deletions(-) diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md index a0b80658a8e..f8ea94f1cf5 100644 --- a/libraries/OpenThread/README.md +++ b/libraries/OpenThread/README.md @@ -70,5 +70,3 @@ extern OpenThreadCLI OThreadCLI; - `setTxBufferSize(size_t tx_queue_len)`: Sets the transmit buffer size (default is 256 bytes). - `setRxBufferSize(size_t rx_queue_len)`: Sets the receive buffer size (default is 1024 bytes). - `write(uint8_t)`, `available()`, `read()`, `peek()`, `flush()`: Standard Stream methods implementation for OpenThread CLI object. - - diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_lamp/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino index 68b2865bb71..4e515e7ac2a 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -1,34 +1,25 @@ #include "OThreadCLI.h" #include "OThreadCLI_Util.h" -#define OT_CHANNEL "24" -#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" -#define OT_MCAST_ADDR "ff05::abcd" +#define OT_CHANNEL "24" +#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define OT_MCAST_ADDR "ff05::abcd" #define OT_COAP_RESOURCE_NAME "Lamp" const char *otSetupLeader[] = { // clear/disable all - "coap", "stop", - "thread", "stop", - "ifconfig", "down", - "dataset", "clear", + "coap", "stop", "thread", "stop", "ifconfig", "down", "dataset", "clear", // set dataset - "dataset", "init new", - "dataset channel", OT_CHANNEL, - "dataset networkkey", OT_NETWORK_KEY, - "dataset", "commit active", + "dataset", "init new", "dataset channel", OT_CHANNEL, "dataset networkkey", OT_NETWORK_KEY, "dataset", "commit active", // network start - "ifconfig", "up", - "thread", "start" + "ifconfig", "up", "thread", "start" }; const char *otCoapLamp[] = { // create a multicast IPv6 Address for this device "ipmaddr add", OT_MCAST_ADDR, // start and create a CoAP resource - "coap", "start", - "coap resource", OT_COAP_RESOURCE_NAME, - "coap set", "0" + "coap", "start", "coap resource", OT_COAP_RESOURCE_NAME, "coap set", "0" }; bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole) { @@ -47,7 +38,7 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap } Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); // wait for the expected Device Role to start - uint8_t tries = 24; // 24 x 2.5 sec = 1 min + uint8_t tries = 24; // 24 x 2.5 sec = 1 min while (tries && otGetDeviceRole() != expectedRole) { Serial.print("."); delay(2500); @@ -72,7 +63,7 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap } Serial.println("OpenThread setup done. Node is ready."); // all fine! LED goes Green - neopixelWrite(RGB_BUILTIN, 0, 64, 8); // GREEN ... Lamp is ready! + neopixelWrite(RGB_BUILTIN, 0, 64, 8); // GREEN ... Lamp is ready! return true; } @@ -80,14 +71,12 @@ void setupNode() { // tries to set the Thread Network node and only returns when succeded bool startedCorrectly = false; while (!startedCorrectly) { - startedCorrectly |= otDeviceSetup(otSetupLeader, sizeof(otSetupLeader) / sizeof(char *) / 2, - otCoapLamp, sizeof(otCoapLamp) / sizeof(char *) / 2, - OT_ROLE_LEADER); + startedCorrectly |= + otDeviceSetup(otSetupLeader, sizeof(otSetupLeader) / sizeof(char *) / 2, otCoapLamp, sizeof(otCoapLamp) / sizeof(char *) / 2, OT_ROLE_LEADER); if (!startedCorrectly) { Serial.println("Setup Failed...\r\nTrying again..."); } } - } // this function is used by the Lamp mode to listen for CoAP frames from the Switch Node @@ -107,16 +96,16 @@ void otCOAPListen() { log_i("CoAP PUT [%s]\r\n", payload == '0' ? "OFF" : "ON"); if (payload == '0') { for (int16_t c = 248; c > 16; c -= 8) { - neopixelWrite(RGB_BUILTIN, c, c, c); // ramp down + neopixelWrite(RGB_BUILTIN, c, c, c); // ramp down delay(5); } - neopixelWrite(RGB_BUILTIN, 0, 0, 0); // Lamp Off + neopixelWrite(RGB_BUILTIN, 0, 0, 0); // Lamp Off } else { for (int16_t c = 16; c < 248; c += 8) { - neopixelWrite(RGB_BUILTIN, c, c, c); // ramp up + neopixelWrite(RGB_BUILTIN, c, c, c); // ramp up delay(5); } - neopixelWrite(RGB_BUILTIN, 255, 255, 255); // Lamp On + neopixelWrite(RGB_BUILTIN, 255, 255, 255); // Lamp On } } } @@ -126,8 +115,8 @@ void setup() { Serial.begin(115200); // LED starts RED, indicating not connected to Thread network. neopixelWrite(RGB_BUILTIN, 64, 0, 0); - OThreadCLI.begin(false); // No AutoStart is necessary - OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response + OThreadCLI.begin(false); // No AutoStart is necessary + OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response setupNode(); // LED goes Green when all is ready and Red when failed. } diff --git a/libraries/OpenThread/examples/COAP/coap_switch/ci.json b/libraries/OpenThread/examples/COAP/coap_switch/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/ci.json +++ b/libraries/OpenThread/examples/COAP/coap_switch/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino index de1ea6d1cd7..5e71d478ac3 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -1,33 +1,30 @@ #include "OThreadCLI.h" #include "OThreadCLI_Util.h" -#define USER_BUTTON 9 // C6/H2 Boot button -#define OT_CHANNEL "24" -#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" -#define OT_MCAST_ADDR "ff05::abcd" +#define USER_BUTTON 9 // C6/H2 Boot button +#define OT_CHANNEL "24" +#define OT_NETWORK_KEY "00112233445566778899aabbccddeeff" +#define OT_MCAST_ADDR "ff05::abcd" #define OT_COAP_RESOURCE_NAME "Lamp" const char *otSetupChild[] = { // clear/disable all - "coap", "stop", - "thread", "stop", - "ifconfig", "down", - "dataset", "clear", + "coap", "stop", "thread", "stop", "ifconfig", "down", "dataset", "clear", // set dataset - "dataset channel", OT_CHANNEL, - "dataset networkkey", OT_NETWORK_KEY, - "dataset", "commit active", + "dataset channel", OT_CHANNEL, "dataset networkkey", OT_NETWORK_KEY, "dataset", "commit active", // network start - "ifconfig", "up", - "thread", "start" + "ifconfig", "up", "thread", "start" }; const char *otCoapSwitch[] = { // start and create a CoAP resource - "coap", "start", + "coap", + "start", }; -bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole1, ot_device_role_t expectedRole2) { +bool otDeviceSetup( + const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole1, ot_device_role_t expectedRole2 +) { Serial.println("Starting OpenThread."); Serial.println("Running as Switch - use the BOOT button to toggle the other C6/H2 as a Lamp"); uint8_t i; @@ -43,7 +40,7 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap } Serial.println("OpenThread started.\r\nWaiting for activating correct Device Role."); // wait for the expected Device Role to start - uint8_t tries = 24; // 24 x 2.5 sec = 1 min + uint8_t tries = 24; // 24 x 2.5 sec = 1 min while (tries && otGetDeviceRole() != expectedRole1 && otGetDeviceRole() != expectedRole2) { Serial.print("."); delay(2500); @@ -68,23 +65,21 @@ bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoap } Serial.println("OpenThread setup done. Node is ready."); // all fine! LED goes and stays Blue - neopixelWrite(RGB_BUILTIN, 0, 0, 64); // BLUE ... Swtich is ready! + neopixelWrite(RGB_BUILTIN, 0, 0, 64); // BLUE ... Swtich is ready! return true; } - void setupNode() { // tries to set the Thread Network node and only returns when succeded bool startedCorrectly = false; while (!startedCorrectly) { - startedCorrectly |= otDeviceSetup(otSetupChild, sizeof(otSetupChild) / sizeof(char *) / 2, - otCoapSwitch, sizeof(otCoapSwitch) / sizeof(char *) / 2, - OT_ROLE_CHILD, OT_ROLE_ROUTER); + startedCorrectly |= otDeviceSetup( + otSetupChild, sizeof(otSetupChild) / sizeof(char *) / 2, otCoapSwitch, sizeof(otCoapSwitch) / sizeof(char *) / 2, OT_ROLE_CHILD, OT_ROLE_ROUTER + ); if (!startedCorrectly) { Serial.println("Setup Failed...\r\nTrying again..."); } } - } // Sends the CoAP frame to the Lamp node @@ -133,12 +128,12 @@ bool otCoapPUT(bool lampState) { void checkUserButton() { static long unsigned int lastPress = 0; const long unsigned int debounceTime = 500; - static bool lastLampState = true; // first button press will turn the Lamp OFF from inital Green + static bool lastLampState = true; // first button press will turn the Lamp OFF from inital Green - pinMode(USER_BUTTON, INPUT_PULLUP); // C6/H2 User Button + pinMode(USER_BUTTON, INPUT_PULLUP); // C6/H2 User Button if (millis() > lastPress + debounceTime && digitalRead(USER_BUTTON) == LOW) { lastLampState = !lastLampState; - if (!otCoapPUT(lastLampState)) { // failed: Lamp Node is not responding due to be off or unreachable + if (!otCoapPUT(lastLampState)) { // failed: Lamp Node is not responding due to be off or unreachable // timeout from the CoAP PUT message... restart the node. neopixelWrite(RGB_BUILTIN, 255, 0, 0); // RED ... something failed! Serial.println("Reseting the Node as Switch... wait."); @@ -153,8 +148,8 @@ void setup() { Serial.begin(115200); // LED starts RED, indicating not connected to Thread network. neopixelWrite(RGB_BUILTIN, 64, 0, 0); - OThreadCLI.begin(false); // No AutoStart is necessary - OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response + OThreadCLI.begin(false); // No AutoStart is necessary + OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response setupNode(); // LED goes and keeps Blue when all is ready and Red when failed. } diff --git a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino index 732e1946499..db9dc910e94 100644 --- a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino +++ b/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino @@ -2,20 +2,19 @@ * OpenThread.begin(false) will not automatically start a node in a Thread Network * The user will need to start it manually using the OpenThread CLI commands * Use the Serial Monitor to interact with the OpenThread CLI - * + * * Type 'help' for a list of commands. * Documentation: https://openthread.io/reference/cli/commands - * + * */ #include "OThreadCLI.h" void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(false); // No AutoStart - fresh start Serial.println("OpenThread CLI started - type 'help' for a list of commands."); OThreadCLI.startConsole(Serial); } -void loop() { -} \ No newline at end of file +void loop() {} diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/SimpleCLI/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/SimpleCLI/ci.json +++ b/libraries/OpenThread/examples/SimpleCLI/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino index e895153e43a..b7f48c82b5d 100644 --- a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino +++ b/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino @@ -1,7 +1,7 @@ /* * OpenThread.begin() will automatically start a node in a Thread Network * If NVS is empty, default configuration will be as follow: - * + * * NETWORK_NAME "OpenThread-ESP" * MESH_LOCAL_PREFIX "fd00:db8:a0:0::/64" * NETWORK_CHANNEL 15 @@ -21,8 +21,8 @@ void setup() { Serial.begin(115200); - OThreadCLI.begin(); // AutoStart using Thread default settings - otPrintNetworkInformation(Serial); // Print Current Thread Network Information + OThreadCLI.begin(); // AutoStart using Thread default settings + otPrintNetworkInformation(Serial); // Print Current Thread Network Information } void loop() { diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/SimpleNode/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/SimpleNode/ci.json +++ b/libraries/OpenThread/examples/SimpleNode/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino index 59d597b6bba..6439c5ec4bd 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -2,26 +2,26 @@ * OpenThread.begin(false) will not automatically start a node in a Thread Network * A Leader node is the first device, that has a complete dataset, to start Thread * A complete dataset is easily achieved by using the OpenThread CLI command "dataset init new" - * - * In order to allow other node to join the network, + * + * In order to allow other node to join the network, * all of them shall use the same network master key * The network master key is a 16-byte key that is used to secure the network - * + * * Using the same channel will make the process faster - * + * */ #include "OThreadCLI.h" #include "OThreadCLI_Util.h" -#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" +#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" #define CLI_NETWORK_CHANEL "dataset channel 24" void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(false); // No AutoStart - fresh start Serial.println("Setting up OpenThread Node as Leader"); - + OThreadCLI.println("dataset init new"); OThreadCLI.println(CLI_NETWORK_KEY); OThreadCLI.println(CLI_NETWORK_CHANEL); @@ -34,4 +34,4 @@ void loop() { Serial.print("Thread Node State: "); Serial.println(otGetStringDeviceRole()); delay(5000); -} \ No newline at end of file +} diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino index 129b6217d79..8b393893386 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -1,24 +1,24 @@ /* * OpenThread.begin(false) will not automatically start a node in a Thread Network - * A Router/Child node is the device that will join an existing Thread Network - * - * In order to allow this node to join the network, + * A Router/Child node is the device that will join an existing Thread Network + * + * In order to allow this node to join the network, * it shall use the same network master key as used by the Leader Node * The network master key is a 16-byte key that is used to secure the network - * + * * Using the same channel will make the process faster - * + * */ #include "OThreadCLI.h" #include "OThreadCLI_Util.h" -#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" +#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff" #define CLI_NETWORK_CHANEL "dataset channel 24" void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(false); // No AutoStart - fresh start Serial.println("Setting up OpenThread Node as Router/Child"); Serial.println("Make sure the Leader Node is already running"); diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json +++ b/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino index 905faa8a132..f2a5711a4ea 100644 --- a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino +++ b/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino @@ -13,8 +13,8 @@ void setup() { Serial.begin(115200); - OThreadCLI.begin(true); // For scanning, AutoStart must be active, any setup - OThreadCLI.setTimeout(100); // Set a timeout for the CLI response + OThreadCLI.begin(true); // For scanning, AutoStart must be active, any setup + OThreadCLI.setTimeout(100); // Set a timeout for the CLI response Serial.println(); Serial.println("This sketch will continuously scan the Thread Local Network and all devices IEEE 802.15.4 compatible"); } diff --git a/libraries/OpenThread/examples/ThreadScan/ci.json b/libraries/OpenThread/examples/ThreadScan/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/ThreadScan/ci.json +++ b/libraries/OpenThread/examples/ThreadScan/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/onReceive/ci.json b/libraries/OpenThread/examples/onReceive/ci.json index 68806c42a07..10def841de0 100644 --- a/libraries/OpenThread/examples/onReceive/ci.json +++ b/libraries/OpenThread/examples/onReceive/ci.json @@ -6,4 +6,4 @@ "esp32s2": false, "esp32s3": false } - } \ No newline at end of file + } diff --git a/libraries/OpenThread/examples/onReceive/onReceive.ino b/libraries/OpenThread/examples/onReceive/onReceive.ino index dde182f1f1c..24a9e0ccc23 100644 --- a/libraries/OpenThread/examples/onReceive/onReceive.ino +++ b/libraries/OpenThread/examples/onReceive/onReceive.ino @@ -16,7 +16,7 @@ void otReceivedLine() { line += ch; } } - // ignores empty lines, usually EOL sequence + // ignores empty lines, usually EOL sequence if (line.length() > 0) { Serial.print("OpenThread CLI RESP===> "); Serial.println(line.c_str()); @@ -25,7 +25,7 @@ void otReceivedLine() { void setup() { Serial.begin(115200); - OThreadCLI.begin(); // AutoStart + OThreadCLI.begin(); // AutoStart OThreadCLI.onReceive(otReceivedLine); } diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 045ee405f4a..53432b13fbb 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -28,7 +28,7 @@ static esp_openthread_platform_config_t ot_native_config; static TaskHandle_t s_ot_task = NULL; static esp_netif_t *openthread_netif = NULL; -#define OT_CLI_MAX_LINE_LENGTH 512 +#define OT_CLI_MAX_LINE_LENGTH 512 typedef struct { Stream *cliStream; @@ -36,7 +36,7 @@ typedef struct { String prompt; OnReceiveCb_t responseCallBack; } ot_cli_console_t; -static ot_cli_console_t otConsole = {NULL, false, (const char *) NULL, NULL}; +static ot_cli_console_t otConsole = {NULL, false, (const char *)NULL, NULL}; // process the CLI commands sent to the OpenThread stack static void ot_cli_loop(void *context) { @@ -59,7 +59,7 @@ static void ot_cli_loop(void *context) { } else { // only allow printable characters if (c > 31 && c < 127) { - sTxString += (char)c; + sTxString += (char)c; } } } @@ -69,8 +69,7 @@ static void ot_cli_loop(void *context) { } // process the CLI responses received from the OpenThread stack -static int ot_cli_output_callback(void *context, const char *format, va_list args) -{ +static int ot_cli_output_callback(void *context, const char *format, va_list args) { char prompt_check[3]; int ret = 0; @@ -115,7 +114,7 @@ static void ot_cli_console_worker(void *context) { ot_cli_console_t *cli = (ot_cli_console_t *)context; // prints the prompt as first action - if (cli->prompt && cli->echoback) { + if (cli->prompt && cli->echoback) { cli->cliStream->print(cli->prompt.c_str()); } // manages and synchronizes the Stream flow with OpenThread CLI response @@ -131,14 +130,14 @@ static void ot_cli_console_worker(void *context) { if (c == '\r') { c = '\n'; // just mark it as New Line } - if (c == '\n' && lastReadChar == '\n') { + if (c == '\n' && lastReadChar == '\n') { continue; - } - + } + // echo it back to the console if (cli->echoback) { if (c == '\n') { - cli->cliStream->println(); // follows whatever is defined as EOL in Arduino + cli->cliStream->println(); // follows whatever is defined as EOL in Arduino } else { cli->cliStream->write(c); } @@ -155,7 +154,7 @@ static void ot_cli_console_worker(void *context) { // echo it back to the console if (cli->echoback) { if (c == '\n') { - cli->cliStream->println(); // follows whatever is defined as EOL in Arduino + cli->cliStream->println(); // follows whatever is defined as EOL in Arduino } else { cli->cliStream->write(c); } @@ -175,19 +174,19 @@ void OpenThreadCLI::setEchoBack(bool echoback) { } void OpenThreadCLI::setPrompt(char *prompt) { - otConsole.prompt = prompt; // NULL will make the prompt not visible + otConsole.prompt = prompt; // NULL will make the prompt not visible } -void OpenThreadCLI::setStream(Stream& otStream) { +void OpenThreadCLI::setStream(Stream &otStream) { otConsole.cliStream = &otStream; } void OpenThreadCLI::onReceive(OnReceiveCb_t func) { - otConsole.responseCallBack = func; // NULL will set it off + otConsole.responseCallBack = func; // NULL will set it off } // Stream object shall be already started and configured before calling this function -void OpenThreadCLI::startConsole(Stream& otStream, bool echoback, const char *prompt) { +void OpenThreadCLI::startConsole(Stream &otStream, bool echoback, const char *prompt) { if (!otStarted) { log_e("OpenThread CLI has not started. Please begin() it before starting the console."); return; @@ -196,7 +195,7 @@ void OpenThreadCLI::startConsole(Stream& otStream, bool echoback, const char *pr if (s_console_cli_task == NULL) { otConsole.cliStream = &otStream; otConsole.echoback = echoback; - otConsole.prompt = prompt; // NULL will invalidate the String + otConsole.prompt = prompt; // NULL will invalidate the String // it will run in the same priority (1) as the Arduino setup()/loop() task xTaskCreate(ot_cli_console_worker, "ot_cli_console", 4096, &otConsole, 1, &s_console_cli_task); } else { @@ -321,7 +320,6 @@ void OpenThreadCLI::begin(bool OThreadAutoStart) { } else { log_i("AUTO start OpenThread done"); } - } otStarted = true; return; @@ -352,7 +350,6 @@ void OpenThreadCLI::end() { otStarted = false; } - size_t OpenThreadCLI::write(uint8_t c) { if (tx_queue == NULL) { return 0; @@ -363,7 +360,7 @@ size_t OpenThreadCLI::write(uint8_t c) { return 1; } -size_t OpenThreadCLI::setBuffer(xQueueHandle & queue, size_t queue_len) { +size_t OpenThreadCLI::setBuffer(xQueueHandle &queue, size_t queue_len) { if (queue) { vQueueDelete(queue); queue = NULL; @@ -423,7 +420,6 @@ void OpenThreadCLI::flush() { while (uxQueueMessagesWaiting(tx_queue)); } - OpenThreadCLI OThreadCLI; #endif /* CONFIG_OPENTHREAD_ENABLED */ diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index 9185124e840..3d18589a07d 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -24,6 +24,7 @@ class OpenThreadCLI : public Stream { private: static size_t setBuffer(xQueueHandle &queue, size_t len); bool otStarted = false; + public: OpenThreadCLI(); ~OpenThreadCLI(); @@ -31,13 +32,13 @@ class OpenThreadCLI : public Stream { operator bool() const; // starts a task to read/write otStream. Default prompt is "ot> ". Set it to NULL to make it invisible. - void startConsole(Stream& otStream, bool echoback = true, const char *prompt = "ot> "); + void startConsole(Stream &otStream, bool echoback = true, const char *prompt = "ot> "); void stopConsole(); - void setPrompt(char *prompt); // changes the console prompt. NULL is an empty prompt. - void setEchoBack(bool echoback); // changes the console echoback option - void setStream(Stream& otStream); // changes the console Stream object + void setPrompt(char *prompt); // changes the console prompt. NULL is an empty prompt. + void setEchoBack(bool echoback); // changes the console echoback option + void setStream(Stream &otStream); // changes the console Stream object void onReceive(OnReceiveCb_t func); // called on a complete line of output from OT CLI, as OT Response - + void begin(bool OThreadAutoStart = true); void end(); @@ -45,7 +46,7 @@ class OpenThreadCLI : public Stream { size_t setTxBufferSize(size_t tx_queue_len); // default size is 1024 bytes size_t setRxBufferSize(size_t rx_queue_len); - + size_t write(uint8_t); int available(); int read(); diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index 16629a20c5c..f26b964cc32 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -6,11 +6,11 @@ #include static const char *otRoleString[] = { - "Disabled", ///< The Thread stack is disabled. - "Detached", ///< Not currently participating in a Thread network/partition. - "Child", ///< The Thread Child role. - "Router", ///< The Thread Router role. - "Leader", ///< The Thread Leader role. + "Disabled", ///< The Thread stack is disabled. + "Detached", ///< Not currently participating in a Thread network/partition. + "Child", ///< The Thread Child role. + "Router", ///< The Thread Router role. + "Leader", ///< The Thread Leader role. }; ot_device_role_t otGetDeviceRole() { @@ -18,10 +18,10 @@ ot_device_role_t otGetDeviceRole() { return OT_ROLE_DISABLED; } otInstance *instance = esp_openthread_get_instance(); - return (ot_device_role_t) otThreadGetDeviceRole(instance); + return (ot_device_role_t)otThreadGetDeviceRole(instance); } -const char* otGetStringDeviceRole() { +const char *otGetStringDeviceRole() { return otRoleString[otGetDeviceRole()]; } @@ -40,7 +40,7 @@ bool otGetRespCmd(const char *cmd, char *resp, uint32_t respTimeout) { OThreadCLI.println(cmd); log_d("CMD[%s]", cmd); uint32_t timeout = millis() + respTimeout; - while(millis() < timeout) { + while (millis() < timeout) { size_t len = OThreadCLI.readBytesUntil('\n', cliResp, sizeof(cliResp)); // clip it on EOL for (int i = 0; i < len; i++) { @@ -51,7 +51,7 @@ bool otGetRespCmd(const char *cmd, char *resp, uint32_t respTimeout) { log_d("Resp[%s]", cliResp); if (strncmp(cliResp, "Done", 4) && strncmp(cliResp, "Error", 4)) { cliRespAllLines += cliResp; - cliRespAllLines.println(); // Adds whatever EOL is for the OS + cliRespAllLines.println(); // Adds whatever EOL is for the OS } else { break; } @@ -107,18 +107,22 @@ bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode //Error 7: InvalidArgs char *i = cliResp; char *m = cliResp; - while (*i && *i != ':') i++; + while (*i && *i != ':') { + i++; + } if (*i) { *i = '\0'; - m = i + 2; // message is 2 characters after ':' - while (i > cliResp && *i != ' ') i--; // search for ' ' before ":' + m = i + 2; // message is 2 characters after ':' + while (i > cliResp && *i != ' ') { + i--; // search for ' ' before ":' + } if (*i == ' ') { - i++; // move it forward to the number begining + i++; // move it forward to the number begining returnCode->errorCode = atoi(i); returnCode->errorMessage = m; - } // otherwise, it will keep the "bad error message" information - } // otherwise, it will keep the "bad error message" information - } // returnCode is NULL pointer + } // otherwise, it will keep the "bad error message" information + } // otherwise, it will keep the "bad error message" information + } // returnCode is NULL pointer return false; } } @@ -145,7 +149,7 @@ bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout) { if (strncmp(cliResp, "Done", 4) && strncmp(cliResp, "Error", 4)) { output.println(cliResp); memset(cliResp, 0, sizeof(cliResp)); - timeout = millis() + respTimeout; // renew timeout, line per line + timeout = millis() + respTimeout; // renew timeout, line per line } else { break; } @@ -158,28 +162,28 @@ bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout) { void otPrintNetworkInformation(Stream &output) { if (!OThreadCLI) { - return; + return; } char resp[512]; output.println("Thread Setup:"); if (otGetRespCmd("state", resp)) { output.printf("Node State: \t%s", resp); - } + } if (otGetRespCmd("networkname", resp)) { output.printf("Network Name: \t%s", resp); - } + } if (otGetRespCmd("channel", resp)) { output.printf("Channel: \t%s", resp); - } + } if (otGetRespCmd("panid", resp)) { output.printf("Pan ID: \t%s", resp); - } + } if (otGetRespCmd("extpanid", resp)) { output.printf("Ext Pan ID: \t%s", resp); - } + } if (otGetRespCmd("networkkey", resp)) { output.printf("Network Key: \t%s", resp); - } + } if (otGetRespCmd("ipaddr", resp)) { output.println("Node IP Addresses are:"); output.printf("%s", resp); @@ -190,6 +194,5 @@ void otPrintNetworkInformation(Stream &output) { } } - #endif /* CONFIG_OPENTHREAD_ENABLED */ #endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h index 02a05c30b5f..5484776889d 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.h +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -5,11 +5,11 @@ #if CONFIG_OPENTHREAD_ENABLED typedef enum { - OT_ROLE_DISABLED = 0, ///< The Thread stack is disabled. - OT_ROLE_DETACHED = 1, ///< Not currently participating in a Thread network/partition. - OT_ROLE_CHILD = 2, ///< The Thread Child role. - OT_ROLE_ROUTER = 3, ///< The Thread Router role. - OT_ROLE_LEADER = 4, ///< The Thread Leader role. + OT_ROLE_DISABLED = 0, ///< The Thread stack is disabled. + OT_ROLE_DETACHED = 1, ///< Not currently participating in a Thread network/partition. + OT_ROLE_CHILD = 2, ///< The Thread Child role. + OT_ROLE_ROUTER = 3, ///< The Thread Router role. + OT_ROLE_LEADER = 4, ///< The Thread Leader role. } ot_device_role_t; typedef struct { @@ -18,11 +18,11 @@ typedef struct { } ot_cmd_return_t; ot_device_role_t otGetDeviceRole(); -const char* otGetStringDeviceRole(); +const char *otGetStringDeviceRole(); bool otGetRespCmd(const char *cmd, char *resp = NULL, uint32_t respTimeout = 5000); bool otExecCommand(const char *cmd, const char *arg, ot_cmd_return_t *returnCode = NULL); bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout); void otPrintNetworkInformation(Stream &output); #endif /* CONFIG_OPENTHREAD_ENABLED */ -#endif /* SOC_IEEE802154_SUPPORTED */ \ No newline at end of file +#endif /* SOC_IEEE802154_SUPPORTED */ From 55f9378549b5aee32f4064f857c56ec8e4de17b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 24 Jun 2024 10:28:21 -0300 Subject: [PATCH 24/25] feat(openthread): formatting text --- .../examples/COAP/coap_lamp/coap_lamp.ino | 40 ++++++++++++++----- .../examples/COAP/coap_switch/coap_switch.ino | 32 ++++++++++----- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino index 4e515e7ac2a..c7a28975f37 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -7,19 +7,41 @@ #define OT_COAP_RESOURCE_NAME "Lamp" const char *otSetupLeader[] = { - // clear/disable all - "coap", "stop", "thread", "stop", "ifconfig", "down", "dataset", "clear", - // set dataset - "dataset", "init new", "dataset channel", OT_CHANNEL, "dataset networkkey", OT_NETWORK_KEY, "dataset", "commit active", - // network start - "ifconfig", "up", "thread", "start" + // -- clear/disable all + // stop CoAP + "coap", "stop", + // stop Thread + "thread", "stop", + // stop the interface + "ifconfig", "down", + // clear the dataset + "dataset", "clear", + // -- set dataset + // create a new complete dataset with random data + "dataset", "init new", + // set the channel + "dataset channel", OT_CHANNEL, + // set the network key + "dataset networkkey", OT_NETWORK_KEY, + // commit the dataset + "dataset", "commit active", + // -- network start + // start the interface + "ifconfig", "up", + // start the Thread network + "thread", "start" }; const char *otCoapLamp[] = { - // create a multicast IPv6 Address for this device + // -- create a multicast IPv6 Address for this device "ipmaddr add", OT_MCAST_ADDR, - // start and create a CoAP resource - "coap", "start", "coap resource", OT_COAP_RESOURCE_NAME, "coap set", "0" + // -- start and create a CoAP resource + // start CoAP as server + "coap", "start", + // create a CoAP resource + "coap resource", OT_COAP_RESOURCE_NAME, + // set the CoAP resource initial value + "coap set", "0" }; bool otDeviceSetup(const char **otSetupCmds, uint8_t nCmds1, const char **otCoapCmds, uint8_t nCmds2, ot_device_role_t expectedRole) { diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino index 5e71d478ac3..0ba645b9fd5 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -8,18 +8,32 @@ #define OT_COAP_RESOURCE_NAME "Lamp" const char *otSetupChild[] = { - // clear/disable all - "coap", "stop", "thread", "stop", "ifconfig", "down", "dataset", "clear", - // set dataset - "dataset channel", OT_CHANNEL, "dataset networkkey", OT_NETWORK_KEY, "dataset", "commit active", - // network start - "ifconfig", "up", "thread", "start" + // -- clear/disable all + // stop CoAP + "coap", "stop", + // stop Thread + "thread", "stop", + // stop the interface + "ifconfig", "down", + // clear the dataset + "dataset", "clear", + // -- set dataset + // set the channel + "dataset channel", OT_CHANNEL, + // set the network key + "dataset networkkey", OT_NETWORK_KEY, + // commit the dataset + "dataset", "commit active", + // -- network start + // start the interface + "ifconfig", "up", + // start the Thread network + "thread", "start" }; const char *otCoapSwitch[] = { - // start and create a CoAP resource - "coap", - "start", + // -- start CoAP as client + "coap", "start" }; bool otDeviceSetup( From 81d62e97e44de6fa116ab7a561190432b943cb9c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:23:00 +0000 Subject: [PATCH 25/25] ci(pre-commit): Apply automatic fixes --- .../OpenThread/examples/COAP/coap_lamp/coap_lamp.ino | 8 ++++---- .../OpenThread/examples/COAP/coap_switch/coap_switch.ino | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino index c7a28975f37..81d9b35e48f 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino @@ -8,20 +8,20 @@ const char *otSetupLeader[] = { // -- clear/disable all - // stop CoAP + // stop CoAP "coap", "stop", - // stop Thread + // stop Thread "thread", "stop", // stop the interface "ifconfig", "down", // clear the dataset "dataset", "clear", // -- set dataset - // create a new complete dataset with random data + // create a new complete dataset with random data "dataset", "init new", // set the channel "dataset channel", OT_CHANNEL, - // set the network key + // set the network key "dataset networkkey", OT_NETWORK_KEY, // commit the dataset "dataset", "commit active", diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino index 0ba645b9fd5..37942dcf576 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino @@ -9,9 +9,9 @@ const char *otSetupChild[] = { // -- clear/disable all - // stop CoAP + // stop CoAP "coap", "stop", - // stop Thread + // stop Thread "thread", "stop", // stop the interface "ifconfig", "down", @@ -20,7 +20,7 @@ const char *otSetupChild[] = { // -- set dataset // set the channel "dataset channel", OT_CHANNEL, - // set the network key + // set the network key "dataset networkkey", OT_NETWORK_KEY, // commit the dataset "dataset", "commit active",