Library to easily communicate with XBee modules.

Dependencies:   DigiLogger

Dependents:   WaterLogger XbeeGateway XBee_Cooker ProjetReceiver ... more

Use XBee radio modules to easily improve your project with wireless connectivity. You can enable entire networks of connected devices. XBees can exchange data with other modules in the network and configure remote modules as well as trigger actions or collect sensor data on XBee nodes without needing additional external microcontrollers. Using this documentation and configuration tools with XBee modules, it is easy to develop these types of applications and more.

/media/uploads/spastor/xbee-xbeepro-series1.jpg

The XBee mbed Library is a ready-to-import mbed extension that dramatically reduces development time for XBee projects on the mbed platforms. There are many modular examples, making it an easy and smooth process to add wireless networking to a whole range of useful applications.

Info

Currently 802.15.4 (Series 1 and 2), ZigBee (Series 2) and DigiMesh (Series 1 and 2) modules are supported. The libraries can be extended to support other protocols like DigiMesh point-to-point, WiFi, etc.

User manual

The user manual can be found at this project's Wiki pages:

  1. Configuring the library
  2. Debugging the library
  3. Initializing modules
  4. Resetting the local module
  5. Receiving Data from other module
  6. Sending data to another module
  7. Discovering nodes in the network
  8. Configuring local and remote modules
  9. Handling modem status changes
  10. Handling remote modules DIOs, ADCs and PWMs
  11. Handling IO Data Samples from other module
  12. Radio Power Management

Ready to use examples

There are a lot of ready to use examples to get started quickly.
Make sure you have a valid example setup before running the examples:

Examples for ZigBee modules

Import programXBeeZB_Receive_Data

ZigBee Receive Data example for mbed XBeeLib By Digi

Import programXBeeZB_Send_Data

ZigBee Send Data example for mbed XBeeLib By Digi

Import programXBeeZB_module_config

ZigBee network configuration example for mbed XBeeLib By Digi

Import programXBeeZB_AT_Commands

ZigBee AT Commands example for mbed XBeeLib By Digi

Import programXBeeZB_dio_adc

ZigBee DIOs and ADCs example for mbed XBeeLib By Digi

Import programXBeeZB_IO_Sample_Callback

ZigBee IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBeeZB_modem_status

ZigBee Modem Status example for mbed XBeeLib By Digi

Import programXBeeZB_node_discovery

ZigBee Node Discovery example for mbed XBeeLib By Digi

Import programXBeeZB_power_mngmnt_cyclic_sleep

ZigBee Power Management using Cyclic Sleep example for mbed XBeeLib By Digi

Import programXBeeZB_power_mngmnt_pin_sleep

ZigBee Power Management using Pin Sleep example for mbed XBeeLib By Digi

Examples for 802.15.4 modules

Import programXBee802_Receive_Data

802.15.4 Receive Data example for mbed XBeeLib By Digi

Import programXBee802_Send_Data

802.15.4 Send Data example for mbed XBeeLib By Digi

Import programXBee802_module_config

802.15.4 network configuration example for mbed XBeeLib By Digi

Import programXBee802_AT_Commands

802.15.4 AT Commands example for mbed XBeeLib By Digi

Import programXBee802_dio_adc_pwm

802.15.4 DIOs, ADCs and PWM example for mbed XBeeLib By Digi

Import programXBee802_IO_Sample_Callback

802.15.4 IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBee802_node_discovery

802.15.4 Node Discovery example for mbed XBeeLib By Digi

Import programXBee802_power_mngmnt_cyclic_sleep

802.15.4 Power Management using Cyclic Sleep example for mbed XBeeLib By Digi

Import programXBee802_power_mngmnt_pin_sleep

802.15.4 Power Management using Pin Sleep example for mbed XBeeLib By Digi

Examples for DigiMesh modules

Import programXBeeDM_Receive_Data

DigiMesh Receive Data example for mbed XBeeLib By Digi

Import programXBeeDM_Send_Data

DigiMesh Send Data example for mbed XBeeLib By Digi

Import programXBeeDM_module_config

DigiMesh network configuration example for mbed XBeeLib By Digi

Import programXBeeDM_AT_Commands

DigiMesh AT Commands example for mbed XBeeLib By Digi

Import programXBeeDM_dio_adc_pwm

DigiMEsh DIOs, ADCs and PWMs example for mbed XBeeLib By Digi

Import programXBeeDM_IO_Sample_Callback

DigiMesh IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBeeDM_modem_status

DigiMesh Modem Status example for mbed XBeeLib By Digi

Import programXBeeDM_node_discovery

DigiMesh Node Discovery example for mbed XBeeLib By Digi

Import programXBeeDM_power_mngmnt_asyncr_cyclic_sleep

DigiMesh Power Management using Asynchronous Cyclic Sleep example for mbed XBeeLib By Digi

Import programXBeeDM_power_mngmnt_pin_sleep

DigiMesh Power Management using Pin Sleep example for mbed XBeeLib By Digi

