Digi XBeeLib fixed for NonCopyable issue

Dependents:   XBeeZB_Receive_Data

Fork of XBeeLib by Digi International Inc.

This lib fixes NonCopyable<T> issues of Digi XBeeLib. Also, lib has been reworked in order to make it RTOS-aware, overcoming several others issues due to stdio Mutex operations.

Files at this revision

API Documentation at this revision

Comitter:
hbujanda
Date:
Thu Jul 28 10:17:20 2016 +0200
Parent:
5:da2ea7a76243
Child:
7:3ac2a461ce76
Commit message:
Automatic upload

Changed in this revision

FrameHandlers/FH_AtCmdResp.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_AtCmdResp.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSampleDM.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSampleDM.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_RxPacketDM.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_RxPacketDM.h Show annotated file Show diff for this revision Revisions of this file
Frames/ApiFrame.h Show annotated file Show diff for this revision Revisions of this file
Frames/DigiMeshFrames.cpp Show annotated file Show diff for this revision Revisions of this file
Frames/DigiMeshFrames.h Show annotated file Show diff for this revision Revisions of this file
Frames/ZigbeeFrames.cpp Show annotated file Show diff for this revision Revisions of this file
IO/IOSampleDM.cpp Show annotated file Show diff for this revision Revisions of this file
IO/IOSampleDM.h Show annotated file Show diff for this revision Revisions of this file
IO/IOSampleZB.h Show annotated file Show diff for this revision Revisions of this file
RemoteXBee/RemoteXBee.cpp Show annotated file Show diff for this revision Revisions of this file
RemoteXBee/RemoteXBee.h Show annotated file Show diff for this revision Revisions of this file
XBee/RadioConfig.cpp Show annotated file Show diff for this revision Revisions of this file
XBee/XBee.cpp Show annotated file Show diff for this revision Revisions of this file
XBee/XBee.h Show annotated file Show diff for this revision Revisions of this file
XBee802/XBee802.cpp Show annotated file Show diff for this revision Revisions of this file
XBee802/XBee802.h Show annotated file Show diff for this revision Revisions of this file
XBeeDM/XBeeDM.cpp Show annotated file Show diff for this revision Revisions of this file
XBeeDM/XBeeDM.h Show annotated file Show diff for this revision Revisions of this file
XBeeLib.h Show annotated file Show diff for this revision Revisions of this file
XBeeZB/XBeeZB.cpp Show annotated file Show diff for this revision Revisions of this file
XBeeZB/XBeeZB.h Show annotated file Show diff for this revision Revisions of this file
--- a/FrameHandlers/FH_AtCmdResp.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/FrameHandlers/FH_AtCmdResp.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -159,3 +159,50 @@
 
     node_discovery_cb(remote, nodeid);
 }
+
+/** Class constructor */
+FH_NodeDiscoveryDM::FH_NodeDiscoveryDM() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscoveryDM::~FH_NodeDiscoveryDM()
+{
+}
+
+void FH_NodeDiscoveryDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscoveryDM::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscoveryDM::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data(); /* The data payload we get here is the full AT command response payload, excluding the frameid. Keep that in mind for the offsets */
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+    const char * const node_id = (const char *)&data[ATCMD_RESP_NI_OFFSET];
+    RemoteXBeeDM remote = RemoteXBeeDM(addr64);
+
+    node_discovery_cb(remote, node_id);
+}
\ No newline at end of file
--- a/FrameHandlers/FH_AtCmdResp.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/FrameHandlers/FH_AtCmdResp.h	Thu Jul 28 10:17:20 2016 +0200
@@ -82,6 +82,40 @@
  * @defgroup callback_types "Callback types declaration"
  * @{
  */
+/** Node Discovery Response callback type declaration for ZigBee
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_dm_cb_t)(const RemoteXBeeDM& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscoveryDM : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_dm_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscoveryDM();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscoveryDM();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_dm_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
 /** Node Discovery Response callback type declaration for 802.15.4
   * @param remote discovered remote node.
   * @param node_id Node Identifier (NI parameter) of remote.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_IoDataSampleDM.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,56 @@
+/**
+ * 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 "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampeDM::FH_IoDataSampeDM() : FrameHandler(ApiFrame::IoSampleRxZBDM),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampeDM::~FH_IoDataSampeDM()
+{
+}
+
+void FH_IoDataSampeDM::register_io_data_cb(io_data_cb_dm_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampeDM::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+/* DM RX packet offsets */
+#define DM_IO_SAMPLE_DATA_OFFSET            11
+
+void FH_IoDataSampeDM::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const RemoteXBeeDM sender = RemoteXBeeDM(sender64);
+    const IOSampleDM ioSample = IOSampleDM(&datap[DM_IO_SAMPLE_DATA_OFFSET], frame->get_data_len() - DM_IO_SAMPLE_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_IoDataSampleDM.h	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,58 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_DM_H_)
+#define __FH_IO_DATA_SAMPLE_DM_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSampleDM;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (ZigBee modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSampleDM that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_dm_t)(const RemoteXBeeDM& remote, const IOSampleDM& sample_data);
+/**
+ * @}
+ */
+
+class FH_IoDataSampeDM : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampeDM();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampeDM();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_dm_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_dm_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_DM_H_ */
--- a/FrameHandlers/FH_IoDataSampleZB.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/FrameHandlers/FH_IoDataSampleZB.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -15,7 +15,7 @@
 using namespace XBeeLib;
 
 /** Class constructor */
-FH_IoDataSampeZB::FH_IoDataSampeZB() : FrameHandler(ApiFrame::IoSampleRxZB),
+FH_IoDataSampeZB::FH_IoDataSampeZB() : FrameHandler(ApiFrame::IoSampleRxZBDM),
     io_data_cb(NULL)
 {
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_RxPacketDM.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,59 @@
+/**
+ * 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 "FH_RxPacketDM.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacketDM::FH_RxPacketDM() : FrameHandler(ApiFrame::RxPacketAO0), receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacketDM::~FH_RxPacketDM()
+{
+}
+
+void FH_RxPacketDM::register_receive_cb(receive_dm_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacketDM::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* DM RX packet offsets */
+#define DM_RX_OPTIONS_OFFSET        10
+#define DM_RX_DATA_OFFSET           11
+#define DM_RX_OVERHEAD              (8+2+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacketDM::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint8_t rx_options = datap[DM_RX_OPTIONS_OFFSET];
+    const RemoteXBeeDM sender = RemoteXBeeDM(sender64);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[DM_RX_DATA_OFFSET], frame->get_data_len() - DM_RX_OVERHEAD);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_RxPacketDM.h	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,61 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_DM_H_)
+#define __FH_RX_PACKET_DM_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_dm_cb_t)(const RemoteXBeeDM& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacketDM : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_dm_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacketDM();
+
+        /** Class destructor */
+        virtual ~FH_RxPacketDM();
+
+        /** Method called by the stack to process the modem status frame data
+
+            \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        void register_receive_cb(receive_dm_cb_t function);
+
+        void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_DM_H_ */
--- a/Frames/ApiFrame.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/Frames/ApiFrame.h	Thu Jul 28 10:17:20 2016 +0200
@@ -29,8 +29,8 @@
             TxReq16Bit      = 0x01,     /**< TxReq16Bit: Only for 802.15.4 modules */
             AtCmd           = 0x08,     /**< AtCmd */
             AtCmdQueuePV    = 0x09,     /**< AtCmdQueuePV */
