Library to easily communicate with XBee modules.

Dependencies:   DigiLogger

Dependents:   WaterLogger XbeeGateway XBee_Cooker ProjetReceiver ... more

Discovering nodes in the network

In most applications the precise number of nodes in a network is not known in advance, therefore the XBee modules implement a mechanism for discovering the nodes in the network. However, identifying each node only by its 64-bit or 16-bit addresses is not very flexible or scalable in most cases. To make it easier for humans to identify the nodes XBee modules have a Node Identifier (NI parameter), which is an ASCII string of up to 20 characters for a human-readable name so the node is easier to identify. There are two ways of discovering node information at runtime:

  1. Search for all nodes currently on the network
  2. Search for only one node

Warning

Assigning a unique Node Identifier for each node in the network is responsibility of the user. If there are duplicate Node Identifiers in the network, node lookup behaviors are undetermined and the results may be unpredictable.

Information

The default value of NI is a white space (" ").

Search for all nodes

The discovered nodes are represented by two parameters, a RemoteXBee object (RemoteXBee802, RemoteXBeeZB or RemoteDM) and a null-terminated string containing the Node Identifier.

Example of use

Here are the steps for discovering all the nodes in your network:

  1. Create an XBee object.
  2. Initialize the XBee.
  3. Register the function callback. This function will be called by the library when a remote node answers the Node Discovery # request.
  4. Configure the Node Discovery options (optional).
  5. Initiate the Node Discovery process.
  6. Periodically ask the XBee library to process received frames until node discovery process finishes.

Create an XBee object

Create an XBee object of the desired variant:

ZigBee

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
     [...]
      
     XBeeZB xbee = XBeeZB(RADIO_TX, RADIO_RX, RADIO_RESET);
      
     [...]
}

802.15.4

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
     [...]
      
     XBee802 xbee = XBee802(RADIO_TX, RADIO_RX, RADIO_RESET);
      
     [...]
}

DigiMesh

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
     [...]
      
     XBeeDM xbee = XBeeDM(RADIO_TX, RADIO_RX, RADIO_RESET);
      
     [...]
}

Initialize the XBee

Next, initialize the XBee. That means calling to the init() method (see Initializing modules) and optionally any method required to put the device in the desired network.

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
int main()
{
    [...]
     
    xbee.init();
}

Register desired receive function callback

The user has to provide the desired function to be called when specific frames are received. For every protocol, there is a single receive callback for both unicast and broadcast messages. However, depending on the XBee variant the callback function has a different prototype, as they take different RemoteXBee objects.

ZigBee

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
/** Callback function, invoked when a Node Discovery response is received */
void discovery_function(const RemoteXBeeZB& remote, char const * const node_id)
{
    log_serial->printf("Found device '%s'\r\n", node_id);
}
 
int main()
{
    [...]
      
    /* Register callbacks */
    xbee.register_node_discovery_cb(&discovery_function);
      
    [...]
}

802.15.4

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
/** Callback function, invoked when a Node Discovery response is received */
void discovery_function(const RemoteXBee802& remote, char const * const node_id)
{
    log_serial->printf("Found device '%s'\r\n", node_id);
}
 
int main()
{
    [...]
      
    /* Register callbacks */
    xbee.register_node_discovery_cb(&discovery_function);
      
    [...]
}

DigiMesh

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
/** Callback function, invoked when a Node Discovery response is received */
void discovery_function(const RemoteXBeeDM& remote, char const * const node_id)
{
    log_serial->printf("Found device '%s'\r\n", node_id);
}
 
int main()
{
    [...]
      
    /* Register callbacks */
    xbee.register_node_discovery_cb(&discovery_function);
      
    [...]
}

Configure the Node Discovery options (optional)

