Fork of my original MQTTGateway

Dependencies:   mbed-http

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RadioConfig.cpp Source File

RadioConfig.cpp

00001 /**
00002  * Copyright (c) 2015 Digi International Inc.,
00003  * All rights not expressly granted are reserved.
00004  *
00005  * This Source Code Form is subject to the terms of the Mozilla Public
00006  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
00007  * You can obtain one at http://mozilla.org/MPL/2.0/.
00008  *
00009  * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
00010  * =======================================================================
00011  */
00012 
00013 #include "XBeeLib.h"
00014 #include "Frames/ApiFrame.h"
00015 
00016 using namespace XBeeLib;
00017 
00018 RadioStatus XBee::write_config(void)
00019 {
00020     AtCmdFrame::AtCmdResp cmdresp;
00021 
00022     cmdresp = set_param("WR");
00023     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00024         return Failure;
00025     }
00026     return Success;
00027 }
00028 
00029 RadioStatus XBee::set_power_level(uint8_t  level)
00030 {
00031     AtCmdFrame::AtCmdResp cmdresp;
00032 
00033     if (level > 4) {
00034         return Failure;
00035     }
00036 
00037     cmdresp = set_param("PL", level);
00038     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00039         return Failure;
00040     }
00041 
00042     return Success;
00043 }
00044 
00045 RadioStatus XBee::get_power_level(uint8_t * const  level)
00046 {
00047     if (level == NULL) {
00048         return Failure;
00049     }
00050     AtCmdFrame::AtCmdResp cmdresp;
00051 
00052     uint32_t var32;
00053     cmdresp = get_param("PL", &var32);
00054     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00055         return Failure;
00056     }
00057     *level = var32;
00058     return Success;
00059 }
00060 
00061 RadioStatus XBee::software_reset(void)
00062 {
00063     volatile uint16_t * const rst_cnt_p = &_wd_reset_cnt;
00064     const uint16_t init_rst_cnt = *rst_cnt_p;
00065 
00066     AtCmdFrame::AtCmdResp cmdresp;
00067 
00068     cmdresp = set_param("FR");
00069     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00070         digi_log(LogLevelError, "software_reset failed!\r\n");
00071         return Failure;
00072     }
00073 
00074     return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
00075 }
00076 
00077 RadioStatus XBee::set_node_identifier(const char * const node_id)
00078 {
00079     if (node_id == NULL) {
00080         return Failure;
00081     }
00082 
00083     AtCmdFrame::AtCmdResp cmdresp;
00084     const size_t str_len = strlen(node_id);
00085 
00086     if(str_len > 20 || str_len < 1) {
00087         return Failure;
00088     }
00089 
00090     cmdresp = set_param("NI", (const uint8_t *)node_id, str_len);
00091     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00092         return Failure;
00093     }
00094     return Success;
00095 }
00096 
00097 RadioStatus XBee::get_node_identifier(char * const node_id)
00098 {
00099     if (node_id == NULL) {
00100         return Failure;
00101     }
00102 
00103     uint16_t max_ni_length = 20;
00104     AtCmdFrame::AtCmdResp cmdresp;
00105 
00106     cmdresp = get_param("NI", (uint8_t *)node_id, &max_ni_length);
00107     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00108         return Failure;
00109     }
00110     node_id[max_ni_length] = '\0';
00111     return Success;
00112 }
00113 
00114 RadioStatus XBee::enable_network_encryption(bool enable)
00115 {
00116     AtCmdFrame::AtCmdResp cmdresp;
00117 
00118     cmdresp = set_param("EE", enable);
00119     return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
00120 }
00121 
00122 RadioStatus XBee::set_network_encryption_key(const uint8_t * const key, const uint16_t length)
00123 {
00124     if (key == NULL || length == 0 || length > 16) {
00125         return Failure;
00126     }
00127     AtCmdFrame::AtCmdResp cmdresp;
00128 
00129     cmdresp = set_param("KY", key, length);
00130     return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
00131 }
00132 
00133 uint16_t XBee::get_hw_version() const
00134 {
00135     return _hw_version;
00136 }
00137 
00138 uint16_t XBee::get_fw_version() const
00139 {
00140     return _fw_version;
00141 }
00142 
00143 void XBee::set_tx_options(uint8_t options)
00144 {
00145     _tx_options = options;
00146 }
00147 
00148 uint8_t XBee::get_tx_options() const
00149 {
00150     return _tx_options;
00151 }
00152 
00153 RadioStatus XBee::start_node_discovery()
00154 {
00155     RadioStatus status;
00156     uint16_t nd_timeout;
00157 
00158     status = get_node_discovery_timeout(&nd_timeout);
00159     if (status != Success) {
00160         return status;
00161     }
00162 
00163     _nd_timeout = nd_timeout;
00164 
00165     _nd_timer.start();
00166 
00167     AtCmdFrame cmd_frame = AtCmdFrame("ND");
00168     send_api_frame(&cmd_frame);
00169 
00170     return Success;
00171 }
00172 
00173 bool XBee::is_node_discovery_in_progress()
00174 {
00175     const int nd_timer = _nd_timer.read_ms();
00176 
00177     if (nd_timer == 0)
00178         return false;
00179 
00180     if (nd_timer > _nd_timeout) {
00181         _nd_timer.stop();
00182         _nd_timer.reset();
00183     }
00184 
00185     return true;
00186 }
00187 
00188 void XBee::_get_remote_node_by_id(const char * const node_id, uint64_t * const addr64, uint16_t * const addr16)
00189 {
00190     *addr64 = ADDR64_UNASSIGNED;
00191     *addr16 = ADDR16_UNKNOWN;
00192     if (node_id == NULL) {
00193         return;
00194     }
00195     const size_t node_id_len = strlen(node_id);
00196     if (node_id_len == 0 || node_id_len > MAX_NI_PARAM_LEN) {
00197         return;
00198     }
00199 
00200     const uint16_t old_timeout = _timeout_ms;
00201 
00202     RadioStatus status;
00203     uint16_t nd_timeout;
00204     bool wait_for_complete_timeout;
00205 
00206     status = get_node_discovery_timeout(&nd_timeout, &wait_for_complete_timeout);
00207     if (status != Success) {
00208         return;
00209     }
00210     _timeout_ms = nd_timeout;
00211 
00212     Timer nd_timer = Timer();
00213 
00214     nd_timer.start();
00215 
00216     AtCmdFrame atnd_frame = AtCmdFrame("ND", (const uint8_t *)node_id, strlen(node_id));
00217     const uint8_t frame_id = atnd_frame.get_frame_id();
00218     _node_by_ni_frame_id = frame_id;
00219     send_api_frame(&atnd_frame);
00220 
00221     ApiFrame * const resp_frame = get_this_api_frame(frame_id, ApiFrame::AtCmdResp);
00222     _timeout_ms = old_timeout;
00223 
00224     _node_by_ni_frame_id = 0;
00225 
00226     if (resp_frame == NULL) {
00227         digi_log(LogLevelWarning, "_get_remote_node_by_id: timeout when waiting for ATND response");
00228         return;
00229     }
00230 
00231     if (resp_frame->get_data_len() < sizeof (uint16_t) + sizeof (uint64_t)) {
00232         /* In 802.15.4 this might be the OK or Timeout message with no information */
00233         digi_log(LogLevelInfo, "_get_remote_node_by_id: node not found\r\n", __FUNCTION__, node_id);
00234         _framebuf_syncr.free_frame(resp_frame);
00235         return;
00236     }
00237 
00238     const AtCmdFrame::AtCmdResp resp = (AtCmdFrame::AtCmdResp)resp_frame->get_data_at(ATCMD_RESP_STATUS_OFFSET);
00239     if (resp != AtCmdFrame::AtCmdRespOk) {
00240         digi_log(LogLevelWarning, "_get_remote_node_by_id: send_at_cmd bad response: 0x%x\r\n", resp);
00241         _framebuf_syncr.free_frame(resp_frame);
00242         return;
00243     }
00244 
00245     rmemcpy((uint8_t *)addr16, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET, sizeof *addr16);
00246     rmemcpy((uint8_t *)addr64, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET + sizeof *addr16, sizeof *addr64);
00247     _framebuf_syncr.free_frame(resp_frame);
00248 
00249     if (wait_for_complete_timeout) {
00250         while (nd_timer.read_ms() < nd_timeout) {
00251             wait_ms(10);
00252         }
00253     }
00254 
00255     return;
00256 }
00257 
00258 RadioStatus XBee::config_node_discovery(uint16_t backoff_ms, uint8_t options)
00259 {
00260     AtCmdFrame::AtCmdResp cmdresp;
00261 
00262     cmdresp = set_param("NT", (uint8_t)(backoff_ms / 100));
00263     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00264         return Failure;
00265     }
00266 
00267     cmdresp = set_param("NO", (uint8_t)options);
00268     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00269         return Failure;
00270     }
00271     cmdresp = set_param("AC");
00272     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00273         return Failure;
00274     }
00275 
00276     return Success;
00277 }
00278 
00279 RadioStatus XBee::get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options)
00280 {
00281     AtCmdFrame::AtCmdResp cmdresp;
00282     uint32_t var32;
00283 
00284     cmdresp = get_param("NT", &var32);
00285     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00286         return Failure;
00287     }
00288     *backoff_ms = var32;
00289 
00290     cmdresp = get_param("NO", &var32);
00291     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00292         return Failure;
00293     }
00294     *options = var32;
00295     return Success;
00296 }
00297 
00298 RadioStatus XBee::_get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len)
00299 {
00300     AtCmdFrame::AtCmdResp cmdresp;
00301 
00302     /* Force a sample read */
00303     cmdresp = get_param(remote, "IS", io_sample, len);
00304     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00305         digi_log(LogLevelError, "_get_iosample error %d:\r\n", cmdresp);
00306         return Failure;
00307     }
00308 
00309     return Success;
00310 }
00311 
00312 RadioStatus XBee::config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination)
00313 {
00314     uint32_t dh;
00315     uint32_t dl;
00316 
00317     if (destination.is_valid_addr64b()) {
00318         const uint64_t dest64 = destination.get_addr64();
00319         dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
00320         dl = (uint32_t)((dest64 & 0xFFFFFFFF));
00321     } else if (destination.is_valid_addr16b()) {
00322         const uint16_t destAddr16 = destination.get_addr16();
00323         dh = 0;
00324         dl = destAddr16;
00325     } else {
00326         digi_log(LogLevelError, "send_io_sample_to: Invalid destination");
00327         return Failure;
00328     }
00329 
00330     AtCmdFrame::AtCmdResp cmdresp;
00331 
00332     cmdresp = set_param(remote, "DH", dh);
00333     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00334         digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
00335         return Failure;
00336     }
00337 
00338     cmdresp = set_param(remote, "DL", dl);
00339     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00340         digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
00341         return Failure;
00342     }
00343 
00344     return Success;
00345 }
00346 
00347 RadioStatus XBee::set_io_sample_rate(const RemoteXBee& remote, const float seconds)
00348 {
00349     const float max_seconds = 65.535;
00350 
00351     if (seconds > max_seconds) {
00352         digi_log(LogLevelError, "XBee::set_io_sample_rate error seconds rate exceeds maximum %d:\r\n", max_seconds);
00353         return Failure;
00354     }
00355 
00356     AtCmdFrame::AtCmdResp cmdresp;
00357     const uint16_t milliseconds = seconds * 1000;
00358 
00359     cmdresp = set_param(remote, "IR", milliseconds);
00360     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
00361         digi_log(LogLevelError, "XBee::set_io_sample_rate error %d:\r\n", cmdresp);
00362         return Failure;
00363     }
00364 
00365     return Success;
00366 }