-            TxReqZB         = 0x10,     /**< TxReqZB: Only for ZigBee modules */
-            ExpAddrCmd      = 0x11,     /**< ExpAddrCmd: Only for ZigBee modules */
+            TxReqZBDM       = 0x10,     /**< TxReqZBDM: Only for ZigBee and DigiMesh modules */
+            ExpAddrCmd      = 0x11,     /**< ExpAddrCmd: Only for ZigBee modules and DigiMesh */
             RemoteCmdReq    = 0x17,     /**< RemoteCmdReq */
             CreateSrcRoute  = 0x21,     /**< CreateSrcRoute */
             RxPacket64Bit   = 0x80,     /**< RxPacket64Bit: Only for 802.15.4 modules */
@@ -40,12 +40,14 @@
             AtCmdResp       = 0x88,     /**< AtCmdResp */
             TxStatus        = 0x89,     /**< TxStatus */
             AtModemStatus   = 0x8A,     /**< AtModemStatus */
-            TxStatusZB      = 0x8B,     /**< TxStatusZB: Only for ZigBee modules */
-            RxPacketAO0     = 0x90,     /**< RxPacketAO0: Only for ZigBee modules */
-            RxPacketAO1     = 0x91,     /**< RxPacketAO1: Only for ZigBee modules */
-            IoSampleRxZB    = 0x92,     /**< IoSampleRxZB: Only for ZigBee modules */
+            TxStatusZBDM    = 0x8B,     /**< TxStatusZBDM: Only for ZigBee and DigiMesh modules */
+            RouteInfo       = 0x8D,     /**< RouteInfo: Only for DigiMesh modules */
+            AggregateAddr   = 0x8E,     /**< AggregateAddr: Only for DigiMesh modules */
+            RxPacketAO0     = 0x90,     /**< RxPacketAO0: Only for ZigBee and DigiMesh modules */
+            RxPacketAO1     = 0x91,     /**< RxPacketAO1: Only for ZigBee and DigiMesh modules */
+            IoSampleRxZBDM  = 0x92,     /**< IoSampleRxZBDM: Only for ZigBee and DigiMesh modules */
             SensorRxIndAO0  = 0x94,     /**< SensorRxIndAO0: Only for ZigBee modules */
-            NodeIdentIndAO0 = 0x95,     /**< NodeIdentIndAO0: Only for ZigBee modules */
+            NodeIdentIndAO0 = 0x95,     /**< NodeIdentIndAO0: Only for ZigBee and DigiMesh modules */
             RemoteCmdResp   = 0x97,     /**< RemoteCmdResp */
             OtaFwUpStatus   = 0xA0,     /**< OtaFwUpStatus */
             RouteRecInd     = 0xA1,     /**< RouteRecInd */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/DigiMeshFrames.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,88 @@
+/**
+ * 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 "DigiMeshFrames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define BROADCAST_RADIOUS_LEN     1
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + BROADCAST_RADIOUS_LEN + \
+                                   OPTIONS_LEN)
+#define SOURCE_EP_LEN             1
+#define DEST_EP_LEN               1
+#define CLUSTER_ID_LEN            2
+#define PROFILE_ID_LEN            2
+
+#define EXP_ADDR_OVERHEAD         (TX_REQUEST_OVERHEAD + SOURCE_EP_LEN + \
+                                   DEST_EP_LEN + CLUSTER_ID_LEN + \
+                                   PROFILE_ID_LEN)
+
+/** Class constructor */
+TxFrameDM::TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad, uint8_t tx_opt,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = broadcast_rad;
+    frame_data[12] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[13], data, len);
+    }
+
+    set_api_frame(TxReqZBDM, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrameDM::TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[EXP_ADDR_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the end point source and destination addresses, the cluster and profile IDs,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = source_ep;
+    frame_data[12] = dest_ep;
+    frame_data[13] = (uint8_t)(cluster_id >> 8);
+    frame_data[14] = (uint8_t)cluster_id;
+    frame_data[15] = (uint8_t)(profile_id >> 8);
+    frame_data[16] = (uint8_t)profile_id;
+    frame_data[17] = broadcast_rad;
+    frame_data[18] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[19], data, len);
+    }
+
+    set_api_frame(ExpAddrCmd, frame_data, EXP_ADDR_OVERHEAD + len);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/DigiMeshFrames.h	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,31 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__DIGIMESH_FRAME_H_)
+#define __DIGIMESH_FRAME_H_
+
+#include "ApiFrame.h"
+
+class TxFrameDM : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad,
+                    uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+
+        /** Class constructor */
+        TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+};
+
+#endif /* __DIGIMESH_FRAME_H_ */
--- a/Frames/ZigbeeFrames.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/Frames/ZigbeeFrames.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -51,7 +51,7 @@
         memcpy(&frame_data[13], data, len);
     }
 
-    set_api_frame(TxReqZB, frame_data, TX_REQUEST_OVERHEAD + len);
+    set_api_frame(TxReqZBDM, frame_data, TX_REQUEST_OVERHEAD + len);
 }
 
 /** Class constructor */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IOSampleDM.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,86 @@
