* 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>
192 lines
5.5 KiB
C++
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 */
|