There are two parameters to configure in the Node Discovery process:

  • backoff_ms: max allowed time for devices in the network to answer to the Node Discovery request (in milliseconds). The remote nodes will try to reply to the ND request after waiting a random time between 0 and backoff_ms. However it is possible that responses will be received after the timeout has expired due to the time a message takes to propagate among the network.
  • options: other options encoded as a bit field. This is passed to the NO parameter, so you should see the module's reference manual to learn more about the available options. For example:
    • 802.15.4:
      • XBEE802_ND_OPTION_SELF_RESPONSE: Local device sends ND response frame when ND is issued.
    • ZigBee:
      • XBEEZB_ND_OPTION_APPEND_DD: Append DD value (to ND responses or API node identification frames)
      • XBEEZB_ND_OPTION_SELF_RESPONSE: Local device sends ND response frame when ND is issued.
    • DigiMesh:
      • XBEEDM_ND_OPTION_APPEND_DD: Append DD value (to ND responses or API node identification frames)
      • XBEEDM_ND_OPTION_SELF_RESPONSE: Local device sends ND response frame when ND is issued.
      • XBEEDM_ND_OPTION_INCLUDE_RSSI: Include RSSI information in response.

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
int main()
{
    [...]
    const uint16_t nd_timeout_in_seconds = 10;
    const uint16_t nd_timeout_in_milliseconds = nd_timeout_in_seconds * 1000;
    const uint8_t enable_auto_discovery = XBEEZB_ND_OPTION_SELF_RESPONSE;
 
    xbee.config_node_discovery(nd_timeout_in_milliseconds, enable_auto_discovery );
    
    [...]
}

Initiate the Node Discovery process

Once everything is set up, the Node Discovery process can be started. To do so, simply call the start_node_discovery() method, next the callback will be called whenever a node responds the request.

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
int main()
{
    [...]
    xbee.start_node_discovery();
    [...]
}

Information

  • There is no guarantee that all nodes in a network will reply the Node Discovery process. There are several different reasons why a node might not reply: sleeping end-devices (ZigBee), a network with a lot of nodes, packet loss due to noise and so forth. Before initiating a new Node Discovery process, it is recommended to wait until previous Node Discovery process ends.

Periodically ask the XBee library to process received frames until node discovery process finishes

The process_rx_frames() method must be called periodically by the user so the XBee library delivers the frames to the corresponding registered callbacks. You can manually wait the desired time or much better call the is_node_discovery_in_progress() method to realize when the node discovery process should have finished.

Help

See more info on Frame Receive Process

Make sure you call process_rx_frames() method periodically:

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
    [...]
     
    while (true) {
        xbee.process_rx_frames();
        wait_ms(100);
        printf(".");
    } while(xbee->is_node_discovery_in_progress());
     
    [...]
}

Search for only one node

In some applications the target node's NI is already known, so there is no need to discover all the nodes in the network. The get_remote_node_by_id() method takes the remote node's NI and returns a RemoteXBee object ready to be used in other functions (such as send_data(), get_param(), set_param(), etc.)

Example of use

Choose RemoteXBee object accordingly.

get_remote_node_by_id()

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
    [...]
    xbee.init();
    [...]
    RemoteXBee802 remote_node = xbee.get_remote_node_by_id("MyNodeID");
    if (remote_node.is_valid()) {
	const char message[] = "Hello XBee!";
	const TxStatus txStatus = xbee.send_data(remote_node, (const uint8_t *)message, sizeof message - 1);
	if (txStatus != TxStatusSuccess) {
		printf("Found an error while sending data %d\r\n", txStatus);
	}
    } else {
	printf("Couldn't find MyNodeID node\r\n");
    }
    [...]
}

Examples

Here is a ready to use example:

For ZigBee modules:

Import programXBeeZB_node_discovery

ZigBee Node Discovery example for mbed XBeeLib By Digi

For 802.15.4 modules:

Import programXBee802_node_discovery

802.15.4 Node Discovery example for mbed XBeeLib By Digi

For DigiMesh modules:

Import programXBeeDM_node_discovery

DigiMesh Node Discovery example for mbed XBeeLib By Digi