John Bailey / XBeeApi

Dependencies:   CircularBuffer FixedLengthList

Dependents:   XBeeApiTest XBeeApiSimpleATCmdsExample XBeeApiBroadcastExample XBeeApiBroadcastExampleRTOS ... more

Files at this revision

API Documentation at this revision

Comitter:
johnb
Date:
Fri Aug 08 11:59:52 2014 +0000
Parent:
55:610aa4a2ed3b
Commit message:
Add support for setting up encrypted communications; Re-jig XBeeApiCmdAt virtual functions to make inheritance by XBeeDeviceRemoteAt cleaner.

Changed in this revision

Remote/XBeeDeviceRemoteAt.cpp Show annotated file Show diff for this revision Revisions of this file
Remote/XBeeDeviceRemoteAt.hpp Show annotated file Show diff for this revision Revisions of this file
Utility/XBeeApiCmdAt.cpp Show annotated file Show diff for this revision Revisions of this file
Utility/XBeeApiCmdAt.hpp Show annotated file Show diff for this revision Revisions of this file
Utility/XBeeApiCmdAtBlocking.cpp Show annotated file Show diff for this revision Revisions of this file
Utility/XBeeApiCmdAtBlocking.hpp Show annotated file Show diff for this revision Revisions of this file
--- a/Remote/XBeeDeviceRemoteAt.cpp	Sat Aug 02 16:41:14 2014 +0000
+++ b/Remote/XBeeDeviceRemoteAt.cpp	Fri Aug 08 11:59:52 2014 +0000
@@ -20,9 +20,8 @@
 
 #define XBEE_API_CMD_REMOTE_REQ_HEADER_LEN 14U
 
-template< typename T >
-class XBeeApiCmdAtRemoteSet : public XBeeApiFrame {
-    uint8_t m_buffer[ XBEE_API_CMD_REMOTE_REQ_HEADER_LEN + sizeof( T ) ];
+class XBeeApiCmdAtRemoteFrame : public XBeeApiFrame {
+    uint8_t m_buffer[ XBEE_API_CMD_REMOTE_REQ_HEADER_LEN + XBEE_CMD_MAX_PARAM_LENGTH ];
     public:
         /** Constructor
                    
@@ -31,34 +30,16 @@
                           request
             \param p_val New value for the parameter 
         */
-        XBeeApiCmdAtRemoteSet( const uint8_t        p_frameId,
-                               const uint16_t       p_addr16Bit,
-                               const uint64_t       p_addr64Bit,
-                               const XBeeDevice::XBeeApiAddrType_t p_type,
-                               const bool           p_applyChanges,
-                               const uint8_t* const p_data,
-                               const T p_val );
+        XBeeApiCmdAtRemoteFrame( const uint8_t        p_frameId,
+                                 const uint16_t       p_addr16Bit,
+                                 const uint64_t       p_addr64Bit,
+                                 const XBeeDevice::XBeeApiAddrType_t p_type,
+                                 const bool           p_applyChanges,
+                                 const uint8_t* const p_data,
+                                 const uint8_t* const p_val,
+                                 const uint8_t        p_len );
         /** Destructor */
-        virtual ~XBeeApiCmdAtRemoteSet();
-};
-
-class XBeeApiCmdAtRemoteReq : public XBeeApiFrame {
-    uint8_t m_buffer[ XBEE_API_CMD_REMOTE_REQ_HEADER_LEN ];
-    public:
-        /** Constructor
-                   
-            \param p_data Pointer to a buffer of length 2 bytes identifying
-                          the command, e.g. 'V', 'R' would set up a version
-                          request
-            \param p_val New value for the parameter 
-        */
-        XBeeApiCmdAtRemoteReq( const uint8_t        p_frameId,
-                               const uint16_t       p_addr16Bit,
-                               const uint64_t       p_addr64Bit,
-                               const XBeeDevice::XBeeApiAddrType_t p_type,
-                               const uint8_t* const p_data );
-        /** Destructor */
-        virtual ~XBeeApiCmdAtRemoteReq();
+        virtual ~XBeeApiCmdAtRemoteFrame();
 };
 
 XBeeDeviceRemoteAt::XBeeDeviceRemoteAt( XBeeDevice* p_device,
@@ -148,39 +129,14 @@
     return ret_val;
 }
 
-void XBeeDeviceRemoteAt::SendCmd_uint8_t( const uint8_t        p_frameId,
-                                          const uint8_t* const p_data,
-                                          const uint8_t&       p_val )
+void XBeeDeviceRemoteAt::SendCmd( const uint8_t p_frameId,
+                                  const uint8_t* const p_data,
+                                  const uint8_t* const p_val,
+                                  const uint8_t        p_len )
 {
      uint64_t addr64Bit = (((uint64_t)m_snHigh) << 32U) | (uint64_t)m_snLow;
      /* TODO: Add option to force usage of 16 or 64-bit addressing */
-     XBeeApiCmdAtRemoteSet<uint8_t> req( p_frameId, m_sourceAddress, addr64Bit, m_addressingType, m_applyChanges, p_data, p_val );
-     m_device->SendFrame( &req );
-}
-
-void XBeeDeviceRemoteAt::SendCmd_uint16_t( const uint8_t        p_frameId,
-                                           const uint8_t* const p_data,
-                                           const uint16_t&      p_val )
-{
-     uint64_t addr64Bit = (((uint64_t)m_snHigh) << 32U) | (uint64_t)m_snLow;
-     XBeeApiCmdAtRemoteSet<uint16_t> req( p_frameId, m_sourceAddress, addr64Bit, m_addressingType, m_applyChanges, p_data, p_val );
-     m_device->SendFrame( &req );
-}
-
-void XBeeDeviceRemoteAt::SendCmd_uint32_t( const uint8_t        p_frameId,
-                                           const uint8_t* const p_data,
-                                           const uint32_t&      p_val )
-{
-     uint64_t addr64Bit = (((uint64_t)m_snHigh) << 32U) | (uint64_t)m_snLow;
-     XBeeApiCmdAtRemoteSet<uint32_t> req( p_frameId, m_sourceAddress, addr64Bit, m_addressingType, m_applyChanges, p_data, p_val );
-     m_device->SendFrame( &req );
-}
-
-void XBeeDeviceRemoteAt::SendReq( const uint8_t             p_frameId,
-                                  const uint8_t*            p_data )
-{
-     uint64_t addr64Bit = (((uint64_t)m_snHigh) << 32U) | (uint64_t)m_snLow;
-     XBeeApiCmdAtRemoteReq req( p_frameId, m_sourceAddress, addr64Bit, m_addressingType, p_data );
+     XBeeApiCmdAtRemoteFrame req( p_frameId, m_sourceAddress, addr64Bit, m_addressingType, m_applyChanges, p_data, p_val, p_len );
      m_device->SendFrame( &req );
 }
 
@@ -245,72 +201,69 @@
     }
 }
 
