通过 Arduino 的 UART 串行交互 shell?
Interactive shell via UART serial for Arduino?
我想通过 Arduino 的 UART 串行端口使用纯 C++ OOP 样式代码实现交互式 shell。但是我觉得如果在代码中判断用户输入命令的时候if-else判断太多,会有点难看,
所以我想问一下,有什么办法可以避免使用if-else语句吗?例如,
之前:
while(Serial.available())
{
serialReceive = Serial.readString();// read the incoming data as string
Serial.println(serialReceive);
}
if(serialReceive.equals("factory-reset"))
{
MyService::ResetSettings();
}
else if(serialReceive.equals("get-freeheap"))
{
MyService::PrintFreeHeap();
}
else if(serialReceive.equals("get-version"))
{
MyService::PrintVersion();
}
之后:
while(Serial.available())
{
serialReceive = Serial.readString();// read the incoming data as string
Serial.println(serialReceive);
}
MagicClass::AssignCommand("factory-reset", MyService::ResetSettings);
MagicClass::AssignCommand("get-freeheap", MyService::PrintFreeHeap);
MagicClass::AssignCommand("get-version", MyService::PrintVersion);
您可以使用一个数组来存储函数指针以及触发命令的字符串(您可以创建一个结构来存储两者)。
不幸的是 Arduino 不支持 std::vector class 所以对于我的例子我将使用 c 类型的数组。然而,Arduino 有一个库,它为 Arduino 添加了一些 STL 支持 https://github.com/maniacbug/StandardCplusplus(对于这个库,您还可以使用函数库来使传递函数作为参数更容易)
//struct that stores function to call and trigger word (can actually have spaces and special characters
struct shellCommand_t
{
//function pointer that accepts functions that look like "void test(){...}"
void (*f)(void);
String cmd;
};
//array to store the commands
shellCommand_t* commands;
有了这个,您可以在开始时将命令数组初始化为一个大小,或者在每次添加命令时调整它的大小,这取决于您的用例。
假设您已经在数组中分配了足够的 space 用于添加命令的基本函数可能如下所示
int nCommands = 0;
void addCommand(String cmd, void (*f)(void))
{
shellCommand_t sc;
sc.cmd = cmd;
sc.f = f;
commands[nCommands++] = sc;
}
然后在您的设置函数中,您可以按照与上述类似的方式添加命令
addCommand("test", test);
addCommand("hello world", helloWorld);
最后,在循环函数中,您可以使用 for 循环查看所有命令,检查输入字符串与所有命令字符串的对比。
你可以这样调用匹配命令的函数
(*(commands[i].f))();
我想通过 Arduino 的 UART 串行端口使用纯 C++ OOP 样式代码实现交互式 shell。但是我觉得如果在代码中判断用户输入命令的时候if-else判断太多,会有点难看,
所以我想问一下,有什么办法可以避免使用if-else语句吗?例如,
之前:
while(Serial.available())
{
serialReceive = Serial.readString();// read the incoming data as string
Serial.println(serialReceive);
}
if(serialReceive.equals("factory-reset"))
{
MyService::ResetSettings();
}
else if(serialReceive.equals("get-freeheap"))
{
MyService::PrintFreeHeap();
}
else if(serialReceive.equals("get-version"))
{
MyService::PrintVersion();
}
之后:
while(Serial.available())
{
serialReceive = Serial.readString();// read the incoming data as string
Serial.println(serialReceive);
}
MagicClass::AssignCommand("factory-reset", MyService::ResetSettings);
MagicClass::AssignCommand("get-freeheap", MyService::PrintFreeHeap);
MagicClass::AssignCommand("get-version", MyService::PrintVersion);
您可以使用一个数组来存储函数指针以及触发命令的字符串(您可以创建一个结构来存储两者)。
不幸的是 Arduino 不支持 std::vector class 所以对于我的例子我将使用 c 类型的数组。然而,Arduino 有一个库,它为 Arduino 添加了一些 STL 支持 https://github.com/maniacbug/StandardCplusplus(对于这个库,您还可以使用函数库来使传递函数作为参数更容易)
//struct that stores function to call and trigger word (can actually have spaces and special characters
struct shellCommand_t
{
//function pointer that accepts functions that look like "void test(){...}"
void (*f)(void);
String cmd;
};
//array to store the commands
shellCommand_t* commands;
有了这个,您可以在开始时将命令数组初始化为一个大小,或者在每次添加命令时调整它的大小,这取决于您的用例。
假设您已经在数组中分配了足够的 space 用于添加命令的基本函数可能如下所示
int nCommands = 0;
void addCommand(String cmd, void (*f)(void))
{
shellCommand_t sc;
sc.cmd = cmd;
sc.f = f;
commands[nCommands++] = sc;
}
然后在您的设置函数中,您可以按照与上述类似的方式添加命令
addCommand("test", test);
addCommand("hello world", helloWorld);
最后,在循环函数中,您可以使用 for 循环查看所有命令,检查输入字符串与所有命令字符串的对比。
你可以这样调用匹配命令的函数
(*(commands[i].f))();