Library to easily communicate with XBee modules.

Dependencies:   DigiLogger

Dependents:   WaterLogger XbeeGateway XBee_Cooker ProjetReceiver ... more

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

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

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

Info

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

User manual

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

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

Ready to use examples

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

Examples for ZigBee modules

Import programXBeeZB_Receive_Data

ZigBee Receive Data example for mbed XBeeLib By Digi

Import programXBeeZB_Send_Data

ZigBee Send Data example for mbed XBeeLib By Digi

Import programXBeeZB_module_config

ZigBee network configuration example for mbed XBeeLib By Digi

Import programXBeeZB_AT_Commands

ZigBee AT Commands example for mbed XBeeLib By Digi

Import programXBeeZB_dio_adc

ZigBee DIOs and ADCs example for mbed XBeeLib By Digi

Import programXBeeZB_IO_Sample_Callback

ZigBee IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBeeZB_modem_status

ZigBee Modem Status example for mbed XBeeLib By Digi

Import programXBeeZB_node_discovery

ZigBee Node Discovery example for mbed XBeeLib By Digi

Import programXBeeZB_power_mngmnt_cyclic_sleep

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

Import programXBeeZB_power_mngmnt_pin_sleep

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

Examples for 802.15.4 modules

Import programXBee802_Receive_Data

802.15.4 Receive Data example for mbed XBeeLib By Digi

Import programXBee802_Send_Data

802.15.4 Send Data example for mbed XBeeLib By Digi

Import programXBee802_module_config

802.15.4 network configuration example for mbed XBeeLib By Digi

Import programXBee802_AT_Commands

802.15.4 AT Commands example for mbed XBeeLib By Digi

Import programXBee802_dio_adc_pwm

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

Import programXBee802_IO_Sample_Callback

802.15.4 IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBee802_node_discovery

802.15.4 Node Discovery example for mbed XBeeLib By Digi

Import programXBee802_power_mngmnt_cyclic_sleep

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

Import programXBee802_power_mngmnt_pin_sleep

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

Examples for DigiMesh modules

Import programXBeeDM_Receive_Data

DigiMesh Receive Data example for mbed XBeeLib By Digi

Import programXBeeDM_Send_Data

DigiMesh Send Data example for mbed XBeeLib By Digi

Import programXBeeDM_module_config

DigiMesh network configuration example for mbed XBeeLib By Digi

Import programXBeeDM_AT_Commands

DigiMesh AT Commands example for mbed XBeeLib By Digi

Import programXBeeDM_dio_adc_pwm

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

Import programXBeeDM_IO_Sample_Callback

DigiMesh IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBeeDM_modem_status

DigiMesh Modem Status example for mbed XBeeLib By Digi

Import programXBeeDM_node_discovery

DigiMesh Node Discovery example for mbed XBeeLib By Digi

Import programXBeeDM_power_mngmnt_asyncr_cyclic_sleep

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

Import programXBeeDM_power_mngmnt_pin_sleep

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

XBee/XBee.h

Committer:
hbujanda
Date:
2016-07-29
Revision:
9:780db84ce891
Parent:
8:b5f4a0e92249

File content as of revision 9:780db84ce891:

/**
 * 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(__DIGI_RADIO_H_)
#define __DIGI_RADIO_H_

#include <stdint.h>
#include "config.h"
#include "Utils/Debug.h"
#include "Frames/AtCmdFrame.h"
#include "FrameHandlers/FrameHandler.h"
#include "FrameHandlers/FH_ModemStatus.h"
#include "FrameBuffer/FrameBuffer.h"
#include "Addresses.h"
#include "RemoteXBee/RemoteXBee.h"
#include "IO/IO.h"

#define MAX_FRAME_HANDLERS      4
#define RESET_TIMEOUT_MS        5000

#define DR_API_FRAME_OVERHEAD   4       /* Start of frame + frame len + checksum */
#define DR_MIN_API_FRAME_LEN    4
#define DR_START_OF_FRAME       0x7E
#define DR_ESCAPE_BYTE          0x7D
#define DR_XON_BYTE             0x11
#define DR_XOFF_BYTE            0x13
#define DR_ESCAPE_XOR_BYTE      0x20

/* TODO, verify these flags work in all modules */
#define DISABLE_RETRIES_AND_ROUTE_REPAIR    0x01
#define ENABLE_APS_ENCRYPTION               0x20
#define USE_EXTENDED_TX_TIMEOUT             0x40

