arduino-esp32/libraries/OpenThread/src/OThreadCLI_Util.cpp
Sugar Glider ef995b6564
feat(openthread): adds native api (#11474)
* feat(openthread): adds native api

* feat(openthread): adds source code to CMakeLists.txt

* ci(pre-commit): Apply automatic fixes

---------

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2025-06-16 13:15:54 +03:00

192 lines
5.5 KiB
C++

// 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.
#include "OThreadCLI.h"
#if SOC_IEEE802154_SUPPORTED
#if CONFIG_OPENTHREAD_ENABLED
#include "OThreadCLI_Util.h"
#include <StreamString.h>
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) {
if (!OThreadCLI) {
return false;
}
char cliResp[256] = {0};
if (cmd == NULL) {
return true;
}
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 beginning
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;
}
}
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 otCLIPrintNetworkInformation(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 */