Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
scogswell committed Jan 11, 2013
0 parents commit bd993d4
Show file tree
Hide file tree
Showing 5 changed files with 369 additions and 0 deletions.
38 changes: 38 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
An Arduino library to tokenize and parse commands received over a serial port.

Initially documented here: http://awtfy.com/2011/05/23/a-minimal-arduino-library-for-processing-serial-commands/

An alternate version of this library is available as https://github.com/kroimon/Arduino-SerialCommand

This version is the one on Github.


/*******************************************************************************
SerialCommand - An Arduino library to tokenize and parse commands received over
a serial port.
Copyright (C) 2011 Steven Cogswell <[email protected]>
http://husks.wordpress.com

Version 20110523B.

Version History:
May 11 2011 - Initial version
May 13 2011 - Prevent overwriting bounds of SerialCommandCallback[] array in addCommand()
defaultHandler() for non-matching commands
Mar 2012 - Some const char * changes to make compiler happier about deprecated warnings.
Arduino 1.0 compatibility (Arduino.h header)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
***********************************************************************************/
155 changes: 155 additions & 0 deletions SerialCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*******************************************************************************
SerialCommand - An Arduino library to tokenize and parse commands received over
a serial port.
Copyright (C) 2011 Steven Cogswell <[email protected]>
http://husks.wordpress.com
Version 20110523B.
See SerialCommand.h for version history.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
***********************************************************************************/

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include <string.h>
#include "SerialCommand.h"

// Constructor makes sure some things are set.
SerialCommand::SerialCommand()
{
strncpy(delim," ",MAXDELIMETER); // strtok_r needs a null-terminated string
term='\r'; // return character, default terminator for commands
numCommand=0; // Number of callback handlers installed
clearBuffer();
}

//
// Initialize the command buffer being processed to all null characters
//
void SerialCommand::clearBuffer()
{
for (int i=0; i<SERIALCOMMANDBUFFER; i++)
{
buffer[i]='\0';
}
bufPos=0;
}

// Retrieve the next token ("word" or "argument") from the Command buffer.
// returns a NULL if no more tokens exist.
char *SerialCommand::next()
{
char *nextToken;
nextToken = strtok_r(NULL, delim, &last);
return nextToken;
}

// This checks the Serial stream for characters, and assembles them into a buffer.
// When the terminator character (default '\r') is seen, it starts parsing the
// buffer for a prefix command, and calls handlers setup by addCommand() member
void SerialCommand::readSerial()
{
while (Serial.available() > 0)
{
int i;
boolean matched;
inChar=Serial.read(); // Read single available character, there may be more waiting
#ifdef SERIALCOMMANDDEBUG
Serial.print(inChar); // Echo back to serial stream
#endif
if (inChar==term) { // Check for the terminator (default '\r') meaning end of command
#ifdef SERIALCOMMANDDEBUG
Serial.print("Received: ");
Serial.println(buffer);
#endif
bufPos=0; // Reset to start of buffer
token = strtok_r(buffer,delim,&last); // Search for command at start of buffer
if (token == NULL) return;
matched=false;
for (i=0; i<numCommand; i++) {
#ifdef SERIALCOMMANDDEBUG
Serial.print("Comparing [");
Serial.print(token);
Serial.print("] to [");
Serial.print(CommandList[i].command);
Serial.println("]");
#endif
// Compare the found command against the list of known commands for a match
if (strncmp(token,CommandList[i].command,SERIALCOMMANDBUFFER) == 0)
{
#ifdef SERIALCOMMANDDEBUG
Serial.print("Matched Command: ");
Serial.println(token);
#endif
// Execute the stored handler function for the command
(*CommandList[i].function)();
clearBuffer();
matched=true;
break;
}
}
if (matched==false) {
(*defaultHandler)();
clearBuffer();
}

}
if (isprint(inChar)) // Only printable characters into the buffer
{
buffer[bufPos++]=inChar; // Put character into buffer
buffer[bufPos]='\0'; // Null terminate
if (bufPos > SERIALCOMMANDBUFFER-1) bufPos=0; // wrap buffer around if full
}
}
}

// Adds a "command" and a handler function to the list of available commands.
// This is used for matching a found token in the buffer, and gives the pointer
// to the handler function to deal with it.
void SerialCommand::addCommand(const char *command, void (*function)())
{
if (numCommand < MAXSERIALCOMMANDS) {
#ifdef SERIALCOMMANDDEBUG
Serial.print(numCommand);
Serial.print("-");
Serial.print("Adding command for ");
Serial.println(command);
#endif

strncpy(CommandList[numCommand].command,command,SERIALCOMMANDBUFFER);
CommandList[numCommand].function = function;
numCommand++;
} else {
// In this case, you tried to push more commands into the buffer than it is compiled to hold.
// Not much we can do since there is no real visible error assertion, we just ignore adding
// the command
#ifdef SERIALCOMMANDDEBUG
Serial.println("Too many handlers - recompile changing MAXSERIALCOMMANDS");
#endif
}
}

