用于Arduino的UART串口交互式shell?

时间:2017-01-11 04:41:26

标签: c++ arduino esp8266 arduino-esp8266 platformio

我想通过UART串口为Arduino实现交互式shell,使用纯C ++ OOP样式代码。但是我认为如果在判断代码中的用户输入命令时判断有太多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);

1 个答案:

答案 0 :(得分:3)

您可以拥有一个存储函数指针的数组以及触发该命令的字符串(您可以创建一个结构来存储它们)。

不幸的是Arduino不支持std :: vector类,所以对于我的例子,我将使用c类型数组。但是有一个Arduino库,它为Arduino https://github.com/maniacbug/StandardCplusplus添加了一些STL支持(也可以使用这个库,你可以使用函数库使参数传递更容易)

//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;

使用此功能,您可以在启动时将命令数组初始化为一个大小,也可以在每次添加命令时将其调整大小,这取决于您的用例。

假设您已在阵列中分配足够空间以添加命令的基本功能可能如下所示

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))();