namespace XBeeLib {

/**
 * @defgroup RadioStatus
 * @{
 */
/**
 * RadioStatus
 */
enum RadioStatus {
    Success         = 0,    /**< Success */
    Failure         = -1,   /**< Failure */
};
/**
 * @}
 */

/**
 * @defgroup TxStatus
 * @{
 */
/**
 * TxStatus
 */
enum TxStatus {
    TxStatusSuccess            = 0,     /**< Success */
    TxStatusAckFail            = 1,     /**< MAC ACK Failure */
    TxStatusCCAFail            = 2,     /**< CCA Failure */
    TxStatusInvDestEP          = 0x15,  /**< Invalid destination endpoint */
    TxStatusNwAckFail          = 0x21,  /**< Network ACK Failure */
    TxStatusNotJoinNw          = 0x22,  /**< Not Joined to Network */
    TxStatusSelfAddr           = 0x23,  /**< Self-addressed */
    TxStatusAddrNotFound       = 0x24,  /**< Address Not Found */
    TxStatusRouteNotFound      = 0x25,  /**< Route Not Found */
    TxStatusBroadSrcFail2Heard = 0x26,  /**< Broadcast source failed to hear a neighbor relay the message */
    TxStatusInvBindTableIdx    = 0x2B,  /**< Invalid binding table index */
    TxStatusResourceError      = 0x2C,  /**< Resource error lack of free buffers, timers, etc. */
    TxStatusAttBroadcWithAPS   = 0x2D,  /**< Attempted broadcast with APS transmission */
    TxStatusAttUnicWithAPSEE0  = 0x2E,  /**< Attempted unicast with APS transmission, but EE=0 */
    TxStatusResourceError2     = 0x31,  /**< TxStatusResourceError2 */
    TxStatusInternalError      = 0x32,  /**< Resource error lack of free buffers, timers, etc. */
    TxStatusPayloadTooLarge    = 0x74,  /**< Data payload too large */
    TxStatusIndirectMsgUnReq   = 0x75,  /**< Indirect message unrequested */
    TxStatusInvalidAddr        = 0xfe,  /**< Invalid Address (Error generated by the library) */
    TxStatusTimeout            = 0xff,  /**< Timeout (Error generated by the library) */
};
/**
 * @}
 */

/**
 * @defgroup RadioLocation
 * @{
 */
/**
 * RadioLocation
 */
enum RadioLocation {
    RadioLocal     = 0,     /**< Local Radio */
    RadioRemote    = 1,     /**< Remote Radio */
};
/**
 * @}
 */

/** Parent Class for XBee modules, not to be directly used */
class XBee
{
    private:
    /** wait_for_module_to_reset - waits until a Modem Status packet with a reset status
     * is received, or the timeout expires.
     *
     *  @returns
     *     Success if a Modem Status was received,
     *     Failure otherwise
     */
    RadioStatus wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt);

    protected:
    /** buffer to store the received frames */
    static FrameBuffer _framebuf_app;
    static FrameBuffer _framebuf_syncr;

    public:

        /**
         * RadioMode
         */
        enum RadioMode {
            ModeUnknown     = 0,  /**< Unknown */
            ModeAPI1        = 1,  /**< API1 */
            ModeAPI2        = 2,  /**< API2 */
            ModeTransparent = 3,  /**< Transparent */
            ModeBootloader  = 4,  /**< Bootloader */
        };

        /** 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
         * */
        XBee(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);

        XBee(const XBee& other); /* Intentionally not implemented */
        /** Class destructor */
        virtual ~XBee();

        /** 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();

        /** get_addr64 - returns the 64bit address of the local device
         *
         *  @returns the 64bit address of the local device
         */
        uint64_t get_addr64() const;

        /** hardware_reset - performs a hardware reset. The reset GPIO must have
         * been provided to the constructor
         *
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus hardware_reset();

        /** software_reset - performs a firmware reset
         *
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus software_reset();

        /** device_reset - performs a hardware reset if there is a GPIO connected to the
         * reset line of the device. Otherwise, performs a firmware reset.
         *
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
#if defined(UNIT_TEST)
        virtual
#endif
        RadioStatus device_reset();

        /** set_tx_options - sets the transmit options byte, used with the transmit frames.
         *                   Valid flags are:
         *                       - DISABLE_RETRIES_AND_ROUTE_REPAIR
         *                       - ENABLE_APS_ENCRYPTION
         *                       - USE_EXTENDED_TX_TIMEOUT
         *
         *  @param options variable with the option flags
         */
        void set_tx_options(uint8_t options);

