Vergil Cola
/
MQTTGatewayK64
Fork of my MQTTGateway
XbeeMonitor/XBeeLib/XBee/XBee.h
- Committer:
- vpcola
- Date:
- 2017-04-08
- Revision:
- 0:f1d3878b8dd9
File content as of revision 0:f1d3878b8dd9:
/** * 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_) */