API for communicating with XBee devices.

Dependencies:   CircularBuffer FixedLengthList

Dependents:   XBeeApiTest XBeeApiSimpleATCmdsExample XBeeApiBroadcastExample XBeeApiBroadcastExampleRTOS ... more

Overview

XBeeApi is intended to be a library for providing a high-level API interface to the XBee - for example getChannel() and setChannel(2) methods rather than needing to send( "ATCH" ) and send( "ATCH 2" ) - and then de-code the responses.

See the notebook page here for a description of how the API works & some details on the various classes.

Features:

  • Support for transmission & reception of data packets
  • Support for reading & changing settings
  • Support for "Remote AT" interface to access settings & I/O channels on remote XBees
  • XBeeApi should work if you're using mbed-rtos, though it is not currently threadsafe. Take a look at the XBeeApiBroadcastExampleRTOS example if you're including mbed-rtos.

Example Programs

There are also example programs available:

Transmit

Import programXBeeApiSimpleBroadcastExample

Simple example of how to use XBeeApi - set up the XBee, configure P2P networking then transmit a frame.

Import programXBeeApiBroadcastExample

Example for XBeeAPI; a little more involved than XBeeApiSimpleBroadcastExample with report on failure to set up the XBee and on the transmit status of the message.

Import programXBeeApiBroadcastExampleRTOS

Example of using the XBeeApi library to broadcast a message, based on XBeeApiBroadcastExample. This example shows how to use the library when using mbed-rtos. Before compiling you must open "XbeeApi\Config\XBeeApiCfg.hpp" and change the '#if 0' to '#if 1' on the line above the comment reading "Use RTOS features to make XBeeApi threadsafe"

Settings/Status

Import programXBeeApiSimpleATCmdsExample

Simple example of using XBeeApi to send AT-style commands to the XBee

Import programXBeeApiRemoteATCmdsExample

Example of using the XBeeApi library to send AT commands to remote XBee devices in order to read/write settings

Receive

Import programXBeeApiSimpleReceiveExample

Simple example of using XBeeApi to receive data packets via wireless

Import programXBeeApiReceiveCallbackExample

Example of using the XBeeApi library to receive a message via a callback method

Import programXBeeApiReceiveCallbackExampleRTOS

Example of using the XBeeApi library to receive a message via a callback method. This example shows how to use the library when using mbed-rtos. See the comment at the top of main.cpp

Remote I/O

Import programXBeeApiRemoteIOExample

Example of using the XBeeApi library to read inputs on a remote XBee

If you have 2 mbed connected XBees available then you can use XBeeApiSimpleReceiveExample and XBeeApiSimpleBroadcastExample as a pair.

Note that this is still a work in progress! XBeeApiTodoList tracks some of the functionality still to be added.

Committer:
johnb
Date:
Fri Jan 31 23:53:16 2014 +0000
Revision:
11:bfcf1356027b
Parent:
8:1b48b619d7f6
Child:
13:302e7c1ea0b3
Switch to using macros to implement the access functions in XBeeApiCmdAtBlocking.; Implement XBeeApiCmdAtBlocking::setChannel()

Who changed what in which revision?