Committer:
hbujanda
Date:
Thu Jul 28 15:36:36 2016 +0200
Revision:
7:3ac2a461ce76
Parent:
6:06522f3a6642
Child:
8:b5f4a0e92249
Automatic upload

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hbujanda 6:06522f3a6642 1 /**
hbujanda 6:06522f3a6642 2 * Copyright (c) 2015 Digi International Inc.,
hbujanda 6:06522f3a6642 3 * All rights not expressly granted are reserved.
hbujanda 6:06522f3a6642 4 *
hbujanda 6:06522f3a6642 5 * This Source Code Form is subject to the terms of the Mozilla Public
hbujanda 6:06522f3a6642 6 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
hbujanda 6:06522f3a6642 7 * You can obtain one at http://mozilla.org/MPL/2.0/.
hbujanda 6:06522f3a6642 8 *
hbujanda 6:06522f3a6642 9 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
hbujanda 6:06522f3a6642 10 * =======================================================================
hbujanda 6:06522f3a6642 11 */
hbujanda 6:06522f3a6642 12
hbujanda 6:06522f3a6642 13 #include "XBeeDM.h"
hbujanda 6:06522f3a6642 14 #include "IO/IOSampleDM.h"
hbujanda 6:06522f3a6642 15 #include "Frames/DigiMeshFrames.h"
hbujanda 6:06522f3a6642 16
hbujanda 6:06522f3a6642 17 using namespace XBeeLib;
hbujanda 6:06522f3a6642 18
hbujanda 6:06522f3a6642 19 #define BROADCAST_RADIUS_USE_NH 0x00
hbujanda 6:06522f3a6642 20
hbujanda 6:06522f3a6642 21 /* Class constructor */
hbujanda 6:06522f3a6642 22 XBeeDM::XBeeDM(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
hbujanda 6:06522f3a6642 23 XBee(tx, rx, reset, rts, cts, baud), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL)
hbujanda 6:06522f3a6642 24 {
hbujanda 6:06522f3a6642 25 }
hbujanda 6:06522f3a6642 26
hbujanda 6:06522f3a6642 27 RadioStatus XBeeDM::init()
hbujanda 6:06522f3a6642 28 {
hbujanda 6:06522f3a6642 29 RadioStatus retval = XBee::init();
hbujanda 6:06522f3a6642 30
hbujanda 6:06522f3a6642 31 const RadioProtocol radioProtocol = get_radio_protocol();
hbujanda 6:06522f3a6642 32 if (radioProtocol != DigiMesh) {
hbujanda 6:06522f3a6642 33 digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", DigiMesh, radioProtocol);
hbujanda 6:06522f3a6642 34 retval = Failure;
hbujanda 6:06522f3a6642 35 }
hbujanda 6:06522f3a6642 36 assert(radioProtocol == DigiMesh);
hbujanda 6:06522f3a6642 37
hbujanda 6:06522f3a6642 38 return retval;
hbujanda 6:06522f3a6642 39 }
hbujanda 6:06522f3a6642 40
hbujanda 6:06522f3a6642 41 /* Class destructor */
hbujanda 6:06522f3a6642 42 XBeeDM::~XBeeDM()
hbujanda 6:06522f3a6642 43 {
hbujanda 6:06522f3a6642 44 unregister_node_discovery_cb();
hbujanda 6:06522f3a6642 45 unregister_receive_cb();
hbujanda 6:06522f3a6642 46 unregister_io_sample_cb();
hbujanda 6:06522f3a6642 47 }
hbujanda 6:06522f3a6642 48
hbujanda 6:06522f3a6642 49 RadioStatus XBeeDM::set_channel(uint8_t channel)
hbujanda 6:06522f3a6642 50 {
hbujanda 6:06522f3a6642 51 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 52
hbujanda 6:06522f3a6642 53 /* Pro and Non-Pro modules have different channels available. The at
hbujanda 6:06522f3a6642 54 command will return an error if the selected channel is not available */
hbujanda 6:06522f3a6642 55 cmdresp = set_param("CH", channel);
hbujanda 6:06522f3a6642 56 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 57 return Failure;
hbujanda 6:06522f3a6642 58 }
hbujanda 6:06522f3a6642 59 return Success;
hbujanda 6:06522f3a6642 60 }
hbujanda 6:06522f3a6642 61
hbujanda 6:06522f3a6642 62 RadioStatus XBeeDM::get_channel(uint8_t * const channel)
hbujanda 6:06522f3a6642 63 {
hbujanda 6:06522f3a6642 64 if (channel == NULL) {
hbujanda 6:06522f3a6642 65 return Failure;
hbujanda 6:06522f3a6642 66 }
hbujanda 6:06522f3a6642 67 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 68
hbujanda 6:06522f3a6642 69 uint32_t var32;
hbujanda 6:06522f3a6642 70 cmdresp = get_param("CH", &var32);
hbujanda 6:06522f3a6642 71 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 72 return Failure;
hbujanda 6:06522f3a6642 73 }
hbujanda 6:06522f3a6642 74 *channel = var32;
hbujanda 6:06522f3a6642 75 return Success;
hbujanda 6:06522f3a6642 76 }
hbujanda 6:06522f3a6642 77
hbujanda 6:06522f3a6642 78 RadioStatus XBeeDM::set_network_id(uint16_t network_id)
hbujanda 6:06522f3a6642 79 {
hbujanda 6:06522f3a6642 80 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 81
hbujanda 6:06522f3a6642 82 cmdresp = set_param("ID", network_id);
hbujanda 6:06522f3a6642 83 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 84 return Failure;
hbujanda 6:06522f3a6642 85 }
hbujanda 6:06522f3a6642 86 return Success;
hbujanda 6:06522f3a6642 87 }
hbujanda 6:06522f3a6642 88
hbujanda 6:06522f3a6642 89 RadioStatus XBeeDM::get_network_id(uint16_t * const network_id)
hbujanda 6:06522f3a6642 90 {
hbujanda 6:06522f3a6642 91 if (network_id == NULL) {
hbujanda 6:06522f3a6642 92 return Failure;
hbujanda 6:06522f3a6642 93 }
hbujanda 6:06522f3a6642 94 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 95
hbujanda 6:06522f3a6642 96 uint32_t var32;
hbujanda 6:06522f3a6642 97 cmdresp = get_param("ID", &var32);
hbujanda 6:06522f3a6642 98 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 99 return Failure;
hbujanda 6:06522f3a6642 100 }
hbujanda 6:06522f3a6642 101 *network_id = var32;
hbujanda 6:06522f3a6642 102 return Success;
hbujanda 6:06522f3a6642 103 }
hbujanda 6:06522f3a6642 104
hbujanda 6:06522f3a6642 105 RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms)
hbujanda 6:06522f3a6642 106 {
hbujanda 6:06522f3a6642 107 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 108 uint32_t var32;
hbujanda 6:06522f3a6642 109
hbujanda 6:06522f3a6642 110 cmdresp = get_param("N?", &var32);
hbujanda 6:06522f3a6642 111 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 112 return Failure;
hbujanda 6:06522f3a6642 113 }
hbujanda 6:06522f3a6642 114 *timeout_ms = (uint16_t)var32;
hbujanda 6:06522f3a6642 115
hbujanda 6:06522f3a6642 116 return Success;
hbujanda 6:06522f3a6642 117 }
hbujanda 6:06522f3a6642 118
hbujanda 6:06522f3a6642 119 RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
hbujanda 6:06522f3a6642 120 {
hbujanda 6:06522f3a6642 121 const RadioStatus status = get_node_discovery_timeout(timeout_ms);
hbujanda 6:06522f3a6642 122
hbujanda 6:06522f3a6642 123 *wait_for_complete_timeout = false;
hbujanda 6:06522f3a6642 124
hbujanda 6:06522f3a6642 125 return status;
hbujanda 6:06522f3a6642 126 }
hbujanda 6:06522f3a6642 127
hbujanda 6:06522f3a6642 128 RadioStatus XBeeDM::set_network_security_key(const uint8_t * const key, const uint16_t length)
hbujanda 6:06522f3a6642 129 {
hbujanda 6:06522f3a6642 130 if (key == NULL || length == 0 || length > 16) {
hbujanda 6:06522f3a6642 131 return Failure;
hbujanda 6:06522f3a6642 132 }
hbujanda 6:06522f3a6642 133 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 134
hbujanda 6:06522f3a6642 135 cmdresp = set_param("NK", key, length);
hbujanda 6:06522f3a6642 136 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 137 }
hbujanda 6:06522f3a6642 138
hbujanda 6:06522f3a6642 139 RadioStatus XBeeDM::set_encryption_options(const uint8_t options)
hbujanda 6:06522f3a6642 140 {
hbujanda 6:06522f3a6642 141 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 142
hbujanda 6:06522f3a6642 143 cmdresp = set_param("EO", options);
hbujanda 6:06522f3a6642 144 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 145 }
hbujanda 6:06522f3a6642 146
hbujanda 6:06522f3a6642 147 void XBeeDM::radio_status_update(AtCmdFrame::ModemStatus modem_status)
hbujanda 6:06522f3a6642 148 {
hbujanda 6:06522f3a6642 149 /* Update the radio status variables */
hbujanda 6:06522f3a6642 150 if (modem_status == AtCmdFrame::HwReset) {
hbujanda 6:06522f3a6642 151 _hw_reset_cnt++;
hbujanda 6:06522f3a6642 152 } else if (modem_status == AtCmdFrame::WdReset) {
hbujanda 6:06522f3a6642 153 _wd_reset_cnt++;
hbujanda 6:06522f3a6642 154 }
hbujanda 6:06522f3a6642 155
hbujanda 6:06522f3a6642 156 _modem_status = modem_status;
hbujanda 6:06522f3a6642 157
hbujanda 6:06522f3a6642 158 digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
hbujanda 6:06522f3a6642 159 }
hbujanda 6:06522f3a6642 160
hbujanda 6:06522f3a6642 161 TxStatus XBeeDM::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 162 {
hbujanda 6:06522f3a6642 163 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 164 return TxStatusInvalidAddr;
hbujanda 6:06522f3a6642 165 }
hbujanda 6:06522f3a6642 166
hbujanda 6:06522f3a6642 167 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 168 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 169
hbujanda 6:06522f3a6642 170 TxFrameDM frame = TxFrameDM(remote64, remote16, BROADCAST_RADIUS_USE_NH,
hbujanda 6:06522f3a6642 171 _tx_options, data, len);
hbujanda 6:06522f3a6642 172 if (syncr) {
hbujanda 6:06522f3a6642 173 return send_data(&frame);
hbujanda 6:06522f3a6642 174 } else {
hbujanda 6:06522f3a6642 175 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 176 send_api_frame(&frame);
hbujanda 6:06522f3a6642 177 return TxStatusSuccess;
hbujanda 6:06522f3a6642 178 }
hbujanda 6:06522f3a6642 179 }
hbujanda 6:06522f3a6642 180
hbujanda 6:06522f3a6642 181 TxStatus XBeeDM::send_data(const RemoteXBee& remote, uint8_t source_ep,
hbujanda 6:06522f3a6642 182 uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
hbujanda 6:06522f3a6642 183 const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 184 {
hbujanda 6:06522f3a6642 185 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 186 return TxStatusInvalidAddr;
hbujanda 6:06522f3a6642 187 }
hbujanda 6:06522f3a6642 188
hbujanda 6:06522f3a6642 189 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 190 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 191
hbujanda 6:06522f3a6642 192 TxFrameDM frame = TxFrameDM(remote64, remote16, source_ep, dest_ep,
hbujanda 6:06522f3a6642 193 cluster_id, profile_id, BROADCAST_RADIUS_USE_NH,
hbujanda 6:06522f3a6642 194 _tx_options, data, len);
hbujanda 6:06522f3a6642 195 if (syncr) {
hbujanda 6:06522f3a6642 196 return send_data(&frame);
hbujanda 6:06522f3a6642 197 } else {
hbujanda 6:06522f3a6642 198 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 199 send_api_frame(&frame);
hbujanda 6:06522f3a6642 200 return TxStatusSuccess;
hbujanda 6:06522f3a6642 201 }
hbujanda 6:06522f3a6642 202 }
hbujanda 6:06522f3a6642 203
hbujanda 6:06522f3a6642 204 TxStatus XBeeDM::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 205 {
hbujanda 6:06522f3a6642 206 const uint64_t remaddr = ADDR64_COORDINATOR;
hbujanda 6:06522f3a6642 207
hbujanda 6:06522f3a6642 208 TxFrameDM frame = TxFrameDM(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len);
hbujanda 6:06522f3a6642 209 if (syncr) {
hbujanda 6:06522f3a6642 210 return send_data(&frame);
hbujanda 6:06522f3a6642 211 } else {
hbujanda 6:06522f3a6642 212 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 213 send_api_frame(&frame);
hbujanda 6:06522f3a6642 214 return TxStatusSuccess;
hbujanda 6:06522f3a6642 215 }
hbujanda 6:06522f3a6642 216 }
hbujanda 6:06522f3a6642 217
hbujanda 6:06522f3a6642 218 RemoteXBeeDM XBeeDM::get_remote_node_by_id(const char * const node_id)
hbujanda 6:06522f3a6642 219 {
hbujanda 6:06522f3a6642 220 uint64_t addr64;
hbujanda 6:06522f3a6642 221 uint16_t addr16;
hbujanda 6:06522f3a6642 222 _get_remote_node_by_id(node_id, &addr64, &addr16);
hbujanda 6:06522f3a6642 223 return RemoteXBeeDM(addr64);
hbujanda 6:06522f3a6642 224 }
hbujanda 6:06522f3a6642 225
hbujanda 6:06522f3a6642 226 XBeeDM::AssocStatus XBeeDM::get_assoc_status(void)
hbujanda 6:06522f3a6642 227 {
hbujanda 6:06522f3a6642 228 return (AssocStatus)get_AI();
hbujanda 6:06522f3a6642 229 }
hbujanda 6:06522f3a6642 230
hbujanda 6:06522f3a6642 231 void XBeeDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
hbujanda 6:06522f3a6642 232 {
hbujanda 6:06522f3a6642 233 if (_nd_handler == NULL) {
hbujanda 6:06522f3a6642 234 _nd_handler = new FH_NodeDiscoveryDM();
hbujanda 6:06522f3a6642 235 register_frame_handler(_nd_handler);
hbujanda 6:06522f3a6642 236 }
hbujanda 6:06522f3a6642 237 _nd_handler->register_node_discovery_cb(function);
hbujanda 6:06522f3a6642 238 }
hbujanda 6:06522f3a6642 239
hbujanda 6:06522f3a6642 240 void XBeeDM::unregister_node_discovery_cb()
hbujanda 6:06522f3a6642 241 {
hbujanda 6:06522f3a6642 242 if (_nd_handler != NULL) {
hbujanda 6:06522f3a6642 243 _nd_handler->unregister_node_discovery_cb();
hbujanda 6:06522f3a6642 244 unregister_frame_handler(_nd_handler);
hbujanda 6:06522f3a6642 245 delete _nd_handler;
hbujanda 6:06522f3a6642 246 _nd_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 247 }
hbujanda 6:06522f3a6642 248 }
hbujanda 6:06522f3a6642 249
hbujanda 6:06522f3a6642 250 void XBeeDM::register_receive_cb(receive_dm_cb_t function)
hbujanda 6:06522f3a6642 251 {
hbujanda 6:06522f3a6642 252 if (_rx_pkt_handler == NULL) {
hbujanda 6:06522f3a6642 253 _rx_pkt_handler = new FH_RxPacketDM();
hbujanda 6:06522f3a6642 254 register_frame_handler(_rx_pkt_handler);
hbujanda 6:06522f3a6642 255 }
hbujanda 6:06522f3a6642 256 _rx_pkt_handler->register_receive_cb(function);
hbujanda 6:06522f3a6642 257 }
hbujanda 6:06522f3a6642 258
hbujanda 6:06522f3a6642 259 void XBeeDM::unregister_receive_cb()
hbujanda 6:06522f3a6642 260 {
hbujanda 6:06522f3a6642 261 if (_rx_pkt_handler != NULL) {
hbujanda 6:06522f3a6642 262 _rx_pkt_handler->unregister_receive_cb();
hbujanda 6:06522f3a6642 263 unregister_frame_handler(_rx_pkt_handler);
hbujanda 6:06522f3a6642 264 delete _rx_pkt_handler;
hbujanda 6:06522f3a6642 265 _rx_pkt_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 266 }
hbujanda 6:06522f3a6642 267 }
hbujanda 6:06522f3a6642 268
hbujanda 6:06522f3a6642 269 void XBeeDM::register_io_sample_cb(io_data_cb_dm_t function)
hbujanda 6:06522f3a6642 270 {
hbujanda 6:06522f3a6642 271 if (_io_data_handler == NULL) {
hbujanda 6:06522f3a6642 272 _io_data_handler = new FH_IoDataSampeDM();
hbujanda 6:06522f3a6642 273 register_frame_handler(_io_data_handler);
hbujanda 6:06522f3a6642 274 }
hbujanda 6:06522f3a6642 275 _io_data_handler->register_io_data_cb(function);
hbujanda 6:06522f3a6642 276 }
hbujanda 6:06522f3a6642 277
hbujanda 6:06522f3a6642 278 void XBeeDM::unregister_io_sample_cb()
hbujanda 6:06522f3a6642 279 {
hbujanda 6:06522f3a6642 280 if (_io_data_handler != NULL) {
hbujanda 6:06522f3a6642 281 _io_data_handler->unregister_io_data_cb();
hbujanda 6:06522f3a6642 282 unregister_frame_handler(_io_data_handler);
hbujanda 6:06522f3a6642 283 delete _io_data_handler;
hbujanda 6:06522f3a6642 284 _io_data_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 285 }
hbujanda 6:06522f3a6642 286 }
hbujanda 6:06522f3a6642 287
hbujanda 6:06522f3a6642 288 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
hbujanda 6:06522f3a6642 289 {
hbujanda 6:06522f3a6642 290 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 291 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 292 }
hbujanda 6:06522f3a6642 293
hbujanda 6:06522f3a6642 294 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 295 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 296 uint16_t len = sizeof *data;
hbujanda 6:06522f3a6642 297 AtCmdFrame::AtCmdResp atCmdResponse;
hbujanda 6:06522f3a6642 298
hbujanda 6:06522f3a6642 299 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
hbujanda 6:06522f3a6642 300 atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
hbujanda 6:06522f3a6642 301
hbujanda 6:06522f3a6642 302 if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
hbujanda 6:06522f3a6642 303 atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
hbujanda 6:06522f3a6642 304 }
hbujanda 6:06522f3a6642 305
hbujanda 6:06522f3a6642 306 return atCmdResponse;
hbujanda 6:06522f3a6642 307 }
hbujanda 6:06522f3a6642 308
hbujanda 6:06522f3a6642 309 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
hbujanda 6:06522f3a6642 310 {
hbujanda 6:06522f3a6642 311 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 312 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 313 }
hbujanda 6:06522f3a6642 314
hbujanda 6:06522f3a6642 315 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 316 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 317
hbujanda 6:06522f3a6642 318 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data);
hbujanda 6:06522f3a6642 319 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
hbujanda 6:06522f3a6642 320 }
hbujanda 6:06522f3a6642 321
hbujanda 6:06522f3a6642 322 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
hbujanda 6:06522f3a6642 323 {
hbujanda 6:06522f3a6642 324 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 325 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 326 }
hbujanda 6:06522f3a6642 327
hbujanda 6:06522f3a6642 328 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 329 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 330
hbujanda 6:06522f3a6642 331 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len);
hbujanda 6:06522f3a6642 332 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
hbujanda 6:06522f3a6642 333 }
hbujanda 6:06522f3a6642 334
hbujanda 6:06522f3a6642 335 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
hbujanda 6:06522f3a6642 336 {
hbujanda 6:06522f3a6642 337
hbujanda 6:06522f3a6642 338 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 339 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 340 }
hbujanda 6:06522f3a6642 341
hbujanda 6:06522f3a6642 342 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 343 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 344
hbujanda 6:06522f3a6642 345 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
hbujanda 6:06522f3a6642 346 return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
hbujanda 6:06522f3a6642 347 }
hbujanda 6:06522f3a6642 348
hbujanda 6:06522f3a6642 349 static void get_dio_cmd(XBeeDM::IoLine line, char * const iocmd)
hbujanda 6:06522f3a6642 350 {
hbujanda 6:06522f3a6642 351 if (line >= XBeeDM::DIO10_PWM0) {
hbujanda 6:06522f3a6642 352 iocmd[0] = 'P';
hbujanda 6:06522f3a6642 353 iocmd[1] = '0' + line - XBeeDM::DIO10_PWM0;
hbujanda 6:06522f3a6642 354 } else {
hbujanda 6:06522f3a6642 355 iocmd[0] = 'D';
hbujanda 6:06522f3a6642 356 iocmd[1] = '0' + line;
hbujanda 6:06522f3a6642 357 }
hbujanda 6:06522f3a6642 358 iocmd[2] = '\0';
hbujanda 6:06522f3a6642 359 }
hbujanda 6:06522f3a6642 360
hbujanda 6:06522f3a6642 361 RadioStatus XBeeDM::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)
hbujanda 6:06522f3a6642 362 {
hbujanda 6:06522f3a6642 363 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 364 char iocmd[3];
hbujanda 6:06522f3a6642 365
hbujanda 6:06522f3a6642 366 get_dio_cmd(line, iocmd);
hbujanda 6:06522f3a6642 367
hbujanda 6:06522f3a6642 368 cmdresp = set_param(remote, iocmd, (uint8_t)mode);
hbujanda 6:06522f3a6642 369 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 370 digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp);
hbujanda 6:06522f3a6642 371 return Failure;
hbujanda 6:06522f3a6642 372 }
hbujanda 6:06522f3a6642 373
hbujanda 6:06522f3a6642 374 return Success;
hbujanda 6:06522f3a6642 375 }
hbujanda 6:06522f3a6642 376
hbujanda 6:06522f3a6642 377 RadioStatus XBeeDM::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)
hbujanda 6:06522f3a6642 378 {
hbujanda 6:06522f3a6642 379 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 380 char iocmd[3];
hbujanda 6:06522f3a6642 381
hbujanda 6:06522f3a6642 382 get_dio_cmd(line, iocmd);
hbujanda 6:06522f3a6642 383
hbujanda 6:06522f3a6642 384 uint32_t var32;
hbujanda 6:06522f3a6642 385 cmdresp = get_param(remote, iocmd, &var32);
hbujanda 6:06522f3a6642 386 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 387 return Failure;
hbujanda 6:06522f3a6642 388 }
hbujanda 6:06522f3a6642 389 *mode = (IoMode)var32;
hbujanda 6:06522f3a6642 390
hbujanda 6:06522f3a6642 391 return Success;
hbujanda 6:06522f3a6642 392 }
hbujanda 6:06522f3a6642 393
hbujanda 6:06522f3a6642 394 RadioStatus XBeeDM::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
hbujanda 6:06522f3a6642 395 {
hbujanda 6:06522f3a6642 396 return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh);
hbujanda 6:06522f3a6642 397 }
hbujanda 6:06522f3a6642 398
hbujanda 6:06522f3a6642 399 RadioStatus XBeeDM::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
hbujanda 6:06522f3a6642 400 {
hbujanda 6:06522f3a6642 401 return get_iosample(remote).get_dio(line, val);
hbujanda 6:06522f3a6642 402 }
hbujanda 6:06522f3a6642 403
hbujanda 6:06522f3a6642 404 RadioStatus XBeeDM::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
hbujanda 6:06522f3a6642 405 {
hbujanda 6:06522f3a6642 406 return get_iosample(remote).get_adc(line, val);
hbujanda 6:06522f3a6642 407 }
hbujanda 6:06522f3a6642 408
hbujanda 6:06522f3a6642 409 RadioStatus XBeeDM::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)
hbujanda 6:06522f3a6642 410 {
hbujanda 6:06522f3a6642 411 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 412 char iocmd[3] = { 'M', '0', '\0' };
hbujanda 6:06522f3a6642 413
hbujanda 6:06522f3a6642 414 if (line != DIO10_PWM0 && line != DIO11_PWM1) {
hbujanda 6:06522f3a6642 415 return Failure;
hbujanda 6:06522f3a6642 416 }
hbujanda 6:06522f3a6642 417 if (line == DIO11_PWM1) {
hbujanda 6:06522f3a6642 418 iocmd[1] = '1';
hbujanda 6:06522f3a6642 419 }
hbujanda 6:06522f3a6642 420
hbujanda 6:06522f3a6642 421 uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100);
hbujanda 6:06522f3a6642 422
hbujanda 6:06522f3a6642 423 cmdresp = set_param(remote, iocmd, pwm_val);
hbujanda 6:06522f3a6642 424 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 425 }
hbujanda 6:06522f3a6642 426
hbujanda 6:06522f3a6642 427 IOSampleDM XBeeDM::get_iosample(const RemoteXBee& remote)
hbujanda 6:06522f3a6642 428 {
hbujanda 6:06522f3a6642 429 uint8_t io_sample[MAX_IO_SAMPLE_DM_LEN];
hbujanda 6:06522f3a6642 430 uint16_t len = sizeof io_sample;
hbujanda 6:06522f3a6642 431
hbujanda 6:06522f3a6642 432 RadioStatus resp = _get_iosample(remote, io_sample, &len);
hbujanda 6:06522f3a6642 433 if (resp != Success) {
hbujanda 6:06522f3a6642 434 digi_log(LogLevelError, "XBeeDM::get_iosample failed to get an IOSample\r\n");
hbujanda 6:06522f3a6642 435 len = 0;
hbujanda 6:06522f3a6642 436 }
hbujanda 6:06522f3a6642 437
hbujanda 6:06522f3a6642 438 return IOSampleDM(io_sample, len);
hbujanda 6:06522f3a6642 439 }
hbujanda 6:06522f3a6642 440
hbujanda 6:06522f3a6642 441 static uint16_t get_dio_pr_mask(XBeeDM::IoLine line)
hbujanda 6:06522f3a6642 442 {
hbujanda 6:06522f3a6642 443 switch (line) {
hbujanda 6:06522f3a6642 444 case XBeeDM::DIO4:
hbujanda 6:06522f3a6642 445 return (1 << 0);
hbujanda 6:06522f3a6642 446 case XBeeDM::DIO3_AD3:
hbujanda 6:06522f3a6642 447 return (1 << 1);
hbujanda 6:06522f3a6642 448 case XBeeDM::DIO2_AD2:
hbujanda 6:06522f3a6642 449 return (1 << 2);
hbujanda 6:06522f3a6642 450 case XBeeDM::DIO1_AD1:
hbujanda 6:06522f3a6642 451 return (1 << 3);
hbujanda 6:06522f3a6642 452 case XBeeDM::DIO0_AD0:
hbujanda 6:06522f3a6642 453 return (1 << 4);
hbujanda 6:06522f3a6642 454 case XBeeDM::DIO6:
hbujanda 6:06522f3a6642 455 return (1 << 5);
hbujanda 6:06522f3a6642 456 case XBeeDM::DIO8:
hbujanda 6:06522f3a6642 457 return (1 << 6);
hbujanda 6:06522f3a6642 458 case XBeeDM::DIO5:
hbujanda 6:06522f3a6642 459 return (1 << 8);
hbujanda 6:06522f3a6642 460 case XBeeDM::DIO9:
hbujanda 6:06522f3a6642 461 return (1 << 9);
hbujanda 6:06522f3a6642 462 case XBeeDM::DIO12:
hbujanda 6:06522f3a6642 463 return (1 << 10);
hbujanda 6:06522f3a6642 464 case XBeeDM::DIO10_PWM0:
hbujanda 6:06522f3a6642 465 return (1 << 11);
hbujanda 6:06522f3a6642 466 case XBeeDM::DIO11_PWM1:
hbujanda 6:06522f3a6642 467 return (1 << 12);
hbujanda 6:06522f3a6642 468 case XBeeDM::DIO7:
hbujanda 6:06522f3a6642 469 return (1 << 13);
hbujanda 6:06522f3a6642 470 default:
hbujanda 6:06522f3a6642 471 return 0;
hbujanda 6:06522f3a6642 472 }
hbujanda 6:06522f3a6642 473 }
hbujanda 6:06522f3a6642 474
hbujanda 6:06522f3a6642 475 RadioStatus XBeeDM::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
hbujanda 6:06522f3a6642 476 {
hbujanda 6:06522f3a6642 477 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 478 uint32_t var32;
hbujanda 6:06522f3a6642 479 uint16_t pr;
hbujanda 6:06522f3a6642 480
hbujanda 6:06522f3a6642 481 cmdresp = get_param(remote, "PR", &var32);
hbujanda 6:06522f3a6642 482 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 483 return Failure;
hbujanda 6:06522f3a6642 484 }
hbujanda 6:06522f3a6642 485 pr = var32;
hbujanda 6:06522f3a6642 486
hbujanda 6:06522f3a6642 487 const uint16_t dio_mask = get_dio_pr_mask(line);
hbujanda 6:06522f3a6642 488 if (dio_mask == 0) {
hbujanda 6:06522f3a6642 489 digi_log(LogLevelError, "XBeeDM::set_pin_pull_up: invalid pin %d\r\n", line);
hbujanda 6:06522f3a6642 490 return Failure;
hbujanda 6:06522f3a6642 491 }
hbujanda 6:06522f3a6642 492
hbujanda 6:06522f3a6642 493 if (enable) {
hbujanda 6:06522f3a6642 494 pr |= dio_mask;
hbujanda 6:06522f3a6642 495 } else {
hbujanda 6:06522f3a6642 496 pr &= ~dio_mask;
hbujanda 6:06522f3a6642 497 }
hbujanda 6:06522f3a6642 498
hbujanda 6:06522f3a6642 499 cmdresp = set_param(remote, "PR", pr);
hbujanda 6:06522f3a6642 500 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 501 return Failure;
hbujanda 6:06522f3a6642 502 }
hbujanda 6:06522f3a6642 503
hbujanda 6:06522f3a6642 504 return Success;
hbujanda 6:06522f3a6642 505 }
hbujanda 6:06522f3a6642 506
hbujanda 6:06522f3a6642 507 static uint16_t get_dio_ic_mask(XBeeDM::IoLine line)
hbujanda 6:06522f3a6642 508 {
hbujanda 6:06522f3a6642 509 if (line <= XBeeDM::DIO12) {
hbujanda 6:06522f3a6642 510 return (1 << line);
hbujanda 6:06522f3a6642 511 }
hbujanda 6:06522f3a6642 512 return 0;
hbujanda 6:06522f3a6642 513 }
hbujanda 6:06522f3a6642 514
hbujanda 6:06522f3a6642 515 RadioStatus XBeeDM::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
hbujanda 6:06522f3a6642 516 {
hbujanda 6:06522f3a6642 517 if (line > DIO12) {
hbujanda 6:06522f3a6642 518 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: pin not supported (%d)\r\n", line);
hbujanda 6:06522f3a6642 519 return Failure;
hbujanda 6:06522f3a6642 520 }
hbujanda 6:06522f3a6642 521
hbujanda 6:06522f3a6642 522 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 523 uint32_t var32;
hbujanda 6:06522f3a6642 524 uint16_t ic;
hbujanda 6:06522f3a6642 525
hbujanda 6:06522f3a6642 526 cmdresp = get_param(remote, "IC", &var32);
hbujanda 6:06522f3a6642 527 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 528 return Failure;
hbujanda 6:06522f3a6642 529 }
hbujanda 6:06522f3a6642 530 ic = var32;
hbujanda 6:06522f3a6642 531
hbujanda 6:06522f3a6642 532 const uint16_t dio_mask = get_dio_ic_mask(line);
hbujanda 6:06522f3a6642 533 if (dio_mask == 0) {
hbujanda 6:06522f3a6642 534 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: invalid pin %d\r\n", line);
hbujanda 6:06522f3a6642 535 return Failure;
hbujanda 6:06522f3a6642 536 }
hbujanda 6:06522f3a6642 537
hbujanda 6:06522f3a6642 538 if (enable) {
hbujanda 6:06522f3a6642 539 ic |= dio_mask;
hbujanda 6:06522f3a6642 540 } else {
hbujanda 6:06522f3a6642 541 ic &= ~dio_mask;
hbujanda 6:06522f3a6642 542 }
hbujanda 6:06522f3a6642 543
hbujanda 6:06522f3a6642 544 cmdresp = set_param(remote, "IC", ic);
hbujanda 6:06522f3a6642 545 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 546 return Failure;
hbujanda 6:06522f3a6642 547 }
hbujanda 6:06522f3a6642 548
hbujanda 6:06522f3a6642 549 return Success;
hbujanda 6:06522f3a6642 550 }
hbujanda 7:3ac2a461ce76 551
hbujanda 7:3ac2a461ce76 552 RadioStatus XBeeDM::config_poll_destination(const RemoteXBee& destination)
hbujanda 7:3ac2a461ce76 553 {
hbujanda 7:3ac2a461ce76 554 uint32_t dh;
hbujanda 7:3ac2a461ce76 555 uint32_t dl;
hbujanda 7:3ac2a461ce76 556
hbujanda 7:3ac2a461ce76 557 if (destination.is_valid_addr64b()) {
hbujanda 7:3ac2a461ce76 558 const uint64_t dest64 = destination.get_addr64();
hbujanda 7:3ac2a461ce76 559 dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
hbujanda 7:3ac2a461ce76 560 dl = (uint32_t)((dest64 & 0xFFFFFFFF));
hbujanda 7:3ac2a461ce76 561 } else {
hbujanda 7:3ac2a461ce76 562 digi_log(LogLevelError, "config_poll_destination: Invalid destination");
hbujanda 7:3ac2a461ce76 563 return Failure;
hbujanda 7:3ac2a461ce76 564 }
hbujanda 7:3ac2a461ce76 565
hbujanda 7:3ac2a461ce76 566 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 7:3ac2a461ce76 567
hbujanda 7:3ac2a461ce76 568 cmdresp = set_param("DH", dh);
hbujanda 7:3ac2a461ce76 569 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 7:3ac2a461ce76 570 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
hbujanda 7:3ac2a461ce76 571 return Failure;
hbujanda 7:3ac2a461ce76 572 }
hbujanda 7:3ac2a461ce76 573
hbujanda 7:3ac2a461ce76 574 cmdresp = set_param("DL", dl);
hbujanda 7:3ac2a461ce76 575 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 7:3ac2a461ce76 576 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
hbujanda 7:3ac2a461ce76 577 return Failure;
hbujanda 7:3ac2a461ce76 578 }
hbujanda 7:3ac2a461ce76 579
hbujanda 7:3ac2a461ce76 580 return Success;
hbujanda 7:3ac2a461ce76 581 }