XBeeLib modificado para projeto do VSSS
Fork of XBeeLib by
XBeeZB/XBeeZB.cpp
- Committer:
- spastor
- Date:
- 2015-05-08
- Revision:
- 0:fcaad0dfa051
- Child:
- 1:794d1d3e4a08
File content as of revision 0:fcaad0dfa051:
/** * Copyright (c) 2015 Digi International Inc., * All rights not expressly granted are reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343 * ======================================================================= */ #include "XBeeZB.h" #include "IO/IOSampleZB.h" #include "Frames/ZigbeeFrames.h" using namespace XBeeLib; /* Class constructor */ XBeeZB::XBeeZB(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) : XBee(tx, rx, reset, rts, cts, baud), _nw_role(UnknownRole), _joined_network(false), _vcc_exceeded_cnt(0), _broadcast_radious(0), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL) { _reset_timeout = RESET_TIMEOUT_MS; } RadioStatus XBeeZB::init() { RadioStatus retval = XBee::init(); /* Determine the role of this device in the network */ switch(_fw_version & 0xFF00) { case 0x2100: _nw_role = Coordinator; break; case 0x2300: _nw_role = Router; break; case 0x2900: _nw_role = EndDevice; break; default: _nw_role = UnknownRole; break; } const RadioProtocol radioProtocol = get_radio_protocol(); if (radioProtocol != ZigBee) { digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", ZigBee, radioProtocol); retval = Failure; } assert(radioProtocol == ZigBee); return retval; } /* Class destructor */ XBeeZB::~XBeeZB() { unregister_node_discovery_cb(); unregister_receive_cb(); unregister_io_sample_cb(); } RadioStatus XBeeZB::set_channel_mask(uint16_t chmask) { AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("SC", chmask); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } return Success; } RadioStatus XBeeZB::get_channel_mask(uint16_t * const chmask) { if (chmask == NULL) { return Failure; } AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; cmdresp = get_param("SC", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; *chmask = var32; return Success; } RadioStatus XBeeZB::set_panid(uint64_t panid) { uint8_t panid_u8[8]; AtCmdFrame::AtCmdResp cmdresp; rmemcpy(panid_u8, (const uint8_t *) &panid, sizeof panid_u8); cmdresp = set_param("ID", panid_u8, sizeof panid_u8); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } return Success; } RadioStatus XBeeZB::get_operating_panid(uint64_t * const opanid) { if (opanid == NULL) { return Failure; } uint8_t opanid_u8[8]; uint16_t len = sizeof opanid_u8; AtCmdFrame::AtCmdResp cmdresp; cmdresp = get_param("OP", opanid_u8, &len); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } if (len != sizeof opanid_u8) { digi_log(LogLevelError, "XBeeZB::get_operating_panid: Read %d bytes instead of %d for OP", len, sizeof opanid_u8); return Failure; } rmemcpy((uint8_t *)opanid, opanid_u8, len); return Success; } RadioStatus XBeeZB::get_configured_panid(uint64_t * const panid) { if (panid == NULL) { return Failure; } uint8_t panid_u8[8]; uint16_t len = sizeof panid_u8; AtCmdFrame::AtCmdResp cmdresp; cmdresp = get_param("ID", panid_u8, &len); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } if (len != sizeof panid_u8) { digi_log(LogLevelError, "XBeeZB::get_configured_panid: Read %d bytes instead of %d for ID", len, sizeof panid_u8); return Failure; } rmemcpy((uint8_t *)panid, panid_u8, len); return Success; } RadioStatus XBeeZB::set_panid(const RemoteXBee& remote, uint64_t panid) { uint8_t panid_u8[8]; AtCmdFrame::AtCmdResp cmdresp; rmemcpy(panid_u8, (const uint8_t *) &panid, sizeof panid_u8); cmdresp = set_param(remote, "ID", panid_u8, sizeof panid_u8); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } return Success; } RadioStatus XBeeZB::get_operating_panid(const RemoteXBee& remote, uint64_t * const opanid) { if (opanid == NULL) { return Failure; } uint8_t opanid_u8[8]; uint16_t len = sizeof opanid_u8; AtCmdFrame::AtCmdResp cmdresp; cmdresp = get_param(remote, "OP", opanid_u8, &len); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } if (len != sizeof opanid_u8) { digi_log(LogLevelError, "XBeeZB::get_operating_panid: Read %d bytes instead of %d for OP", len, sizeof opanid_u8); return Failure; } rmemcpy((uint8_t *)opanid, opanid_u8, len); return Success; } RadioStatus XBeeZB::get_configured_panid(const RemoteXBee& remote, uint64_t * const panid) { if (panid == NULL) { return Failure; } uint8_t panid_u8[8]; uint16_t len = sizeof panid_u8; AtCmdFrame::AtCmdResp cmdresp; cmdresp = get_param(remote, "ID", panid_u8, &len); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } if (len != sizeof panid_u8) { digi_log(LogLevelError, "XBeeZB::get_configured_panid: Read %d bytes instead of %d for ID", len, sizeof panid_u8); return Failure; } rmemcpy((uint8_t *)panid, panid_u8, len); return Success; } RadioStatus XBeeZB::check_for_coordinator_at_start(bool enable) { AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("JV", (uint8_t)enable); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } RadioStatus XBeeZB::enable_network_encryption(bool enable) { AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("EE", enable); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } RadioStatus XBeeZB::set_encryption_key(const uint8_t * const key, const uint16_t length) { if (key == NULL || length == 0) { return Failure; } AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("NK", key, length); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } RadioStatus XBeeZB::set_tc_link_key(const uint8_t * const key, const uint16_t length) { if (key == NULL || length == 0) { return Failure; } AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("KY", key, length); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } RadioStatus XBeeZB::set_encryption_options(const uint8_t options) { AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("EO", options); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } void XBeeZB::radio_status_update(AtCmdFrame::ModemStatus modem_status) { /* Update the radio status variables */ if (modem_status == AtCmdFrame::HwReset) { _hw_reset_cnt++; _joined_network = false; } else if (modem_status == AtCmdFrame::WdReset) { _wd_reset_cnt++; _joined_network = false; } else if (modem_status == AtCmdFrame::JoinedNW) _joined_network = true; else if (modem_status == AtCmdFrame::Disassociated) _joined_network = false; else if (modem_status == AtCmdFrame::VccExceeded) _vcc_exceeded_cnt++; _modem_status = modem_status; digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status); } TxStatus XBeeZB::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len) { if (!remote.is_valid_addr64b()) return TxStatusInvalidAddr; const uint64_t remote64 = remote.get_addr64(); const uint16_t remote16 = remote.get_addr16(); TxFrameZB frame = TxFrameZB(remote64, remote16, _broadcast_radious, _tx_options, data, len); return send_data(&frame); } TxStatus XBeeZB::send_data(uint64_t remote64, const uint8_t *const data, uint16_t len) { TxFrameZB frame = TxFrameZB(remote64, ADDR16_UNKNOWN, _broadcast_radious, _tx_options, data, len); return send_data(&frame); } TxStatus XBeeZB::send_data(uint64_t remote64, uint16_t remote16, const uint8_t *const data, uint16_t len) { TxFrameZB frame = TxFrameZB(remote64, remote16, _broadcast_radious, _tx_options, data, len); return send_data(&frame); } TxStatus XBeeZB::send_data(const RemoteXBee& remote, uint8_t source_ep, uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id, const uint8_t *const data, uint16_t len) { if (!remote.is_valid_addr64b()) return TxStatusInvalidAddr; const uint64_t remote64 = remote.get_addr64(); const uint16_t remote16 = remote.get_addr16(); TxFrameZB frame = TxFrameZB(remote64, remote16, source_ep, dest_ep, cluster_id, profile_id, _broadcast_radious, _tx_options, data, len); return send_data(&frame); } TxStatus XBeeZB::send_data(uint64_t remote64, uint16_t remote16, uint8_t source_ep, uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id, const uint8_t *const data, uint16_t len) { TxFrameZB frame = TxFrameZB(remote64, remote16, source_ep, dest_ep, cluster_id, profile_id, _broadcast_radious, _tx_options, data, len); return send_data(&frame); } TxStatus XBeeZB::send_data_to_coordinator(const uint8_t *const data, uint16_t len) { const uint64_t remaddr = ADDR64_COORDINATOR; TxFrameZB frame = TxFrameZB(remaddr, ADDR16_UNKNOWN, _broadcast_radious, _tx_options, data, len); return send_data(&frame); } RemoteXBeeZB XBeeZB::get_remote_node_by_id(const char * const node_id) { uint64_t addr64; uint16_t addr16; _get_remote_node_by_id(node_id, &addr64, &addr16); return RemoteXBeeZB(addr64, addr16); } NetworkRole XBeeZB::get_network_role() { return _nw_role; } bool XBeeZB::is_joined() { return _joined_network; } void XBeeZB::register_node_discovery_cb(node_discovery_zb_cb_t function) { if (_nd_handler == NULL) { _nd_handler = new FH_NodeDiscoveryZB(); register_frame_handler(_nd_handler); } _nd_handler->register_node_discovery_cb(function); } void XBeeZB::unregister_node_discovery_cb() { if (_nd_handler != NULL) { _nd_handler->unregister_node_discovery_cb(); unregister_frame_handler(_nd_handler); delete _nd_handler; _nd_handler = NULL; /* as delete does not set to NULL */ } } void XBeeZB::register_receive_cb(receive_zb_cb_t function) { if (_rx_pkt_handler == NULL) { _rx_pkt_handler = new FH_RxPacketZB(); register_frame_handler(_rx_pkt_handler); } _rx_pkt_handler->register_receive_cb(function); } void XBeeZB::unregister_receive_cb() { if (_rx_pkt_handler != NULL) { _rx_pkt_handler->unregister_receive_cb(); unregister_frame_handler(_rx_pkt_handler); delete _rx_pkt_handler; _rx_pkt_handler = NULL; /* as delete does not set to NULL */ } } void XBeeZB::register_io_sample_cb(io_data_cb_zb_t function) { if (_io_data_handler == NULL) { _io_data_handler = new FH_IoDataSampeZB(); register_frame_handler(_io_data_handler); } _io_data_handler->register_io_data_cb(function); } void XBeeZB::unregister_io_sample_cb() { if (_io_data_handler != NULL) { _io_data_handler->unregister_io_data_cb(); unregister_frame_handler(_io_data_handler); delete _io_data_handler; _io_data_handler = NULL; /* as delete does not set to NULL */ } } AtCmdFrame::AtCmdResp XBeeZB::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) { if (!remote.is_valid_addr64b()) return AtCmdFrame::AtCmdRespInvalidAddr; const uint64_t remote64 = remote.get_addr64(); const uint16_t remote16 = remote.get_addr16(); uint16_t len = sizeof *data; AtCmdFrame::AtCmdResp atCmdResponse; AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param); atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote); if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch; return atCmdResponse; } AtCmdFrame::AtCmdResp XBeeZB::set_param(const RemoteXBee& remote, const char * const param, uint32_t data) { if (!remote.is_valid_addr64b()) return AtCmdFrame::AtCmdRespInvalidAddr; const uint64_t remote64 = remote.get_addr64(); const uint16_t remote16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data); return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); } AtCmdFrame::AtCmdResp XBeeZB::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len) { if (!remote.is_valid_addr64b()) return AtCmdFrame::AtCmdRespInvalidAddr; const uint64_t remote64 = remote.get_addr64(); const uint16_t remote16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len); return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); } AtCmdFrame::AtCmdResp XBeeZB::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) { if (!remote.is_valid_addr64b()) return AtCmdFrame::AtCmdRespInvalidAddr; const uint64_t remote64 = remote.get_addr64(); const uint16_t remote16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param); return send_at_cmd(&cmd_frame, data, len, RadioRemote, false); } static void get_dio_cmd(XBeeZB::IoLine line, char * const iocmd) { if (line >= XBeeZB::DIO10) { iocmd[0] = 'P'; iocmd[1] = '0' + line - XBeeZB::DIO10; } else { iocmd[0] = 'D'; iocmd[1] = '0' + line; } iocmd[2] = '\0'; } RadioStatus XBeeZB::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode) { AtCmdFrame::AtCmdResp cmdresp; char iocmd[3]; get_dio_cmd(line, iocmd); cmdresp = set_param(remote, iocmd, (uint8_t)mode); if (cmdresp != AtCmdFrame::AtCmdRespOk) { digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp); return Failure; } return Success; } RadioStatus XBeeZB::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode) { AtCmdFrame::AtCmdResp cmdresp; char iocmd[3]; get_dio_cmd(line, iocmd); uint32_t var32; cmdresp = get_param(remote, iocmd, &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } *mode = (IoMode)var32; return Success; } RadioStatus XBeeZB::set_dio(const RemoteXBee& remote, IoLine line, DioVal val) { if (val == Low) return set_pin_config(remote, line, DigitalOutLow); else return set_pin_config(remote, line, DigitalOutHigh); } RadioStatus XBeeZB::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val) { uint8_t io_sample[MAX_IO_SAMPLE_BUF_LEN]; uint16_t len; RadioStatus resp = get_iosample(remote, io_sample, &len); if (resp != Success) return resp; IOSampleZB ioSample = IOSampleZB(io_sample, len); return ioSample.get_dio(line, val); } RadioStatus XBeeZB::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val) { uint8_t io_sample[MAX_IO_SAMPLE_BUF_LEN]; uint16_t len; switch (line) { case SUPPLY_VOLTAGE: case DIO3_AD3: case DIO2_AD2: case DIO1_AD1: case DIO0_AD0: break; default: digi_log(LogLevelError, "get_adc: Pin %d not supported as ADC\r\n", line); return Failure; } RadioStatus resp = get_iosample(remote, io_sample, &len); if (resp != Success) return resp; IOSampleZB ioSample = IOSampleZB(io_sample, len); return ioSample.get_adc(line, val); } static uint16_t get_dio_pr_mask(XBeeZB::IoLine line) { switch (line) { case XBeeZB::DIO4: return (1 << 0); case XBeeZB::DIO3_AD3: return (1 << 1); case XBeeZB::DIO2_AD2: return (1 << 2); case XBeeZB::DIO1_AD1: return (1 << 3); case XBeeZB::DIO0_AD0: return (1 << 4); case XBeeZB::DIO6: return (1 << 5); case XBeeZB::DIO5: return (1 << 8); case XBeeZB::DIO12: return (1 << 10); case XBeeZB::DIO10: return (1 << 11); case XBeeZB::DIO11: return (1 << 12); case XBeeZB::DIO7: return (1 << 13); default: return 0; } } RadioStatus XBeeZB::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable) { AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; uint16_t pr; cmdresp = get_param(remote, "PR", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } pr = var32; const uint16_t dio_mask = get_dio_pr_mask(line); if (dio_mask == 0) { digi_log(LogLevelError, "XBeeZB::set_pin_pull_up: invalid pin %d\r\n", line); return Failure; } if (enable) { pr |= dio_mask; } else { pr &= ~dio_mask; } cmdresp = set_param(remote, "PR", pr); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } static uint16_t get_dio_ic_mask(XBeeZB::IoLine line) { if (line < XBeeZB::DIO12) { return (1 << line); } return 0; } RadioStatus XBeeZB::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable) { if (line > DIO11) { digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: pin not supported (%d)\r\n", line); return Failure; } AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; uint16_t ic; cmdresp = get_param(remote, "IC", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } ic = var32; const uint16_t dio_mask = get_dio_ic_mask(line); if (dio_mask == 0) { digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: invalid pin %d\r\n", line); return Failure; } if (enable) { ic |= dio_mask; } else { ic &= ~dio_mask; } cmdresp = set_param(remote, "IC", ic); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; }