+/**
+ * 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 "XBeeLib.h"
+#include "IO/IOSampleDM.h"
+
+#define IO_SAMPLE_DM_MIN_SIZE              (2 + 1 + 2)
+
+using namespace XBeeLib;
+
+IOSampleDM::IOSampleDM(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _digital_mask = 0;
+        _analog_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_DM_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _digital_mask = UINT16(raw_data[1], raw_data[2]);
+    _analog_mask = raw_data[3];
+    _sampled_data_size = size - 4;
+    memcpy(&_sampled_data[0], &raw_data[4], _sampled_data_size);
+}
+
+IOSampleDM::~IOSampleDM()
+{
+
+}
+
+RadioStatus IOSampleDM::get_dio(XBeeDM::IoLine line, DioVal* const dio_value) const
+{
+    const uint16_t mask = 1 << line;
+    if (mask & _digital_mask) {
+        const uint16_t digital_channels = get_digital_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSampleDM::get_adc(XBeeDM::IoLine line, uint16_t* const val) const
+{
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & _analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = _digital_mask == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (_analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline uint16_t IOSampleDM::get_digital_channels(void) const
+{
+    if (_digital_mask == 0) {
+        return 0;
+    }
+    return UINT16(_sampled_data[0], _sampled_data[1]);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IOSampleDM.h	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,71 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLEDM_H_
+#define _IO_IOSAMPLEDM_H_
+
+#define MAX_IO_SAMPLE_DM_LEN   (2 + 2 * 5)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in ZigBee modules */
+class IOSampleDM {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZBDM (0x92) frames
+         *  @param size size (in bytes) of raw_data.
+         */
+        IOSampleDM(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSampleDM();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBeeDM::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBeeDM::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSampleDM object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _digital_mask != 0 || _analog_mask != 0;
+        }
+
+    protected:
+        uint16_t _digital_mask;
+        uint8_t _analog_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_DM_LEN];
+        uint8_t _sampled_data_size;
+
+        inline uint16_t get_digital_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLEDM_H_ */
--- a/IO/IOSampleZB.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/IO/IOSampleZB.h	Thu Jul 28 10:17:20 2016 +0200
@@ -21,7 +21,7 @@
 class IOSampleZB {
     public:
         /** Class constructor
-         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZB (0x92) frames
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZBDM (0x92) frames
          *  @param size size (in bytes) of raw_data.
          */
         IOSampleZB(const uint8_t* const raw_data = NULL, size_t size = 0);
--- a/RemoteXBee/RemoteXBee.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/RemoteXBee/RemoteXBee.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -77,3 +77,15 @@
 RemoteXBeeZB::~RemoteXBeeZB()
 {
 }
+
+RemoteXBeeDM::RemoteXBeeDM() : RemoteXBee()
+{
+}
+
+RemoteXBeeDM::RemoteXBeeDM(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBeeDM::~RemoteXBeeDM()
+{
+}
--- a/RemoteXBee/RemoteXBee.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/RemoteXBee/RemoteXBee.h	Thu Jul 28 10:17:20 2016 +0200
@@ -154,6 +154,29 @@
         }
 };
 
+/** Class for DigiMesh Remote XBee modules */
+class RemoteXBeeDM : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a DigiMesh remote device (connected wirelessly). No address set.
+         */
+        RemoteXBeeDM();
+
+       /** Class constructor for a DigiMesh remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBeeDM(uint64_t remote64);
+
+        /** Class destructor */
+        ~RemoteXBeeDM();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b();
+        }
+};
+
 }   /* namespace XBeeLib */
 
 #endif /* defined(__XBEE_REMOTE_H_) */
--- a/XBee/RadioConfig.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBee/RadioConfig.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -58,22 +58,6 @@
     return Success;
 }
 
