// Modified from @gcjr
// https://forum.arduino.cc/t/commands-over-serial/1320091/14
// multiword command processing
// split separate word/values (i.e. tokens) in command line
// search for cmd in command-table, cmds[], and execute if found
// test with example command lines
char s [90]; // for sprintf()
// -----------------------------------------------------------------------------
// arrays of tokens (char *) and corresponging values if numeric
// a token in one word of text/numeric
#define MAX_TOKS 10
char * toks [MAX_TOKS];
int vals [MAX_TOKS];
int nTok;
char buf [90]; // char buffer when input is const char
#include <util/crc16.h>
unsigned int crc16a(unsigned char *message) {
int i;
unsigned int byte, crc;
i = 0;
while (message[i] != 0) {
_crc16_update (crc,message[i++]);
}
return crc;
}
// -------------------------------------
// display the current arrays of tokens and values
void
tokDisp ()
{
Serial.println (" tokDisp:");
for (int n = 0; n < nTok; n++) {
sprintf (s, " %6d %s, crc16:%x\n", vals [n], toks [n], crc16a(toks[n]));
Serial.print (s);
}
}
// -------------------------------------
// locate tokens in provide string, set ptrs in tokens
int
tokenize (
char *str )
{
nTok = 0;
sprintf (s, " tokenize: %s\n", str);
Serial.print (s);
strcpy (buf, str); // copy possible const char array into char array
// initially call strtok() with char array, subsequent calls are passed nul
// continue processing until nul token found
// attempt to translate all tokens into numberic value
for (toks [nTok] = strtok (buf, " "); toks [nTok]; ) {
vals [nTok] = atoi (toks [nTok]);
toks [++nTok] = strtok (NULL, " ");
}
return nTok;
}
// -----------------------------------------------------------------------------
// test command functions used to demonstrate processing
void a (char *toks [], int n) { Serial.print (" a:\n"); tokDisp (); }
void b (char *toks [], int n) { Serial.print (" b:\n"); tokDisp (); }
void c (char *toks [], int n) { Serial.print (" c:\n"); tokDisp (); }
void d (char *toks [], int n) { Serial.print (" d:\n"); tokDisp (); }
// -------------------------------------
// command table - function ptr and command string
struct Cmd {
void (*f) (char *tok [], int nTok);
const char *name;
}
cmds [] = { // table for above command functions
{ a, "tom" },
{ b, "dick" },
{ c, "harry" },
{ d, "martha" },
};
const int Ncmd = sizeof(cmds)/sizeof(Cmd);
// -------------------------------------
// tokenize command line and search for cmd, 1st token, in cmds []
void
processCmd (
char *buf )
{
sprintf (s, "\nprocessCmd: %s\n", buf);
Serial.print (s);
tokenize (buf);
for (int n = 0; n < Ncmd; n++) {
// execute cmd when found and return
if (! strcmp (cmds [n].name, toks [0])) {
cmds [n].f (toks, nTok);
return;
}
}
// only reached if cmd not found
sprintf (s, " processCmd: unknown cmd %s\n", toks [0]);
Serial.print (s);
}
// -----------------------------------------------------------------------------
// define test command lines
char *str [] = {
(char *)"martha",
(char *)"tom 0 1 2 3",
(char *)"dick xyz 040",
(char *)"harry 0 1 abc 2",
};
const int Nstr = 4;
void setup ()
{
Serial.begin (9600);
delay (200);
// process each test cmd line
for (int n = 0; n < Nstr; n++)
processCmd (str [n]);
}
void loop () { }