Skip to content
This repository was archived by the owner on Mar 22, 2024. It is now read-only.

Commit b4e5650

Browse files
author
kroimon
committed
0 parents  commit b4e5650

File tree

4 files changed

+319
-0
lines changed

4 files changed

+319
-0
lines changed

SerialCommand.cpp

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*******************************************************************************
2+
SerialCommand - An Arduino library to tokenize and parse commands received over
3+
a serial port.
4+
Copyright (C) 2011 Steven Cogswell <[email protected]>
5+
http://husks.wordpress.com
6+
7+
Version 20110523B.
8+
9+
See SerialCommand.h for version history.
10+
11+
This library is free software; you can redistribute it and/or
12+
modify it under the terms of the GNU Lesser General Public
13+
License as published by the Free Software Foundation; either
14+
version 2.1 of the License, or (at your option) any later version.
15+
16+
This library is distributed in the hope that it will be useful,
17+
but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
Lesser General Public License for more details.
20+
21+
You should have received a copy of the GNU Lesser General Public
22+
License along with this library; if not, write to the Free Software
23+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24+
***********************************************************************************/
25+
26+
#include "WProgram.h"
27+
#include <string.h>
28+
#include "SerialCommand.h"
29+
30+
// Constructor makes sure some things are set.
31+
SerialCommand::SerialCommand()
32+
{
33+
strncpy(delim," ",MAXDELIMETER); // strtok_r needs a null-terminated string
34+
term='\r'; // return character, default terminator for commands
35+
numCommand=0; // Number of callback handlers installed
36+
clearBuffer();
37+
}
38+
39+
//
40+
// Initialize the command buffer being processed to all null characters
41+
//
42+
void SerialCommand::clearBuffer()
43+
{
44+
for (int i=0; i<SERIALCOMMANDBUFFER; i++)
45+
{
46+
buffer[i]='\0';
47+
}
48+
bufPos=0;
49+
}
50+
51+
// Retrieve the next token ("word" or "argument") from the Command buffer.
52+
// returns a NULL if no more tokens exist.
53+
char *SerialCommand::next()
54+
{
55+
char *nextToken;
56+
nextToken = strtok_r(NULL, delim, &last);
57+
return nextToken;
58+
}
59+
60+
// This checks the Serial stream for characters, and assembles them into a buffer.
61+
// When the terminator character (default '\r') is seen, it starts parsing the
62+
// buffer for a prefix command, and calls handlers setup by addCommand() member
63+
void SerialCommand::readSerial()
64+
{
65+
while (Serial.available() > 0)
66+
{
67+
int i;
68+
boolean matched;
69+
inChar=Serial.read(); // Read single available character, there may be more waiting
70+
#ifdef SERIALCOMMANDDEBUG
71+
Serial.print(inChar); // Echo back to serial stream
72+
#endif
73+
if (inChar==term) { // Check for the terminator (default '\r') meaning end of command
74+
#ifdef SERIALCOMMANDDEBUG
75+
Serial.print("Received: ");
76+
Serial.println(buffer);
77+
#endif
78+
bufPos=0; // Reset to start of buffer
79+
token = strtok_r(buffer,delim,&last); // Search for command at start of buffer
80+
if (token == NULL) return;
81+
matched=false;
82+
for (i=0; i<numCommand; i++) {
83+
#ifdef SERIALCOMMANDDEBUG
84+
Serial.print("Comparing [");
85+
Serial.print(token);
86+
Serial.print("] to [");
87+
Serial.print(CommandList[i].command);
88+
Serial.println("]");
89+
#endif
90+
// Compare the found command against the list of known commands for a match
91+
if (strncmp(token,CommandList[i].command,SERIALCOMMANDBUFFER) == 0)
92+
{
93+
#ifdef SERIALCOMMANDDEBUG
94+
Serial.print("Matched Command: ");
95+
Serial.println(token);
96+
#endif
97+
// Execute the stored handler function for the command
98+
(*CommandList[i].function)();
99+
clearBuffer();
100+
matched=true;
101+
break;
102+
}
103+
}
104+
if (matched==false) {
105+
(*defaultHandler)();
106+
clearBuffer();
107+
}
108+
109+
}
110+
if (isprint(inChar)) // Only printable characters into the buffer
111+
{
112+
buffer[bufPos++]=inChar; // Put character into buffer
113+
buffer[bufPos]='\0'; // Null terminate
114+
if (bufPos > SERIALCOMMANDBUFFER-1) bufPos=0; // wrap buffer around if full
115+
}
116+
}
117+
}
118+
119+
// Adds a "command" and a handler function to the list of available commands.
120+
// This is used for matching a found token in the buffer, and gives the pointer
121+
// to the handler function to deal with it.
122+
void SerialCommand::addCommand(char command[], void (*function)())
123+
{
124+
if (numCommand < MAXSERIALCOMMANDS) {
125+
#ifdef SERIALCOMMANDDEBUG
126+
Serial.print(numCommand);
127+
Serial.print("-");
128+
Serial.print("Adding command for ");
129+
Serial.println(command);
130+
#endif
131+
132+
strncpy(CommandList[numCommand].command,command,SERIALCOMMANDBUFFER);
133+
CommandList[numCommand].function = function;
134+
numCommand++;
135+
} else {
136+
// In this case, you tried to push more commands into the buffer than it is compiled to hold.
137+
// Not much we can do since there is no real visible error assertion, we just ignore adding
138+
// the command
139+
#ifdef SERIALCOMMANDDEBUG
140+
Serial.println("Too many handlers - recompile changing MAXSERIALCOMMANDS");
141+
#endif
142+
}
143+
}
144+
145+
// This sets up a handler to be called in the event that the receveived command string
146+
// isn't in the list of things with handlers.
147+
void SerialCommand::addDefaultHandler(void (*function)())
148+
{
149+
defaultHandler = function;
150+
}

