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
+ }
0 commit comments