        /** get_tx_options - returns the tx options byte configured in the library.
         *
         *  @returns the tx options byte configured in the library.
         */
        uint8_t get_tx_options() const;

        /************************ Configuration member methods *************************/
        /** write_config - write settings to non volatile memory
         *
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus write_config();

        /** config_io_sample_destination - configures to which node a remote module will send its IO Samples to.
         * @Note: this will modify 'remote' DH and DL parameters, if the remote node is configured in transparent mode this could lead to unwanted behavior.
         * Consult the module's reference manual for more information.
         *
         *  @param remote remote device that will be sending the IO Samples
         *  @param destination remote device that will be receiving the IO Samples sent by 'remote'
         *  @returns the result of the data transfer
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination);

        /** set_io_sample_rate - configures how often the IO Samples should be sent to the destination (see @ref send_io_sample_to).
         *
         *  @param remote remote device that will be sending the IO Samples
         *  @param seconds the IO Sample sending rate in seconds (granularity is of 1 millisecond). Maximum is 65.535 seconds.
         *  @returns the result of the data transfer
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus set_io_sample_rate(const RemoteXBee& remote, float seconds);

        /** set_power_level - sets the power level at which the radio will transmit
         *
         *  @param level power level at which the radio will transmit
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus set_power_level(uint8_t level);

        /** get_power_level - reads the power level configured in the radio
         *
         *  @param level pointer where the read power level will be stored
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus get_power_level(uint8_t * const level);

        /** get_hw_version - gets the hardware version of the radio
         *
         *  @returns the hardware version of the radio
         */
        uint16_t get_hw_version() const;

        /** get_fw_version - gets the firmware version of the radio
         *
         *  @returns the firmware version of the radio
         */
        uint16_t get_fw_version() const;

        /** set_node_identifier - configures the Node Identifier string
         *
         *  @param node_id NULL-terminated string with the Node Identifier that will be set on the module. Up to 20 characters length (21 with NULL-terminator).
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus set_node_identifier(const char * const node_id);

        /** get_node_identifier - reads the configured Node Identifier string
         *
         *  @param node_id Pointer to where to store the read Node Identifier, it must point to a buffer with at least 21-bytes length.
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus get_node_identifier(char * const node_id);

        /** enable_network_encryption - Enable network encryption.
         *
         *  @param enable whether to enable this feature or not
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus enable_network_encryption(bool enable);

        /** set_network_encryption_key - Sets the 128-bit AES key used for encryption and decryption. Setting it to 0 will cause the coordinator to transmit the network key in the clear to joining devices, and will cause joining devices to acquire the network key in the clear when joining.
         *  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_encryption_key(const uint8_t * const key, const uint16_t length);

        /** start_node_discovery - starts a node discovery operation. The responses
         * have to be processes on the callback function that have to be registered
         * for that purpose.
         *
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus start_node_discovery();

        /** is_node_discovery_in_progress - checks if node discovery is in progress.
         *  @returns true if node discovery is in progress, false otherwise
         */
        bool is_node_discovery_in_progress();

#define XBEEZB_ND_OPTION_APPEND_DD          (1 << 0)
#define XBEEZB_ND_OPTION_SELF_RESPONSE      (1 << 1)
#define XBEE802_ND_OPTION_SELF_RESPONSE     (1 << 0)
#define XBEEDM_ND_OPTION_APPEND_DD          (1 << 0)
#define XBEEDM_ND_OPTION_SELF_RESPONSE      (1 << 1)
#define XBEEDM_ND_OPTION_INCLUDE_RSSI       (1 << 2)

        /** config_node_discovery - configures the node discovery operation
         *
         *  @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)
         *              XBEEZB_ND_OPTION_SELF_RESPONSE - to allow the module self responding (ZigBee only)
         *              XBEEZB_ND_OPTION_APPEND_DD - to append the DD value to the response (ZigBee only)
         *              XBEEDM_ND_OPTION_INCLUDE_RSSI - to include RSSI information in response (DigiMesh only)
         *              XBEEDM_ND_OPTION_SELF_RESPONSE - to allow the module self responding (DigiMesh only)
         *              XBEEDM_ND_OPTION_APPEND_DD - to append the DD value to the response (DigiMesh only)
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
         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 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 backoff_ms, uint8_t * const options);

        /** set_timeout - sets the timeout in ms, used by sync methods
         *
         *  @param timeout_ms new timeout in ms
         */
        void set_timeout(uint16_t timeout_ms);