-RadioStatus XBee::get_network_address(uint16_t * const  addr16)
-{
-    if (addr16 == NULL) {
-        return Failure;
-    }
-    AtCmdFrame::AtCmdResp cmdresp;
-
-    uint32_t var32;
-    cmdresp = get_param("MY", &var32);
-    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        return Failure;
-    }
-    *addr16 = var32;
-    return Success;
-}
-
 RadioStatus XBee::software_reset(void)
 {
     volatile uint16_t * const rst_cnt_p = &_wd_reset_cnt;
@@ -168,17 +152,15 @@
 
 RadioStatus XBee::start_node_discovery()
 {
-    AtCmdFrame::AtCmdResp cmdresp;
-    uint32_t nd_timeout_cfg;
+    RadioStatus status;
+    uint16_t nd_timeout;
 
-    cmdresp = get_param("NT", &nd_timeout_cfg);
-    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        return Failure;
+    status = get_node_discovery_timeout(&nd_timeout);
+    if (status != Success) {
+	    return status;
     }
 
-    const unsigned int guard_time_ms = 1000;
-    const uint32_t nd_timeout_cfg_ms = nd_timeout_cfg * 100;
-    _nd_timeout = nd_timeout_cfg_ms + guard_time_ms;
+    _nd_timeout = nd_timeout;
 
     _nd_timer.start();
 
@@ -217,15 +199,16 @@
 
     const uint16_t old_timeout = _timeout_ms;
 
-    uint32_t nd_timeout_100msec;
-    const AtCmdFrame::AtCmdResp nt_resp = get_param("NT", &nd_timeout_100msec);
-    if (nt_resp != AtCmdFrame::AtCmdRespOk) {
-        _timeout_ms = 10000;
-    } else {
-        _timeout_ms = (uint16_t)nd_timeout_100msec * 100 + 1000;
+    RadioStatus status;
+    uint16_t nd_timeout;
+	bool wait_for_complete_timeout;
+
+    status = get_node_discovery_timeout(&nd_timeout, &wait_for_complete_timeout);
+    if (status != Success) {
+	    return;
     }
+	_timeout_ms = nd_timeout;
 
-    const int nd_timeout = _timeout_ms;
     Timer nd_timer = Timer();
 
     nd_timer.start();
@@ -263,18 +246,20 @@
     rmemcpy((uint8_t *)addr64, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET + sizeof *addr16, sizeof *addr64);
     _framebuf_syncr.free_frame(resp_frame);
 
-    while (nd_timer.read_ms() < nd_timeout) {
-        wait_ms(10);
+    if (wait_for_complete_timeout) {
+        while (nd_timer.read_ms() < nd_timeout) {
+            wait_ms(10);
+        }
     }
 
     return;
 }
 
-RadioStatus XBee::config_node_discovery(uint16_t timeout_ms, uint8_t options)
+RadioStatus XBee::config_node_discovery(uint16_t backoff_ms, uint8_t options)
 {
     AtCmdFrame::AtCmdResp cmdresp;
 
-    cmdresp = set_param("NT", (uint8_t)(timeout_ms / 100));
+    cmdresp = set_param("NT", (uint8_t)(backoff_ms / 100));
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
         return Failure;
     }
@@ -291,7 +276,7 @@
     return Success;
 }
 
-RadioStatus XBee::get_config_node_discovery(uint16_t * const timeout_ms, uint8_t * const options)
+RadioStatus XBee::get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options)
 {
     AtCmdFrame::AtCmdResp cmdresp;
     uint32_t var32;
@@ -300,7 +285,7 @@
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
         return Failure;
     }
-    *timeout_ms = var32;
+    *backoff_ms = var32;
 
     cmdresp = get_param("NO", &var32);
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
--- a/XBee/XBee.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBee/XBee.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -295,38 +295,40 @@
                         const ApiFrame::ApiFrameType frame_type = (ApiFrame::ApiFrameType)data;
                         switch (frame_type)
                         {
-                            case ApiFrame::AtCmdResp:       /**< AtCmdResp */
-                            case ApiFrame::RemoteCmdResp:   /**< RemoteCmdResp */
-                            case ApiFrame::TxStatusZB:      /**< TxStatusZB: Only for ZigBee modules */
-                            case ApiFrame::TxStatus:        /**< TxStatus */
+                            case ApiFrame::AtCmdResp:
+                            case ApiFrame::RemoteCmdResp:
+                            case ApiFrame::TxStatusZBDM:
+                            case ApiFrame::TxStatus:
                                 framebuf = &_framebuf_syncr;
                                 break;
 
-                            case ApiFrame::RxPacket64Bit:   /**< RxPacket64Bit: Only for 802.15.4 modules */
-                            case ApiFrame::RxPacket16Bit:   /**< RxPacket16Bit: Only for 802.15.4 modules */
-                            case ApiFrame::Io64Bit:         /**< Io64Bit: Only for 802.15.4 modules */
-                            case ApiFrame::Io16Bit:         /**< Io16Bit */
-                            case ApiFrame::AtModemStatus:   /**< AtModemStatus */
-                            case ApiFrame::RxPacketAO0:     /**< RxPacketAO0: Only for ZigBee modules */
-                            case ApiFrame::IoSampleRxZB:    /**< IoSampleRxZB: Only for ZigBee modules */
+                            case ApiFrame::RxPacket64Bit:
+                            case ApiFrame::RxPacket16Bit:
+                            case ApiFrame::Io64Bit:
+                            case ApiFrame::Io16Bit:
+                            case ApiFrame::AtModemStatus:
+                            case ApiFrame::RxPacketAO0:
+                            case ApiFrame::IoSampleRxZBDM:
                                 framebuf = &_framebuf_app;
                                 break;
 
-                            case ApiFrame::RxPacketAO1:     /**< RxPacketAO1: Only for ZigBee modules */
-                            case ApiFrame::SensorRxIndAO0:  /**< SensorRxIndAO0: Only for ZigBee modules */
-                            case ApiFrame::NodeIdentIndAO0: /**< NodeIdentIndAO0: Only for ZigBee modules */
-                            case ApiFrame::OtaFwUpStatus:   /**< OtaFwUpStatus */
-                            case ApiFrame::RouteRecInd:     /**< RouteRecInd */
-                            case ApiFrame::Many2OneRRInd:   /**< Many2OneRRInd */
-                            case ApiFrame::TxReq64Bit:      /**< TxReq64Bit: Only for 802.15.4 modules */
-                            case ApiFrame::TxReq16Bit:      /**< TxReq16Bit: Only for 802.15.4 modules */
-                            case ApiFrame::AtCmd:           /**< AtCmd */
-                            case ApiFrame::AtCmdQueuePV:    /**< AtCmdQueuePV */
-                            case ApiFrame::TxReqZB:         /**< TxReqZB: Only for ZigBee modules */
-                            case ApiFrame::ExpAddrCmd:      /**< ExpAddrCmd: Only for ZigBee modules */
-                            case ApiFrame::RemoteCmdReq:    /**< RemoteCmdReq */
-                            case ApiFrame::CreateSrcRoute:  /**< CreateSrcRoute */
-                            case ApiFrame::Invalid:         /**< Invalid */
+                            case ApiFrame::RxPacketAO1:
+                            case ApiFrame::SensorRxIndAO0:
+                            case ApiFrame::NodeIdentIndAO0:
+                            case ApiFrame::OtaFwUpStatus:
+                            case ApiFrame::RouteRecInd:
+                            case ApiFrame::Many2OneRRInd:
+                            case ApiFrame::TxReq64Bit:
+                            case ApiFrame::TxReq16Bit:
+                            case ApiFrame::AtCmd:
+                            case ApiFrame::AtCmdQueuePV:
+                            case ApiFrame::TxReqZBDM:
+                            case ApiFrame::ExpAddrCmd:
+                            case ApiFrame::RemoteCmdReq:
+                            case ApiFrame::CreateSrcRoute:
+                            case ApiFrame::Invalid:
+                            case ApiFrame::RouteInfo:
+                            case ApiFrame::AggregateAddr:
                                 framebuf = NULL;
                                 break;
                         }
@@ -365,13 +367,13 @@
                     const ApiFrame::ApiFrameType frame_type = (ApiFrame::ApiFrameType)frame_cached[0];
                     switch (frame_type)
                     {
-                        case ApiFrame::RemoteCmdResp:   /**< RemoteCmdResp */
-                        case ApiFrame::TxStatusZB:      /**< TxStatusZB: Only for ZigBee modules */
-                        case ApiFrame::TxStatus:        /**< TxStatus */
+                        case ApiFrame::RemoteCmdResp:
+                        case ApiFrame::TxStatusZBDM:
+                        case ApiFrame::TxStatus:
                             framebuf = &_framebuf_syncr;
                             break;
 
-                        case ApiFrame::AtCmdResp:       /**< AtCmdResp */
+                        case ApiFrame::AtCmdResp:
                             if ((frame_cached[1] != _node_by_ni_frame_id ) && (frame_cached[2] == 'N') && (data == 'D'))
                             {
                                 framebuf = &_framebuf_app;
@@ -380,31 +382,33 @@
                             }
                             break;
 
-                        case ApiFrame::RxPacket64Bit:   /**< RxPacket64Bit: Only for 802.15.4 modules */
-                        case ApiFrame::RxPacket16Bit:   /**< RxPacket16Bit: Only for 802.15.4 modules */
-                        case ApiFrame::Io64Bit:         /**< Io64Bit: Only for 802.15.4 modules */
-                        case ApiFrame::Io16Bit:         /**< Io16Bit */
-                        case ApiFrame::AtModemStatus:   /**< AtModemStatus */
-                        case ApiFrame::RxPacketAO0:     /**< RxPacketAO0: Only for ZigBee modules */
-                        case ApiFrame::IoSampleRxZB:    /**< IoSampleRxZB: Only for ZigBee modules */
+                        case ApiFrame::RxPacket64Bit:
+                        case ApiFrame::RxPacket16Bit:
+                        case ApiFrame::Io64Bit:
+                        case ApiFrame::Io16Bit:
+                        case ApiFrame::AtModemStatus:
+                        case ApiFrame::RxPacketAO0:
+                        case ApiFrame::IoSampleRxZBDM:
                             framebuf = &_framebuf_app;
                             break;
 
-                        case ApiFrame::RxPacketAO1:     /**< RxPacketAO1: Only for ZigBee modules */
-                        case ApiFrame::SensorRxIndAO0:  /**< SensorRxIndAO0: Only for ZigBee modules */
-                        case ApiFrame::NodeIdentIndAO0: /**< NodeIdentIndAO0: Only for ZigBee modules */
-                        case ApiFrame::OtaFwUpStatus:   /**< OtaFwUpStatus */
-                        case ApiFrame::RouteRecInd:     /**< RouteRecInd */
-                        case ApiFrame::Many2OneRRInd:   /**< Many2OneRRInd */
-                        case ApiFrame::TxReq64Bit:      /**< TxReq64Bit: Only for 802.15.4 modules */
-                        case ApiFrame::TxReq16Bit:      /**< TxReq16Bit: Only for 802.15.4 modules */
-                        case ApiFrame::AtCmd:           /**< AtCmd */
-                        case ApiFrame::AtCmdQueuePV:    /**< AtCmdQueuePV */
-                        case ApiFrame::TxReqZB:         /**< TxReqZB: Only for ZigBee modules */
-                        case ApiFrame::ExpAddrCmd:      /**< ExpAddrCmd: Only for ZigBee modules */
-                        case ApiFrame::RemoteCmdReq:    /**< RemoteCmdReq */
-                        case ApiFrame::CreateSrcRoute:  /**< CreateSrcRoute */
-                        case ApiFrame::Invalid:         /**< Invalid */
+                        case ApiFrame::RxPacketAO1:
+                        case ApiFrame::SensorRxIndAO0:
+                        case ApiFrame::NodeIdentIndAO0:
+                        case ApiFrame::OtaFwUpStatus:
+                        case ApiFrame::RouteRecInd:
+                        case ApiFrame::Many2OneRRInd:
+                        case ApiFrame::TxReq64Bit:
+                        case ApiFrame::TxReq16Bit:
+                        case ApiFrame::AtCmd:
+                        case ApiFrame::AtCmdQueuePV:
+                        case ApiFrame::TxReqZBDM:
+                        case ApiFrame::ExpAddrCmd:
+                        case ApiFrame::RemoteCmdReq:
+                        case ApiFrame::CreateSrcRoute:
+                        case ApiFrame::Invalid:
+                        case ApiFrame::RouteInfo:
+                        case ApiFrame::AggregateAddr:
                             framebuf = NULL;
                             break;
                     }
@@ -760,6 +764,9 @@
     } else if (hw_version_msb == XB900HP_NZ) {
         return DigiPoint;
     } else if (hw_version_msb == XBP24C_TH_DIP || hw_version_msb == XB24C_TH_DIP || hw_version_msb == XBP24C_S2C_SMT) {
+        if (fw_4_bytes_len && fw_nibble_3 == 9) {
+            return DigiMesh;
+        }
         if (fw_4_bytes_len && fw_nibble_3 == 5) {
             return SmartEnergy;
         }
@@ -787,12 +794,12 @@
 
     /* Wait for the transmit status response packet */
     resp_frame = get_this_api_frame(frame->get_frame_id(),
-                    ApiFrame::TxStatusZB, ApiFrame::TxStatus);
+                    ApiFrame::TxStatusZBDM, ApiFrame::TxStatus);
     if (resp_frame == NULL) {
         return resp;
     }
 
