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:
Thu Feb 06 22:26:27 2014 +0000
Revision:
31:c144106e55b5
Parent:
30:9532b01a1ae1
Child:
32:af4e495afd62
Add method to set XBee's source address; Macro-ise XBeeApiCmdAt's method generation; Fix bug with timeout on XBeeApiCmdAtBlocking's get/set methods

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 13:302e7c1ea0b3 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 13:302e7c1ea0b3 23 #define CMD_RESPONSE_GET_VR '1'
johnb 13:302e7c1ea0b3 24 #define CMD_RESPONSE_GET_HV '2'
johnb 13:302e7c1ea0b3 25 #define CMD_RESPONSE_GET_CH '3'
johnb 13:302e7c1ea0b3 26 #define CMD_RESPONSE_SET_CH '4'
johnb 13:302e7c1ea0b3 27 #define CMD_RESPONSE_SET_CE '5'
johnb 13:302e7c1ea0b3 28 #define CMD_RESPONSE_GET_CE '6'
johnb 13:302e7c1ea0b3 29 #define CMD_RESPONSE_SET_EDA '7'
johnb 13:302e7c1ea0b3 30 #define CMD_RESPONSE_GET_EDA '8'
johnb 13:302e7c1ea0b3 31 #define CMD_RESPONSE_SET_PID '9'
johnb 13:302e7c1ea0b3 32 #define CMD_RESPONSE_GET_PID '0'
johnb 31:c144106e55b5 33 #define CMD_RESPONSE_SET_MY 'a'
johnb 31:c144106e55b5 34 #define CMD_RESPONSE_GET_MY 'b'
johnb 13:302e7c1ea0b3 35
johnb 30:9532b01a1ae1 36 /** Lowest channel supported by the XBee S1 */
johnb 30:9532b01a1ae1 37 #define XBEE_CHAN_MIN 0x0b
johnb 30:9532b01a1ae1 38 /** Highest channel supported by the XBee S1 */
johnb 30:9532b01a1ae1 39 #define XBEE_CHAN_MAX 0x1a
johnb 13:302e7c1ea0b3 40
johnb 30:9532b01a1ae1 41 /** Lowest channel supported by the XBee S1 Pro */
johnb 30:9532b01a1ae1 42 #define XBEE_PRO_CHAN_MIN 0x0c
johnb 30:9532b01a1ae1 43 /** Highest channel supported by the XBee S1 Pro */
johnb 30:9532b01a1ae1 44 #define XBEE_PRO_CHAN_MAX 0x17
johnb 8:1b48b619d7f6 45
johnb 8:1b48b619d7f6 46 /* Content for the various commands - value of 0 indicates a value to be populated (i.e. variable) */
johnb 8:1b48b619d7f6 47
johnb 13:302e7c1ea0b3 48 const uint8_t cmd_vr[] = { CMD_RESPONSE_GET_VR, 'V', 'R' };
johnb 13:302e7c1ea0b3 49 const uint8_t cmd_hv[] = { CMD_RESPONSE_GET_HV, 'H', 'V' };
johnb 13:302e7c1ea0b3 50
johnb 13:302e7c1ea0b3 51 const uint8_t cmd_ch[] = { CMD_RESPONSE_GET_CH, 'C', 'H' };
johnb 13:302e7c1ea0b3 52 const uint8_t cmd_set_ch[] = { CMD_RESPONSE_SET_CH, 'C', 'H', 0 };
johnb 13:302e7c1ea0b3 53
johnb 13:302e7c1ea0b3 54 const uint8_t cmd_ce[] = { CMD_RESPONSE_GET_CE, 'C', 'E' };
johnb 13:302e7c1ea0b3 55 const uint8_t cmd_set_ce[] = { CMD_RESPONSE_SET_CE, 'C', 'E', 0 };
johnb 13:302e7c1ea0b3 56
johnb 13:302e7c1ea0b3 57 const uint8_t cmd_eda[] = { CMD_RESPONSE_GET_EDA, 'A', '1' };
johnb 13:302e7c1ea0b3 58 const uint8_t cmd_set_eda[] = { CMD_RESPONSE_SET_EDA, 'A', '1', 0 };
johnb 13:302e7c1ea0b3 59
johnb 13:302e7c1ea0b3 60 const uint8_t cmd_pid[] = { CMD_RESPONSE_GET_PID, 'I', 'D' };
johnb 13:302e7c1ea0b3 61 const uint8_t cmd_set_pid[] = { CMD_RESPONSE_SET_PID, 'I', 'D', 0, 0 };
johnb 8:1b48b619d7f6 62
johnb 31:c144106e55b5 63 const uint8_t cmd_my[] = { CMD_RESPONSE_GET_MY, 'M', 'Y' };
johnb 31:c144106e55b5 64 const uint8_t cmd_set_my[] = { CMD_RESPONSE_SET_MY, 'M', 'Y', 0, 0 };
johnb 31:c144106e55b5 65
johnb 31:c144106e55b5 66
johnb 8:1b48b619d7f6 67 #define XBEE_CMD_POSN_FRAME_ID (4U)
johnb 13:302e7c1ea0b3 68 #define XBEE_CMD_POSN_STATUS (7U)
johnb 8:1b48b619d7f6 69 #define XBEE_CMD_POSN_PARAM_START (8U)
johnb 8:1b48b619d7f6 70
johnb 13:302e7c1ea0b3 71 #define XBEE_CMD_RESPONS_HAS_DATA( _p_len ) ((_p_len > ( XBEE_CMD_POSN_PARAM_START + 1 ))
johnb 13:302e7c1ea0b3 72
johnb 29:c6d037cceb02 73 XBeeApiCmdAt::XBeeApiCmdAt( XBeeDevice* const p_device ) : XBeeApiFrameDecoder( p_device ) ,
johnb 31:c144106e55b5 74 m_have_hwVer( false ),
johnb 31:c144106e55b5 75 m_have_fwVer( false ),
johnb 31:c144106e55b5 76 m_have_chan( false ),
johnb 31:c144106e55b5 77 m_have_PANId( false ),
johnb 31:c144106e55b5 78 m_have_EDA( false ),
johnb 31:c144106e55b5 79 m_have_CE( false ),
johnb 31:c144106e55b5 80 m_have_sourceAddress( false )
johnb 8:1b48b619d7f6 81 {
johnb 8:1b48b619d7f6 82 }
johnb 8:1b48b619d7f6 83
johnb 8:1b48b619d7f6 84 bool XBeeApiCmdAt::decodeCallback( const uint8_t* const p_data, size_t p_len )
johnb 8:1b48b619d7f6 85 {
johnb 8:1b48b619d7f6 86 bool ret_val = false;
johnb 13:302e7c1ea0b3 87
johnb 13:302e7c1ea0b3 88 if( XBEE_CMD_AT_RESPONSE == p_data[ XBEE_CMD_POSN_API_ID ] ) {
johnb 13:302e7c1ea0b3 89
johnb 13:302e7c1ea0b3 90 switch( p_data[ XBEE_CMD_POSN_FRAME_ID ] ) {
johnb 8:1b48b619d7f6 91 case CMD_RESPONSE_GET_HV:
johnb 13:302e7c1ea0b3 92 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 13:302e7c1ea0b3 93 {
johnb 13:302e7c1ea0b3 94 m_hwVer = ((uint16_t)p_data[ XBEE_CMD_POSN_PARAM_START ] << 8) + p_data[ XBEE_CMD_POSN_PARAM_START + 1 ];
johnb 31:c144106e55b5 95 m_have_hwVer = true;
johnb 13:302e7c1ea0b3 96 }
johnb 13:302e7c1ea0b3 97 else
johnb 13:302e7c1ea0b3 98 {
johnb 31:c144106e55b5 99 /* TODO */
johnb 13:302e7c1ea0b3 100 }
johnb 13:302e7c1ea0b3 101 ret_val = true;
johnb 13:302e7c1ea0b3 102 break;
johnb 13:302e7c1ea0b3 103
johnb 13:302e7c1ea0b3 104 case CMD_RESPONSE_GET_VR:
johnb 13:302e7c1ea0b3 105 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 13:302e7c1ea0b3 106 {
johnb 13:302e7c1ea0b3 107 m_fwVer = ((uint16_t)p_data[ XBEE_CMD_POSN_PARAM_START ] << 8) + p_data[ XBEE_CMD_POSN_PARAM_START + 1 ];
johnb 31:c144106e55b5 108 m_have_fwVer = true;
johnb 13:302e7c1ea0b3 109 }
johnb 13:302e7c1ea0b3 110 else
johnb 13:302e7c1ea0b3 111 {
johnb 31:c144106e55b5 112 /* TODO */
johnb 13:302e7c1ea0b3 113 }
johnb 13:302e7c1ea0b3 114 ret_val = true;
johnb 13:302e7c1ea0b3 115 break;
johnb 13:302e7c1ea0b3 116
johnb 13:302e7c1ea0b3 117 case CMD_RESPONSE_GET_CH:
johnb 13:302e7c1ea0b3 118 case CMD_RESPONSE_SET_CH:
johnb 13:302e7c1ea0b3 119 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 13:302e7c1ea0b3 120 {
johnb 13:302e7c1ea0b3 121 if( CMD_RESPONSE_GET_CH == p_data[ XBEE_CMD_POSN_API_ID ] )
johnb 13:302e7c1ea0b3 122 {
johnb 13:302e7c1ea0b3 123 m_chan = p_data[ XBEE_CMD_POSN_PARAM_START ];
johnb 13:302e7c1ea0b3 124 }
johnb 13:302e7c1ea0b3 125 else
johnb 13:302e7c1ea0b3 126 {
johnb 13:302e7c1ea0b3 127 m_chan = m_chanPend;
johnb 13:302e7c1ea0b3 128 }
johnb 13:302e7c1ea0b3 129 #if 0
johnb 13:302e7c1ea0b3 130 printf("\r\n%02x (%2d) - %02x %02x %02x %02x %02x %02x %02x %02x %02x\r\n",p_data[ XBEE_CMD_POSN_API_ID ],p_len,
johnb 13:302e7c1ea0b3 131 p_data[0],p_data[1],p_data[2],p_data[3],p_data[4],p_data[5],p_data[6],p_data[7],p_data[8]);
johnb 13:302e7c1ea0b3 132 #endif
johnb 31:c144106e55b5 133 m_have_chan = true;
johnb 13:302e7c1ea0b3 134 }
johnb 13:302e7c1ea0b3 135 else
johnb 13:302e7c1ea0b3 136 {
johnb 13:302e7c1ea0b3 137 /* TODO */
johnb 13:302e7c1ea0b3 138 }
johnb 8:1b48b619d7f6 139 ret_val = true;
johnb 8:1b48b619d7f6 140 break;
johnb 13:302e7c1ea0b3 141
johnb 13:302e7c1ea0b3 142 case CMD_RESPONSE_SET_CE:
johnb 13:302e7c1ea0b3 143 case CMD_RESPONSE_GET_CE:
johnb 13:302e7c1ea0b3 144 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 13:302e7c1ea0b3 145 {
johnb 13:302e7c1ea0b3 146 if( CMD_RESPONSE_GET_CE == p_data[ XBEE_CMD_POSN_API_ID ] )
johnb 13:302e7c1ea0b3 147 {
johnb 13:302e7c1ea0b3 148 m_CE = p_data[ XBEE_CMD_POSN_PARAM_START ];
johnb 13:302e7c1ea0b3 149 }
johnb 13:302e7c1ea0b3 150 else
johnb 13:302e7c1ea0b3 151 {
johnb 13:302e7c1ea0b3 152 m_CE = m_CEPend;
johnb 13:302e7c1ea0b3 153 }
johnb 31:c144106e55b5 154 m_have_CE = true;
johnb 13:302e7c1ea0b3 155 }
johnb 13:302e7c1ea0b3 156 else
johnb 13:302e7c1ea0b3 157 {
johnb 31:c144106e55b5 158 /* TODO */
johnb 13:302e7c1ea0b3 159 }
johnb 8:1b48b619d7f6 160 ret_val = true;
johnb 8:1b48b619d7f6 161 break;
johnb 13:302e7c1ea0b3 162
johnb 13:302e7c1ea0b3 163 case CMD_RESPONSE_SET_PID:
johnb 13:302e7c1ea0b3 164 case CMD_RESPONSE_GET_PID:
johnb 13:302e7c1ea0b3 165 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 13:302e7c1ea0b3 166 {
johnb 13:302e7c1ea0b3 167 if( CMD_RESPONSE_GET_PID == p_data[ XBEE_CMD_POSN_API_ID ] )
johnb 13:302e7c1ea0b3 168 {
johnb 13:302e7c1ea0b3 169 m_PANId = p_data[ XBEE_CMD_POSN_PARAM_START ];
johnb 13:302e7c1ea0b3 170 }
johnb 13:302e7c1ea0b3 171 else
johnb 13:302e7c1ea0b3 172 {
johnb 13:302e7c1ea0b3 173 m_PANId = m_PANIdPend;
johnb 13:302e7c1ea0b3 174 }
johnb 31:c144106e55b5 175 m_have_PANId = true;
johnb 13:302e7c1ea0b3 176 }
johnb 13:302e7c1ea0b3 177 else
johnb 13:302e7c1ea0b3 178 {
johnb 31:c144106e55b5 179 /* TODO */
johnb 13:302e7c1ea0b3 180 }
johnb 8:1b48b619d7f6 181 ret_val = true;
johnb 8:1b48b619d7f6 182 break;
johnb 13:302e7c1ea0b3 183
johnb 13:302e7c1ea0b3 184 case CMD_RESPONSE_SET_EDA:
johnb 13:302e7c1ea0b3 185 case CMD_RESPONSE_GET_EDA:
johnb 13:302e7c1ea0b3 186 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 13:302e7c1ea0b3 187 {
johnb 13:302e7c1ea0b3 188 if( CMD_RESPONSE_GET_EDA == p_data[ XBEE_CMD_POSN_API_ID ] )
johnb 13:302e7c1ea0b3 189 {
johnb 13:302e7c1ea0b3 190 m_EDA = p_data[ XBEE_CMD_POSN_PARAM_START ];
johnb 13:302e7c1ea0b3 191 }
johnb 13:302e7c1ea0b3 192 else
johnb 13:302e7c1ea0b3 193 {
johnb 13:302e7c1ea0b3 194 m_EDA = m_EDAPend;
johnb 13:302e7c1ea0b3 195 }
johnb 31:c144106e55b5 196 m_have_EDA = true;
johnb 13:302e7c1ea0b3 197 }
johnb 13:302e7c1ea0b3 198 else
johnb 13:302e7c1ea0b3 199 {
johnb 31:c144106e55b5 200 /* TODO */
johnb 31:c144106e55b5 201 }
johnb 31:c144106e55b5 202 ret_val = true;
johnb 31:c144106e55b5 203 break;
johnb 31:c144106e55b5 204 case CMD_RESPONSE_SET_MY:
johnb 31:c144106e55b5 205 case CMD_RESPONSE_GET_MY:
johnb 31:c144106e55b5 206 if( p_data[ XBEE_CMD_POSN_STATUS ] == 0 )
johnb 31:c144106e55b5 207 {
johnb 31:c144106e55b5 208 if( CMD_RESPONSE_GET_MY == p_data[ XBEE_CMD_POSN_API_ID ] )
johnb 31:c144106e55b5 209 {
johnb 31:c144106e55b5 210 m_sourceAddress = ((uint16_t)p_data[ XBEE_CMD_POSN_PARAM_START ] << 8) + p_data[ XBEE_CMD_POSN_PARAM_START + 1 ];
johnb 31:c144106e55b5 211 }
johnb 31:c144106e55b5 212 else
johnb 31:c144106e55b5 213 {
johnb 31:c144106e55b5 214 m_sourceAddress = m_sourceAddressPend;
johnb 31:c144106e55b5 215 }
johnb 31:c144106e55b5 216 m_have_sourceAddress = true;
johnb 31:c144106e55b5 217 }
johnb 31:c144106e55b5 218 else
johnb 31:c144106e55b5 219 {
johnb 31:c144106e55b5 220 /* TODO */
johnb 13:302e7c1ea0b3 221 }
johnb 13:302e7c1ea0b3 222 ret_val = true;
johnb 8:1b48b619d7f6 223 break;
johnb 13:302e7c1ea0b3 224
johnb 8:1b48b619d7f6 225 }
johnb 8:1b48b619d7f6 226 }
johnb 8:1b48b619d7f6 227 return ret_val;
johnb 8:1b48b619d7f6 228 }
johnb 8:1b48b619d7f6 229
johnb 8:1b48b619d7f6 230 bool XBeeApiCmdAt::setChannel( uint8_t const p_chan )
johnb 8:1b48b619d7f6 231 {
johnb 29:c6d037cceb02 232 bool ret_val = false;
johnb 29:c6d037cceb02 233
johnb 29:c6d037cceb02 234 if((( m_device->getXBeeModel() == XBeeDevice::XBEEDEVICE_S1 ) &&
johnb 29:c6d037cceb02 235 ( p_chan >= XBEE_CHAN_MIN ) &&
johnb 29:c6d037cceb02 236 ( p_chan <= XBEE_CHAN_MAX )) ||
johnb 29:c6d037cceb02 237 (( m_device->getXBeeModel() == XBeeDevice::XBEEDEVICE_S1_PRO ) &&
johnb 29:c6d037cceb02 238 ( p_chan >= XBEE_PRO_CHAN_MIN ) &&
johnb 29:c6d037cceb02 239 ( p_chan <= XBEE_PRO_CHAN_MAX )))
johnb 29:c6d037cceb02 240 {
johnb 29:c6d037cceb02 241 XBeeApiCmdAtSet<uint8_t> req( cmd_set_ch, p_chan );
johnb 29:c6d037cceb02 242
johnb 29:c6d037cceb02 243 m_chanPend = p_chan;
johnb 29:c6d037cceb02 244 m_device->SendFrame( &req );
johnb 29:c6d037cceb02 245 ret_val = true;
johnb 29:c6d037cceb02 246 }
johnb 29:c6d037cceb02 247 return ret_val;
johnb 8:1b48b619d7f6 248 }
johnb 8:1b48b619d7f6 249
johnb 31:c144106e55b5 250 #define MAKE_REQUEST( _name, _mnemonic, _cmd ) \
johnb 31:c144106e55b5 251 bool XBeeApiCmdAt::request ## _name( void ) \
johnb 31:c144106e55b5 252 {\
johnb 31:c144106e55b5 253 XBeeApiFrame req( XBEE_CMD_AT_CMD, _cmd, sizeof( _cmd ));\
johnb 31:c144106e55b5 254 m_have_ ## _mnemonic = false;\
johnb 31:c144106e55b5 255 m_device->SendFrame( &req );\
johnb 31:c144106e55b5 256 return true;\
johnb 8:1b48b619d7f6 257 }
johnb 8:1b48b619d7f6 258
johnb 31:c144106e55b5 259 MAKE_REQUEST( HardwareVersion, hwVer, cmd_hv )
johnb 31:c144106e55b5 260 MAKE_REQUEST( FirmwareVersion, fwVer, cmd_vr )
johnb 31:c144106e55b5 261 MAKE_REQUEST( Channel, chan, cmd_ch )
johnb 31:c144106e55b5 262 MAKE_REQUEST( PanId, PANId, cmd_pid )
johnb 31:c144106e55b5 263 MAKE_REQUEST( CoordinatorEnabled, CE, cmd_ce )
johnb 31:c144106e55b5 264 MAKE_REQUEST( EndDeviceAssociationEnabled, EDA, cmd_eda )
johnb 31:c144106e55b5 265 MAKE_REQUEST( SourceAddress, sourceAddress, cmd_my )
johnb 8:1b48b619d7f6 266
johnb 31:c144106e55b5 267 #define MAKE_GET(_name, _mnemonic, _type ) \
johnb 31:c144106e55b5 268 bool XBeeApiCmdAt::get ## _name( _type* const p_param ) \
johnb 31:c144106e55b5 269 {\
johnb 31:c144106e55b5 270 if( m_have_ ## _mnemonic ) {\
johnb 31:c144106e55b5 271 *p_param = m_ ## _mnemonic;\
johnb 31:c144106e55b5 272 } \
johnb 31:c144106e55b5 273 return m_have_ ## _mnemonic; \
johnb 13:302e7c1ea0b3 274 }
johnb 13:302e7c1ea0b3 275
johnb 31:c144106e55b5 276 MAKE_GET( FirmwareVersion, fwVer, uint16_t )
johnb 31:c144106e55b5 277 MAKE_GET( HardwareVersion, hwVer, uint16_t )
johnb 31:c144106e55b5 278 MAKE_GET( Channel, chan, uint8_t )
johnb 31:c144106e55b5 279 MAKE_GET( CoordinatorEnabled, CE, bool );
johnb 31:c144106e55b5 280 MAKE_GET( EndDeviceAssociationEnabled, EDA, bool )
johnb 31:c144106e55b5 281 MAKE_GET( PanId, PANId, panId_t )
johnb 31:c144106e55b5 282 MAKE_GET( SourceAddress, sourceAddress, uint16_t )
johnb 25:db6874b7ac4b 283
johnb 31:c144106e55b5 284 #define MAKE_SET( _name, _mnemonic, _cmd, _type ) \
johnb 31:c144106e55b5 285 bool XBeeApiCmdAt::set ## _name( const _type p_param ) \
johnb 31:c144106e55b5 286 {\
johnb 31:c144106e55b5 287 XBeeApiCmdAtSet<_type> req( _cmd, p_param );\
johnb 31:c144106e55b5 288 \
johnb 31:c144106e55b5 289 m_have_ ## _mnemonic = false;\
johnb 31:c144106e55b5 290 m_## _mnemonic ## Pend = p_param;\
johnb 31:c144106e55b5 291 m_device->SendFrame( &req );\
johnb 31:c144106e55b5 292 return true;\
johnb 13:302e7c1ea0b3 293 }
johnb 13:302e7c1ea0b3 294
johnb 31:c144106e55b5 295 MAKE_SET( CoordinatorEnabled, CE, cmd_set_ce, bool )
johnb 31:c144106e55b5 296 MAKE_SET( EndDeviceAssociationEnabled, EDA, cmd_set_eda, bool )
johnb 31:c144106e55b5 297 MAKE_SET( PanId, PANId, cmd_set_pid, panId_t )
johnb 31:c144106e55b5 298 MAKE_SET( SourceAddress, sourceAddress, cmd_set_my, uint16_t )
johnb 13:302e7c1ea0b3 299
johnb 29:c6d037cceb02 300 XBeeApiCmdAtBlocking::XBeeApiCmdAtBlocking( XBeeDevice* const p_device, const uint16_t p_timeout, const uint16_t p_slice ) :
johnb 29:c6d037cceb02 301 XBeeApiCmdAt( p_device ),
johnb 13:302e7c1ea0b3 302 m_timeout( p_timeout ),
johnb 13:302e7c1ea0b3 303 m_slice( p_slice )
johnb 8:1b48b619d7f6 304 {
johnb 8:1b48b619d7f6 305 }
johnb 8:1b48b619d7f6 306
johnb 13:302e7c1ea0b3 307 /**
johnb 11:bfcf1356027b 308 Macro to wrap around the "requestXXX" & "getXXX" methods and implement a blocking call.
johnb 11:bfcf1356027b 309 This macro is used as the basis for getXXX functions in XBeeApiCmdAtBlocking.
johnb 8:1b48b619d7f6 310
johnb 13:302e7c1ea0b3 311 Originally looked to achieve this using a template function passing method pointers, however
johnb 13:302e7c1ea0b3 312 there's no way to get a method pointer to the parent class implementation as opposed to the
johnb 13:302e7c1ea0b3 313 implementation in this class, meaning that the result was a recursive method call. The joys of
johnb 11:bfcf1356027b 314 polymorphism.
johnb 13:302e7c1ea0b3 315
johnb 11:bfcf1356027b 316 e.g. We pass a pointer to method getHardwareVersion(). The function receiving the pointer
johnb 11:bfcf1356027b 317 uses it to make a function call. The actual function that's called is (correctly)
johnb 11:bfcf1356027b 318 the one implemented in this class, however what we actually wanted in this case
johnb 11:bfcf1356027b 319 was to call the implementation in the base class. Using static_cast<> doesn't have
johnb 11:bfcf1356027b 320 any effect and taking the address of XBeeApiCmdAt::getHardwareVersion ends up with
johnb 11:bfcf1356027b 321 XBeeApiCmdAtBlocking::getHardwareVersion being called due to polymorphism. */
johnb 11:bfcf1356027b 322 #define BLOCKING_GET( _REQ_FN, _GET_FN, _VAR ) \
johnb 11:bfcf1356027b 323 bool ret_val = false; \
johnb 11:bfcf1356027b 324 \
johnb 11:bfcf1356027b 325 if( _GET_FN( _VAR ) )\
johnb 11:bfcf1356027b 326 {\
johnb 11:bfcf1356027b 327 ret_val = true;\
johnb 11:bfcf1356027b 328 } \
johnb 11:bfcf1356027b 329 else if( _REQ_FN() )\
johnb 11:bfcf1356027b 330 {\
johnb 31:c144106e55b5 331 uint16_t counter = m_timeout; \
johnb 31:c144106e55b5 332 bool cont;\
johnb 11:bfcf1356027b 333 \
johnb 11:bfcf1356027b 334 do{\
johnb 31:c144106e55b5 335 cont = false; \
johnb 11:bfcf1356027b 336 wait_ms( m_slice );\
johnb 11:bfcf1356027b 337 if( _GET_FN( _VAR ) )\
johnb 11:bfcf1356027b 338 {\
johnb 11:bfcf1356027b 339 ret_val = true;\
johnb 11:bfcf1356027b 340 }\
johnb 11:bfcf1356027b 341 else if( counter > m_slice ) {\
johnb 11:bfcf1356027b 342 counter -= m_slice; \
johnb 11:bfcf1356027b 343 cont = true;\
johnb 11:bfcf1356027b 344 } \
johnb 11:bfcf1356027b 345 } while( cont );\
johnb 11:bfcf1356027b 346 }\
johnb 11:bfcf1356027b 347 \
johnb 8:1b48b619d7f6 348 return( ret_val );
johnb 8:1b48b619d7f6 349
johnb 13:302e7c1ea0b3 350 /**
johnb 11:bfcf1356027b 351 Macro to wrap around the "setXXX" & "getXXX" methods and implement a blocking call.
johnb 11:bfcf1356027b 352 This macro is used as the basis for setXXX functions in XBeeApiCmdAtBlocking.
johnb 11:bfcf1356027b 353 */
johnb 11:bfcf1356027b 354 #define BLOCKING_SET( _SET_FN, _GET_FN, _VAR, _TYPE ) \
johnb 11:bfcf1356027b 355 bool ret_val = false; \
johnb 11:bfcf1356027b 356 uint16_t counter = m_timeout; \
johnb 11:bfcf1356027b 357 _TYPE readback; \
johnb 11:bfcf1356027b 358 \
johnb 11:bfcf1356027b 359 if( _SET_FN( _VAR ) )\
johnb 11:bfcf1356027b 360 {\
johnb 31:c144106e55b5 361 bool cont;\
johnb 11:bfcf1356027b 362 \
johnb 11:bfcf1356027b 363 do{\
johnb 31:c144106e55b5 364 cont = false;\
johnb 11:bfcf1356027b 365 wait_ms( m_slice );\
johnb 11:bfcf1356027b 366 if( _GET_FN( &readback ) &&\
johnb 13:302e7c1ea0b3 367 ( readback == _VAR ))\
johnb 11:bfcf1356027b 368 {\
johnb 11:bfcf1356027b 369 ret_val = true;\
johnb 11:bfcf1356027b 370 }\
johnb 11:bfcf1356027b 371 else if( counter > m_slice ) {\
johnb 11:bfcf1356027b 372 counter -= m_slice; \
johnb 11:bfcf1356027b 373 cont = true;\
johnb 11:bfcf1356027b 374 } \
johnb 11:bfcf1356027b 375 } while( cont );\
johnb 11:bfcf1356027b 376 }\
johnb 11:bfcf1356027b 377 \
johnb 11:bfcf1356027b 378 return( ret_val );
johnb 8:1b48b619d7f6 379
johnb 13:302e7c1ea0b3 380
johnb 8:1b48b619d7f6 381 bool XBeeApiCmdAtBlocking::getHardwareVersion( uint16_t* const p_ver )
johnb 8:1b48b619d7f6 382 {
johnb 13:302e7c1ea0b3 383 BLOCKING_GET( XBeeApiCmdAt::requestHardwareVersion,
johnb 13:302e7c1ea0b3 384 XBeeApiCmdAt::getHardwareVersion,
johnb 11:bfcf1356027b 385 p_ver );
johnb 8:1b48b619d7f6 386 }
johnb 8:1b48b619d7f6 387
johnb 8:1b48b619d7f6 388 bool XBeeApiCmdAtBlocking::getFirmwareVersion( uint16_t* const p_ver )
johnb 8:1b48b619d7f6 389 {
johnb 14:edec6cd78ffb 390 BLOCKING_GET( XBeeApiCmdAt::requestFirmwareVersion,
johnb 14:edec6cd78ffb 391 XBeeApiCmdAt::getFirmwareVersion,
johnb 11:bfcf1356027b 392 p_ver );
johnb 8:1b48b619d7f6 393 }
johnb 8:1b48b619d7f6 394
johnb 8:1b48b619d7f6 395 bool XBeeApiCmdAtBlocking::getChannel( uint8_t* const p_chan )
johnb 8:1b48b619d7f6 396 {
johnb 14:edec6cd78ffb 397 BLOCKING_GET( XBeeApiCmdAt::requestChannel,
johnb 14:edec6cd78ffb 398 XBeeApiCmdAt::getChannel,
johnb 11:bfcf1356027b 399 p_chan );
johnb 8:1b48b619d7f6 400 }
johnb 13:302e7c1ea0b3 401
johnb 8:1b48b619d7f6 402 bool XBeeApiCmdAtBlocking::setChannel( uint8_t const p_chan )
johnb 8:1b48b619d7f6 403 {
johnb 14:edec6cd78ffb 404 BLOCKING_SET( XBeeApiCmdAt::setChannel,
johnb 14:edec6cd78ffb 405 XBeeApiCmdAt::getChannel,
johnb 11:bfcf1356027b 406 p_chan,
johnb 13:302e7c1ea0b3 407 uint8_t );
johnb 13:302e7c1ea0b3 408 }
johnb 13:302e7c1ea0b3 409
johnb 13:302e7c1ea0b3 410 bool XBeeApiCmdAtBlocking::getCoordinatorEnabled( bool* const p_en )
johnb 13:302e7c1ea0b3 411 {
johnb 13:302e7c1ea0b3 412 BLOCKING_GET( XBeeApiCmdAt::requestCoordinatorEnabled,
johnb 13:302e7c1ea0b3 413 XBeeApiCmdAt::getCoordinatorEnabled,
johnb 13:302e7c1ea0b3 414 p_en );
johnb 13:302e7c1ea0b3 415 }
johnb 13:302e7c1ea0b3 416
johnb 13:302e7c1ea0b3 417 bool XBeeApiCmdAtBlocking::setCoordinatorEnabled( const bool p_en )
johnb 13:302e7c1ea0b3 418 {
johnb 14:edec6cd78ffb 419 BLOCKING_SET( XBeeApiCmdAt::setCoordinatorEnabled,
johnb 14:edec6cd78ffb 420 XBeeApiCmdAt::getCoordinatorEnabled,
johnb 13:302e7c1ea0b3 421 p_en,
johnb 13:302e7c1ea0b3 422 bool );
johnb 13:302e7c1ea0b3 423 }
johnb 13:302e7c1ea0b3 424
johnb 13:302e7c1ea0b3 425 bool XBeeApiCmdAtBlocking::getEndDeviceAssociationEnabled( bool* const p_en )
johnb 13:302e7c1ea0b3 426 {
johnb 13:302e7c1ea0b3 427 BLOCKING_GET( XBeeApiCmdAt::requestEndDeviceAssociationEnabled,
johnb 13:302e7c1ea0b3 428 XBeeApiCmdAt::getEndDeviceAssociationEnabled,
johnb 13:302e7c1ea0b3 429 p_en );
johnb 8:1b48b619d7f6 430 }
johnb 8:1b48b619d7f6 431
johnb 13:302e7c1ea0b3 432 bool XBeeApiCmdAtBlocking::setEndDeviceAssociationEnabled( const bool p_en )
johnb 13:302e7c1ea0b3 433 {
johnb 14:edec6cd78ffb 434 BLOCKING_SET( XBeeApiCmdAt::setEndDeviceAssociationEnabled,
johnb 14:edec6cd78ffb 435 XBeeApiCmdAt::getEndDeviceAssociationEnabled,
johnb 13:302e7c1ea0b3 436 p_en,
johnb 13:302e7c1ea0b3 437 bool );
johnb 13:302e7c1ea0b3 438 }
johnb 13:302e7c1ea0b3 439
johnb 13:302e7c1ea0b3 440 bool XBeeApiCmdAtBlocking::getPanId( panId_t* const p_chan )
johnb 13:302e7c1ea0b3 441 {
johnb 13:302e7c1ea0b3 442 BLOCKING_GET( XBeeApiCmdAt::requestPanId,
johnb 13:302e7c1ea0b3 443 XBeeApiCmdAt::getPanId,
johnb 13:302e7c1ea0b3 444 p_chan );
johnb 13:302e7c1ea0b3 445 }
johnb 13:302e7c1ea0b3 446
johnb 13:302e7c1ea0b3 447 bool XBeeApiCmdAtBlocking::setPanId( const panId_t p_chan )
johnb 13:302e7c1ea0b3 448 {
johnb 14:edec6cd78ffb 449 BLOCKING_SET( XBeeApiCmdAt::setPanId,
johnb 14:edec6cd78ffb 450 XBeeApiCmdAt::getPanId,
johnb 13:302e7c1ea0b3 451 p_chan,
johnb 13:302e7c1ea0b3 452 panId_t );
johnb 13:302e7c1ea0b3 453 }
johnb 13:302e7c1ea0b3 454
johnb 31:c144106e55b5 455 bool XBeeApiCmdAtBlocking::getSourceAddress( uint16_t* const p_addr )
johnb 31:c144106e55b5 456 {
johnb 31:c144106e55b5 457 BLOCKING_GET( XBeeApiCmdAt::requestSourceAddress,
johnb 31:c144106e55b5 458 XBeeApiCmdAt::getSourceAddress,
johnb 31:c144106e55b5 459 p_addr );
johnb 31:c144106e55b5 460 }
johnb 31:c144106e55b5 461
johnb 31:c144106e55b5 462 bool XBeeApiCmdAtBlocking::setSourceAddress( const uint16_t p_addr )
johnb 31:c144106e55b5 463 {
johnb 31:c144106e55b5 464 BLOCKING_SET( XBeeApiCmdAt::setSourceAddress,
johnb 31:c144106e55b5 465 XBeeApiCmdAt::getSourceAddress,
johnb 31:c144106e55b5 466 p_addr,
johnb 31:c144106e55b5 467 uint16_t );
johnb 31:c144106e55b5 468 }
johnb 31:c144106e55b5 469
johnb 31:c144106e55b5 470
johnb 25:db6874b7ac4b 471 template < typename T >
johnb 25:db6874b7ac4b 472 XBeeApiCmdAt::XBeeApiCmdAtSet<T>::XBeeApiCmdAtSet( const uint8_t* const p_data,
johnb 25:db6874b7ac4b 473 const T p_val ) : XBeeApiFrame( )
johnb 8:1b48b619d7f6 474 {
johnb 25:db6874b7ac4b 475 size_t s;
johnb 25:db6874b7ac4b 476 uint8_t* dest;
johnb 25:db6874b7ac4b 477 const uint8_t* src = (uint8_t*)(&p_val);
johnb 25:db6874b7ac4b 478
johnb 13:302e7c1ea0b3 479 m_apiId = XBEE_CMD_AT_CMD;
johnb 25:db6874b7ac4b 480
johnb 25:db6874b7ac4b 481 m_buffer[0] = p_data[0];
johnb 25:db6874b7ac4b 482 m_buffer[1] = p_data[1];
johnb 25:db6874b7ac4b 483 m_buffer[2] = p_data[2];
johnb 25:db6874b7ac4b 484
johnb 25:db6874b7ac4b 485 dest = &( m_buffer[3] );
johnb 25:db6874b7ac4b 486
johnb 25:db6874b7ac4b 487 for( s = 0;
johnb 25:db6874b7ac4b 488 s < sizeof( T );
johnb 25:db6874b7ac4b 489 s++, dest++, src++ ) {
johnb 25:db6874b7ac4b 490 *dest = *src;
johnb 25:db6874b7ac4b 491 }
johnb 25:db6874b7ac4b 492
johnb 13:302e7c1ea0b3 493 m_data = m_buffer;
johnb 25:db6874b7ac4b 494 m_dataLen = sizeof( m_buffer );
johnb 8:1b48b619d7f6 495 }
johnb 13:302e7c1ea0b3 496
johnb 25:db6874b7ac4b 497 template < typename T >
johnb 25:db6874b7ac4b 498 XBeeApiCmdAt::XBeeApiCmdAtSet<T>::~XBeeApiCmdAtSet()
johnb 13:302e7c1ea0b3 499 {
johnb 25:db6874b7ac4b 500 }