        /** get_timeout - gets the timeout in ms configured in the library. This value
         *                is used in sync commands
         *
         *  @returns the configured timeout value in ms
         */
        uint16_t get_timeout() const;

        /* ... */

        /*********************** 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) = 0;

        /** send_data_broadcast - sends data to all devices in the network, using the broadcast address.
         *
         *  @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_broadcast(const uint8_t *const data, uint16_t len, bool syncr = true);

        /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
         *
         *  @param param parameter to be set.
         *  @param data the parameter value (4 bytes) to be set.
         *  @returns the command response status.
         */
        AtCmdFrame::AtCmdResp set_param(const char * const param, uint32_t data);

        /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
         *
         *  @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.
         */
        AtCmdFrame::AtCmdResp set_param(const char * const param, const uint8_t * data = NULL, uint16_t len = 0);

        /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
         *
         *  @param param parameter to be get.
         *  @param data pointer where the param value (4 bytes) will be stored.
         *  @returns the command response status.
         */
        AtCmdFrame::AtCmdResp get_param(const char * const param, uint32_t * const data);

        /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
         *
         *  @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.
         */
        AtCmdFrame::AtCmdResp get_param(const char * const param, uint8_t * const data, uint16_t * const len);

        /** 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) = 0;

        /** 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) = 0;

        /** 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) = 0;

        /** 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) = 0;

        /** process_rx_frames - method that processes the frames queued in the reception
         *                      buffer. Calls the process_frame_data method of the frame
         *                      handlers registered
         *
         *  @returns Number of dropped frames since latest call to this method.
         */
        uint32_t process_rx_frames();

        /** register_modem_status_cb - registers the callback function that will be called
         * when a Modem Status packet is received
         *
         *  @param function function pointer with the callback function
         */
        void register_modem_status_cb(modem_status_cb_t function);

        /** unregister_modem_status_cb - removes the Modem Status reception callback */
        void unregister_modem_status_cb();

    protected:

#define EXTRA_XBEE_PROTOCOLS

        enum RadioProtocol {
            None,
            ZigBee,
            Raw_802_15_4,
#ifdef EXTRA_XBEE_PROTOCOLS
            XBeeWiFi,
            DigiMesh,
            SmartEnergy,
            DigiPoint,
            ZNet,
#endif
        };
        /** send_byte_escaping_if - sends a byte, through the serial interface, to
         * the radio, escaping the byte if the working mode of the radio is API2.
         *
         *  @param line PWM line being set
         *  @param data the byte that will be send to radio
         */
        void send_byte_escaping_if(uint8_t data);

        /** uart_read_cb - serial interface callback, called when data is received on
         * the serial port. The function parses the incoming data and, when a good
         * frame is detected, saves it in the frame list
         */
        void uart_read_cb();

        /** get_this_api_frame - searches in the FrameBuffer for an incoming frame
         *                       with frameid equal to id and frame type equal to type
         *                       or type2. If after timeout the frame hast not been found,
         *                       returns.
         *
         *  @param id id of the frame we are looking for.
         *  @param type tye type we expect the frame to be.
         *  @param type2 alternative valid type, if provided.
         *  @returns a pointer to the frame found in the FrameBuffer or a null pointer if
         *           the frame has not been found and the timeout expired.
         */
        ApiFrame * get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
                    ApiFrame::ApiFrameType type2 = ApiFrame::Invalid);

        /** send_api_frame - method to send, over the serial port, an API frame
         *
         * @param frame pointer to the frame that will be sent.
         */
#if defined(UNIT_TEST)
        virtual
