Sending messages to sleepy end devices
Categories:
There are certain factors to take into account when sending messages to sleepy devices: Buffered messages take up packet buffers on the parent. The poll rate directly influences latency in the delivery of a message to a sleepy device. The time that a parent will buffer a message for a sleepy device is typically 7.68 seconds in a ZigBee Pro network. This article will explain in more detail how to consider these limiting factors when designing your application for a network with sleepy end devices.
In EmberZNet you can call emberSendUnicast() (or ezspSendUnicast in EZSP host platforms) to send a message to a sleepy end device, just like you would any other destination. However, because the destination device is very likely to be
asleep, this message must be buffered by the parent of the sleepy end
device until the device next wakes up and polls for data from the
parent. When the parent receives the message for its child, it will
set the "message pending" flag for that child. When the child polls the
parent for data, in the poll response (MAC ACK) it will see that the message
pending flag is set as part of the frame control bits, and that will cause the sleepy end device child to leave its radio on for up to approximately 20ms after the poll, which allow the parent to deliver the message to the child before it goes back to sleep. This is the case regardless of whether the originator of the message (the sender) is the parent of the destination device.
There are 3 main limiting factors to this mechanism:
1.
Each buffered message on the parent uses up some of its packet buffers. For a small message, this might be 2 packet buffers per buffered
message, up to a maximum of 4 packet buffers per message (32 bytes per buffer x 4 = 128 bytes including header). If the parent runs out of packet
buffers to allocate for these buffered messages, it will no longer
buffer messages for its children until some packet buffers are freed
up. (Recall that the size of the available buffer pool is configured by EMBER_PACKET_BUFFER_COUNT in SoC designs or EZSP_CONFIG_PACKET_BUFFER_COUNT in EZSP NCP designs.) For example, if a router has allocated 24 packet buffers, and messages are short, it may be possible to have 12 messages buffered at one time for sleepy end device children. If the router has more than 12 children, this is less than one message per child.
2.
The maximum time that a parent will buffer a message for a sleepy end
device child is called the Indirect Transmission Timeout. EmberZNet allows this value to be up to 30 seconds, but ZigBee Pro requires it to be set to 7.68 seconds to ensure compliance and interoperability, so you shouldn't alter this unless you are creating a closed network where ZigBee Pro compliance isn't a requirement. This value is configurable by redefining the indirect transmission timeout via the
project's CONFIGURATION HEADER file like the following (this example shows the maximum 30
second timeout).
#define EMBER_INDIRECT_TRANSMISSION_TIMEOUT 30000
The Indirect Transmission Timeout effectively limits the sleep cycle of sleepy end devices during periods where they are expected to communicate reliably with other devices; when end devices sleep beyond this internal ("hibernate"), they are likely to miss any messages sent to them, because the parent will sometimes remove the buffered message before the child next polls for data (depending on at what point during the sleep cycle the message is sent). Some applications may switch between a shorter sleep duration within the Indirect Transmission Timeout (a phenomenon referred to as "napping") and a longer timeout more suited to preserving the battery ("hibernating") depending on what kind of responsiveness is expected from the device. If a parent does time out a message for an end device due to this timeout, an Indirect Transaction Expiry route error will be passed back to the sender to denote the delivery error. Sender applications can catch this exception via the optional emberIncomingRouteErrorHandler() callback if desired.
#define EMBER_INDIRECT_TRANSMISSION_TIMEOUT 30000
The Indirect Transmission Timeout effectively limits the sleep cycle of sleepy end devices during periods where they are expected to communicate reliably with other devices; when end devices sleep beyond this internal ("hibernate"), they are likely to miss any messages sent to them, because the parent will sometimes remove the buffered message before the child next polls for data (depending on at what point during the sleep cycle the message is sent). Some applications may switch between a shorter sleep duration within the Indirect Transmission Timeout (a phenomenon referred to as "napping") and a longer timeout more suited to preserving the battery ("hibernating") depending on what kind of responsiveness is expected from the device. If a parent does time out a message for an end device due to this timeout, an Indirect Transaction Expiry route error will be passed back to the sender to denote the delivery error. Sender applications can catch this exception via the optional emberIncomingRouteErrorHandler() callback if desired.
3.
The duration between polls to the parent by the sleepy end device (i.e.
the time spent sleeping) directly influences the latency in the
delivery of the message to the sleepy end device. Often the delay
between polls is greater than than the length APS message timeout (which is calculated by multiplying EMBER_MAX_HOPS * 50ms; generally 1500ms in ZigBee Pro networks), so to the sender of the message must use an extended APS retry timeout when communicating with a sleepy device. The stack will do this automatically if the Extended Timeout flag is set for destination, but this typically requires that EMBER_OUTGOING_VIA_BINDING_TABLE or EMBER_OUTGOING_VIA_ADDRESS_TABLE be used as the EmberOutgoingMessageType for the delivery, unless the target is a child of the sender. (See http://portal.ember.com/retries for more about the extended timeout and how it is used in the retry mechanism.) When sending to a destination for whom the sender has the Extended Timeout flag set, the sender will wait the normal retry time plus the Indirect Transmission Timeout (as described in #2 above) to receiver the APS ACK before retrying the APS delivery. This means that a failed delivery (all 3 retries timing out) in a ZigBee Pro network can take almost 30 seconds to achieve.
4.
Since broadcasts are only held on a parent device until either all children have retrieved it or the Indirect Transmission Timeout has been met, broadcasts (and multicasts, which are built on top of the broadcast mechanism) are not guaranteed to reach all sleepy end devices, since some sleepy nodes may be hibernating and won't poll in time to retrieve the message. Thus, if your application relies on any broadcast mechanisms of delivery, the sleepy end devices will need a backup plan based on unicast queries to the broadcaster after they wake up so that they can determine what they may have missed.
In summary, when sending messages to sleepy end devices...
- Maximize the number of packet buffers on router (or coordinator) devices.
- Minimize the number of messages sent to sleepy end devices joined to any particular router at a time.
- Use Address or Binding table entries to communicate with sleepy end devices; this way the stack can track the Extended Timeout flag for that destination and not prematurely timeout messages when APS retries are used.
- Be sure those end devices are polling regularly ("napping" rather than "hibernating") so that they can reliably receive and ACK your messages. (Optionally, implement the emberIncomingRouteErrorHandler() to detect scenarios where your delivery has exceeded the Indirect Transmission Timeout.)
Note: There are other mechanisms for delivering messages to sleepy end devices that do not have these limitations (see http://portal.ember.com/alarms); however, this is the simplest way
to send a message to a sleepy end device without requiring special support from the stack/application at the parent device. The limitations
imposed by this mechanism may be worth living with for the simplicity
it brings to the application.