SerialCommand.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*******************************************************************************
2+
SerialCommand - An Arduino library to tokenize and parse commands received over
3+
a serial port.
4+
Copyright (C) 2011 Steven Cogswell <[email protected]>
5+
http://husks.wordpress.com
6+
7+
Version 20110523B.
8+
9+
Version History:
10+
May 11 2011 - Initial version
11+
May 13 2011 - Prevent overwriting bounds of SerialCommandCallback[] array in addCommand()
12+
defaultHandler() for non-matching commands
13+
14+
This library is free software; you can redistribute it and/or
15+
modify it under the terms of the GNU Lesser General Public
16+
License as published by the Free Software Foundation; either
17+
version 2.1 of the License, or (at your option) any later version.
18+
19+
This library is distributed in the hope that it will be useful,
20+
but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22+
Lesser General Public License for more details.
23+
24+
You should have received a copy of the GNU Lesser General Public
25+
License along with this library; if not, write to the Free Software
26+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27+
***********************************************************************************/
28+
#ifndef SerialCommand_h
29+
#define SerialCommand_h
30+
31+
#include "WProgram.h"
32+
#include <string.h>
33+
34+
#define SERIALCOMMANDBUFFER 16
35+
#define MAXSERIALCOMMANDS 10
36+
#define MAXDELIMETER 2
37+
38+
#define SERIALCOMMANDDEBUG 1
39+
#undef SERIALCOMMANDDEBUG // Comment this out to run the library in debug mode (verbose messages)
40+
41+
class SerialCommand
42+
{
43+
public:
44+
SerialCommand(); // Constructor
45+
void clearBuffer(); // Sets the command buffer to all '\0' (nulls)
46+
char *next(); // returns pointer to next token found in command buffer (for getting arguments to commands)
47+
void readSerial(); // Main entry point.
48+
void addCommand(char *, void(*)()); // Add commands to processing dictionary
49+
void addDefaultHandler(void (*function)()); // A handler to call when no valid command received.
50+
51+
private:
52+
char inChar; // A character read from the serial stream
53+
char buffer[SERIALCOMMANDBUFFER]; // Buffer of stored characters while waiting for terminator character
54+
char bufPos; // Current position in the buffer
55+
char delim[MAXDELIMETER]; // null-terminated list of character to be used as delimeters for tokenizing (default " ")
56+
char term; // Character that signals end of command (default '\r')
57+
char *token; // Returned token from the command buffer as returned by strtok_r
58+
char *last; // State variable used by strtok_r during processing
59+
typedef struct _callback {
60+
char command[SERIALCOMMANDBUFFER];
61+
void (*function)();
62+
} SerialCommandCallback; // Data structure to hold Command/Handler function key-value pairs
63+
int numCommand;
64+
SerialCommandCallback CommandList[MAXSERIALCOMMANDS]; // Actual definition for command/handler array
65+
void (*defaultHandler)(); // Pointer to the default handler function
66+
};
67+
68+
#endif //SerialCommand_h
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Demo Code for SerialCommand Library
2+
// Steven Cogswell
3+
// May 2011
4+
5+
#include <SerialCommand.h>
6+
7+
#define arduinoLED 13 // Arduino LED on board
8+
9+
SerialCommand SCmd; // The demo SerialCommand object
10+
11+
void setup()
12+
{
13+
pinMode(arduinoLED,OUTPUT); // Configure the onboard LED for output
14+
digitalWrite(arduinoLED,LOW); // default to LED off
15+
16+
Serial.begin(9600);
17+
18+
// Setup callbacks for SerialCommand commands
19+
SCmd.addCommand("ON",LED_on); // Turns LED on
20+
SCmd.addCommand("OFF",LED_off); // Turns LED off
21+
SCmd.addCommand("HELLO",SayHello); // Echos the string argument back
22+
SCmd.addCommand("P",process_command); // Converts two arguments to integers and echos them back
23+
SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
24+
Serial.println("Ready");
25+
26+
}
27+
28+
void loop()
29+
{
30+
SCmd.readSerial(); // We don't do much, just process serial commands
31+
}
32+
33+
34+
void LED_on()
35+
{
36+
Serial.println("LED on");
37+
digitalWrite(arduinoLED,HIGH);
38+
}
39+
40+
void LED_off()
41+
{
42+
Serial.println("LED off");
43+
digitalWrite(arduinoLED,LOW);
44+
}
45+
46+
void SayHello()
47+
{
48+
char *arg;
49+
arg = SCmd.next(); // Get the next argument from the SerialCommand object buffer
50+
if (arg != NULL) // As long as it existed, take it
51+
{
52+
Serial.print("Hello ");
53+
Serial.println(arg);
54+
}
55+
else {
56+
Serial.println("Hello, whoever you are");
57+
}
58+
}
59+
60+
61+
void process_command()
62+
{
63+
int aNumber;
64+
char *arg;
65+
66+
Serial.println("We're in process_command");
67+
arg = SCmd.next();
68+
if (arg != NULL)
69+
{
70+
aNumber=atoi(arg); // Converts a char string to an integer
71+
Serial.print("First argument was: ");
72+
Serial.println(aNumber);
73+
}
74+
else {
75+
Serial.println("No arguments");
76+
}
77+
78+
arg = SCmd.next();
79+
if (arg != NULL)
80+
{
81+
aNumber=atol(arg);
82+
Serial.print("Second argument was: ");
83+
Serial.println(aNumber);
84+
}
85+
else {
86+
Serial.println("No second argument");
87+
}
88+
89+
}
90+
91+
// This gets set as the default handler, and gets called when no other command matches.
92+
void unrecognized()
93+
{
94+
Serial.println("What?");
95+
}
96+

keywords.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
SerialCommand KEYWORD1
2+
clearBuffer KEYWORD2
3+
next KEYWORD2
4+
readSerial KEYWORD2
5+
addCommand KEYWORd2

0 commit comments

Comments
 (0)