CmdMessenger  3.0
CmdMessenger is a messaging library for the Arduino Platform. It has uses the serial port as its transport layer
D:/My Documents/Github/Arduino-Code-and-Libraries/Libraries/CmdMessenger/CmdMessenger.h
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