From f8512de1cddd68efd99f3c46ec5481753536051d Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 16 Jun 2025 02:27:44 -0300 Subject: [PATCH 1/3] feat(openthread): adds native api --- libraries/OpenThread/README.md | 201 +++++++++- .../examples/{ => CLI}/COAP/coap_lamp/ci.json | 0 .../{ => CLI}/COAP/coap_lamp/coap_lamp.ino | 9 +- .../{ => CLI}/COAP/coap_switch/ci.json | 0 .../COAP/coap_switch/coap_switch.ino | 9 +- .../{ => CLI}/SimpleCLI/SimpleCLI.ino | 5 +- .../examples/{ => CLI}/SimpleCLI/ci.json | 0 .../{ => CLI}/SimpleNode/SimpleNode.ino | 9 +- .../examples/{ => CLI}/SimpleNode/ci.json | 0 .../ExtendedRouterNode/ExtendedRouterNode.ino | 9 +- .../ExtendedRouterNode/ci.json | 0 .../LeaderNode/LeaderNode.ino | 11 +- .../SimpleThreadNetwork/LeaderNode/ci.json | 0 .../RouterNode/RouterNode.ino | 9 +- .../SimpleThreadNetwork/RouterNode/ci.json | 0 .../{ => CLI}/ThreadScan/ThreadScan.ino | 7 +- .../examples/{ => CLI}/ThreadScan/ci.json | 0 .../examples/{ => CLI}/onReceive/ci.json | 0 .../{ => CLI}/onReceive/onReceive.ino | 3 +- .../LeaderNode/LeaderNode.ino | 34 ++ .../SimpleThreadNetwork/LeaderNode/ci.json | 6 + .../RouterNode/RouterNode.ino | 29 ++ .../SimpleThreadNetwork/RouterNode/ci.json | 6 + libraries/OpenThread/keywords.txt | 26 ++ libraries/OpenThread/src/OThread.cpp | 365 ++++++++++++++++++ libraries/OpenThread/src/OThread.h | 107 +++++ libraries/OpenThread/src/OThreadCLI.cpp | 156 ++------ libraries/OpenThread/src/OThreadCLI.h | 6 +- libraries/OpenThread/src/OThreadCLI_Util.cpp | 22 +- libraries/OpenThread/src/OThreadCLI_Util.h | 11 - 30 files changed, 834 insertions(+), 206 deletions(-) rename libraries/OpenThread/examples/{ => CLI}/COAP/coap_lamp/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/COAP/coap_lamp/coap_lamp.ino (95%) rename libraries/OpenThread/examples/{ => CLI}/COAP/coap_switch/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/COAP/coap_switch/coap_switch.ino (95%) rename libraries/OpenThread/examples/{ => CLI}/SimpleCLI/SimpleCLI.ino (89%) rename libraries/OpenThread/examples/{ => CLI}/SimpleCLI/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/SimpleNode/SimpleNode.ino (81%) rename libraries/OpenThread/examples/{ => CLI}/SimpleNode/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino (89%) rename libraries/OpenThread/examples/{ => CLI}/SimpleThreadNetwork/ExtendedRouterNode/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/SimpleThreadNetwork/LeaderNode/LeaderNode.ino (93%) rename libraries/OpenThread/examples/{ => CLI}/SimpleThreadNetwork/LeaderNode/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/SimpleThreadNetwork/RouterNode/RouterNode.ino (92%) rename libraries/OpenThread/examples/{ => CLI}/SimpleThreadNetwork/RouterNode/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/ThreadScan/ThreadScan.ino (89%) rename libraries/OpenThread/examples/{ => CLI}/ThreadScan/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/onReceive/ci.json (100%) rename libraries/OpenThread/examples/{ => CLI}/onReceive/onReceive.ino (96%) create mode 100644 libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/LeaderNode.ino create mode 100644 libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/ci.json create mode 100644 libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/RouterNode.ino create mode 100644 libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/ci.json create mode 100644 libraries/OpenThread/src/OThread.cpp create mode 100644 libraries/OpenThread/src/OThread.h diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md index cd9deb9ebf6..7b4702958ad 100644 --- a/libraries/OpenThread/README.md +++ b/libraries/OpenThread/README.md @@ -1,9 +1,177 @@ | Supported Targets | ESP32-C6 | ESP32-H2 | | ----------------- | -------- | -------- | -# ESP32 Arduino OpenThreadCLI +# General View -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. +This Arduino OpenThread Library allows using ESP OpenThread implementation using CLI and/or Native OpenThread API. + +The Library implements 3 C++ Classes: +- `OThread` Class for Native OpenThread API +- `OThreadCLI` Class for CLI OpenThread API +- `DataSet` Class for OpenThread dataset manipulation using Native `OThread` Class + +# ESP32 Arduino OpenThread Native + +The `OThread` class provides methods for managing the OpenThread instance and controlling the Thread network. It allows you to initialize, start, stop, and manage the Thread network using native OpenThread APIs. + +## Class Definition + +```cpp +class OpenThread { + public: + static bool otStarted; // Indicates whether the OpenThread stack is running. + + // Get the current Thread device role (e.g., Leader, Router, Child, etc.). + static ot_device_role_t otGetDeviceRole(); + + // Get the current Thread device role as a string. + static const char *otGetStringDeviceRole(); + + // Print network information (e.g., network name, channel, PAN ID) to the specified stream. + static void otPrintNetworkInformation(Stream &output); + + OpenThread(); + ~OpenThread(); + + // Returns true if the OpenThread stack is running. + operator bool() const; + + // Initialize the OpenThread stack. + static void begin(bool OThreadAutoStart = true); + + // Deinitialize the OpenThread stack. + static void end(); + + // Start the Thread network. + void start(); + + // Stop the Thread network. + void stop(); + + // Bring up the Thread network interface (equivalent to "ifconfig up"). + void networkInterfaceUp(); + + // Bring down the Thread network interface (equivalent to "ifconfig down"). + void networkInterfaceDown(); + + // Commit a dataset to the OpenThread instance. + void commitDataSet(const DataSet &dataset); + +private: + static otInstance *mInstance; // Pointer to the OpenThread instance. + DataSet mCurrentDataSet; // Current dataset being used by the OpenThread instance. +}; + +extern OpenThread OThread; +``` +## Class Overview + +The `OThread` class provides a simple and intuitive interface for managing the OpenThread stack and Thread network. It abstracts the complexity of the OpenThread APIs and provides Arduino-style methods for common operations. + +## Public Methods +### Initialization and Deinitialization +- `begin(bool OThreadAutoStart = true)`: Initializes the OpenThread stack. If `OThreadAutoStart` is `true`, the Thread network will start automatically using NVS data. +- `end()`: Deinitializes the OpenThread stack and releases resources. +### Thread Network Control +- `start()`: Starts the Thread network. This is equivalent to the CLI command "thread start". +- `stop()`: Stops the Thread network. This is equivalent to the CLI command "thread stop". +### Network Interface Control +- `networkInterfaceUp()`: Brings up the Thread network interface. This is equivalent to the CLI command "ifconfig up". +- `networkInterfaceDown()`: Brings down the Thread network interface. This is equivalent to the CLI command "ifconfig down". +### Dataset Management +- `commitDataSet(const DataSet &dataset)`: Commits a dataset to the OpenThread instance. This is used to configure the Thread network with specific parameters (e.g., network name, channel, PAN ID). +### Network Information +- `otGetDeviceRole()`: Returns the current Thread device role as an `ot_device_role_t` enum (e.g., `OT_ROLE_LEADER`, `OT_ROLE_ROUTER`). +- `otGetStringDeviceRole()`: Returns the current Thread device role as a string (e.g., "Leader", "Router"). +- `otPrintNetworkInformation(Stream &output)`: Prints the current network information (e.g., network name, channel, PAN ID) to the specified stream. + +## Key Features +- **Initialization and Cleanup**: Easily initialize and deinitialize the OpenThread stack. +- **Network Control**: Start and stop the Thread network with simple method calls. +- **Dataset Management**: Configure the Thread network using the `DataSet` class and commit it to the OpenThread instance. +- **Network Information**: Retrieve and print the current network information and device role. + +## Notes +- The `OThread` class is designed to simplify the use of OpenThread APIs in Arduino sketches. +- It works seamlessly with the DataSet class for managing Thread network configurations. +- Ensure that the OpenThread stack is initialized (`OThread.begin()`) before calling other methods. + +This documentation provides a comprehensive overview of the `OThread` class, its methods, and example usage. It is designed to help developers quickly integrate OpenThread functionality into their Arduino projects. + +# DataSet Class + +The `DataSet` class provides a structured way to manage and configure Thread network datasets using native OpenThread APIs. It allows you to set and retrieve network parameters such as the network name, channel, PAN ID, and more. The `DataSet` class works seamlessly with the `OThread` class to apply these configurations to the OpenThread instance. + +## Class Definition + +```cpp +class DataSet { +public: + DataSet(); + void clear(); + void initNew(); + const otOperationalDataset &getDataset() const; + + // Setters + void setNetworkName(const char *name); + void setExtendedPanId(const uint8_t *extPanId); + void setNetworkKey(const uint8_t *key); + void setChannel(uint8_t channel); + void setPanId(uint16_t panId); + + // Getters + const char *getNetworkName() const; + const uint8_t *getExtendedPanId() const; + const uint8_t *getNetworkKey() const; + uint8_t getChannel() const; + uint16_t getPanId() const; + + // Apply the dataset to the OpenThread instance + void apply(otInstance *instance); + +private: + otOperationalDataset mDataset; // Internal representation of the dataset +}; +``` + +## Class Overview +The DataSet` class simplifies the management of Thread network datasets by providing intuitive methods for setting, retrieving, and applying network parameters. It abstracts the complexity of the OpenThread dataset APIs and provides Arduino-style methods for common operations. + +## Public Methods +### Initialization +- `DataSet()`: Constructor that initializes an empty dataset. +- `void clear()`: Clears the dataset, resetting all fields to their default values. +- `void initNew()`: Initializes a new dataset with default values (equivalent to the CLI command dataset init new). +### Setters +- `void setNetworkName(const char *name)`: Sets the network name. +- `void setExtendedPanId(const uint8_t *extPanId)`: Sets the extended PAN ID. +- `void setNetworkKey(const uint8_t *key)`: Sets the network key. +- `void setChannel(uint8_t channel)`: Sets the channel. +- `void setPanId(uint16_t panId)`: Sets the PAN ID. +### Getters +- `const char *getNetworkName() const`: Retrieves the network name. +- `const uint8_t *getExtendedPanId() const`: Retrieves the extended PAN ID. +- `const uint8_t *getNetworkKey() const`: Retrieves the network key. +- `uint8_t getChannel() const`: Retrieves the channel. +- `uint16_t getPanId() const`: Retrieves the PAN ID. +### Dataset Application +- `void apply(otInstance *instance)`: Applies the dataset to the specified OpenThread instance. + +## Key Features +- **Dataset Initialization**: Easily initialize a new dataset with default values using initNew(). +- **Custom Configuration**: Set custom network parameters such as the network name, channel, and PAN ID using setter methods. +- **Dataset Application**: Apply the configured dataset to the OpenThread instance using apply(). + +** Notes +- The `DataSet` class is designed to work seamlessly with the `OThread` class for managing Thread network configurations. +- Ensure that the OpenThread stack is initialized (`OThread.begin()`) before applying a dataset. +- The initNew()`` method provides default values for the dataset, which can be customized using the setter methods. + +This documentation provides a comprehensive overview of the `DataSet` class, its methods, and example usage. It is designed to help developers easily manage Thread network configurations in their Arduino projects. + +# OpenThreadCLI Class + +The `OpenThreadCLI` class is an Arduino API for interacting with the OpenThread Command Line Interface (CLI). It allows you to send commands to the OpenThread stack and receive responses. This class is designed to simplify the use of OpenThread CLI commands in Arduino sketches. 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. @@ -20,7 +188,7 @@ Below are the details of the class: class OpenThreadCLI : public Stream { private: static size_t setBuffer(QueueHandle_t &queue, size_t len); - bool otStarted = false; + static bool otCLIStarted = false; public: OpenThreadCLI(); @@ -59,14 +227,35 @@ extern OpenThreadCLI OThreadCLI; - You can customize the console behavior by adjusting parameters such as echoback and buffer sizes. ## Public Methods +### Initialization and Deinitialization +- `begin()`: Initializes the OpenThread stack (optional auto-start). +- `end()`: Deinitializes the OpenThread stack and releases resources. +### Console Management - `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. - `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. +### Buffer Management - `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. +### Stream Methods +- `write(uint8_t)`: Writes a byte to the CLI. +- `available()`: Returns the number of bytes available to read. +- `read()`: Reads a byte from the CLI. +- `peek()`: Returns the next byte without removing it from the buffer. +- `flush()`: Flushes the CLI buffer. + +## Key Features +- **Arduino Stream Compatibility**: Inherits from the Stream class, making it compatible with Arduino's standard I/O functions. +- **Customizable Console**: Allows customization of the CLI prompt, echoback behavior, and buffer sizes. +- **Callback Support**: Provides a callback mechanism to handle CLI responses asynchronously. +- **Seamless Integration**: Designed to work seamlessly with the OThread and DataSet classes + +## Notes +- The `OThreadCLI` class is designed to simplify the use of OpenThread CLI commands in Arduino sketches. +- It works seamlessly with the `OThread` and `DataSet` classes for managing Thread networks. +- Ensure that the OpenThread stack is initialized (`OThreadCLI.begin()`) before starting the CLI console. + +This documentation provides a comprehensive overview of the `OThreadCLI` class, its methods, and example usage. It is designed to help developers easily integrate OpenThread CLI functionality into their Arduino projects. \ No newline at end of file diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/ci.json b/libraries/OpenThread/examples/CLI/COAP/coap_lamp/ci.json similarity index 100% rename from libraries/OpenThread/examples/COAP/coap_lamp/ci.json rename to libraries/OpenThread/examples/CLI/COAP/coap_lamp/ci.json diff --git a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino similarity index 95% rename from libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino rename to libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino index 51483bb4c7c..e2d53675456 100644 --- a/libraries/OpenThread/examples/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino @@ -75,18 +75,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 && otGetDeviceRole() != expectedRole) { + while (tries && OThread.otGetDeviceRole() != expectedRole) { Serial.print("."); delay(2500); tries--; } Serial.println(); if (!tries) { - log_e("Sorry, Device Role failed by timeout! Current Role: %s.", otGetStringDeviceRole()); + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", OThread.otGetStringDeviceRole()); rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! return false; } - Serial.printf("Device is %s.\r\n", otGetStringDeviceRole()); + Serial.printf("Device is %s.\r\n", OThread.otGetStringDeviceRole()); for (i = 0; i < nCmds2; i++) { if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { break; @@ -151,7 +151,8 @@ void setup() { Serial.begin(115200); // LED starts RED, indicating not connected to Thread network. rgbLedWrite(RGB_BUILTIN, 64, 0, 0); - OThreadCLI.begin(false); // No AutoStart is necessary + OThread.begin(false); // No AutoStart is necessary + OThreadCLI.begin(); 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/CLI/COAP/coap_switch/ci.json similarity index 100% rename from libraries/OpenThread/examples/COAP/coap_switch/ci.json rename to libraries/OpenThread/examples/CLI/COAP/coap_switch/ci.json diff --git a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino similarity index 95% rename from libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino rename to libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino index aac5db0bc82..00f2cc72e6b 100644 --- a/libraries/OpenThread/examples/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino @@ -69,18 +69,18 @@ bool otDeviceSetup( 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 && otGetDeviceRole() != expectedRole1 && otGetDeviceRole() != expectedRole2) { + while (tries && OThread.otGetDeviceRole() != expectedRole1 && OThread.otGetDeviceRole() != expectedRole2) { Serial.print("."); delay(2500); tries--; } Serial.println(); if (!tries) { - log_e("Sorry, Device Role failed by timeout! Current Role: %s.", otGetStringDeviceRole()); + log_e("Sorry, Device Role failed by timeout! Current Role: %s.", OThread.otGetStringDeviceRole()); rgbLedWrite(RGB_BUILTIN, 255, 0, 0); // RED ... failed! return false; } - Serial.printf("Device is %s.\r\n", otGetStringDeviceRole()); + Serial.printf("Device is %s.\r\n", OThread.otGetStringDeviceRole()); for (i = 0; i < nCmds2; i++) { if (!otExecCommand(otCoapCmds[i * 2], otCoapCmds[i * 2 + 1])) { break; @@ -176,7 +176,8 @@ void setup() { Serial.begin(115200); // LED starts RED, indicating not connected to Thread network. rgbLedWrite(RGB_BUILTIN, 64, 0, 0); - OThreadCLI.begin(false); // No AutoStart is necessary + OThread.begin(false); // No AutoStart is necessary + OThreadCLI.begin(); 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/CLI/SimpleCLI/SimpleCLI.ino similarity index 89% rename from libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino rename to libraries/OpenThread/examples/CLI/SimpleCLI/SimpleCLI.ino index feef800c0fa..dec3aaeb218 100644 --- a/libraries/OpenThread/examples/SimpleCLI/SimpleCLI.ino +++ b/libraries/OpenThread/examples/CLI/SimpleCLI/SimpleCLI.ino @@ -1,4 +1,4 @@ -// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,7 +26,8 @@ void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThread.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(); Serial.println("OpenThread CLI started - type 'help' for a list of commands."); OThreadCLI.startConsole(Serial); } diff --git a/libraries/OpenThread/examples/SimpleCLI/ci.json b/libraries/OpenThread/examples/CLI/SimpleCLI/ci.json similarity index 100% rename from libraries/OpenThread/examples/SimpleCLI/ci.json rename to libraries/OpenThread/examples/CLI/SimpleCLI/ci.json diff --git a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino b/libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino similarity index 81% rename from libraries/OpenThread/examples/SimpleNode/SimpleNode.ino rename to libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino index 95bf7a2401a..6f3e8f92c79 100644 --- a/libraries/OpenThread/examples/SimpleNode/SimpleNode.ino +++ b/libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino @@ -1,4 +1,4 @@ -// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,12 +35,13 @@ void setup() { Serial.begin(115200); - OThreadCLI.begin(); // AutoStart using Thread default settings - otPrintNetworkInformation(Serial); // Print Current Thread Network Information + OThread.begin(); // AutoStart using Thread default settings + OThreadCLI.begin(); + OThread.otPrintNetworkInformation(Serial); // Print Current Thread Network Information } void loop() { Serial.print("Thread Node State: "); - Serial.println(otGetStringDeviceRole()); + Serial.println(OThread.otGetStringDeviceRole()); delay(5000); } diff --git a/libraries/OpenThread/examples/SimpleNode/ci.json b/libraries/OpenThread/examples/CLI/SimpleNode/ci.json similarity index 100% rename from libraries/OpenThread/examples/SimpleNode/ci.json rename to libraries/OpenThread/examples/CLI/SimpleNode/ci.json diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino similarity index 89% rename from libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino rename to libraries/OpenThread/examples/CLI/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino index 4fc8a921584..40f046aeab5 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino +++ b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/ExtendedRouterNode/ExtendedRouterNode.ino @@ -1,4 +1,4 @@ -// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,7 +22,8 @@ bool otStatus = true; void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThread.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(); Serial.println("Setting up OpenThread Node as Router/Child"); Serial.println("Make sure the Leader Node is already running"); @@ -39,7 +40,7 @@ void setup() { } // wait for the node to enter in the router state uint32_t timeout = millis() + 90000; // waits 90 seconds to - while (otGetDeviceRole() != OT_ROLE_CHILD && otGetDeviceRole() != OT_ROLE_ROUTER) { + while (OThread.otGetDeviceRole() != OT_ROLE_CHILD && OThread.otGetDeviceRole() != OT_ROLE_ROUTER) { Serial.print("."); if (millis() > timeout) { Serial.println("\r\n\t===> Timeout! Failed."); @@ -70,7 +71,7 @@ void loop() { if (otStatus) { Serial.println("Thread NetworkInformation: "); Serial.println("---------------------------"); - otPrintNetworkInformation(Serial); + OThread.otPrintNetworkInformation(Serial); Serial.println("---------------------------"); } else { Serial.println("Some OpenThread operation has failed..."); diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/ExtendedRouterNode/ci.json similarity index 100% rename from libraries/OpenThread/examples/SimpleThreadNetwork/ExtendedRouterNode/ci.json rename to libraries/OpenThread/examples/CLI/SimpleThreadNetwork/ExtendedRouterNode/ci.json diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino similarity index 93% rename from libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino rename to libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino index 7b709717692..44c928226e2 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/LeaderNode.ino +++ b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -1,4 +1,4 @@ -// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,8 @@ otInstance *aInstance = NULL; void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThread.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(); Serial.println(); Serial.println("Setting up OpenThread Node as Leader"); aInstance = esp_openthread_get_instance(); @@ -51,11 +52,11 @@ void setup() { void loop() { Serial.println("============================================="); Serial.print("Thread Node State: "); - Serial.println(otGetStringDeviceRole()); + Serial.println(OThread.otGetStringDeviceRole()); // Native OpenThread API calls: // wait until the node become Child or Router - if (otGetDeviceRole() == OT_ROLE_LEADER) { + if (OThread.otGetDeviceRole() == OT_ROLE_LEADER) { // Network Name const char *networkName = otThreadGetNetworkName(aInstance); Serial.printf("Network Name: %s\r\n", networkName); @@ -98,4 +99,4 @@ void loop() { } delay(5000); -} +} \ No newline at end of file diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/ci.json similarity index 100% rename from libraries/OpenThread/examples/SimpleThreadNetwork/LeaderNode/ci.json rename to libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/ci.json diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/RouterNode/RouterNode.ino similarity index 92% rename from libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino rename to libraries/OpenThread/examples/CLI/SimpleThreadNetwork/RouterNode/RouterNode.ino index 45475fa0c6a..f802bd7ef01 100644 --- a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/RouterNode.ino +++ b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -1,4 +1,4 @@ -// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -34,7 +34,8 @@ otInstance *aInstance = NULL; void setup() { Serial.begin(115200); - OThreadCLI.begin(false); // No AutoStart - fresh start + OThread.begin(false); // No AutoStart - fresh start + OThreadCLI.begin(); Serial.println(); Serial.println("Setting up OpenThread Node as Router/Child"); Serial.println("Make sure the Leader Node is already running"); @@ -51,11 +52,11 @@ void setup() { void loop() { Serial.println("============================================="); Serial.print("Thread Node State: "); - Serial.println(otGetStringDeviceRole()); + Serial.println(OThread.otGetStringDeviceRole()); // Native OpenThread API calls: // wait until the node become Child or Router - if (otGetDeviceRole() == OT_ROLE_CHILD || otGetDeviceRole() == OT_ROLE_ROUTER) { + if (OThread.otGetDeviceRole() == OT_ROLE_CHILD || OThread.otGetDeviceRole() == OT_ROLE_ROUTER) { // Network Name const char *networkName = otThreadGetNetworkName(aInstance); Serial.printf("Network Name: %s\r\n", networkName); diff --git a/libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/RouterNode/ci.json similarity index 100% rename from libraries/OpenThread/examples/SimpleThreadNetwork/RouterNode/ci.json rename to libraries/OpenThread/examples/CLI/SimpleThreadNetwork/RouterNode/ci.json diff --git a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino b/libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino similarity index 89% rename from libraries/OpenThread/examples/ThreadScan/ThreadScan.ino rename to libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino index 9d0074bb180..e106275b567 100644 --- a/libraries/OpenThread/examples/ThreadScan/ThreadScan.ino +++ b/libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino @@ -1,4 +1,4 @@ -// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,8 @@ void setup() { Serial.begin(115200); - OThreadCLI.begin(true); // For scanning, AutoStart must be active, any setup + OThread.begin(true); // For scanning, AutoStart must be active, any setup + OThreadCLI.begin(); 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"); @@ -41,7 +42,7 @@ void loop() { Serial.println("Scan Failed..."); } delay(5000); - if (otGetDeviceRole() < OT_ROLE_CHILD) { + if (OThread.otGetDeviceRole() < OT_ROLE_CHILD) { Serial.println(); Serial.println("This device has not started Thread yet, bypassing Discovery Scan"); return; diff --git a/libraries/OpenThread/examples/ThreadScan/ci.json b/libraries/OpenThread/examples/CLI/ThreadScan/ci.json similarity index 100% rename from libraries/OpenThread/examples/ThreadScan/ci.json rename to libraries/OpenThread/examples/CLI/ThreadScan/ci.json diff --git a/libraries/OpenThread/examples/onReceive/ci.json b/libraries/OpenThread/examples/CLI/onReceive/ci.json similarity index 100% rename from libraries/OpenThread/examples/onReceive/ci.json rename to libraries/OpenThread/examples/CLI/onReceive/ci.json diff --git a/libraries/OpenThread/examples/onReceive/onReceive.ino b/libraries/OpenThread/examples/CLI/onReceive/onReceive.ino similarity index 96% rename from libraries/OpenThread/examples/onReceive/onReceive.ino rename to libraries/OpenThread/examples/CLI/onReceive/onReceive.ino index b37c2fc7931..f53cc33f5ec 100644 --- a/libraries/OpenThread/examples/onReceive/onReceive.ino +++ b/libraries/OpenThread/examples/CLI/onReceive/onReceive.ino @@ -39,7 +39,8 @@ void otReceivedLine() { void setup() { Serial.begin(115200); - OThreadCLI.begin(); // AutoStart + OThread.begin(); // AutoStart + OThreadCLI.begin(); OThreadCLI.onReceive(otReceivedLine); } diff --git a/libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/LeaderNode.ino new file mode 100644 index 00000000000..dfea9776838 --- /dev/null +++ b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -0,0 +1,34 @@ +#include "OThread.h" + +OpenThread threadLeaderNode; +DataSet dataset; + +void setup() { + Serial.begin(115200); + + // Start OpenThread Stack - false for not using NVS dataset information + threadLeaderNode.begin(false); + + // Create a new Thread Network Dataset for a Leader Node + dataset.initNew(); + // Configure the dataset + dataset.setNetworkName("ESP_OpenThread"); + uint8_t extPanId[OT_EXT_PAN_ID_SIZE] = {0xDE, 0xAD, 0x00, 0xBE, 0xEF, 0x00, 0xCA, 0xFE}; + dataset.setExtendedPanId(extPanId); + uint8_t networkKey[OT_NETWORK_KEY_SIZE] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; + dataset.setNetworkKey(networkKey); + dataset.setChannel(15); + dataset.setPanId(0x1234); + + // Apply the dataset and start the network + threadLeaderNode.commitDataSet(dataset); + threadLeaderNode.networkInterfaceUp(); + threadLeaderNode.start(); +} + +void loop() { + // Print network information every 5 seconds + Serial.println("=============================================="); + threadLeaderNode.otPrintNetworkInformation(Serial); + delay(5000); +} diff --git a/libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/ci.json b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/LeaderNode/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/RouterNode.ino b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/RouterNode.ino new file mode 100644 index 00000000000..5ffa535ad51 --- /dev/null +++ b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/RouterNode.ino @@ -0,0 +1,29 @@ +#include "OThread.h" + +OpenThread threadChildNode; +DataSet dataset; + +void setup() { + Serial.begin(115200); + + // Start OpenThread Stack - false for not using NVS dataset information + threadChildNode.begin(false); + + // clear dataset + dataset.clear(); + // Configure the dataset with the same Network Key of the Leader Node + uint8_t networkKey[OT_NETWORK_KEY_SIZE] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; + dataset.setNetworkKey(networkKey); + + // Apply the dataset and start the network + threadChildNode.commitDataSet(dataset); + threadChildNode.networkInterfaceUp(); + threadChildNode.start(); +} + +void loop() { + // Print network information every 5 seconds + Serial.println("=============================================="); + threadChildNode.otPrintNetworkInformation(Serial); + delay(5000); +} diff --git a/libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/ci.json b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/ci.json new file mode 100644 index 00000000000..2ee6af3490e --- /dev/null +++ b/libraries/OpenThread/examples/Native/SimpleThreadNetwork/RouterNode/ci.json @@ -0,0 +1,6 @@ +{ + "requires": [ + "CONFIG_OPENTHREAD_ENABLED=y", + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt index d7193de188d..33e10e2c222 100644 --- a/libraries/OpenThread/keywords.txt +++ b/libraries/OpenThread/keywords.txt @@ -7,7 +7,10 @@ ####################################### OThreadCLI KEYWORD1 +OThread KEYWORD1 OpenThreadCLI KEYWORD1 +OpenThread KEYWORD1 +DataSet KEYWORD1 ot_cmd_return_t KEYWORD1 ot_device_role_t KEYWORD1 @@ -35,6 +38,27 @@ otGetRespCmd KEYWORD2 otExecCommand KEYWORD2 otPrintRespCLI KEYWORD2 otPrintNetworkInformation KEYWORD2 +clear KEYWORD2 +initNew KEYWORD2 +getDataset KEYWORD2 +setNetworkName KEYWORD2 +getNetworkName KEYWORD2 +setExtendedPanId KEYWORD2 +getExtendedPanId KEYWORD2 +setNetworkKey KEYWORD2 +getNetworkKey KEYWORD2 +setChannel KEYWORD2 +getChannel KEYWORD2 +setPanId KEYWORD2 +getPanId KEYWORD2 +apply KEYWORD2 +otStarted KEYWORD2 +otCLIStarted KEYWORD2 +start KEYWORD2 +stop KEYWORD2 +networkInterfaceUp KEYWORD2 +networkInterfaceDown KEYWORD2 +commitDataSet KEYWORD2 ####################################### # Constants (LITERAL1) @@ -45,3 +69,5 @@ OT_ROLE_DETACHED LITERAL1 OT_ROLE_CHILD LITERAL1 OT_ROLE_ROUTER LITERAL1 OT_ROLE_LEADER LITERAL1 +OT_EXT_PAN_ID_SIZE LITERAL1 +OT_NETWORK_KEY_SIZE LITERAL1 \ No newline at end of file diff --git a/libraries/OpenThread/src/OThread.cpp b/libraries/OpenThread/src/OThread.cpp new file mode 100644 index 00000000000..e529316efad --- /dev/null +++ b/libraries/OpenThread/src/OThread.cpp @@ -0,0 +1,365 @@ +#include "OThread.h" +#if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + +#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_net_stack.h" +#include "esp_openthread_netif_glue.h" +#include "lwip/netif.h" + +static esp_openthread_platform_config_t ot_native_config; +static esp_netif_t *openthread_netif = NULL; + +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. + "Unknown", ///< Unknown role, not initialized or not started. +}; + +static TaskHandle_t s_ot_task = NULL; +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM +static struct netif *ot_lwip_netif = NULL; +#endif + +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM +extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) { + if (ot_lwip_netif && ot_lwip_netif == inp) { + return 0; + } + if (ip6_addr_isany_val(inp->ip6_addr[0].u_addr.ip6)) { + // We don't have an LL address -> eat this packet here, so it won't get accepted on input netif + pbuf_free(p); + return 1; + } + return 0; +} +#endif + + +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 esp_netif bindings + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); + openthread_netif = esp_netif_new(&cfg); +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM + // Get LwIP Netif + if (openthread_netif != NULL) { + ot_lwip_netif = (struct netif *)esp_netif_get_netif_impl(openthread_netif); + if (ot_lwip_netif == NULL) { + log_e("Failed to get OpenThread LwIP netif"); + } + } +#endif + } + 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); +} + +// DataSet Implementation +DataSet::DataSet() { + memset(&mDataset, 0, sizeof(mDataset)); +} + +void DataSet::clear() { + memset(&mDataset, 0, sizeof(mDataset)); +} + +void DataSet::initNew() { + otInstance *mInstance = esp_openthread_get_instance(); + if (!mInstance) { + log_e("OpenThread not started. Please begin() it before initializing a new dataset."); + return; + } + clear(); + otDatasetCreateNewNetwork(mInstance, &mDataset); +} + +const otOperationalDataset &DataSet::getDataset() const { + return mDataset; +} + +void DataSet::setNetworkName(const char *name) { + strncpy(mDataset.mNetworkName.m8, name, sizeof(mDataset.mNetworkName.m8)); + mDataset.mComponents.mIsNetworkNamePresent = true; +} + +void DataSet::setExtendedPanId(const uint8_t *extPanId) { + memcpy(mDataset.mExtendedPanId.m8, extPanId, OT_EXT_PAN_ID_SIZE); + mDataset.mComponents.mIsExtendedPanIdPresent = true; +} + +void DataSet::setNetworkKey(const uint8_t *key) { + memcpy(mDataset.mNetworkKey.m8, key, OT_NETWORK_KEY_SIZE); + mDataset.mComponents.mIsNetworkKeyPresent = true; +} + +void DataSet::setChannel(uint8_t channel) { + mDataset.mChannel = channel; + mDataset.mComponents.mIsChannelPresent = true; +} + +void DataSet::setPanId(uint16_t panId) { + mDataset.mPanId = panId; + mDataset.mComponents.mIsPanIdPresent = true; +} + +const char *DataSet::getNetworkName() const { + return mDataset.mNetworkName.m8; +} + +const uint8_t *DataSet::getExtendedPanId() const { + return mDataset.mExtendedPanId.m8; +} + +const uint8_t *DataSet::getNetworkKey() const { + return mDataset.mNetworkKey.m8; +} + +uint8_t DataSet::getChannel() const { + return mDataset.mChannel; +} + +uint16_t DataSet::getPanId() const { + return mDataset.mPanId; +} + +void DataSet::apply(otInstance *instance) { + otDatasetSetActive(instance, &mDataset); +} + +// OpenThread Implementation +bool OpenThread::otStarted = false; + +otInstance *OpenThread::mInstance = nullptr; +OpenThread::OpenThread() {} + +OpenThread::~OpenThread() { + end(); +} + +OpenThread::operator bool() const { + return otStarted; +} + +void OpenThread::begin(bool OThreadAutoStart) { + if (otStarted) { + log_w("OpenThread already started"); + return; + } + + 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; + + // Initialize OpenThread stack + xTaskCreate(ot_task_worker, "ot_main_loop", 10240, NULL, 20, &s_ot_task); + if (s_ot_task == NULL) { + log_e("Error: Failed to create OpenThread task"); + return; + } + log_d("OpenThread task created successfully"); + // get the OpenThread instance that will be used for all operations + mInstance = esp_openthread_get_instance(); + if (!mInstance) { + log_e("Error: Failed to initialize OpenThread instance"); + end(); + return; + } + // 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"); + } + 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"); + } + } + otStarted = true; +} + +void OpenThread::end() { + if (s_ot_task != NULL) { + vTaskDelete(s_ot_task); + s_ot_task = NULL; + // Clean up + esp_openthread_deinit(); + esp_openthread_netif_glue_deinit(); +#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM + ot_lwip_netif = NULL; +#endif + esp_netif_destroy(openthread_netif); + esp_vfs_eventfd_unregister(); + } + otStarted = false; +} + +void OpenThread::start() { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return; + } + otThreadSetEnabled(mInstance, true); + log_d("Thread network started"); +} + +void OpenThread::stop() { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return; + } + otThreadSetEnabled(mInstance, false); + log_d("Thread network stopped"); +} + +void OpenThread::networkInterfaceUp() { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return; + } + // Enable the Thread interface (equivalent to CLI Command "ifconfig up") + otError error = otIp6SetEnabled(mInstance, true); + if (error != OT_ERROR_NONE) { + log_e("Error: Failed to enable Thread interface (error code: %d)\n", error); + } + log_d("OpenThread Network Interface is up"); +} + +void OpenThread::networkInterfaceDown() { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return; + } + // Disable the Thread interface (equivalent to CLI Command "ifconfig down") + otError error = otIp6SetEnabled(mInstance, false); + if (error != OT_ERROR_NONE) { + log_e("Error: Failed to disable Thread interface (error code: %d)\n", error); + } + log_d("OpenThread Network Interface is down"); +} + +void OpenThread::commitDataSet(const DataSet &dataset) { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return; + } + // Commit the dataset as the active dataset + otError error = otDatasetSetActive(mInstance, &(dataset.getDataset())); + if (error != OT_ERROR_NONE) { + log_e("Error: Failed to commit dataset (error code: %d)\n", error); + return; + } + log_d("Dataset committed successfully"); +} + +ot_device_role_t OpenThread::otGetDeviceRole() { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return OT_ROLE_DISABLED; + } + return (ot_device_role_t)otThreadGetDeviceRole(mInstance); +} + +const char *OpenThread::otGetStringDeviceRole() { + return otRoleString[otGetDeviceRole()]; +} + +void OpenThread::otPrintNetworkInformation(Stream &output) { + if (!mInstance) { + log_w("Error: OpenThread instance not initialized"); + return; + } + + output.printf("Role: %s", otGetStringDeviceRole()); + output.println(); + output.printf("Network Name: %s", otThreadGetNetworkName(mInstance)); + output.println(); + output.printf("Channel: %d", otLinkGetChannel(mInstance)); + output.println(); + output.printf("PAN ID: 0x%04x", otLinkGetPanId(mInstance)); + output.println(); + + const otExtendedPanId *extPanId = otThreadGetExtendedPanId(mInstance); + output.print("Extended PAN ID: "); + for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) { + output.printf("%02x", extPanId->m8[i]); + } + output.println(); + + otNetworkKey networkKey; + otThreadGetNetworkKey(mInstance, &networkKey); + output.print("Network Key: "); + for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) { + output.printf("%02x", networkKey.m8[i]); + } + output.println(); +} + +OpenThread OThread; + +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThread.h b/libraries/OpenThread/src/OThread.h new file mode 100644 index 00000000000..394143efb3e --- /dev/null +++ b/libraries/OpenThread/src/OThread.h @@ -0,0 +1,107 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED +#if CONFIG_OPENTHREAD_ENABLED + +#include +#include +#include +#include +#include +#include +#include + +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; +extern const char *otRoleString[]; + +class DataSet { + public: + DataSet(); + void clear(); + void initNew(); + const otOperationalDataset &getDataset() const; + + // Setters + void setNetworkName(const char *name); + void setExtendedPanId(const uint8_t *extPanId); + void setNetworkKey(const uint8_t *key); + void setChannel(uint8_t channel); + void setPanId(uint16_t panId); + + // Getters + const char *getNetworkName() const; + const uint8_t *getExtendedPanId() const; + const uint8_t *getNetworkKey() const; + uint8_t getChannel() const; + uint16_t getPanId() const; + + // Apply the dataset to the OpenThread instance + void apply(otInstance *instance); + + private: + otOperationalDataset mDataset; +}; + +class OpenThread { + public: + static bool otStarted; + static ot_device_role_t otGetDeviceRole(); + static const char *otGetStringDeviceRole(); + static void otPrintNetworkInformation(Stream &output); + + OpenThread(); + ~OpenThread(); + // returns true if OpenThread Stack is running + operator bool() const; + + // Initialize OpenThread + static void begin(bool OThreadAutoStart = true); + + // Initialize OpenThread + static void end(); + + // Start the Thread network + void start(); + + // Stop the Thread network + void stop(); + + // Start Thread Network Interface + void networkInterfaceUp(); + + // Stop Thread Network Interface + void networkInterfaceDown(); + + // Set the dataset + void commitDataSet(const DataSet &dataset); + + private: + static otInstance *mInstance; + DataSet mCurrentDataSet; +}; + +extern OpenThread OThread; + +#endif /* CONFIG_OPENTHREAD_ENABLED */ +#endif /* SOC_IEEE802154_SUPPORTED */ diff --git a/libraries/OpenThread/src/OThreadCLI.cpp b/libraries/OpenThread/src/OThreadCLI.cpp index 85ba03563e8..2f0f97a0539 100644 --- a/libraries/OpenThread/src/OThreadCLI.cpp +++ b/libraries/OpenThread/src/OThreadCLI.cpp @@ -33,18 +33,12 @@ #include "esp_netif_net_stack.h" #include "lwip/netif.h" +bool OpenThreadCLI::otCLIStarted = false; static TaskHandle_t s_cli_task = NULL; static TaskHandle_t s_console_cli_task = NULL; static QueueHandle_t rx_queue = NULL; static QueueHandle_t 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; -#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM -static struct netif *ot_lwip_netif = NULL; -#endif - #define OT_CLI_MAX_LINE_LENGTH 512 typedef struct { @@ -53,21 +47,7 @@ typedef struct { String prompt; OnReceiveCb_t responseCallBack; } ot_cli_console_t; -static ot_cli_console_t otConsole = {NULL, false, (const char *)NULL, NULL}; - -#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM -extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) { - if (ot_lwip_netif && ot_lwip_netif == inp) { - return 0; - } - if (ip6_addr_isany_val(inp->ip6_addr[0].u_addr.ip6)) { - // We don't have an LL address -> eat this packet here, so it won't get accepted on input netif - pbuf_free(p); - return 1; - } - return 0; -} -#endif +static ot_cli_console_t otConsole = {nullptr, false, (const char *)nullptr, nullptr}; // process the CLI commands sent to the OpenThread stack static void ot_cli_loop(void *context) { @@ -131,7 +111,7 @@ static int ot_cli_output_callback(void *context, const char *format, va_list arg } // 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) { + if (otConsole.responseCallBack != nullptr) { otConsole.responseCallBack(); } } @@ -205,7 +185,7 @@ void OpenThreadCLI::setEchoBack(bool echoback) { } void OpenThreadCLI::setPrompt(char *prompt) { - otConsole.prompt = prompt; // NULL will make the prompt not visible + otConsole.prompt = prompt; // nullptr can make the prompt not visible } void OpenThreadCLI::setStream(Stream &otStream) { @@ -213,12 +193,12 @@ void OpenThreadCLI::setStream(Stream &otStream) { } void OpenThreadCLI::onReceive(OnReceiveCb_t func) { - otConsole.responseCallBack = func; // NULL will set it off + otConsole.responseCallBack = func; // nullptr 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) { - if (!otStarted) { + if (!otCLIStarted) { log_e("OpenThread CLI has not started. Please begin() it before starting the console."); return; } @@ -226,7 +206,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; // nullptr 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 { @@ -242,12 +222,6 @@ void OpenThreadCLI::stopConsole() { } 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 = ""; } @@ -256,79 +230,19 @@ OpenThreadCLI::~OpenThreadCLI() { } OpenThreadCLI::operator bool() const { - return otStarted; + return otCLIStarted; } -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(), ot_cli_output_callback, NULL); - - // Initialize the esp_netif bindings - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - openthread_netif = esp_netif_new(&cfg); -#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM - // Get LwIP Netif - if (openthread_netif != NULL) { - ot_lwip_netif = (struct netif *)esp_netif_get_netif_impl(openthread_netif); - if (ot_lwip_netif == NULL) { - log_e("Failed to get OpenThread LwIP netif"); - } - } -#endif - } - 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) { - if (otStarted) { +void OpenThreadCLI::begin() { + if (otCLIStarted) { 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); + if (!OpenThread::otStarted) { + log_w("OpenThread not started. Please begin() it before starting CLI."); + return; + } //RX Buffer default has 1024 bytes if not preset if (rx_queue == NULL) { @@ -342,55 +256,29 @@ void OpenThreadCLI::begin(bool OThreadAutoStart) { log_e("HW CDC RX Buffer error"); } } + xTaskCreate(ot_cli_loop, "ot_cli", 4096, xTaskGetCurrentTaskHandle(), 2, &s_cli_task); + // Initialize the OpenThread cli + otCliInit(esp_openthread_get_instance(), ot_cli_output_callback, NULL); - // 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"); - } - 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"); - } - } - otStarted = true; + otCLIStarted = true; return; } void OpenThreadCLI::end() { - if (!otStarted) { + if (!otCLIStarted) { 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(); -#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM - ot_lwip_netif = NULL; -#endif - esp_netif_destroy(openthread_netif); - esp_vfs_eventfd_unregister(); - } if (s_cli_task != NULL) { vTaskDelete(s_cli_task); + s_cli_task = NULL; } - if (s_console_cli_task != NULL) { - vTaskDelete(s_console_cli_task); - } + stopConsole(); esp_event_loop_delete_default(); setRxBufferSize(0); setTxBufferSize(0); - otStarted = false; + otCLIStarted = false; } size_t OpenThreadCLI::write(uint8_t c) { diff --git a/libraries/OpenThread/src/OThreadCLI.h b/libraries/OpenThread/src/OThreadCLI.h index bc8dc5d2b19..788edc2709b 100644 --- a/libraries/OpenThread/src/OThreadCLI.h +++ b/libraries/OpenThread/src/OThreadCLI.h @@ -21,7 +21,6 @@ #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" @@ -31,13 +30,14 @@ #include "openthread/dataset_ftd.h" #include "Arduino.h" +#include "OThread.h" typedef std::function OnReceiveCb_t; class OpenThreadCLI : public Stream { private: static size_t setBuffer(QueueHandle_t &queue, size_t len); - bool otStarted = false; + static bool otCLIStarted; public: OpenThreadCLI(); @@ -53,7 +53,7 @@ class OpenThreadCLI : public Stream { 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 begin(); void end(); // default size is 256 bytes diff --git a/libraries/OpenThread/src/OThreadCLI_Util.cpp b/libraries/OpenThread/src/OThreadCLI_Util.cpp index d21daa1effc..aad435107bb 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.cpp +++ b/libraries/OpenThread/src/OThreadCLI_Util.cpp @@ -19,26 +19,6 @@ #include "OThreadCLI_Util.h" #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. -}; - -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 *otGetStringDeviceRole() { - return otRoleString[otGetDeviceRole()]; -} - bool otGetRespCmd(const char *cmd, char *resp, uint32_t respTimeout) { if (!OThreadCLI) { return false; @@ -174,7 +154,7 @@ bool otPrintRespCLI(const char *cmd, Stream &output, uint32_t respTimeout) { return true; } -void otPrintNetworkInformation(Stream &output) { +void otCLIPrintNetworkInformation(Stream &output) { if (!OThreadCLI) { return; } diff --git a/libraries/OpenThread/src/OThreadCLI_Util.h b/libraries/OpenThread/src/OThreadCLI_Util.h index 1ab2e061dfc..116b886e095 100644 --- a/libraries/OpenThread/src/OThreadCLI_Util.h +++ b/libraries/OpenThread/src/OThreadCLI_Util.h @@ -18,25 +18,14 @@ #if SOC_IEEE802154_SUPPORTED #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_device_role_t; - typedef struct { int errorCode; String errorMessage; } ot_cmd_return_t; -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 */ #endif /* SOC_IEEE802154_SUPPORTED */ From bf0e55ee0fd2bc000e7674ee2643fc075770f64d Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 16 Jun 2025 02:38:24 -0300 Subject: [PATCH 2/3] feat(openthread): adds source code to CMakeLists.txt --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d53d612962d..e8f44ac5ee0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,7 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) set(ARDUINO_LIBRARY_OpenThread_SRCS + libraries/OpenThread/src/OThread.cpp libraries/OpenThread/src/OThreadCLI.cpp libraries/OpenThread/src/OThreadCLI_Util.cpp) From a0e01f46b33c2a3b243a772d5639627ef7ca2bea 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, 16 Jun 2025 09:43:23 +0000 Subject: [PATCH 3/3] ci(pre-commit): Apply automatic fixes --- libraries/OpenThread/README.md | 4 +- .../examples/CLI/COAP/coap_lamp/coap_lamp.ino | 2 +- .../CLI/COAP/coap_switch/coap_switch.ino | 2 +- .../examples/CLI/SimpleNode/SimpleNode.ino | 2 +- .../LeaderNode/LeaderNode.ino | 2 +- .../examples/CLI/ThreadScan/ThreadScan.ino | 2 +- libraries/OpenThread/keywords.txt | 2 +- libraries/OpenThread/src/OThread.cpp | 1 - libraries/OpenThread/src/OThread.h | 102 +++++++++--------- 9 files changed, 59 insertions(+), 60 deletions(-) diff --git a/libraries/OpenThread/README.md b/libraries/OpenThread/README.md index 7b4702958ad..8d0386f34fb 100644 --- a/libraries/OpenThread/README.md +++ b/libraries/OpenThread/README.md @@ -32,7 +32,7 @@ class OpenThread { OpenThread(); ~OpenThread(); - + // Returns true if the OpenThread stack is running. operator bool() const; @@ -258,4 +258,4 @@ extern OpenThreadCLI OThreadCLI; - It works seamlessly with the `OThread` and `DataSet` classes for managing Thread networks. - Ensure that the OpenThread stack is initialized (`OThreadCLI.begin()`) before starting the CLI console. -This documentation provides a comprehensive overview of the `OThreadCLI` class, its methods, and example usage. It is designed to help developers easily integrate OpenThread CLI functionality into their Arduino projects. \ No newline at end of file +This documentation provides a comprehensive overview of the `OThreadCLI` class, its methods, and example usage. It is designed to help developers easily integrate OpenThread CLI functionality into their Arduino projects. diff --git a/libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino b/libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino index e2d53675456..bcaf8ae9793 100644 --- a/libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino +++ b/libraries/OpenThread/examples/CLI/COAP/coap_lamp/coap_lamp.ino @@ -151,7 +151,7 @@ void setup() { Serial.begin(115200); // LED starts RED, indicating not connected to Thread network. rgbLedWrite(RGB_BUILTIN, 64, 0, 0); - OThread.begin(false); // No AutoStart is necessary + OThread.begin(false); // No AutoStart is necessary OThreadCLI.begin(); OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response setupNode(); diff --git a/libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino b/libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino index 00f2cc72e6b..bacac47ddeb 100644 --- a/libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino +++ b/libraries/OpenThread/examples/CLI/COAP/coap_switch/coap_switch.ino @@ -176,7 +176,7 @@ void setup() { Serial.begin(115200); // LED starts RED, indicating not connected to Thread network. rgbLedWrite(RGB_BUILTIN, 64, 0, 0); - OThread.begin(false); // No AutoStart is necessary + OThread.begin(false); // No AutoStart is necessary OThreadCLI.begin(); OThreadCLI.setTimeout(250); // waits 250ms for the OpenThread CLI response setupNode(); diff --git a/libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino b/libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino index 6f3e8f92c79..d17b692cc74 100644 --- a/libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino +++ b/libraries/OpenThread/examples/CLI/SimpleNode/SimpleNode.ino @@ -35,7 +35,7 @@ void setup() { Serial.begin(115200); - OThread.begin(); // AutoStart using Thread default settings + OThread.begin(); // AutoStart using Thread default settings OThreadCLI.begin(); OThread.otPrintNetworkInformation(Serial); // Print Current Thread Network Information } diff --git a/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino index 44c928226e2..a945a5c8f77 100644 --- a/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino +++ b/libraries/OpenThread/examples/CLI/SimpleThreadNetwork/LeaderNode/LeaderNode.ino @@ -99,4 +99,4 @@ void loop() { } delay(5000); -} \ No newline at end of file +} diff --git a/libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino b/libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino index e106275b567..87c29339fb7 100644 --- a/libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino +++ b/libraries/OpenThread/examples/CLI/ThreadScan/ThreadScan.ino @@ -27,7 +27,7 @@ void setup() { Serial.begin(115200); - OThread.begin(true); // For scanning, AutoStart must be active, any setup + OThread.begin(true); // For scanning, AutoStart must be active, any setup OThreadCLI.begin(); OThreadCLI.setTimeout(100); // Set a timeout for the CLI response Serial.println(); diff --git a/libraries/OpenThread/keywords.txt b/libraries/OpenThread/keywords.txt index 33e10e2c222..b62c2c23ddc 100644 --- a/libraries/OpenThread/keywords.txt +++ b/libraries/OpenThread/keywords.txt @@ -70,4 +70,4 @@ OT_ROLE_CHILD LITERAL1 OT_ROLE_ROUTER LITERAL1 OT_ROLE_LEADER LITERAL1 OT_EXT_PAN_ID_SIZE LITERAL1 -OT_NETWORK_KEY_SIZE LITERAL1 \ No newline at end of file +OT_NETWORK_KEY_SIZE LITERAL1 diff --git a/libraries/OpenThread/src/OThread.cpp b/libraries/OpenThread/src/OThread.cpp index e529316efad..43d8ce02918 100644 --- a/libraries/OpenThread/src/OThread.cpp +++ b/libraries/OpenThread/src/OThread.cpp @@ -48,7 +48,6 @@ extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) { } #endif - static void ot_task_worker(void *aContext) { esp_vfs_eventfd_config_t eventfd_config = { .max_fds = 3, diff --git a/libraries/OpenThread/src/OThread.h b/libraries/OpenThread/src/OThread.h index 394143efb3e..359d581bb9d 100644 --- a/libraries/OpenThread/src/OThread.h +++ b/libraries/OpenThread/src/OThread.h @@ -36,69 +36,69 @@ typedef enum { extern const char *otRoleString[]; class DataSet { - public: - DataSet(); - void clear(); - void initNew(); - const otOperationalDataset &getDataset() const; - - // Setters - void setNetworkName(const char *name); - void setExtendedPanId(const uint8_t *extPanId); - void setNetworkKey(const uint8_t *key); - void setChannel(uint8_t channel); - void setPanId(uint16_t panId); - - // Getters - const char *getNetworkName() const; - const uint8_t *getExtendedPanId() const; - const uint8_t *getNetworkKey() const; - uint8_t getChannel() const; - uint16_t getPanId() const; - - // Apply the dataset to the OpenThread instance - void apply(otInstance *instance); - - private: - otOperationalDataset mDataset; +public: + DataSet(); + void clear(); + void initNew(); + const otOperationalDataset &getDataset() const; + + // Setters + void setNetworkName(const char *name); + void setExtendedPanId(const uint8_t *extPanId); + void setNetworkKey(const uint8_t *key); + void setChannel(uint8_t channel); + void setPanId(uint16_t panId); + + // Getters + const char *getNetworkName() const; + const uint8_t *getExtendedPanId() const; + const uint8_t *getNetworkKey() const; + uint8_t getChannel() const; + uint16_t getPanId() const; + + // Apply the dataset to the OpenThread instance + void apply(otInstance *instance); + +private: + otOperationalDataset mDataset; }; class OpenThread { - public: - static bool otStarted; - static ot_device_role_t otGetDeviceRole(); - static const char *otGetStringDeviceRole(); - static void otPrintNetworkInformation(Stream &output); +public: + static bool otStarted; + static ot_device_role_t otGetDeviceRole(); + static const char *otGetStringDeviceRole(); + static void otPrintNetworkInformation(Stream &output); - OpenThread(); - ~OpenThread(); - // returns true if OpenThread Stack is running - operator bool() const; + OpenThread(); + ~OpenThread(); + // returns true if OpenThread Stack is running + operator bool() const; - // Initialize OpenThread - static void begin(bool OThreadAutoStart = true); + // Initialize OpenThread + static void begin(bool OThreadAutoStart = true); - // Initialize OpenThread - static void end(); + // Initialize OpenThread + static void end(); - // Start the Thread network - void start(); + // Start the Thread network + void start(); - // Stop the Thread network - void stop(); + // Stop the Thread network + void stop(); - // Start Thread Network Interface - void networkInterfaceUp(); + // Start Thread Network Interface + void networkInterfaceUp(); - // Stop Thread Network Interface - void networkInterfaceDown(); + // Stop Thread Network Interface + void networkInterfaceDown(); - // Set the dataset - void commitDataSet(const DataSet &dataset); + // Set the dataset + void commitDataSet(const DataSet &dataset); - private: - static otInstance *mInstance; - DataSet mCurrentDataSet; +private: + static otInstance *mInstance; + DataSet mCurrentDataSet; }; extern OpenThread OThread;