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