// This sets up a handler to be called in the event that the receveived command string
// isn't in the list of things with handlers.
void SerialCommand::addDefaultHandler(void (*function)())
{
defaultHandler = function;
}
75 changes: 75 additions & 0 deletions SerialCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*******************************************************************************
SerialCommand - An Arduino library to tokenize and parse commands received over
a serial port.
Copyright (C) 2011 Steven Cogswell <[email protected]>
http://husks.wordpress.com
Version 20110523B.
Version History:
May 11 2011 - Initial version
May 13 2011 - Prevent overwriting bounds of SerialCommandCallback[] array in addCommand()
defaultHandler() for non-matching commands
Mar 2012 - Some const char * changes to make compiler happier about deprecated warnings.
Arduino 1.0 compatibility (Arduino.h header)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
***********************************************************************************/
#ifndef SerialCommand_h
#define SerialCommand_h

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include <string.h>

#define SERIALCOMMANDBUFFER 16
#define MAXSERIALCOMMANDS 10
#define MAXDELIMETER 2

#define SERIALCOMMANDDEBUG 1
#undef SERIALCOMMANDDEBUG // Comment this out to run the library in debug mode (verbose messages)

class SerialCommand
{
public:
SerialCommand(); // Constructor
void clearBuffer(); // Sets the command buffer to all '\0' (nulls)
char *next(); // returns pointer to next token found in command buffer (for getting arguments to commands)
void readSerial(); // Main entry point.
void addCommand(const char *, void(*)()); // Add commands to processing dictionary
void addDefaultHandler(void (*function)()); // A handler to call when no valid command received.

private:
char inChar; // A character read from the serial stream
char buffer[SERIALCOMMANDBUFFER]; // Buffer of stored characters while waiting for terminator character
int bufPos; // Current position in the buffer
char delim[MAXDELIMETER]; // null-terminated list of character to be used as delimeters for tokenizing (default " ")
char term; // Character that signals end of command (default '\r')
char *token; // Returned token from the command buffer as returned by strtok_r
char *last; // State variable used by strtok_r during processing
typedef struct _callback {
char command[SERIALCOMMANDBUFFER];
void (*function)();
} SerialCommandCallback; // Data structure to hold Command/Handler function key-value pairs
int numCommand;
SerialCommandCallback CommandList[MAXSERIALCOMMANDS]; // Actual definition for command/handler array
void (*defaultHandler)(); // Pointer to the default handler function
};

#endif //SerialCommand_h
96 changes: 96 additions & 0 deletions examples/SerialCommandExample/SerialCommandExample.pde
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Demo Code for SerialCommand Library
// Steven Cogswell
// May 2011

#include <SerialCommand.h>

#define arduinoLED 13 // Arduino LED on board

SerialCommand SCmd; // The demo SerialCommand object

void setup()
{
pinMode(arduinoLED,OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED,LOW); // default to LED off

Serial.begin(9600);

// Setup callbacks for SerialCommand commands
SCmd.addCommand("ON",LED_on); // Turns LED on
SCmd.addCommand("OFF",LED_off); // Turns LED off
SCmd.addCommand("HELLO",SayHello); // Echos the string argument back
SCmd.addCommand("P",process_command); // Converts two arguments to integers and echos them back
SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
Serial.println("Ready");

}

void loop()
{
SCmd.readSerial(); // We don't do much, just process serial commands
}


void LED_on()
{
Serial.println("LED on");
digitalWrite(arduinoLED,HIGH);
}

void LED_off()
{
Serial.println("LED off");
digitalWrite(arduinoLED,LOW);
}

void SayHello()
{
char *arg;
arg = SCmd.next(); // Get the next argument from the SerialCommand object buffer
if (arg != NULL) // As long as it existed, take it
{
Serial.print("Hello ");
Serial.println(arg);
}
else {
Serial.println("Hello, whoever you are");
}
}


void process_command()
{
int aNumber;
char *arg;

Serial.println("We're in process_command");
arg = SCmd.next();
if (arg != NULL)
{
aNumber=atoi(arg); // Converts a char string to an integer
Serial.print("First argument was: ");
Serial.println(aNumber);
}
else {
Serial.println("No arguments");
}

arg = SCmd.next();
if (arg != NULL)
{
aNumber=atol(arg);
Serial.print("Second argument was: ");
Serial.println(aNumber);
}
else {
Serial.println("No second argument");
}

}

// This gets set as the default handler, and gets called when no other command matches.
void unrecognized()
{
Serial.println("What?");
}

5 changes: 5 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SerialCommand KEYWORD1
clearBuffer KEYWORD2
next KEYWORD2
readSerial KEYWORD2
addCommand KEYWORd2

0 comments on commit bd993d4

Please sign in to comment.