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>
1
+ /* *
2
+ * SerialCommand - A Wiring/Arduino library to tokenize and parse commands
3
+ * received over a serial port.
4
+ *
5
+ * Copyright (C) 2012 Stefan Rado
6
+ * Copyright (C) 2011 Steven Cogswell <[email protected] >
7
+ * http://husks.wordpress.com
8
+ *
9
+ * Version 20120522
10
+ *
11
+ * This library is free software: you can redistribute it and/or modify
12
+ * it under the terms of the GNU Lesser General Public License as published by
13
+ * the Free Software Foundation, either version 3 of the License, or
14
+ * (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
19
+ * GNU Lesser General Public License for more details.
20
+ *
21
+ * You should have received a copy of the GNU General Public License
22
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
23
+ */
28
24
#include " SerialCommand.h"
29
25
30
- // Constructor makes sure some things are set.
26
+ /* *
27
+ * Constructor makes sure some things are set.
28
+ */
31
29
SerialCommand::SerialCommand ()
30
+ : commandList(NULL ),
31
+ commandCount(0 ),
32
+ defaultHandler(NULL ),
33
+ term(' \n ' ), // default terminator for commands, newline character
34
+ last(NULL )
32
35
{
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 ();
36
+ strcpy (delim, " " ); // strtok_r needs a null-terminated string
37
+ clearBuffer ();
37
38
}
38
39
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 ;
40
+ /* *
41
+ * Adds a "command" and a handler function to the list of available commands.
42
+ * This is used for matching a found token in the buffer, and gives the pointer
43
+ * to the handler function to deal with it.
44
+ */
45
+ void SerialCommand::addCommand (const char *command, void (*function)()) {
46
+ #ifdef SERIALCOMMAND_DEBUG
47
+ Serial.print (" Adding command (" );
48
+ Serial.print (commandCount);
49
+ Serial.print (" ): " );
50
+ Serial.println (command);
51
+ #endif
52
+
53
+ commandList = (SerialCommandCallback *) realloc (commandList, (commandCount + 1 ) * sizeof (SerialCommandCallback));
54
+ strncpy (commandList[commandCount].command , command, SERIALCOMMAND_MAXCOMMANDLENGTH);
55
+ commandList[commandCount].function = function;
56
+ commandCount++;
49
57
}
50
58
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;
59
+ /* *
60
+ * This sets up a handler to be called in the event that the receveived command string
61
+ * isn't in the list of commands.
62
+ */
63
+ void SerialCommand::setDefaultHandler (void (*function)(const char *)) {
64
+ defaultHandler = function;
58
65
}
59
66
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
67
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
- }
68
+ /* *
69
+ * This checks the Serial stream for characters, and assembles them into a buffer.
70
+ * When the terminator character (default '\n') is seen, it starts parsing the
71
+ * buffer for a prefix command, and calls handlers setup by addCommand() member
72
+ */
73
+ void SerialCommand::readSerial () {
74
+ while (Serial.available () > 0 ) {
75
+ char inChar = Serial.read (); // Read single available character, there may be more waiting
76
+ #ifdef SERIALCOMMAND_DEBUG
77
+ Serial.print (inChar); // Echo back to serial stream
78
+ #endif
79
+
80
+ if (inChar == term) { // Check for the terminator (default '\r') meaning end of command
81
+ #ifdef SERIALCOMMAND_DEBUG
82
+ Serial.print (" Received: " );
83
+ Serial.println (buffer);
84
+ #endif
85
+
86
+ char *command = strtok_r (buffer, delim, &last); // Search for command at start of buffer
87
+ if (command != NULL ) {
88
+ boolean matched = false ;
89
+ for (int i = 0 ; i < commandCount; i++) {
90
+ #ifdef SERIALCOMMAND_DEBUG
91
+ Serial.print (" Comparing [" );
92
+ Serial.print (command);
93
+ Serial.print (" ] to [" );
94
+ Serial.print (commandList[i].command );
95
+ Serial.println (" ]" );
96
+ #endif
97
+
98
+ // Compare the found command against the list of known commands for a match
99
+ if (strncmp (command, commandList[i].command , SERIALCOMMAND_MAXCOMMANDLENGTH) == 0 ) {
100
+ #ifdef SERIALCOMMAND_DEBUG
101
+ Serial.print (" Matched Command: " );
102
+ Serial.println (command);
103
+ #endif
104
+
105
+ // Execute the stored handler function for the command
106
+ (*commandList[i].function )();
107
+ matched = true ;
108
+ break ;
109
+ }
110
+ }
111
+ if (!matched && (defaultHandler != NULL )) {
112
+ (*defaultHandler)(command);
113
+ }
114
+ }
115
+ clearBuffer ();
116
+ }
117
+ else if (isprint (inChar)) { // Only printable characters into the buffer
118
+ if (bufPos < SERIALCOMMAND_BUFFER) {
119
+ buffer[bufPos++] = inChar; // Put character into buffer
120
+ buffer[bufPos] = ' \0 ' ; // Null terminate
121
+ } else {
122
+ #ifdef SERIALCOMMAND_DEBUG
123
+ Serial.println (" Line buffer is full - increase SERIALCOMMAND_BUFFER" );
124
+ #endif
125
+ }
126
+ }
127
+ }
117
128
}
118
129
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
- }
130
+ /*
131
+ * Clear the input buffer.
132
+ */
133
+ void SerialCommand::clearBuffer () {
134
+ buffer[0 ] = ' \0 ' ;
135
+ bufPos = 0 ;
143
136
}
144
137
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
- }
138
+ /* *
139
+ * Retrieve the next token ("word" or "argument") from the command buffer.
140
+ * Returns NULL if no more tokens exist.
141
+ */
142
+ char *SerialCommand::next () {
143
+ return strtok_r (NULL , delim, &last);
144
+ }
0 commit comments