From bd993d48a561f02c4d946b16f04a2d889cd73629 Mon Sep 17 00:00:00 2001 From: Steven Cogswell Date: Fri, 11 Jan 2013 10:45:23 -0400 Subject: [PATCH] Initial commit --- README.txt | 38 +++++ SerialCommand.cpp | 155 ++++++++++++++++++ SerialCommand.h | 75 +++++++++ .../SerialCommandExample.pde | 96 +++++++++++ keywords.txt | 5 + 5 files changed, 369 insertions(+) create mode 100644 README.txt create mode 100644 SerialCommand.cpp create mode 100644 SerialCommand.h create mode 100644 examples/SerialCommandExample/SerialCommandExample.pde create mode 100644 keywords.txt diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..7caf484 --- /dev/null +++ b/README.txt @@ -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 +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 +***********************************************************************************/ diff --git a/SerialCommand.cpp b/SerialCommand.cpp new file mode 100644 index 0000000..e80235c --- /dev/null +++ b/SerialCommand.cpp @@ -0,0 +1,155 @@ +/******************************************************************************* +SerialCommand - An Arduino library to tokenize and parse commands received over +a serial port. +Copyright (C) 2011 Steven Cogswell +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 +#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 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 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; +} \ No newline at end of file diff --git a/SerialCommand.h b/SerialCommand.h new file mode 100644 index 0000000..f2ca3ad --- /dev/null +++ b/SerialCommand.h @@ -0,0 +1,75 @@ +/******************************************************************************* +SerialCommand - An Arduino library to tokenize and parse commands received over +a serial port. +Copyright (C) 2011 Steven Cogswell +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 + +#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 \ No newline at end of file diff --git a/examples/SerialCommandExample/SerialCommandExample.pde b/examples/SerialCommandExample/SerialCommandExample.pde new file mode 100644 index 0000000..7e1ad68 --- /dev/null +++ b/examples/SerialCommandExample/SerialCommandExample.pde @@ -0,0 +1,96 @@ +// Demo Code for SerialCommand Library +// Steven Cogswell +// May 2011 + +#include + +#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?"); +} + diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..9e19284 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,5 @@ +SerialCommand KEYWORD1 +clearBuffer KEYWORD2 +next KEYWORD2 +readSerial KEYWORD2 +addCommand KEYWORd2 \ No newline at end of file