-    uint8_t index = resp_frame->get_frame_type() == ApiFrame::TxStatusZB ?
+    uint8_t index = resp_frame->get_frame_type() == ApiFrame::TxStatusZBDM ?
             TX_STATUS_OFFSET_ZB : TX_STATUS_OFFSET_802;
 
     resp = (TxStatus)resp_frame->get_data_at(index);
--- a/XBee/XBee.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBee/XBee.h	Thu Jul 28 10:17:20 2016 +0200
@@ -165,15 +165,6 @@
          */
         uint64_t get_addr64() const;
 
-        /** get_network_address - gets the 16bit network address of the device
-         *
-         *  @param addr pointer where the device 16bit network address will be stored
-         *  @returns
-         *     Success if the operation was successful,
-         *     Failure otherwise
-         */
-        RadioStatus get_network_address(uint16_t * const addr);
-
         /** hardware_reset - performs a hardware reset. The reset GPIO must have
          * been provided to the constructor
          *
@@ -338,7 +329,7 @@
 
         /** config_node_discovery - configures the node discovery operation
          *
-         *  @param timeout_ms max allowed time for devices in the network to answer
+         *  @param backoff_ms max allowed time for devices in the network to answer
          *                    to the Node Discovery request
          *  @param  options node discovery options (flags)
          *              XBEE802_ND_OPTION_SELF_RESPONSE - to allow the module self responding (802.15.4 only)
@@ -348,18 +339,18 @@
          *     Success if the operation was successful,
          *     Failure otherwise
          */
-         RadioStatus config_node_discovery(uint16_t timeout_ms, uint8_t options = 0);
+         RadioStatus config_node_discovery(uint16_t backoff_ms, uint8_t options = 0);
 
          /** get_config_node_discovery - reads the configuration of the node discovery
           * settings
           *
-          *  @param timeout_ms pointer where the node discovery time out value will be stored
+          *  @param backoff_ms pointer where the configured node discovery back-off time value will be stored
           *  @param  options pointer whre the node discovery options (flags) will be saved
           *  @returns
           *     Success if the operation was successful,
           *     Failure otherwise
           */
-         RadioStatus get_config_node_discovery(uint16_t * const timeout_ms, uint8_t * const options);
+         RadioStatus get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options);
 
         /** set_timeout - sets the timeout in ms, used by sync methods
          *
@@ -638,6 +629,19 @@
          */
         int get_AI(void);
 
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms) = 0;
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout) = 0;
+
         /** serial hardware flow control selected by the user (RTSCTS, RTS,CTS) */
         SerialBase::Flow _serial_flow_type;
 
--- a/XBee802/XBee802.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBee802/XBee802.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -58,16 +58,8 @@
 {
     AtCmdFrame::AtCmdResp cmdresp;
 
-    if (is_PRO()) {
-        if (channel < 0x0C || channel > 0x17) {
-            return Failure;
-        }
-    } else {
-        if (channel < 0x0B || channel > 0x1A) {
-            return Failure;
-        }
-    }
-
+    /* Pro and Non-Pro modules have different channels available. The at 
+       command will return an error if the selected channel is not available */
     cmdresp = set_param("CH", channel);
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
         return Failure;
@@ -118,6 +110,22 @@
     return Success;
 }
 