-template < typename T >
-XBeeApiCmdAtRemoteSet<T>::XBeeApiCmdAtRemoteSet( const uint8_t        p_frameId,
-                                                 const uint16_t       p_addr16Bit,
-                                                 const uint64_t       p_addr64Bit,
-                                                 const XBeeDevice::XBeeApiAddrType_t p_type,
-                                                 const bool           p_applyChanges,
-                                                 const uint8_t* const p_data,
-                                                 const T p_val ) : XBeeApiFrame( )
-{
-    size_t s;
-    uint8_t* dest;
-    const uint8_t* src = (uint8_t*)(&p_val);
-    
+XBeeApiCmdAtRemoteFrame::XBeeApiCmdAtRemoteFrame( const uint8_t        p_frameId,
+                                                  const uint16_t       p_addr16Bit,
+                                                  const uint64_t       p_addr64Bit,
+                                                  const XBeeDevice::XBeeApiAddrType_t p_type,
+                                                  const bool           p_applyChanges,
+                                                  const uint8_t* const p_data,
+                                                  const uint8_t* const p_val,
+                                                  const uint8_t        p_len ) : XBeeApiFrame( )
+{   
     m_apiId = XBEE_CMD_REMOTE_AT_CMD;
     
     m_buffer[0] = p_frameId;
     
     writeAddressToBuffer( &(m_buffer[1]), p_addr16Bit, p_addr64Bit, p_type );
 
-    m_buffer[11] = p_applyChanges << 1;
-
+    if( p_len )
+    {
+        m_buffer[11] = p_applyChanges << 1;
+    }
+    else
+    {
+        m_buffer[11] = 0;
+    }
+    
     m_buffer[12] = p_data[0];
     m_buffer[13] = p_data[1];
     
-    m_dataLen = sizeof( m_buffer );
-
-    /* TODO: This copy code isn't portable - it's assuming that the data in 
-     * p_data is little endian */
+    m_data = m_buffer;
+    m_dataLen = XBEE_API_CMD_REMOTE_REQ_HEADER_LEN;
      
-    dest = &( m_buffer[ m_dataLen - 1 ] );
-    
-    for( s = 0;
-         s < sizeof( T );
-         s++, dest--, src++ ) {
-        *dest = *src;         
+    if(( p_val != NULL ) &&
+       ( p_len <= XBEE_CMD_MAX_PARAM_LENGTH ))
+    {
+        size_t s = 0;
+        uint8_t* dest = &( m_buffer[ XBEE_API_CMD_REMOTE_REQ_HEADER_LEN ] );
+        const uint8_t* src = p_val;
+        
+        for( s = 0;
+             s < p_len;
+             s++, dest++, src++ ) {
+             *dest = *src;         
+        }
+        m_dataLen += p_len;
     }
     
-    m_data = m_buffer;
-}
+#if 0
+    /* Debugging code */
+    extern Serial pc;
+    size_t x = 0;
+    pc.printf("\r\n[%02X][%02X][%02X]",(m_dataLen>>8U)&0xFF,m_dataLen&0xFF,m_apiId);
+    for( x  = 0; x < m_dataLen; x++ )
+    {
+        if(( x> 11 ) && ( x < 14 )) 
+        { 
+            pc.printf("%c",m_data[x]); 
+        }
+        pc.printf("[%02X]",m_data[x]);
+    }
+    pc.printf("\r\n");
+#endif
 
-template < typename T >
-XBeeApiCmdAtRemoteSet<T>::~XBeeApiCmdAtRemoteSet()
-{
 }
 
-XBeeApiCmdAtRemoteReq::XBeeApiCmdAtRemoteReq( const uint8_t        p_frameId,
-                                              const uint16_t       p_addr16Bit,
-                                              const uint64_t       p_addr64Bit,
-                                              const XBeeDevice::XBeeApiAddrType_t p_type,
-                                              const uint8_t* const p_data )
-{
-    m_apiId = XBEE_CMD_REMOTE_AT_CMD;
-    
-    m_buffer[0] = p_frameId;
-    
-    writeAddressToBuffer( &(m_buffer[1]), p_addr16Bit, p_addr64Bit, p_type );
-
-    m_buffer[11] = 0;
-
-    m_buffer[12] = p_data[0];
-    m_buffer[13] = p_data[1];
-    
-    m_dataLen = sizeof( m_buffer );
-    m_data = m_buffer;
-}
-
-XBeeApiCmdAtRemoteReq::~XBeeApiCmdAtRemoteReq()
+XBeeApiCmdAtRemoteFrame::~XBeeApiCmdAtRemoteFrame()
 {
 }
\ No newline at end of file
--- a/Remote/XBeeDeviceRemoteAt.hpp	Sat Aug 02 16:41:14 2014 +0000
+++ b/Remote/XBeeDeviceRemoteAt.hpp	Fri Aug 08 11:59:52 2014 +0000
@@ -45,21 +45,10 @@
         */
         virtual bool decodeCallback( const uint8_t* const p_data, size_t p_len );
 
-        /* TODO: doc */
-        virtual void SendCmd_uint8_t( const uint8_t        p_frameId,
-                                      const uint8_t* const p_data,
-                                      const uint8_t&       p_val );
-        /* TODO: doc */
-        virtual void SendCmd_uint16_t( const uint8_t        p_frameId,
-                                       const uint8_t* const p_data,
-                                       const uint16_t&       p_val );
-        /* TODO: doc */
-        virtual void SendCmd_uint32_t( const uint8_t        p_frameId,
-                                       const uint8_t* const p_data,
-                                       const uint32_t&       p_val );
-        /* TODO: doc */
-        virtual void SendReq( const uint8_t             p_frameId,
-                              const uint8_t*            p_data );
+        virtual void SendCmd( const uint8_t        p_frameId,
+                              const uint8_t* const p_data,
+                              const uint8_t* const p_val,
+                              const uint8_t        p_len );
 
         /* TODO: doc */
         virtual size_t getResponseStatusPos( void ) const;
--- a/Utility/XBeeApiCmdAt.cpp	Sat Aug 02 16:41:14 2014 +0000
+++ b/Utility/XBeeApiCmdAt.cpp	Fri Aug 08 11:59:52 2014 +0000
@@ -70,6 +70,9 @@
 #define CMD_RESPONSE_SET_FR  'L'
 #define CMD_RESPONSE_SET_IS  'M'
 #define CMD_RESPONSE_SET_RE  'N'
+#define CMD_RESPONSE_SET_KY  'O'
+#define CMD_RESPONSE_GET_EE  'P'
+#define CMD_RESPONSE_SET_EE  'Q'
 
 /** Lowest channel supported by the XBee S1 */
 #define XBEE_CHAN_MIN 0x0b
@@ -173,6 +176,14 @@
 static const uint8_t cmd_re[] =        { 'R', 'E' };
 static const uint8_t cmd_re_set_fid =  CMD_RESPONSE_SET_RE;
 
+static const uint8_t cmd_ky_set[] =    { 'K', 'Y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static const uint8_t cmd_ky_set_fid =  CMD_RESPONSE_SET_KY;
+
+static const uint8_t cmd_ee[] =        { 'E', 'E' };
+static const uint8_t cmd_ee_get_fid =  CMD_RESPONSE_GET_EE;
+static const uint8_t cmd_ee_set[] =    { 'E', 'E', 0 };
+static const uint8_t cmd_ee_set_fid =  CMD_RESPONSE_SET_EE;
+
 
 static const uint8_t cmd_d[ XBEE_API_DIO_CHANNEL_COUNT ][2] = {{ 'D', '0' },
                                                                { 'D', '1' },
@@ -197,41 +208,27 @@
 
 #define XBEE_CMD_RESPONS_HAS_DATA( _p_len ) ((_p_len > ( XBEE_CMD_POSN_PARAM_START + 1 ))
 
-/** Template class to create an XBeeApiFrame which can be used to change
+/** Class to create an XBeeApiFrame which can be used to read or change
     the value of one of the XBee parameters.  This class is used by the
-    setXXX methods in XBeeApiCmdAt */
-template< typename T >
-class XBeeApiCmdAtSet : public XBeeApiFrame {
-    uint8_t m_buffer[ XBEE_API_CMD_SET_HEADER_LEN + sizeof( T ) ];
+    requestXXX and setXXX methods in XBeeApiCmdAt */
+class XBeeApiCmdAtFrame : public XBeeApiFrame {
+    uint8_t m_buffer[ XBEE_API_CMD_SET_HEADER_LEN + XBEE_CMD_MAX_PARAM_LENGTH ];
     public:
         /** Constructor
                    
             \param p_data Pointer to a buffer of length 2 bytes identifying
                           the command, e.g. 'V', 'R' would set up a version
                           request
-            \param p_val New value for the parameter 
+            \param p_val Pointer to the new value for the parameter, most
+                        significant byte (MSB) first 
+            \param p_len The length of the data pointed to by p_val 
         */
-        XBeeApiCmdAtSet( const uint8_t        p_frameId,
-                         const uint8_t* const p_data,
-                         const T p_val );
+        XBeeApiCmdAtFrame( const uint8_t        p_frameId,
+                           const uint8_t* const p_data,
+                           const uint8_t* const p_val,
+                           const uint8_t        p_len );
         /** Destructor */
-        virtual ~XBeeApiCmdAtSet();
-};
-
-class XBeeApiCmdAtReq : public XBeeApiFrame {
-    uint8_t m_buffer[ XBEE_API_CMD_REQ_HEADER_LEN ];
-    public:
-        /** Constructor
-                   
-            \param p_data Pointer to a buffer of length 2 bytes identifying
-                          the command, e.g. 'V', 'R' would set up a version
-                          request
-            \param p_val New value for the parameter 
-        */
-        XBeeApiCmdAtReq( const uint8_t        p_frameId,
-                         const uint8_t* const p_data );
-        /** Destructor */
-        virtual ~XBeeApiCmdAtReq();
+        virtual ~XBeeApiCmdAtFrame();
 };
 
 void XBeeApiCmdAt::resetCachedData( void )
@@ -253,6 +250,9 @@
     m_have_sampleRate = false;
     m_have_destHigh = false;
     m_have_destLow = false;
+    m_have_encryptionEnabled = false;
+    m_keySet = false;
+    
     m_writeCount = 0;
     m_applyCount = 0;
     m_resetCount = 0;
@@ -366,6 +366,13 @@
     
     switch( p_data[ XBEE_CMD_POSN_FRAME_ID ] ) 
     {
+        case CMD_RESPONSE_SET_KY:
+            if( RESPONSE_OK( p_data )) 
+            {
+                m_keySet = true;
+            }
+            ret_val = true;
+            break;
         case CMD_RESPONSE_SET_WR:
             if( RESPONSE_OK( p_data )) 
             {
@@ -418,6 +425,7 @@
         PROCESS_SET_GET_RESPONSE_32BIT( DH, destHigh )
         PROCESS_SET_GET_RESPONSE_32BIT( DL, destLow )
         PROCESS_SET_GET_RESPONSE_8BIT( RN, randomDelaySlots )
+        PROCESS_SET_GET_RESPONSE_8BIT_WITHCAST( EE, encryptionEnabled, bool,  )
         PROCESS_SET_GET_RESPONSE_8BIT_WITHCAST( MM, macMode, XBeeApiMACMode_e,  )
         /* TODO: Add D0, D1, D2 response handling */
         PROCESS_SET_GET_RESPONSE_8BIT_WITHCAST( D0, d, XBeeApiDioConfig_e, [0] )
@@ -549,19 +557,11 @@
     return ret_val;
 }
 
-void XBeeApiCmdAt::SendReq( const uint8_t             p_frameId,
-                            const uint8_t*            p_data )
-{
-    XBeeApiCmdAtReq req( p_frameId, p_data );
-    m_device->SendFrame( &req );
-}
-
-
 #define MAKE_REQUEST( _name, _mnemonic, _cmd ) \
 bool XBeeApiCmdAt::request ## _name( void ) \
 {\
     m_have_ ## _mnemonic = false;   \
-    SendReq( _cmd ## _get_fid, _cmd ); \
+    SendCmd( _cmd ## _get_fid, _cmd, NULL, 0 ); \
     return true;\
 }
 
@@ -581,34 +581,35 @@
 MAKE_REQUEST( SampleRate,                  sampleRate,          cmd_ir )
 MAKE_REQUEST( DestinationAddressHigh,      destHigh,            cmd_dh )
 MAKE_REQUEST( DestinationAddressLow,       destLow,             cmd_dl )
+MAKE_REQUEST( EncryptionEnabled,           encryptionEnabled,   cmd_ee )
 
 bool XBeeApiCmdAt::requestWriteSettings( void )
 {
-    SendReq( cmd_wr_set_fid, cmd_wr );
+    SendCmd( cmd_wr_set_fid, cmd_wr, NULL, 0 );
     return true;
 }
 
 bool XBeeApiCmdAt::requestApplyChanges( void )
 {
-    SendReq( cmd_ac_set_fid, cmd_ac );
+    SendCmd( cmd_ac_set_fid, cmd_ac, NULL, 0 );
     return true;
 }
 
 bool XBeeApiCmdAt::requestReset( void )
 {
-    SendReq( cmd_fr_set_fid, cmd_fr );
+    SendCmd( cmd_fr_set_fid, cmd_fr, NULL, 0 );
     return true;
 }
 
 bool XBeeApiCmdAt::requestForceSample( void )
 {
-    SendReq( cmd_is_set_fid, cmd_is );
+    SendCmd( cmd_is_set_fid, cmd_is, NULL, 0 );
     return true;
 }
 
 bool XBeeApiCmdAt::requestRestoreDefaults( void )
 {
-    SendReq( cmd_re_set_fid, cmd_re );
+    SendCmd( cmd_re_set_fid, cmd_re, NULL, 0 );
     return true;
 }
 
@@ -632,7 +633,7 @@
     if( p_chanNo < XBEE_API_DIO_CHANNEL_COUNT )
     {
         m_have_d[ p_chanNo ] = false;   
-        SendReq( cmd_d_get_fid[ p_chanNo ], cmd_d[ p_chanNo ] );
+        SendCmd( cmd_d_get_fid[ p_chanNo ], cmd_d[ p_chanNo ], NULL, 0 );
         ret_val = true;
     }
     return ret_val;
@@ -684,6 +685,7 @@
 MAKE_GET( SampleRate,                  sampleRate,          uint16_t )
 MAKE_GET( DestinationAddressHigh,      destHigh,            uint32_t )
 MAKE_GET( DestinationAddressLow,       destLow,             uint32_t )
+MAKE_GET( EncryptionEnabled,           encryptionEnabled,   bool )
 
 bool XBeeApiCmdAt::getSerialNumber( uint64_t* const p_sn )
 {
@@ -725,6 +727,11 @@
     return ret_val;   
 }
 
+bool XBeeApiCmdAt::getEncryptionKeySet( void )
+{
+    return m_keySet;
+}
+
 #define MAKE_SET( _name, _mnemonic, _cmd, _type, _transmit_type ) \
 bool XBeeApiCmdAt::set ## _name( const _type p_param ) \
 {\
@@ -746,7 +753,17 @@
 MAKE_SET( SampleRate,                  sampleRate,          cmd_ir_set,  uint16_t,         uint16_t )
 MAKE_SET( DestinationAddressHigh,      destHigh,            cmd_dh_set,  uint32_t,         uint32_t )
 MAKE_SET( DestinationAddressLow,       destLow,             cmd_dl_set,  uint32_t,         uint32_t )
+MAKE_SET( EncryptionEnabled,           encryptionEnabled,   cmd_ee_set,  bool,             uint8_t )
 
+#define XBEE_ENCRYPTION_KEY_LEN 16U
+
+bool XBeeApiCmdAt::setEncryptionKey( const uint8_t* p_key )
+{
+    m_keySet = false;
+    SendCmd( cmd_ky_set_fid, cmd_ky_set, p_key, XBEE_ENCRYPTION_KEY_LEN );
+    
+    return true;
+}
 
 bool XBeeApiCmdAt::setDioConfig( const uint8_t p_chanNo, const XBeeApiDioConfig_e p_conf )
 {
@@ -771,81 +788,95 @@
     return true;
 }
 
-
-
 void XBeeApiCmdAt::SendCmd_uint8_t( const uint8_t        p_frameId,
                                     const uint8_t* const p_data,
                                     const uint8_t&       p_val )
 {
-     XBeeApiCmdAtSet<uint8_t> req( p_frameId, p_data, p_val );
-     m_device->SendFrame( &req );
+    SendCmd( p_frameId, p_data, &p_val, sizeof( uint8_t ));
 }
 
 void XBeeApiCmdAt::SendCmd_uint16_t( const uint8_t        p_frameId,
                                      const uint8_t* const p_data,
                                      const uint16_t&       p_val )
 {
-     XBeeApiCmdAtSet<uint16_t> req( p_frameId, p_data, p_val );
-     m_device->SendFrame( &req );
+    uint8_t buffer[ sizeof( uint16_t )];
+    
+    buffer[0] = (uint8_t)((p_val >> 8U) & 0xFF);
+    buffer[1] = (uint8_t)((p_val >> 0U) & 0xFF);
+     
+    SendCmd( p_frameId, p_data, buffer, sizeof( uint16_t ));
 }
 
 void XBeeApiCmdAt::SendCmd_uint32_t( const uint8_t        p_frameId,
                                      const uint8_t* const p_data,
                                      const uint32_t&       p_val )
 {
-     XBeeApiCmdAtSet<uint32_t> req( p_frameId, p_data, p_val );
-     m_device->SendFrame( &req );
+    uint8_t buffer[ sizeof( uint32_t )];
+    
+    buffer[0] = (uint8_t)((p_val >> 24U) & 0xFF);
+    buffer[1] = (uint8_t)((p_val >> 16U) & 0xFF);
+    buffer[2] = (uint8_t)((p_val >> 8U) & 0xFF);
+    buffer[3] = (uint8_t)((p_val >> 0U) & 0xFF);
+     
+    SendCmd( p_frameId, p_data, buffer, sizeof( uint32_t ));
 }
 
-template < typename T >
-XBeeApiCmdAtSet<T>::XBeeApiCmdAtSet( const uint8_t        p_frameId,
-                                     const uint8_t* const p_data,
-                                                    const T p_val ) : XBeeApiFrame( )
+void XBeeApiCmdAt::SendCmd( const uint8_t        p_frameId,
+                            const uint8_t* const p_data,
+                            const uint8_t* const p_val,
+                            const uint8_t        p_len )
 {
-    size_t s;
-    uint8_t* dest;
-    const uint8_t* src = (uint8_t*)(&p_val);
+    XBeeApiCmdAtFrame req( p_frameId, p_data, p_val, p_len );
+    m_device->SendFrame( &req );    
+}
+
+XBeeApiCmdAtFrame::XBeeApiCmdAtFrame( const uint8_t        p_frameId,   
+                                      const uint8_t* const p_data,
+                                      const uint8_t* const p_val,
+                                      const uint8_t        p_len ) : XBeeApiFrame( )
+{
     
     m_apiId = XBEE_CMD_AT_CMD;
     
     m_buffer[0] = p_frameId;
     m_buffer[1] = p_data[0];
     m_buffer[2] = p_data[1];
-    
-    m_dataLen = sizeof( m_buffer );
 
-    /* TODO: This copy code isn't portable - it's assuming that the data in 
-     * p_data is little endian */
-     
-    dest = &( m_buffer[ m_dataLen - 1 ] );
-    
-    for( s = 0;
-         s < sizeof( T );
-         s++, dest--, src++ ) {
-        *dest = *src;         
+    m_data = m_buffer;        
+    m_dataLen = XBEE_API_CMD_SET_HEADER_LEN;
+        
+    if(( p_val != NULL ) &&
+       ( p_len <= XBEE_CMD_MAX_PARAM_LENGTH ))
+    {
+        size_t s = 0;
+        uint8_t* dest = &( m_buffer[ XBEE_API_CMD_SET_HEADER_LEN ] );
+        const uint8_t* src = p_val;
+        
+        for( s = 0;
+             s < p_len;
+             s++, dest++, src++ ) {
+             *dest = *src;         
+        }
+        m_dataLen += p_len;
     }
-    
-    m_data = m_buffer;
+
+#if 0
+    /* Debugging code */
+    extern Serial pc;
+    size_t x = 0;
+    pc.printf("\r\n[%02X][%02X][%02X]",(m_dataLen>>8U)&0xFF,m_dataLen&0xFF,XBEE_CMD_AT_CMD);
+    for( x  = 0; x < m_dataLen; x++ )
+    {
+        if( x < 3 ) 
+        { 
+            pc.printf("%c",m_data[x]); 
+        }
+        pc.printf("[%02X]",m_data[x]);
+    }
+    pc.printf("\r\n");
+#endif
 }
 
-template < typename T >
-XBeeApiCmdAtSet<T>::~XBeeApiCmdAtSet()
-{
-}
-
-XBeeApiCmdAtReq::XBeeApiCmdAtReq( const uint8_t        p_frameId,
-                                  const uint8_t* const p_data )
-{
-    m_apiId = XBEE_CMD_AT_CMD;
-    
-    m_buffer[0] = p_frameId;
-    m_buffer[1] = p_data[0];
-    m_buffer[2] = p_data[1];
-    
-    m_dataLen = sizeof( m_buffer );
-    m_data = m_buffer;
-}
-
-XBeeApiCmdAtReq::~XBeeApiCmdAtReq()
+XBeeApiCmdAtFrame::~XBeeApiCmdAtFrame()
 {
 }
\ No newline at end of file
--- a/Utility/XBeeApiCmdAt.hpp	Sat Aug 02 16:41:14 2014 +0000
+++ b/Utility/XBeeApiCmdAt.hpp	Fri Aug 08 11:59:52 2014 +0000
@@ -86,8 +86,8 @@
     FP         |
     AS         |
     ED         |
-    EE         |
-    KY         |
+    EE         | requestEncryptionEnabled, setEncryptionEnabled, getEncryptionEnabled
+    KY         | setEncryptionKey, getEncryptionKeySet
     PL         |
     CA         |
     SM         |
@@ -197,6 +197,8 @@
         bool m_have_sampleRate;
         bool m_have_destHigh;
         bool m_have_destLow;
+        bool m_have_encryptionEnabled;
+        bool m_keySet;
  
         
         uint16_t m_hwVer;
@@ -236,6 +238,8 @@
         uint32_t m_resetCount; 
         uint32_t m_sampleCount;
         uint32_t m_restoreCount;
+        bool     m_encryptionEnabled;
+        bool     m_encryptionEnabledPend;
         
         time_t   m_ioDigitalUpdatedTime[ XBEE_API_DIO_CHANNEL_COUNT ];
         bool     m_ioDigitalState[ XBEE_API_DIO_CHANNEL_COUNT ];
@@ -243,18 +247,24 @@
         uint16_t m_ioAnalogueVal[ XBEE_API_ADC_CHANNEL_COUNT ];
 
 
-        virtual void SendCmd_uint8_t( const uint8_t        p_frameId,
-                                      const uint8_t* const p_data,
-                                      const uint8_t&       p_val );
-        virtual void SendCmd_uint16_t( const uint8_t        p_frameId,
-                                       const uint8_t* const p_data,
-                                       const uint16_t&       p_val );
-        virtual void SendCmd_uint32_t( const uint8_t        p_frameId,
-                                       const uint8_t* const p_data,
-                                       const uint32_t&       p_val );
-        virtual void SendReq( const uint8_t             p_frameId,
-                              const uint8_t*            p_data );
-
+        void SendCmd_uint8_t( const uint8_t        p_frameId,
+                              const uint8_t* const p_data,
+                              const uint8_t&       p_val );
+        void SendCmd_uint8_t( const uint8_t        p_frameId,
+                              const uint8_t* const p_data,
+                              const uint8_t*       p_val );
+        void SendCmd_uint16_t( const uint8_t        p_frameId,
+                               const uint8_t* const p_data,
+                               const uint16_t&       p_val );
+        void SendCmd_uint32_t( const uint8_t        p_frameId,
+                               const uint8_t* const p_data,
+                               const uint32_t&       p_val );
+                               
+        virtual void SendCmd( const uint8_t p_frameId,
+                              const uint8_t* const p_data,
+                              const uint8_t* const p_val,
+                              const uint8_t        p_len );
+                      
         virtual size_t getResponseStatusPos( void ) const;
 
 
@@ -322,6 +332,7 @@
         bool requestReset( void );
         bool requestForceSample( void );
         bool requestRestoreDefaults( void );
+        bool requestEncryptionEnabled( void );
 
         /** Read the XBee's hardware version identifier.  
        
@@ -389,6 +400,30 @@
         virtual bool getDestinationAddressLow( uint32_t* const p_address );
         virtual bool setDestinationAddressLow( const uint32_t p_address );
 
+        /** Set the encryption key used by the XBee.  This key will only
+            be used if encryption is enabled (see setEncryptionEnable ).
+            Once set the key cannot be read back.
+            
+            \param p_key Pointer to a 16-byte array, with the first array
+                         entry containing the most significant 8 bits of the
+                         128-bit key
+        */
+        virtual bool setEncryptionKey( const uint8_t* p_key );
+        
+        /** Determine whether or not a call to setEncryptionKey has successfully
+            set the key in the XBee.  Note that this will not query the key stored
+            in the XBee and will only evern return true if a call to setEncryptionKey
+            was made
+            
+            \returns true in the case that the XBee has responded to confirm that
+                          a call to setEncryptionKey was successful
+        */
+        virtual bool getEncryptionKeySet( void );
+        
+        virtual bool getEncryptionEnabled( bool* const p_enabled );
+        virtual bool setEncryptionEnabled( const bool  p_enabled );
 };
 
+#define XBEE_CMD_MAX_PARAM_LENGTH (16U)
+
 #endif
\ No newline at end of file
--- a/Utility/XBeeApiCmdAtBlocking.cpp	Sat Aug 02 16:41:14 2014 +0000
+++ b/Utility/XBeeApiCmdAtBlocking.cpp	Fri Aug 08 11:59:52 2014 +0000
@@ -339,4 +339,45 @@
                   XBeeApiCmdAt::getDestinationAddressLow,
                   p_address,
                   uint32_t );
-}
\ No newline at end of file
+}
+
+bool XBeeApiCmdAtBlocking::setEncryptionKey( const uint8_t* p_key )
+{
+    bool ret_val = false;
+    uint16_t counter = m_timeout; 
+
+    if( XBeeApiCmdAt::setEncryptionKey( p_key ) )\
+    {
+        bool cont;
+
+        do{
+            cont = false;
+            wait_ms( m_slice );
+            if( XBeeApiCmdAt::getEncryptionKeySet() )
+            {
+                ret_val = true;
+            }
+            else if( counter > m_slice ) {
+                counter -= m_slice;    
+                cont = true;
+            } 
+        } while( cont );
+    }
+    
+    return( ret_val );
+}
+        
+bool XBeeApiCmdAtBlocking::getEncryptionEnabled( bool* const p_enabled )
+{
+    BLOCKING_GET( XBeeApiCmdAt::requestEncryptionEnabled,
+                  XBeeApiCmdAt::getEncryptionEnabled,
+                  p_enabled );
+}
+
+bool XBeeApiCmdAtBlocking::setEncryptionEnabled( const bool  p_enabled )
+{
+    BLOCKING_SET( XBeeApiCmdAt::setEncryptionEnabled,
+                  XBeeApiCmdAt::getEncryptionEnabled,
+                  p_enabled,
+                  bool );
+}
--- a/Utility/XBeeApiCmdAtBlocking.hpp	Sat Aug 02 16:41:14 2014 +0000
+++ b/Utility/XBeeApiCmdAtBlocking.hpp	Fri Aug 08 11:59:52 2014 +0000
@@ -119,7 +119,11 @@
 
         virtual bool getDestinationAddressLow( uint32_t* const p_address );
         virtual bool setDestinationAddressLow( const uint32_t p_address );
-
+        
+        virtual bool setEncryptionKey( const uint8_t* p_key );
+        
+        virtual bool getEncryptionEnabled( bool* const p_enabled );
+        virtual bool setEncryptionEnabled( const bool  p_enabled );
 };
 
 #endif
\ No newline at end of file