#endif
        void send_api_frame(ApiFrame *frame);

        /** update_radio_status - method called when a modem status frame is received
         *  to update the internal status variables of the library.
         *  @note This is not a pure virtual function because it can be called while
         *        the object is being constructed and we need the implementation of the
         *        base class.
         *
         *  @param status byte with the status received in the modem status frame
         */
        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);

        /** Method used internaly by the derived classes to transmit data to
         * remote nodes, waiting for the answer from the device
         *
         *  @param frame frame that will be sent to the radio (have to be a
         *         proper transmit frame
         *  @returns the result of the data transfer
         *     TxStatusSuccess if the operation was successful,
         *     the error code otherwise
         */
        TxStatus send_data(ApiFrame *frame);

        /** send_at_cmd - sends an AT command to the radio and waits for the response.
         *
         *  @param frame api frame with the command and command params.
         *  @param buf pointer where the param response (n bytes) will be stored.
         *  @param len pointer where the number of bytes of the param response will be stored.
         *  @param radio_location radio location, either RadioLocal or RadioRemote.
         *  @param reverse reverse the byte ordering of the response saved in buf.
         *  @returns the command response status.
         */
        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame,
                    uint8_t *const buf, uint16_t *const len, RadioLocation radio_location = RadioLocal, bool reverse = true);

        /* send_at_cmd - methods used internally by other methods */
        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame);
        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint8_t *data);
        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint16_t *data);
        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint32_t *data);

        /** register_frame_handler - registers an object to handle incoming frames from
         *                           the radio.
         *  @note For any type of frame more than one handler can be registered and all
         *        of them are called, sequentially, when a frame of that type arrives.
         *
         *  @param handler pointer to the frame handler object
         *  @returns the result of the registration
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus register_frame_handler(FrameHandler *const handler);

        /** unregister_frame_handler - removes a previously registered frame handler
         *
         *  @param handler pointer to the frame handler object
         *  @returns the result of the unregister operation
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus unregister_frame_handler(FrameHandler *const handler);

        /** get_radio_protocol - returns the RF protocol that the connected module uses
         *                       based on its firmware and hardware versions
         *
         *  @returns a RadioProtocol enum.
         */
        RadioProtocol get_radio_protocol(void) const;

        /** _get_iosample - forces an io_sample read (reads all digital and analog inputs)
         *
         *  @param remote remote device
         *  @param io_sample buffer where the io_sample response is copied
         *  @param len pointer where the length of the io_sample response is stored
         *  @returns
         *     Success if the operation was successful,
         *     Failure otherwise
         */
        RadioStatus _get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len);

        void _get_remote_node_by_id(const char * const node_id, uint64_t * addr64, uint16_t * addr16);

        /** check_radio_flow_control - checks that the radio has the CTS "D7" and RTS "D6" pins configured
         *                       according to the serial hardware flow control selected by the user
         *
         *  @returns true if check success.
         */
        bool check_radio_flow_control();

        /** get_AI - reads the AI parameter.
         *
         *  @returns
         *      -1 if an error occurred when reading AI.
         *      0-0xFF the AI value.
         */
        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;

        /** Operating mode of the module (API1, API2,...) */
        RadioMode   _mode;

        /** Hardware version value of the radio */
        uint16_t    _hw_version;

        /** Firmware version value of the radio */
        uint16_t    _fw_version;

        /** Timeout in ms for sync operations (when we wait for a response) */
        uint16_t    _timeout_ms;

        /** Device 64 bit address (SH, SL) */
        uint64_t      _dev_addr64;

        /** Serial Interface, use RawSerial as we dont use the streams */
        RawSerial   *_uart;

        /** IO connected to the radio reset line */
        DigitalOut  *_reset;

        /** Transmit options byte */
        uint8_t     _tx_options;

        /** Array of frame handler pointers. We use an array instead of a vector or other
         *  data structure to save memory and avoid dynamic memory allocation, to avoid
         *  memory fragmentation */
        FrameHandler *_fhandlers[MAX_FRAME_HANDLERS];

        /** Hardware reset counter, automatically updated by the library */
        volatile uint16_t    _hw_reset_cnt;

        /** Watchdog reset counter, automatically updated by the library */
        volatile uint16_t    _wd_reset_cnt;

        /** Frame handler used for the Modem Status packets. Automatically registered when a callback
         *  function is registered */
        FH_ModemStatus  *_modem_status_handler;

        /** Latest modem status received */
        AtCmdFrame::ModemStatus _modem_status;

        /** Library is initializing */
        bool _initializing;

        /** Timer used for node discovery */
        Timer _nd_timer;

        /** node discovery timeout */
        int _nd_timeout;

        /** If a _get_remote_node_by_id() is in progress, this keeps the expected frame id */
        uint8_t _node_by_ni_frame_id;
};

}   /* namespace XBeeLib */

#endif /* defined(__DIGI_RADIO_H_) */