+RadioStatus XBee802::get_network_address(uint16_t * const  addr16)
+{
+    if (addr16 == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("MY", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *addr16 = var32;
+    return Success;
+}
+
 RadioStatus XBee802::set_network_address(uint16_t  addr16)
 {
     AtCmdFrame::AtCmdResp cmdresp;
@@ -129,6 +137,34 @@
     return Success;
 }
 
+RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    /* No N? command available for this protocol. Add a fix 1s guard time */
+    *timeout_ms += 1000;
+
+    return Success;
+}
+
+RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    /* This protocol requires to wait for the complete timeout before attempting
+       to execute other commands */
+    *wait_for_complete_timeout = true;
+
+    return status;
+}
+
 void XBee802::radio_status_update(AtCmdFrame::ModemStatus modem_status)
 {
     /* Update the radio status variables */
--- a/XBee802/XBee802.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBee802/XBee802.h	Thu Jul 28 10:17:20 2016 +0200
@@ -123,6 +123,15 @@
          */
         RadioStatus get_channel(uint8_t * const channel);
 
+        /** get_network_address - gets the 16bit network address of the device
+         *
+         *  @param addr pointer where the device 16bit network address will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_network_address(uint16_t * const addr);
+
         /** set_network_address - sets the 16 bit network address of the device
          *
          *  @param addr the device 16bit network address (0x0 - 0xFFFF)
@@ -346,10 +355,6 @@
 #endif
 
     protected:
-        inline bool is_PRO()
-        {
-            return (_hw_version & 0xFF00U) == 0x1800U;
-        }
 
         /** Frame handler used for the node discovery. Registered when a callback function
          * is registered */
@@ -378,6 +383,19 @@
         /* Allow using XBee::send_data() methods from this class */
         using XBee::send_data;
 
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms);
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout);
+
     private:
 
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeDM/XBeeDM.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,550 @@
+/**
+ * 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 "XBeeDM.h"
+#include "IO/IOSampleDM.h"
+#include "Frames/DigiMeshFrames.h"
+
+using namespace XBeeLib;
+
+#define BROADCAST_RADIUS_USE_NH 0x00
+
+/* Class constructor */
+XBeeDM::XBeeDM(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+         XBee(tx, rx, reset, rts, cts, baud), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL)
+{
+}
+
+RadioStatus XBeeDM::init()
+{
+    RadioStatus retval = XBee::init();
+
+    const RadioProtocol radioProtocol = get_radio_protocol();
+    if (radioProtocol != DigiMesh) {
+        digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", DigiMesh, radioProtocol);
+        retval = Failure;
+    }
+    assert(radioProtocol == DigiMesh);
+
+    return retval;
+}
+
+/* Class destructor */
+XBeeDM::~XBeeDM()
+{
+    unregister_node_discovery_cb();
+    unregister_receive_cb();
+    unregister_io_sample_cb();
+}
+
+RadioStatus XBeeDM::set_channel(uint8_t  channel)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    /* Pro and Non-Pro modules have different channels available. The at 
+       command will return an error if the selected channel is not available */
+    cmdresp = set_param("CH", channel);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeDM::get_channel(uint8_t * const  channel)
+{
+    if (channel == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("CH", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *channel = var32;
+    return Success;
+}
+
+RadioStatus XBeeDM::set_network_id(uint16_t network_id)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("ID", network_id);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeDM::get_network_id(uint16_t * const network_id)
+{
+    if (network_id == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("ID", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *network_id = var32;
+    return Success;
+}
+
+RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("N?", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    return Success;
+}
+
+RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    *wait_for_complete_timeout = false;
+
+    return status;
+}
+
+RadioStatus XBeeDM::set_network_security_key(const uint8_t * const key, const uint16_t length)
+{
+    if (key == NULL || length == 0 || length > 16) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("NK", key, length);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+RadioStatus XBeeDM::set_encryption_options(const uint8_t options)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("EO", options);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+void XBeeDM::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    /* Update the radio status variables */
+    if (modem_status == AtCmdFrame::HwReset) {
+        _hw_reset_cnt++;
+    } else if (modem_status == AtCmdFrame::WdReset) {
+        _wd_reset_cnt++;
+    }
+
+    _modem_status = modem_status;
+
+    digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
+}
+
+TxStatus XBeeDM::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (!remote.is_valid_addr64b()) {
+        return TxStatusInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    TxFrameDM frame = TxFrameDM(remote64, remote16, BROADCAST_RADIUS_USE_NH,
+                                _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+TxStatus XBeeDM::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, bool syncr)
+{
+    if (!remote.is_valid_addr64b()) {
+        return TxStatusInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    TxFrameDM frame = TxFrameDM(remote64, remote16, source_ep, dest_ep,
+                                cluster_id, profile_id, BROADCAST_RADIUS_USE_NH,
+                                _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+TxStatus XBeeDM::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr)
+{
+    const uint64_t remaddr = ADDR64_COORDINATOR;
+
+    TxFrameDM frame = TxFrameDM(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+RemoteXBeeDM XBeeDM::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 RemoteXBeeDM(addr64);
+}
+
+XBeeDM::AssocStatus XBeeDM::get_assoc_status(void)
+{
+    return (AssocStatus)get_AI();
+}
+
+void XBeeDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
+{
+    if (_nd_handler == NULL) {
+        _nd_handler = new FH_NodeDiscoveryDM();
+        register_frame_handler(_nd_handler);
+    }
+    _nd_handler->register_node_discovery_cb(function);
+}
+
+void XBeeDM::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 XBeeDM::register_receive_cb(receive_dm_cb_t function)
+{
+    if (_rx_pkt_handler == NULL) {
+        _rx_pkt_handler = new FH_RxPacketDM();
+        register_frame_handler(_rx_pkt_handler);
+    }
+    _rx_pkt_handler->register_receive_cb(function);
+}
+
+void XBeeDM::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 XBeeDM::register_io_sample_cb(io_data_cb_dm_t function)
+{
+    if (_io_data_handler == NULL) {
+        _io_data_handler = new FH_IoDataSampeDM();
+        register_frame_handler(_io_data_handler);
+    }
+    _io_data_handler->register_io_data_cb(function);
+}
+
+void XBeeDM::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 XBeeDM::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 XBeeDM::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 XBeeDM::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 XBeeDM::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(XBeeDM::IoLine line, char * const iocmd)
+{
+    if (line >= XBeeDM::DIO10_PWM0) {
+        iocmd[0] = 'P';
+        iocmd[1] = '0' + line - XBeeDM::DIO10_PWM0;
+    } else {
+        iocmd[0] = 'D';
+        iocmd[1] = '0' + line;
+    }
+    iocmd[2] = '\0';
+}
+
+RadioStatus XBeeDM::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 XBeeDM::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 XBeeDM::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
+{
+    return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh);
+}
+
+RadioStatus XBeeDM::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
+{
+    return get_iosample(remote).get_dio(line, val);
+}
+
+RadioStatus XBeeDM::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
+{
+    return get_iosample(remote).get_adc(line, val);
+}
+
+RadioStatus XBeeDM::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3] = { 'M', '0', '\0' };
+
+    if (line != DIO10_PWM0 && line != DIO11_PWM1) {
+        return Failure;
+    }
+    if (line == DIO11_PWM1) {
+        iocmd[1] = '1';
+    }
+
+    uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100);
+
+    cmdresp = set_param(remote, iocmd, pwm_val);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+IOSampleDM XBeeDM::get_iosample(const RemoteXBee& remote)
+{
+    uint8_t io_sample[MAX_IO_SAMPLE_DM_LEN];
+    uint16_t len = sizeof io_sample;
+
+    RadioStatus resp = _get_iosample(remote, io_sample, &len);
+    if (resp != Success) {
+        digi_log(LogLevelError, "XBeeDM::get_iosample failed to get an IOSample\r\n");
+        len = 0;
+    }
+
+    return IOSampleDM(io_sample, len);
+}
+
+static uint16_t get_dio_pr_mask(XBeeDM::IoLine line)
+{
+    switch (line) {
+        case XBeeDM::DIO4:
+            return (1 << 0);
+        case XBeeDM::DIO3_AD3:
+            return (1 << 1);
+        case XBeeDM::DIO2_AD2:
+            return (1 << 2);
+        case XBeeDM::DIO1_AD1:
+            return (1 << 3);
+        case XBeeDM::DIO0_AD0:
+            return (1 << 4);
+        case XBeeDM::DIO6:
+            return (1 << 5);
+        case XBeeDM::DIO8:
+            return (1 << 6);
+        case XBeeDM::DIO5:
+            return (1 << 8);
+        case XBeeDM::DIO9:
+            return (1 << 9);
+        case XBeeDM::DIO12:
+            return (1 << 10);
+        case XBeeDM::DIO10_PWM0:
+            return (1 << 11);
+        case XBeeDM::DIO11_PWM1:
+            return (1 << 12);
+        case XBeeDM::DIO7:
+            return (1 << 13);
+        default:
+            return 0;
+    }
+}
+
+RadioStatus XBeeDM::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, "XBeeDM::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(XBeeDM::IoLine line)
+{
+    if (line <= XBeeDM::DIO12) {
+        return (1 << line);
+    }
+    return 0;
+}
+
+RadioStatus XBeeDM::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    if (line > DIO12) {
+        digi_log(LogLevelError, "XBeeDM::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, "XBeeDM::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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeDM/XBeeDM.h	Thu Jul 28 10:17:20 2016 +0200
@@ -0,0 +1,414 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_DM_H_)
+#define __XBEE_DM_H_
+
+#include "XBee/XBee.h"
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "FrameHandlers/FH_RxPacketDM.h"
+#include "FrameHandlers/FH_IoDataSampleDM.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/** Class for XBee ZigBee modules, derived from XBee */
+class XBeeDM : public XBee
+{
+    public:
+
+        /**
+         * IoLine for XBeeDM Modules
+         */
+        enum IoLine {
+            DIO0_AD0   = 0,  /**< DIO0_AD0 pin */
+            DIO1_AD1   = 1,  /**< DIO1_AD1 pin */
+            DIO2_AD2   = 2,  /**< DIO2_AD2 pin */
+            DIO3_AD3   = 3,  /**< DIO3_AD3 pin */
+            DIO4       = 4,  /**< DIO4 pin */
+            DIO5       = 5,  /**< DIO5 pin */
+            DIO6       = 6,  /**< DIO6 pin */
+            DIO7       = 7,  /**< DIO7 pin */
+            DIO8       = 8,  /**< DIO8 pin */
+            DIO9       = 9,  /**< DIO9 pin */
+            DIO10_PWM0 = 10, /**< DIO10_PWM0 pin */
+            DIO11_PWM1 = 11, /**< DIO11_PWM1 pin */
+            DIO12      = 12  /**< DIO12 pin */
+        };
+
+        enum AssocStatus {
+            ErrorReading    = -1,       /**< Error occurred when reading parameter. */
+            Joined          = 0x00,     /**< Successfully formed or joined a network. (Coordinators form a network, routers and end devices join a network.) */
+            NoPANs          = 0x21,     /**< Scan found no PANs */
+            NoValidPAN      = 0x22,     /**< Scan found no valid PANs based on current SC and ID settings */
+            JoinNotAllowed  = 0x23,     /**< Valid Coordinator or Routers found, but they are not allowing joining (NJ expired). */
+            NoBeacons       = 0x24,     /**< No joinable beacons were found. */
+            Unexpected      = 0x25,     /**< Unexpected state, node should not be attempting to join at this time. */
+            JoinFailed      = 0x27,     /**< Node Joining attempt failed (typically due to incompatible security settings). */
+            CoordStartFail  = 0x2A,     /**< Coordinator start attempt failed */
+            CheckingCoord   = 0x2B,     /**< Checking for an existing coordinator. */
+            LeaveFail       = 0x2C,     /**< Attempt to leave the network failed. */
+            JoinNoResponse  = 0xAB,     /**< Attempted to join a device that did not respond. */
+            SecKeyUnsec     = 0xAC,     /**< Secure join error - network security key received unsecured. */
+            SecKeyNotRec    = 0xAD,     /**< Secure join error - network security key not received. */
+            SecBadKey       = 0xAF,     /**< Secure join error - joining device does not have the right preconfigured link key. */
+            Scanning        = 0xFF      /**< Scanning for a ZigBee network (routers and end devices). */
+        };
+
+        /** Class constructor
+         * @param tx the TX pin of the UART that will interface the XBee module
+         * @param rx the RX pin of the UART that will interface the XBee module
+         * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+         * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+         * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+         */
+        XBeeDM(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+        /** Class destructor */
+        virtual ~XBeeDM();
+
+        /** init-  initializes object
+         * This function must be called just after creating the object so it initializes internal data.
+         * @returns
+         *         Success if the module has been properly initialized and is ready to process data.
+         *         Failure otherwise.
+         */
+        RadioStatus init();
+
+        /** set_channel - sets the channel number
+         *
+         *  @param channel the channel in which the radio operates. Range is 0x0B - 0x1A for XBee and 0x0C - 0x17 for XBee-PRO.
+         *  The Center Frequency = 2.405 + (CH - 11) * 5 MHz
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_channel(uint8_t channel);
+
+        /** get_channel - gets the channel number
+         *
+         *  @param channel pointer where the channel value will be stored.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_channel(uint8_t * const channel);
+
+        /** set_network_id - sets the Network ID.
+         *
+         *  @param network_id the Network ID value that will be set on the radio
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+         RadioStatus set_network_id(uint16_t network_id);
+
+        /** get_network_id - gets the Network ID, as it was set by @ref set_network_id().
+         *
+         *  @param network_id pointer where the Network ID will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_network_id(uint16_t * const network_id);
+
+        /** set_network_security_key - (Coordinator only) Set the 128-bit AES network encryption key. If set to 0 (default), the module will select a random network key.
+         *  It is not recommended to set the key programmatically, because it could be read through the raw serial port bits.
+         *  @param key pointer to the 128-bit AES key
+         *  @param length size of the buffer pointed by 'key'
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_network_security_key(const uint8_t * const key, const uint16_t length);
+
+#define XBEE_DM_ENC_OPT_SEND_KEY_ON_JOIN    0x01
+#define XBEE_DM_ENC_OPT_USE_TRUST_CENTER    0x02
+        /** set_encryption_options - Configure options for encryption. Unused option bits should be set to 0. Options include:
+         *  - XBEE_DM_ENC_OPT_SEND_KEY_ON_JOIN - Send the security key unsecured over-the-air during joins
+         *  - XBEE_DM_ENC_OPT_USE_TRUST_CENTER - Use trust center (coordinator only)
+         *  @param options bit mask with the encryption options
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_encryption_options(const uint8_t options);
+
+        /** register_node_discovery_cb - registers the callback function that will be called
+         * when the responses to the node discovery command arrive
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_node_discovery_cb(node_discovery_dm_cb_t function);
+
+        /** unregister_node_discovery_cb - removes the node discovery callback */
+        void unregister_node_discovery_cb();
+
+        /** register_receive_cb - registers the callback function that will be called
+         * when a data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_receive_cb(receive_dm_cb_t function);
+
+        /** unregister_receive_cb - removes the rx packet callback */
+        void unregister_receive_cb();
+
+        /** register_io_sample_cb - registers the callback function that will be called
+         * when a IO Sample Data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_io_sample_cb(io_data_cb_dm_t function);
+
+        /** unregister_io_sample_cb - removes the IO Sample Data reception callback */
+        void unregister_io_sample_cb();
+
+        /*********************** send_data member methods ************************/
+        /** send_data - sends data to a remote device
+         *
+         *  @param remote remote device
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** send_data - sends data to a remote device. This method uses
+         *                   the explicit addressing frame, allowing to use source and
+         *                   destination end points and cluster and profile IDs
+         *
+         *  @param remote remote device
+         *  @param source_ep source end point
+         *  @param dest_ep destination end point
+         *  @param cluster_id cluster ID
+         *  @param profile_id profile ID
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus 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, bool syncr = true);
+
+        /** send_data_to_coordinator - sends data to the ZigBee coordinator
+         *
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** get_assoc_status - returns current network association status. This wraps AI parameter, for more information refer to moudle's Reference Manual.
+         *
+         *  @returns an AssocStatus with current network association status.
+         */
+        AssocStatus get_assoc_status(void);
+
+        /** get_remote_node_by_id - searches for a device in the network with the specified Node Identifier.
+         *
+         *  @param node_id node id of the device we are looking for
+         *  @returns a RemoteXBeeDM with the 16-bit and 64-bit address of the remote device whose node id matches with the parameter.
+         *  If node is not found, the returned object will have invalid addresses (RemoteXBeeDM::is_valid() will return false).
+         */
+        RemoteXBeeDM get_remote_node_by_id(const char * const node_id);
+
+        /* Allow using XBee::set_param() methods for local radio from this class */
+        using XBee::set_param;
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data);
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+        /* Allow using XBee::get_param() methods for local radio from this class */
+        using XBee::get_param;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data);
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len);
+
+        /************************* IO member methods **************************/
+        /** set_pin_config - configures a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being configured
+         *  @param mode configuration mode for the selected line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode);
+
+        /** get_pin_config - gets the configuration of a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being read to get its configuration
+         *  @param mode pointer where the configuration will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode);
+
+        /** set_dio - sets to low/high a DIO line
+         *
+         *  @param remote remote device
+         *  @param line DIO line being set
+         *  @param val value that will be set in the DIO line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val);
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param remote remote device
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val);
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param remote remote device
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from hte ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val);
+
+        /** get_iosample - retrieves an @ref IOSampleDM from a remote node. This object can be used to get the remote node's ADC and DIO values.
+         *
+         *  @param remote remote device
+         *  @returns IOSampleDM object with the remote node's DIO and ADC values.
+         */
+        IOSampleDM get_iosample(const RemoteXBee& remote);
+
+        /** set_pwm - sets the duty cycle of a PWM line
+         *
+         *  @param remote remote device
+         *  @param line PWM line being set
+         *  @param duty_cycle duty cycle that will be set in the PWM line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle);
+
+        /** set_pin_pull_up - enables or disables the internal pull-up resistor of a line
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable);
+
+        /** enable_dio_change_detection - enables or disables the notification when a change is detected in a digital input line.
+         * In other words, it will force an IO Sample transmission when the DIO state changes. Only for DIO0 to DIO11.
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);
+
+    protected:
+
+        /** Frame handler used for the node discovery. Registered when a callback function
+         * is registered */
+        FH_NodeDiscoveryDM  *_nd_handler;
+
+        /** Frame handler used for the rx packets. Automatically registered when a callback
+         *  function is registered */
+        FH_RxPacketDM  *_rx_pkt_handler;
+
+        /** Frame handler used for the IO Data Sample packets. Automatically registered when a callback
+         *  function is registered */
+        FH_IoDataSampeDM  *_io_data_handler;
+
+        /** Method called directly by the library when a modem status frame is received to
+         * update the internal status variables */
+        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+        /* Allow using XBee::send_data() methods from this class */
+        using XBee::send_data;
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms);
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout);
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __XBEE_DM_H_ */
--- a/XBeeLib.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBeeLib.h	Thu Jul 28 10:17:20 2016 +0200
@@ -30,6 +30,8 @@
 #include "IO/IOSampleZB.h"
 #include "XBee802/XBee802.h"
 #include "IO/IOSample802.h"
+#include "XBeeDM/XBeeDM.h"
+#include "IO/IOSampleDM.h"
 #include "XBee/Addresses.h"
 #include "RemoteXBee/RemoteXBee.h"
 
--- a/XBeeZB/XBeeZB.cpp	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBeeZB/XBeeZB.cpp	Thu Jul 28 10:17:20 2016 +0200
@@ -27,6 +27,13 @@
 RadioStatus XBeeZB::init()
 {
     RadioStatus retval = XBee::init();
+    uint16_t addr16;
+    RadioStatus error = get_network_address(&addr16);
+    if (error == Success) {
+        digi_log(LogLevelInfo, "ADDR16: %04x\r\n", addr16);
+    } else {
+        digi_log(LogLevelInfo, "ADDR16: UNKNOWN\r\n");
+    }
 
     const RadioProtocol radioProtocol = get_radio_protocol();
     if (radioProtocol != ZigBee) {
@@ -185,6 +192,48 @@
     return Success;
 }
 
+RadioStatus XBeeZB::get_network_address(uint16_t * const  addr16)
+{
+    if (addr16 == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("MY", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *addr16 = var32;
+    return Success;
+}
+
+RadioStatus XBeeZB::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    /* No N? command available for this protocol. Add a fix 1s guard time */
+    *timeout_ms += 1000;
+
+    return Success;
+}
+
+RadioStatus XBeeZB::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    *wait_for_complete_timeout = false;
+
+    return status;
+}
+
 RadioStatus XBeeZB::check_for_coordinator_at_start(bool enable)
 {
     AtCmdFrame::AtCmdResp cmdresp;
--- a/XBeeZB/XBeeZB.h	Thu Mar 31 11:39:30 2016 +0200
+++ b/XBeeZB/XBeeZB.h	Thu Jul 28 10:17:20 2016 +0200
@@ -170,6 +170,15 @@
          */
         RadioStatus get_channel_mask(uint16_t * const chmask);
 
+        /** get_network_address - gets the 16bit network address of the device
+         *
+         *  @param addr pointer where the device 16bit network address will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_network_address(uint16_t * const addr);
+
         /** check_for_coordinator_at_start - (Routers only) If enabled, a router will verify the coordinator is on its operating channel when joining or coming up from a power cycle.
          * If a coordinator is not detected, the router will leave its current channel and attempt to join a new PAN. If JV=0, the router will continue operating on its current channel even if a coordinator is not detected.
          *
@@ -445,6 +454,19 @@
 
         /* Allow using XBee::send_data() methods from this class */
         using XBee::send_data;
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms);
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout);
 };
 
 }   /* namespace XBeeLib */