UserRevisionLine numberNew contents of line
johnb 8:1b48b619d7f6 1 /**
johnb 8:1b48b619d7f6 2
johnb 8:1b48b619d7f6 3 Copyright 2014 John Bailey
johnb 8:1b48b619d7f6 4
johnb 8:1b48b619d7f6 5 Licensed under the Apache License, Version 2.0 (the "License");
johnb 8:1b48b619d7f6 6 you may not use this file except in compliance with the License.
johnb 8:1b48b619d7f6 7 You may obtain a copy of the License at
johnb 8:1b48b619d7f6 8
johnb 8:1b48b619d7f6 9 http://www.apache.org/licenses/LICENSE-2.0
johnb 8:1b48b619d7f6 10
johnb 8:1b48b619d7f6 11 Unless required by applicable law or agreed to in writing, software
johnb 8:1b48b619d7f6 12 distributed under the License is distributed on an "AS IS" BASIS,
johnb 8:1b48b619d7f6 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
johnb 8:1b48b619d7f6 14 See the License for the specific language governing permissions and
johnb 8:1b48b619d7f6 15 limitations under the License.
johnb 8:1b48b619d7f6 16
johnb 8:1b48b619d7f6 17 */
johnb 8:1b48b619d7f6 18
johnb 8:1b48b619d7f6 19 #include "XBeeApiCmdAt.hpp"
johnb 8:1b48b619d7f6 20
johnb 8:1b48b619d7f6 21 /* Set of Frame ID codes for the various commands (see XBEE_CMD_POSN_FRAME_ID) */
johnb 8:1b48b619d7f6 22
johnb 8:1b48b619d7f6 23 #define CMD_RESPONSE_GET_VR '1'
johnb 8:1b48b619d7f6 24 #define CMD_RESPONSE_GET_HV '2'
johnb 8:1b48b619d7f6 25 #define CMD_RESPONSE_GET_CH '3'
johnb 8:1b48b619d7f6 26 #define CMD_RESPONSE_SET_CH '4'
johnb 8:1b48b619d7f6 27
johnb 8:1b48b619d7f6 28 /* Content for the various commands - value of 0 indicates a value to be populated (i.e. variable) */
johnb 8:1b48b619d7f6 29
johnb 8:1b48b619d7f6 30 const uint8_t cmd_vr[] = { CMD_RESPONSE_GET_VR, 'V', 'R' };
johnb 8:1b48b619d7f6 31 const uint8_t cmd_hv[] = { CMD_RESPONSE_GET_HV, 'H', 'V' };
johnb 8:1b48b619d7f6 32 const uint8_t cmd_ch[] = { CMD_RESPONSE_GET_CH, 'C', 'H' };
johnb 8:1b48b619d7f6 33 const uint8_t cmd_set_ch[] = { CMD_RESPONSE_SET_CH, 'C', 'H', 0 };
johnb 8:1b48b619d7f6 34
johnb 8:1b48b619d7f6 35 #define XBEE_CMD_POSN_FRAME_ID (4U)
johnb 8:1b48b619d7f6 36 #define XBEE_CMD_POSN_PARAM_START (8U)
johnb 8:1b48b619d7f6 37
johnb 8:1b48b619d7f6 38 XBeeApiCmdAt::XBeeApiCmdAt() : XBeeApiFrameDecoder( ) , m_haveHwVer( false ),
johnb 8:1b48b619d7f6 39 m_haveFwVer( false ),
johnb 8:1b48b619d7f6 40 m_haveChan( false )
johnb 8:1b48b619d7f6 41 {
johnb 8:1b48b619d7f6 42 }
johnb 8:1b48b619d7f6 43
johnb 8:1b48b619d7f6 44 bool XBeeApiCmdAt::decodeCallback( const uint8_t* const p_data, size_t p_len )
johnb 8:1b48b619d7f6 45 {
johnb 8:1b48b619d7f6 46 bool ret_val = false;
johnb 8:1b48b619d7f6 47
johnb 8:1b48b619d7f6 48 if( XBEE_CMD_AT_RESPONSE == p_data[ XBEE_CMD_POSN_API_ID ] )
johnb 8:1b48b619d7f6 49 {
johnb 8:1b48b619d7f6 50
johnb 8:1b48b619d7f6 51 switch( p_data[ XBEE_CMD_POSN_FRAME_ID ] )
johnb 8:1b48b619d7f6 52 {
johnb 8:1b48b619d7f6 53 case CMD_RESPONSE_GET_HV:
johnb 8:1b48b619d7f6 54 m_haveHwVer = true;
johnb 8:1b48b619d7f6 55 // TODO: Is this right?
johnb 8:1b48b619d7f6 56 m_hwVer = ((uint16_t)p_data[ XBEE_CMD_POSN_PARAM_START ] << 8) + p_data[ XBEE_CMD_POSN_PARAM_START + 1 ];
johnb 8:1b48b619d7f6 57 ret_val = true;
johnb 8:1b48b619d7f6 58 break;
johnb 8:1b48b619d7f6 59
johnb 8:1b48b619d7f6 60 case CMD_RESPONSE_GET_VR:
johnb 8:1b48b619d7f6 61 m_haveFwVer = true;
johnb 8:1b48b619d7f6 62 // TODO: Is this right?
johnb 8:1b48b619d7f6 63 m_fwVer = ((uint16_t)p_data[ XBEE_CMD_POSN_PARAM_START ] << 8) + p_data[ XBEE_CMD_POSN_PARAM_START + 1 ];
johnb 8:1b48b619d7f6 64 ret_val = true;
johnb 8:1b48b619d7f6 65 break;
johnb 8:1b48b619d7f6 66
johnb 8:1b48b619d7f6 67 case CMD_RESPONSE_GET_CH:
johnb 8:1b48b619d7f6 68 m_haveChan = true;
johnb 8:1b48b619d7f6 69 m_chan = p_data[ XBEE_CMD_POSN_PARAM_START ];
johnb 8:1b48b619d7f6 70 ret_val = true;
johnb 8:1b48b619d7f6 71 break;
johnb 8:1b48b619d7f6 72
johnb 8:1b48b619d7f6 73 case CMD_RESPONSE_SET_CH:
johnb 8:1b48b619d7f6 74 m_chan = m_chanPend;
johnb 8:1b48b619d7f6 75 m_haveChan = true;
johnb 8:1b48b619d7f6 76 ret_val = true;
johnb 8:1b48b619d7f6 77 break;
johnb 8:1b48b619d7f6 78 }
johnb 8:1b48b619d7f6 79 }
johnb 8:1b48b619d7f6 80 return ret_val;
johnb 8:1b48b619d7f6 81 }
johnb 8:1b48b619d7f6 82
johnb 8:1b48b619d7f6 83 bool XBeeApiCmdAt::setChannel( uint8_t const p_chan )
johnb 8:1b48b619d7f6 84 {
johnb 8:1b48b619d7f6 85 XBeeApiCmdAt::XBeeApiCmdAtChannelSet req( p_chan );
johnb 8:1b48b619d7f6 86 m_chanPend = p_chan;
johnb 8:1b48b619d7f6 87 m_device->SendFrame( &req );
johnb 8:1b48b619d7f6 88
johnb 8:1b48b619d7f6 89 return true;
johnb 8:1b48b619d7f6 90 }
johnb 8:1b48b619d7f6 91
johnb 8:1b48b619d7f6 92 bool XBeeApiCmdAt::requestHardwareVersion( void )
johnb 8:1b48b619d7f6 93 {
johnb 8:1b48b619d7f6 94 XBeeApiCmdAt::XBeeApiCmdAtHardwareVersionRequest req;
johnb 8:1b48b619d7f6 95 m_haveHwVer = false;
johnb 8:1b48b619d7f6 96 m_device->SendFrame( &req );
johnb 8:1b48b619d7f6 97 return true;
johnb 8:1b48b619d7f6 98 }
johnb 8:1b48b619d7f6 99
johnb 8:1b48b619d7f6 100 bool XBeeApiCmdAt::requestFirmwareVersion( void )
johnb 8:1b48b619d7f6 101 {
johnb 8:1b48b619d7f6 102 XBeeApiCmdAt::XBeeApiCmdAtFirmwareVersionRequest req;
johnb 8:1b48b619d7f6 103 m_haveFwVer = false;
johnb 8:1b48b619d7f6 104 m_device->SendFrame( &req );
johnb 8:1b48b619d7f6 105 return true;
johnb 8:1b48b619d7f6 106 }
johnb 8:1b48b619d7f6 107
johnb 8:1b48b619d7f6 108 bool XBeeApiCmdAt::requestChannel( void )
johnb 8:1b48b619d7f6 109 {
johnb 8:1b48b619d7f6 110 XBeeApiCmdAt::XBeeApiCmdAtChannelRequest req;
johnb 8:1b48b619d7f6 111 m_haveChan = false;
johnb 8:1b48b619d7f6 112 m_device->SendFrame( &req );
johnb 8:1b48b619d7f6 113 return true;
johnb 8:1b48b619d7f6 114 }
johnb 8:1b48b619d7f6 115
johnb 8:1b48b619d7f6 116 bool XBeeApiCmdAt::getFirmwareVersion( uint16_t* const p_ver )
johnb 8:1b48b619d7f6 117 {
johnb 8:1b48b619d7f6 118 if( m_haveFwVer )
johnb 8:1b48b619d7f6 119 {
johnb 8:1b48b619d7f6 120 *p_ver = m_fwVer;
johnb 8:1b48b619d7f6 121 }
johnb 8:1b48b619d7f6 122 return m_haveFwVer;
johnb 8:1b48b619d7f6 123
johnb 8:1b48b619d7f6 124 }
johnb 8:1b48b619d7f6 125
johnb 8:1b48b619d7f6 126 bool XBeeApiCmdAt::getHardwareVersion( uint16_t* const p_ver )
johnb 8:1b48b619d7f6 127 {
johnb 8:1b48b619d7f6 128 if( m_haveHwVer )
johnb 8:1b48b619d7f6 129 {
johnb 8:1b48b619d7f6 130 *p_ver = m_hwVer;
johnb 8:1b48b619d7f6 131 }
johnb 8:1b48b619d7f6 132 return m_haveHwVer;
johnb 8:1b48b619d7f6 133 }
johnb 8:1b48b619d7f6 134
johnb 8:1b48b619d7f6 135 bool XBeeApiCmdAt::getChannel( uint8_t* const p_chan )
johnb 8:1b48b619d7f6 136 {
johnb 8:1b48b619d7f6 137 if( m_haveChan )
johnb 8:1b48b619d7f6 138 {
johnb 8:1b48b619d7f6 139 *p_chan = m_chan;
johnb 8:1b48b619d7f6 140 }
johnb 8:1b48b619d7f6 141 return m_haveChan;
johnb 8:1b48b619d7f6 142 }
johnb 8:1b48b619d7f6 143
johnb 8:1b48b619d7f6 144 XBeeApiCmdAtBlocking::XBeeApiCmdAtBlocking( const uint16_t p_timeout, const uint16_t p_slice ) :
johnb 8:1b48b619d7f6 145 XBeeApiCmdAt( ),
johnb 8:1b48b619d7f6 146 m_timeout( p_timeout ),
johnb 8:1b48b619d7f6 147 m_slice( p_slice )
johnb 8:1b48b619d7f6 148 {
johnb 8:1b48b619d7f6 149 }
johnb 8:1b48b619d7f6 150
johnb 8:1b48b619d7f6 151 extern Serial pc;
johnb 8:1b48b619d7f6 152
johnb 11:bfcf1356027b 153 /**
johnb 11:bfcf1356027b 154 Macro to wrap around the "requestXXX" & "getXXX" methods and implement a blocking call.
johnb 11:bfcf1356027b 155 This macro is used as the basis for getXXX functions in XBeeApiCmdAtBlocking.
johnb 8:1b48b619d7f6 156
johnb 11:bfcf1356027b 157 Originally looked to achieve this using a template function passing method pointers, however
johnb 11:bfcf1356027b 158 there's no way to get a method pointer to the parent class implementation as opposed to the
johnb 11:bfcf1356027b 159 implementation in this class, meaning that the result was a recursive method call. The joys of
johnb 11:bfcf1356027b 160 polymorphism.
johnb 11:bfcf1356027b 161
johnb 11:bfcf1356027b 162 e.g. We pass a pointer to method getHardwareVersion(). The function receiving the pointer
johnb 11:bfcf1356027b 163 uses it to make a function call. The actual function that's called is (correctly)
johnb 11:bfcf1356027b 164 the one implemented in this class, however what we actually wanted in this case
johnb 11:bfcf1356027b 165 was to call the implementation in the base class. Using static_cast<> doesn't have
johnb 11:bfcf1356027b 166 any effect and taking the address of XBeeApiCmdAt::getHardwareVersion ends up with
johnb 11:bfcf1356027b 167 XBeeApiCmdAtBlocking::getHardwareVersion being called due to polymorphism. */
johnb 11:bfcf1356027b 168 #define BLOCKING_GET( _REQ_FN, _GET_FN, _VAR ) \
johnb 11:bfcf1356027b 169 bool ret_val = false; \
johnb 11:bfcf1356027b 170 uint16_t counter = m_timeout; \
johnb 11:bfcf1356027b 171 \
johnb 11:bfcf1356027b 172 if( _GET_FN( _VAR ) )\
johnb 11:bfcf1356027b 173 {\
johnb 11:bfcf1356027b 174 ret_val = true;\
johnb 11:bfcf1356027b 175 } \
johnb 11:bfcf1356027b 176 else if( _REQ_FN() )\
johnb 11:bfcf1356027b 177 {\
johnb 11:bfcf1356027b 178 bool cont = false;\
johnb 11:bfcf1356027b 179 \
johnb 11:bfcf1356027b 180 do{\
johnb 11:bfcf1356027b 181 wait_ms( m_slice );\
johnb 11:bfcf1356027b 182 if( _GET_FN( _VAR ) )\
johnb 11:bfcf1356027b 183 {\
johnb 11:bfcf1356027b 184 ret_val = true;\
johnb 11:bfcf1356027b 185 }\
johnb 11:bfcf1356027b 186 else if( counter > m_slice ) {\
johnb 11:bfcf1356027b 187 counter -= m_slice; \
johnb 11:bfcf1356027b 188 cont = true;\
johnb 11:bfcf1356027b 189 } \
johnb 11:bfcf1356027b 190 } while( cont );\
johnb 11:bfcf1356027b 191 }\
johnb 11:bfcf1356027b 192 \
johnb 8:1b48b619d7f6 193 return( ret_val );
johnb 8:1b48b619d7f6 194
johnb 11:bfcf1356027b 195 /**
johnb 11:bfcf1356027b 196 Macro to wrap around the "setXXX" & "getXXX" methods and implement a blocking call.
johnb 11:bfcf1356027b 197 This macro is used as the basis for setXXX functions in XBeeApiCmdAtBlocking.
johnb 11:bfcf1356027b 198 */
johnb 11:bfcf1356027b 199 #define BLOCKING_SET( _SET_FN, _GET_FN, _VAR, _TYPE ) \
johnb 11:bfcf1356027b 200 bool ret_val = false; \
johnb 11:bfcf1356027b 201 uint16_t counter = m_timeout; \
johnb 11:bfcf1356027b 202 _TYPE readback; \
johnb 11:bfcf1356027b 203 \
johnb 11:bfcf1356027b 204 if( _SET_FN( _VAR ) )\
johnb 11:bfcf1356027b 205 {\
johnb 11:bfcf1356027b 206 bool cont = false;\
johnb 11:bfcf1356027b 207 \
johnb 11:bfcf1356027b 208 do{\
johnb 11:bfcf1356027b 209 wait_ms( m_slice );\
johnb 11:bfcf1356027b 210 if( _GET_FN( &readback ) &&\
johnb 11:bfcf1356027b 211 ( readback == p_chan ))\
johnb 11:bfcf1356027b 212 {\
johnb 11:bfcf1356027b 213 ret_val = true;\
johnb 11:bfcf1356027b 214 }\
johnb 11:bfcf1356027b 215 else if( counter > m_slice ) {\
johnb 11:bfcf1356027b 216 counter -= m_slice; \
johnb 11:bfcf1356027b 217 cont = true;\
johnb 11:bfcf1356027b 218 } \
johnb 11:bfcf1356027b 219 } while( cont );\
johnb 11:bfcf1356027b 220 }\
johnb 11:bfcf1356027b 221 \
johnb 11:bfcf1356027b 222 return( ret_val );
johnb 8:1b48b619d7f6 223
johnb 11:bfcf1356027b 224
johnb 8:1b48b619d7f6 225 bool XBeeApiCmdAtBlocking::getHardwareVersion( uint16_t* const p_ver )
johnb 8:1b48b619d7f6 226 {
johnb 11:bfcf1356027b 227 BLOCKING_GET( XBeeApiCmdAt::requestHardwareVersion,
johnb 11:bfcf1356027b 228 XBeeApiCmdAt::getHardwareVersion,
johnb 11:bfcf1356027b 229 p_ver );
johnb 8:1b48b619d7f6 230 }
johnb 8:1b48b619d7f6 231
johnb 8:1b48b619d7f6 232 bool XBeeApiCmdAtBlocking::getFirmwareVersion( uint16_t* const p_ver )
johnb 8:1b48b619d7f6 233 {
johnb 11:bfcf1356027b 234 BLOCKING_GET( XBeeApiCmdAtBlocking::requestFirmwareVersion,
johnb 11:bfcf1356027b 235 XBeeApiCmdAtBlocking::getFirmwareVersion,
johnb 11:bfcf1356027b 236 p_ver );
johnb 8:1b48b619d7f6 237 }
johnb 8:1b48b619d7f6 238
johnb 8:1b48b619d7f6 239 bool XBeeApiCmdAtBlocking::getChannel( uint8_t* const p_chan )
johnb 8:1b48b619d7f6 240 {
johnb 11:bfcf1356027b 241 BLOCKING_GET( XBeeApiCmdAtBlocking::requestChannel,
johnb 11:bfcf1356027b 242 XBeeApiCmdAtBlocking::getChannel,
johnb 11:bfcf1356027b 243 p_chan );
johnb 8:1b48b619d7f6 244 }
johnb 8:1b48b619d7f6 245
johnb 8:1b48b619d7f6 246 bool XBeeApiCmdAtBlocking::setChannel( uint8_t const p_chan )
johnb 8:1b48b619d7f6 247 {
johnb 11:bfcf1356027b 248 BLOCKING_SET( XBeeApiCmdAtBlocking::setChannel,
johnb 11:bfcf1356027b 249 XBeeApiCmdAtBlocking::getChannel,
johnb 11:bfcf1356027b 250 p_chan,
johnb 11:bfcf1356027b 251 uint8_t );
johnb 8:1b48b619d7f6 252 }
johnb 8:1b48b619d7f6 253
johnb 8:1b48b619d7f6 254 XBeeApiCmdAt::XBeeApiCmdAtFirmwareVersionRequest::XBeeApiCmdAtFirmwareVersionRequest( void ) : XBeeApiFrame( )
johnb 8:1b48b619d7f6 255 {
johnb 8:1b48b619d7f6 256 m_apiId = XBEE_CMD_AT_CMD;
johnb 8:1b48b619d7f6 257 m_data = cmd_vr;
johnb 8:1b48b619d7f6 258 m_dataLen = sizeof( cmd_vr );
johnb 8:1b48b619d7f6 259 }
johnb 8:1b48b619d7f6 260
johnb 8:1b48b619d7f6 261 XBeeApiCmdAt::XBeeApiCmdAtHardwareVersionRequest::XBeeApiCmdAtHardwareVersionRequest( void ) : XBeeApiFrame( )
johnb 8:1b48b619d7f6 262 {
johnb 8:1b48b619d7f6 263 m_apiId = XBEE_CMD_AT_CMD;
johnb 8:1b48b619d7f6 264 m_data = cmd_hv;
johnb 8:1b48b619d7f6 265 m_dataLen = sizeof( cmd_hv );
johnb 8:1b48b619d7f6 266 }
johnb 8:1b48b619d7f6 267
johnb 8:1b48b619d7f6 268 XBeeApiCmdAt::XBeeApiCmdAtChannelRequest::XBeeApiCmdAtChannelRequest( void ) : XBeeApiFrame( )
johnb 8:1b48b619d7f6 269 {
johnb 8:1b48b619d7f6 270 m_apiId = XBEE_CMD_AT_CMD;
johnb 8:1b48b619d7f6 271 m_data = cmd_ch;
johnb 8:1b48b619d7f6 272 m_dataLen = sizeof( cmd_ch );
johnb 8:1b48b619d7f6 273 }
johnb 8:1b48b619d7f6 274
johnb 8:1b48b619d7f6 275 XBeeApiCmdAt::XBeeApiCmdAtChannelSet::XBeeApiCmdAtChannelSet( const uint8_t p_chan ) : XBeeApiFrame( )
johnb 8:1b48b619d7f6 276 {
johnb 8:1b48b619d7f6 277 m_apiId = XBEE_CMD_AT_CMD;
johnb 8:1b48b619d7f6 278 m_buffer[0] = cmd_set_ch[0];
johnb 8:1b48b619d7f6 279 m_buffer[1] = cmd_set_ch[1];
johnb 8:1b48b619d7f6 280 m_buffer[2] = cmd_set_ch[2];
johnb 8:1b48b619d7f6 281 m_buffer[3] = p_chan;
johnb 8:1b48b619d7f6 282 m_data = m_buffer;
johnb 8:1b48b619d7f6 283 m_dataLen = sizeof( cmd_set_ch );
johnb 8:1b48b619d7f6 284 }