Understanding XBee EndPoints
From Digi Developer
Understanding XBee End-Points
The way Digi implimented the XBee/ZigBee end-points in the extended Python Socket API implies that they function like TCP or UDP source and destination port numbers. However unlike TCP or UDP which treats each src/dst port pair as unique conversations, XBee/ZigBee assigns each distinct 'destination end-point' to a single application (or handler) for message delivery. The handler is free to manually assign a meaning to the 'source end-point' in received packets, but it is NOT likely unique.
For example, a Modbus/TCP server can bind on TCP port 502. When five clients connect, each uses a destination port of 502 and a unique 'source port' (per IP address pair). Five 'sockets' may be created, and each of the five server-tasks spawned is blissfully unaware that other clients are active.
In contrast, an XBee server can bind on an end-point such as 0xE8, but five remote devices sending to destination end-point 0xE8 will appear to use the same 'socket'. Additionally, they all may claim a source end-point of 0xE8. The Xbee server code must manually process and distribute messages based on extended address or other criteria.
Which XBee technologies support end-points?
You can use the upper word of the DD setting to distinguish XBee which support end-points and those which do not.
|Upper DD Word||Name||End-Point Support||Description|
|0x0000||Unspecified||Unknown||This means the XBee is mis-configured|
|0x0001||802.15.4||No||Non-mesh star/peer configured nodes on 2.4GHz|
|0x0002||ZNet 2.5||Yes||Digi's older pre-ZigBee firmware|
|0x0003||Digi Zigbee||Yes||Digi's firmware supporting Zigbee 2007|
|0x0004||Digi Mesh 900||Yes||Digi's proprietary mesh on 900Mhz|
|0x0005||Digi Mesh 2.4||Yes||Digi's proprietary mesh on 2.4Ghz|
|0x0006||Digi Point-to-MultiPoint 868||No||Non-mesh star configured nodes on 868Mhz|
|0x0007||Digi Point-to-MultiPoint 868||No||Non-mesh star configured nodes on 900Mhz|
- Use the DD value in the Digi gateway's XBee - you cannot trust that the remote XBee has a valid DD setting!
- Even if the XBee does NOT support end-points, Python may allow you to bind on a specific end-point like 0xE8. However, you will never receive any responses on 0xE8 because all responses appear to be targeted at end-point 0x00.
Managing end-points in XBee
Under XBee AT-Transparent Mode
So a concrete example, sending a packet with (src=0xE9 dst=0xE8) will NOT automatically result in return-responses being received as (src=0xE8 dst=0xE9) - you need to explictely change the AT settings in the remote XBee to return serial data to destination end-point 0xE9.
Therefore, to move your Python script bind end-point away from 0xE8 (the default), then do the following:
- Your Python script binds on an alterative end-point such as 0xE9, 0x01, or 0x41.
- Manually set all required remote XBee with an AT setting DE=0xE9 (or as required). You can do this by:
- Under XCTU, relevant Xbee firmwares (such as ZigBee Router AT 0x2264) will have a closed/collapsed sub-option named "ZigBee Addressing" under Adressing. Click on it to open and you'll see the DE/SE/CI options.
- Newer 2.9.x Digi gateway firmwares expose the DE command under the advanced settings for remote XBee nodes.
- Use standard "remote AT command" API frames or ddo_set_param() calls to force DE to the desired value.
Note that changing the XBee's SE setting does NOT allow moving serial encapsulation away from 0xE8 - it only changes the source end-point cliamed by AT-Transparent responses. The remote XBee in AT-transparent mode will only forward data out the serial port which is targetted at 0xE8.
Under XBee API Mode
When running XBee firmware in API mode, then most source/destination end-points are passed through transparently. It is up to the serial-attached CPU to parse and assign meaning to the end-points. Therefore, an external CPU might gracefully and automatically return responses to requests with (src=0xE9 dst=0xE8) as (src=0xE8 dst=0xE9).
End-Point Numbers to Avoid
Although no exact list is available, you should avoid using these end-points:
|0x00||ZigBee Device Object end-point - reserved by ZigBee stack|
|0xDC to 0xEE||Reserved for Digi use|
|0xEF to 0xF0||Reserved for other vendor use|
|0xF1 to 0xFE||Reserved by ZigBee Alliance / for other uses|
|0xFF||Digi treats as 'any end-point' (a wild-card) during Python socket operations|
End-points 0x01 to 0xDB should be free to use. However, the rules for picking end-point numbers is much like that for TCP/UDP port numbers - be flexible and ready to change if required. For example, you might use TCP port 2101 to tunnel data to a Digi device server. It works, but TCP port 2101 is officially assigned for use as "RTCM-SC104", which is a Radio Technical Commission for Maritime Services standard used to move GPS data via TCP/IP. Microsoft also overloads this port for use with RPC-based MQIS and Active-Directory Lookups. The same may be true of XBee end-points - even if you reuse a preassigned end-point it is only a problem if you require some other tool or function with a conflicting use.
The examples above used 0xE9, which Digi claims is reserved, so might be used for some other purpose in the future. If you select end-point 0x77, some other vendor might create a product requiring a Python script binding on end-point 0x77. So design your system to allow the end-point number selected to be easily changed as required.
EndPoints in the Modbus/IA Engine
You can use the Digi Modbus/IA engine to route Ethernet-based Modbus/TCP requests to remote Modbus/RTU serial devices via Digi XBee 232 Adapters and Digi XBee 485 Adapters. Configuring the XBee module is covered on this Wiki page: Modbus_Example_Serial_Adapter
However, the default Modbus/IA behavior is to use ZigBee endpoint 0xe8, which will conflict with most sample Python programs and the Device Cloud/DIA framework. This conflict is because only 1 task can bind on (or register to receive) incoming XBee packets on endpoint 0xe8.
Therefore you should move the Modbus/IA traffic away from endpoint 0xe8 and use another, such as 0xe9. This is easier than trying to change the behavior of a Python application in an unknown number of places:
- In the remote XBee adapter, set DE as explained above to E9 (or to your desired value)
- In the IA Modbus unit id/slave address mapping table, add the new Xbee endpoint after the '!', so MAC looks like as 00:13:a2:00:40:30:de:cd!E9. Note that this does NOT change the 'destination' endpoint in the outgoing Modbus request - this remains 0xe8 for XBee module reasons. Instead, it causes the Modbus/IA engine to bind on incoming endpoint 0xE9 instead of 0xE8.