Library to easily communicate with XBee modules.

Dependencies:   DigiLogger

Dependents:   WaterLogger XbeeGateway XBee_Cooker ProjetReceiver ... more

You are viewing an older revision! See the latest version

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 (either RemoteXBee802 or RemoteXBeeZB) and a null-terminated string containing the Node Identifer.

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.

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);
      
     [...]
}

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);
      
    [...]
}

Configure the Node Discovery options (optional)

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

  • timeout_ms: the maximum time the local node will wait for responses (in milliseconds). The remote nodes will try to reply to the ND request after waiting a random time between 0 and timeout_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.

#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.discover_remote_nodes();
    [...]
}

Some hints:

  • 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, too low of a timeout, packet loss due to noise and so forth. Before initiating a new Node Discovery process, it is recommended to wait the configured timeout plus at least one second to avoid receiving responses for previous requests.
  • The processing done in the registered node discovery callback must be fast to prevent losing incoming node discovery messages. Please, just catch remote device information in the callback and perform slow operations (like echoing data to the remote) in the main loop. If you are losing node discovery messages, you can try defining FRAME_BUFFER_SIZE_SYNCR in config.h file and setting it to a value higher than the default(2). That will increase the buffers reserved to process node discovery messages but will increase the memory required by the library.

Periodically ask the XBee library to process received frames

The process_rx_frames() method must be called periodically by the user so the XBee library delivers the frames to the corresponding registered callbacks.

Help

See more info on Frame Receive Process

A is_node_discovery_in_progress() method is available so the user can realize when the node discovery process should have finished.

So make sure you call this method periodically:

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

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.)

Information

This function is also affected by the Node Discovery timeout. See the "Configure the Node Discovery options" section in this page.

Example of use

802.15.4

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");
    }
    [...]
}

ZigBee

get_remote_node_by_id()

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
    [...]
    xbee.init();
    [...]
    RemoteXBeeZB 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


All wikipages