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:
- Search for all nodes currently on the network
- 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:
- Create an XBee object.
- Initialize the XBee.
- Register the function callback. This function will be called by the library when a remote node answers the Node Discovery # request.
- Configure the Node Discovery options (optional).
- Call discover_remote_nodes() method.
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.
- 802.15.4:
#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 ); [...] }
Perform Node Discovery¶
Once everything is set up, the Node Discovery process can be doneTo do so, simply call the discover_remote_nodes() 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 discover_remote_nodes() method won't return until the configured timeout (plus a guard time of 1000 mS) elapses.
- 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.
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