Интерактивная оболочка через последовательный порт UART для Arduino?

Я хотел бы реализовать интерактивную оболочку через последовательный порт UART для Arduino с чистым кодом в стиле 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);

person Jackson Ming Hu    schedule 11.01.2017    source источник
comment
Если вы все еще заинтересованы, я написал соответствующий вопрос о проверке кода: codereview.stackexchange.com/questions/260122/   -  person Eric Duminil    schedule 05.05.2021


Ответы (1)


У вас может быть массив, в котором хранится указатель на функцию вместе со строкой, запускающей команду (вы можете создать структуру для хранения обоих).

К сожалению, Arduino не поддерживает класс std::vector, поэтому в моем примере я буду использовать массивы типа c. Однако существует библиотека для Arduino, которая добавляет некоторую поддержку STL для Arduino 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;

При этом вы можете либо инициализировать массив команд до одного размера при запуске, либо изменять его размер каждый раз, когда вы добавляете команду, это просто зависит от вашего варианта использования.

Базовая функция, которая предполагает, что вы уже выделили достаточно места в массиве для добавления команды, может выглядеть так:

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))();
person Jesse Laning    schedule 11.01.2017