DynamicCommandParser library

I’ve done serveral projects where I wanted to pass a commands with parameters over serial or network to an Arduino. Splitting strings and comparing values always produced unneccesarily messy code for me so this led me to hide most of the bare metal by creating a library I called DynamicCommandParser (previously SerialDataParser)

I have removed any Arduino specific code from the library and made it work on the Spark Core as well and thought perhaps this could be of use to the Spark community as well. I have not yet tested this but I bet it could make a simple way to parse the method args from functions executed via the Cloud API.

The library has been added to the Community Libraries and is also available on GitHub:

What it does, a short and sweet example

Start off by creating a DynamicCommandParser object defining a start, end and delimiter character for the commands:

DynamicCommandParser dcp('^', '$', ',');

Now in your setup() method you add your command name and the method it should execute, you can of course keep adding parsers for multiple commands.

dcp.addParser("myCommand", myCommandParser);

Then we create the parser method, the method signature is important:

void myCommandParser(char **values, int valueCount) {
    for (int i = 0; i < valueCount; i++) {
        Serial.println(values[i]);
    }
}

And finally in your loop you start passing serial input to the parser:

while (Serial.available()) {
    dcp.appendChar(Serial.read());
}

Flash this to your device (Arduino or Spark) and open a serial monitor

Send in the string:

^myCommand,val 1,val 2,34,56$

And you should see the output from myCommandParser function. Because this uses a start and end character it does not depend on newlines so you can string multiple commands on the same line if you want.

Happy hacking

6 Likes

Thanks for the library. Any thoughts on other serial libraries? worth porting?

http://playground.arduino.cc/Code/CmdMessenger



http://www.forward.com.au/pfod/pfodParserLibraries/

Similarly I created a Class for structuring multiple variables using a single Spark.function( ):

class httpCommand {
  String argument;
public:
  void extractValues(String);
  String mssgCommand (void) {
    return argument.substring(argument.indexOf("command#") + 8, argument.indexOf("#text="));
  }
  String mssgText (void) {
    return argument.substring(argument.indexOf("#text=") + 6, argument.indexOf("#value0="));
  }
  int mssgValue0 (void) {
    return (argument.substring(argument.indexOf("#value0=") + 8, argument.indexOf("#value1="))).toInt();
  }
  int mssgValue1 (void) {
    return (argument.substring(argument.indexOf("#value1=") + 8, argument.indexOf("?"))).toInt();
  }
};
//
void httpCommand::extractValues (String stringPassed){
    argument = stringPassed;

I peel it open with a simple function:

int httpRequest(String mssgArgs)
{
  DEBUG_PRINTLN("command recieved...");
  oldData = false;
  lastDataTransmitTime = millis();
  httpCommand command;
  command.extractValues(mssgArgs);
  DEBUG_PRINTLN(command.mssgCommand());
  boolean badMessage = true;
  for (int i = 0; i < NUMBER_OF_MESSAGE_TYPES; i++)
  {
    if (command.mssgCommand().equals(messageType[i]))
    {
      DEBUG_PRINTLN("Valid Message Recieved...");
      DEBUG_PRINTLN("Message type:");
      DEBUG_PRINTLN(command.mssgCommand());
      DEBUG_PRINT("messgText = ");
      DEBUG_PRINTLN(command.mssgText());
      DEBUG_PRINT("messgValue0 = ");
      DEBUG_PRINTLN(command.mssgValue0());
      DEBUG_PRINT("messgValue1 = ");
      DEBUG_PRINTLN(command.mssgValue1());
      updateVariables(i, command.mssgText(), command.mssgValue0(), command.mssgValue1());
      badMessage = false;
    }
  }
  if (badMessage)
  {
    DEBUG_PRINTLN("non-conforming message attempt...");
    return -1;
  }
  else return 1;
}

(keeping my standard commands in an array called messageType[ ])

I thought about building a library… well you beat me to it.

Thanks!!!

Hi,
I have come across your library, and am hopeful it will help this recent forray into arduino. I have downloaded, and installed, however the example sketch won’t compile.
I am a absolute novice at the C types of language, but have been doing industrial control and programming, and high level windows programming (PLC’s, labview and similar) for many years.

The error results the IDE compiler are:

Arduino: 1.8.5 (Windows 10), Board: "Arduino Nano, ATmega328P"

In file included from C:\Users\Documents\Arduino\libraries\DynamicCommandParser-master\firmware\examples\SimpleCommandParsing\SimpleCommandParsing.ino:19:0:

C:\Users\\Documents\Arduino\libraries\DynamicCommandParser-master/DynamicCommandParser.h:1:1: error: 'firmware' does not name a type

 firmware/DynamicCommandParser.h

 ^

C:\Users\Documents\Arduino\libraries\DynamicCommandParser-master\firmware\examples\SimpleCommandParsing\SimpleCommandParsing.ino: In function 'void setup()':

SimpleCommandParsing:50: error: 'dcp' was not declared in this scope

   dcp.addParser("COP", commandOnlyParser);

   ^

C:\Users\Documents\Arduino\libraries\DynamicCommandParser-master\firmware\examples\SimpleCommandParsing\SimpleCommandParsing.ino: In function 'void loop()':

SimpleCommandParsing:62: error: 'dcp' was not declared in this scope

     dcp.appendChar(Serial.read());

     ^

exit status 1
'dcp' was not declared in this scope

Am I being stupid, or is there an error?

Regards
Nigel

You seem to be including the wrong files :wink:
There are two files DynamicCommandParser.cpp and DynamicCommandParser.h in the “root” of that GitHub repo, but these are only links to the actual files located inside the firmware folder.
Try using those instead.