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 #ifndef CmdMessenger_h 00026 #define CmdMessenger_h 00027 00028 #include <inttypes.h> 00029 #if ARDUINO >= 100 00030 #include <Arduino.h> 00031 #else 00032 #include <WProgram.h> 00033 #endif 00034 00035 //#include "Stream.h" 00036 00037 extern "C" 00038 { 00039 // callback functions always follow the signature: void cmd(void); 00040 typedef void (*messengerCallbackFunction) (void); 00041 } 00042 00043 #define MAXCALLBACKS 50 // The maximum number of commands (default: 50) 00044 #define MESSENGERBUFFERSIZE 64 // The maximum length of the buffer (default: 64) 00045 #define MAXSTREAMBUFFERSIZE 32 // The maximum length of the buffer (default: 32) 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 commandBuffer[MESSENGERBUFFERSIZE]; // Buffer that holds the data 00072 char streamBuffer[MAXSTREAMBUFFERSIZE]; // Buffer that holds the data 00073 uint8_t messageState; // Current state of message processing 00074 bool dumped; // Indicates if last argument has been externally read 00075 bool ArgOk; // Indicated if last fetched argument could be read 00076 char *current; // Pointer to current buffer position 00077 char *last; // Pointer to previous buffer position 00078 char prevChar; // Previous char (needed for unescaping) 00079 Stream *comms; // Serial data stream 00080 00081 char command_separator; // Character indicating end of command (default: ';') 00082 char field_separator; // Character indicating end of argument (default: ',') 00083 char escape_character; // Character indicating escaping of special chars 00084 00085 messengerCallbackFunction default_callback; // default callback function 00086 messengerCallbackFunction callbackList[MAXCALLBACKS]; // list of attached callback functions 00087 00088 // ****** Private functions ****** 00089 00090 // **** Initialize **** 00091 00092 void init (Stream & comms, const char fld_separator, const char cmd_separator, const char esc_character); 00093 void reset (); 00094 00095 // **** Command processing **** 00096 00097 inline uint8_t processLine (char serialChar) __attribute__((always_inline)); 00098 inline void handleMessage() __attribute__((always_inline)); 00099 inline bool blockedTillReply (unsigned long timeout = DEFAULT_TIMEOUT, int ackCmdId = 1) __attribute__((always_inline)); 00100 inline bool CheckForAck (int AckCommand) __attribute__((always_inline)); 00101 00102 // **** Command sending **** 00103 00107 template < class T > 00108 void writeBin (const T & value) 00109 { 00110 const byte *bytePointer = (const byte *) (const void *) &value; 00111 for (unsigned int i = 0; i < sizeof (value); i++) 00112 { 00113 printEsc (*bytePointer); 00114 *bytePointer++; 00115 } 00116 } 00117 00118 // **** Command receiving **** 00119 00120 int findNext (char *str, char delim); 00121 00125 template < class T > 00126 T readBin (char *str) 00127 { 00128 T value; 00129 unescape (str); 00130 byte *bytePointer = (byte *) (const void *) &value; 00131 for (unsigned int i = 0; i < sizeof (value); i++) 00132 { 00133 *bytePointer = str[i]; 00134 *bytePointer++; 00135 } 00136 return value; 00137 } 00138 00139 // **** Escaping tools **** 00140 00141 char *split_r (char *str, const char delim, char **nextp); 00142 bool isEscaped (char *currChar, const char escapeChar, char *lastChar); 00143 00144 void printEsc (char *str); 00145 void printEsc (char str); 00146 00147 public: 00148 00149 // ****** Public functions ****** 00150 00151 // **** Initialization **** 00152 00153 CmdMessenger (Stream & comms, const char fld_separator = ',', 00154 const char cmd_separator = ';', 00155 const char esc_character = '/'); 00156 00157 void printLfCr (bool addNewLine=true); 00158 void attach (messengerCallbackFunction newFunction); 00159 void attach (byte msgId, messengerCallbackFunction newFunction); 00160 00161 // **** Command processing **** 00162 00163 void feedinSerialData (); 00164 bool next (); 00165 bool available (); 00166 bool isArgOk (); 00167 uint8_t CommandID (); 00168 00169 // **** Command sending **** 00170 00175 template < class T > 00176 bool sendCmd (int cmdId, T arg, bool reqAc = false, int ackCmdId = 1, 00177 int timeout = DEFAULT_TIMEOUT) 00178 { 00179 if (!startCommand) { 00180 sendCmdStart (cmdId); 00181 sendCmdArg (arg); 00182 return sendCmdEnd (reqAc, ackCmdId, timeout); 00183 } 00184 return false; 00185 } 00186 00191 template < class T > 00192 bool sendBinCmd (int cmdId, T arg, bool reqAc = false, int ackCmdId = 1, 00193 int timeout = DEFAULT_TIMEOUT) 00194 { 00195 if (!startCommand) { 00196 sendCmdStart (cmdId); 00197 sendCmdBinArg (arg); 00198 return sendCmdEnd (reqAc, ackCmdId, timeout); 00199 } 00200 return false; 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 long readLongArg (); 00253 char readCharArg (); 00254 float readFloatArg (); 00255 char *readStringArg (); 00256 void copyStringArg (char *string, uint8_t size); 00257 uint8_t compareStringArg (char *string); 00258 00262 template < class T > T readBinArg () 00263 { 00264 if (next ()) 00265 { 00266 dumped = true; 00267 return readBin < T > (current); 00268 } 00269 return (T)0; 00270 } 00271 00272 // **** Escaping tools **** 00273 00274 void unescape (char *fromChar); 00275 }; 00276 #endif