2017-01-11 9 views
1

Я хотел бы реализовать интерактивную оболочку через последовательный порт UART для Arduino с чистым кодом стиля C++ OOP. Но я думаю, что если есть слишком много суждений if-else при оценке пользовательских команд ввода в коде, это будет немного уродливо,Интерактивная оболочка через последовательный порт UART для Arduino?

Поэтому я хотел бы спросить, есть ли способ избежать использования 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); 

ответ

3

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

К сожалению, 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); 

Наконец в вашей функции петли вы можете использовать цикл, чтобы просмотреть все команды, проверьте введенную строку против всех командных строк.

Вы можете вызвать функцию согласованной команды, как это

(*(commands[i].f))();