CmdMessenger
3.0
CmdMessenger is a messaging library for the Arduino Platform. It has uses the serial port as its transport layer
|
00001 /* 00002 CmdMessenger - library that provides command based messaging 00003 00004 Permission is hereby granted, free of charge, to any person obtaining 00005 a copy of this software and associated documentation files (the 00006 "Software"), to deal in the Software without restriction, including 00007 without limitation the rights to use, copy, modify, merge, publish, 00008 distribute, sublicense, and/or sell copies of the Software, and to 00009 permit persons to whom the Software is furnished to do so, subject to 00010 the following conditions: 00011 00012 The above copyright notice and this permission notice shall be 00013 included in all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00016 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00018 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00019 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00020 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00021 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00022 00023 00024 */ 00025 00026 #ifndef CmdMessenger_h 00027 #define CmdMessenger_h 00028 00029 #include <inttypes.h> 00030 #if ARDUINO >= 100 00031 #include <Arduino.h> 00032 #else 00033 #include <WProgram.h> 00034 #endif 00035 00036 //#include "Stream.h" 00037 00038 extern "C" 00039 { 00040 // callback functions always follow the signature: void cmd(void); 00041 typedef void (*messengerCallbackFunction) (void); 00042 } 00043 00044 #define MAXCALLBACKS 50 // The maximum number of commands (default: 50) 00045 #define MESSENGERBUFFERSIZE 64 // The maximum length of the buffer (default: 64) 00046 #define DEFAULT_TIMEOUT 5000 // Time out on unanswered messages. (default: 5s) 00047 00048 // Message States 00049 enum 00050 { 00051 kProccesingMessage, // Message is being received, not reached command separator 00052 kEndOfMessage, // Message is fully received, reached command separator 00053 kProcessingArguments, // Message is received, arguments are being read parsed 00054 }; 00055 00056 class CmdMessenger 00057 { 00058 private: 00059 00060 // **** Private variables *** 00061 00062 bool startCommand; // Indicates if sending of a command is underway 00063 uint8_t lastCommandId; // ID of last received command 00064 uint8_t bufferIndex; // Index where to write data in buffer 00065 uint8_t bufferLength; // Is set to MESSENGERBUFFERSIZE 00066 uint8_t bufferLastIndex; // The last index of the buffer 00067 char ArglastChar; // Bookkeeping of argument escape char 00068 char CmdlastChar; // Bookkeeping of command escape char 00069 bool pauseProcessing; // pauses processing of new commands, during sending 00070 bool print_newlines; // Indicates if \r\n should be added after send command 00071 char buffer[MESSENGERBUFFERSIZE]; // Buffer that holds the data 00072 uint8_t messageState; // Current state of message processing 00073 bool dumped; // Indicates if last argument has been externally read 00074 bool ArgOk; // Indicated if last fetched argument could be read 00075 char *current; // Pointer to current buffer position 00076 char *last; // Pointer to previous buffer position 00077 char prevChar; // Previous char (needed for unescaping) 00078 Stream *comms; // Serial data stream 00079 00080 char command_separator; // Character indicating end of command (default: ';') 00081 char field_separator; // Character indicating end of argument (default: ',') 00082 char escape_character; // Character indicating escaping of special chars 00083 00084 messengerCallbackFunction default_callback; // default callback function 00085 messengerCallbackFunction callbackList[MAXCALLBACKS]; // list of attached callback functions 00086 00087 // ****** Private functions ****** 00088 00089 // **** Initialize **** 00090 00091 void init (Stream & comms, const char fld_separator, const char cmd_separator, const char esc_character); 00092 void reset (); 00093 00094 // **** Command processing **** 00095 00096 uint8_t processAndCallBack (int serialByte); 00097 uint8_t processLine (int serialByte); 00098 void handleMessage (); 00099 00100 bool blockedTillReply (int timeout = DEFAULT_TIMEOUT, int ackCmdId = 1); 00101 bool CheckForAck (int AckCommand); 00102 bool processAndWaitForAck (int serialByte, int AckCommand); 00103 00104 // **** Command sending **** 00105 00109 template < class T > 00110 void writeBin (const T & value) 00111 { 00112 const byte *bytePointer = (const byte *) (const void *) &value; 00113 for (unsigned int i = 0; i < sizeof (value); i++) 00114 { 00115 printEsc (*bytePointer); 00116 *bytePointer++; 00117 } 00118 } 00119 00120 // **** Command receiving **** 00121 00122 int findNext (char *str, char delim); 00123 00127 template < class T > 00128 T readBin (char *str) 00129 { 00130 T value; 00131 unescape (str); 00132 byte *bytePointer = (byte *) (const void *) &value; 00133 for (unsigned int i = 0; i < sizeof (value); i++) 00134 { 00135 *bytePointer = str[i]; 00136 *bytePointer++; 00137 } 00138 return value; 00139 } 00140 00141 // **** Escaping tools **** 00142 00143 char *split_r (char *str, const char delim, char **nextp); 00144 bool isEscaped (char *currChar, const char escapeChar, char *lastChar); 00145 00146 void printEsc (char *str); 00147 void printEsc (char str); 00148 00149 public: 00150 00151 // ****** Public functions ****** 00152 00153 // **** Initialization **** 00154 00155 CmdMessenger (Stream & comms, const char fld_separator = ',', 00156 const char cmd_separator = ';', 00157 const char esc_character = '/'); 00158 00159 void printLfCr (bool addNewLine=true); 00160 void attach (messengerCallbackFunction newFunction); 00161 void attach (byte msgId, messengerCallbackFunction newFunction); 00162 00163 // **** Command processing **** 00164 00165 void feedinSerialData (); 00166 bool next (); 00167 bool available (); 00168 00169 uint8_t CommandID (); 00170 00171 // **** Command sending **** 00172 00177 template < class T > 00178 bool sendCmd (int cmdId, T arg, bool reqAc = false, int ackCmdId = 1, 00179 int timeout = DEFAULT_TIMEOUT) 00180 { 00181 if (!startCommand) { 00182 sendCmdStart (cmdId); 00183 sendCmdArg (arg); 00184 return sendCmdEnd (reqAc, ackCmdId, timeout); 00185 } 00186 } 00187 00192 template < class T > 00193 bool sendBinCmd (int cmdId, T arg, bool reqAc = false, int ackCmdId = 1, 00194 int timeout = DEFAULT_TIMEOUT) 00195 { 00196 if (!startCommand) { 00197 sendCmdStart (cmdId); 00198 sendCmdBinArg (arg); 00199 return sendCmdEnd (reqAc, ackCmdId, timeout); 00200 } 00201 } 00202 00203 // **** Command sending with multiple arguments **** 00204 00205 void sendCmdStart (int cmdId); 00206 void sendCmdEscArg (char *arg); 00207 void sendCmdfArg (char *fmt, ...); 00208 bool sendCmdEnd (bool reqAc = false, int ackCmdId = 1, int timeout = DEFAULT_TIMEOUT); 00209 00214 template < class T > void sendCmdArg (T arg) 00215 { 00216 if (startCommand) 00217 { 00218 comms->print (field_separator); 00219 comms->print (arg); 00220 } 00221 } 00222 00227 template < class T > void sendCmdArg (T arg, int n) 00228 { 00229 if (startCommand) 00230 { 00231 comms->print (field_separator); 00232 comms->print (arg, n); 00233 } 00234 } 00235 00240 template < class T > void sendCmdBinArg (T arg) 00241 { 00242 if (startCommand) 00243 { 00244 comms->print (field_separator); 00245 writeBin (arg); 00246 } 00247 } 00248 00249 // **** Command receiving **** 00250 bool readBoolArg(); 00251 int readIntArg (); 00252 char readCharArg (); 00253 float readFloatArg (); 00254 char *readStringArg (); 00255 void copyStringArg (char *string, uint8_t size); 00256 uint8_t compareStringArg (char *string); 00257 00261 template < class T > T readBinArg () 00262 { 00263 if (next ()) 00264 { 00265 dumped = true; 00266 return readBin < T > (current); 00267 } 00268 } 00269 00270 // **** Escaping tools **** 00271 00272 void unescape (char *fromChar); 00273 }; 00274 #endif