SerialCommand.cpp

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:  }  

Geen opmerkingen:

Een reactie posten