From 5c677bec68d837f81799b9e56df03543b248ec03 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 20 Jun 2024 14:24:58 -0300 Subject: [PATCH] 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