What do I need to do in order to use fragmented messaging (fragmentation) in my application?
NOTE: This writeup shows example code specific to the EmberZNet API (non-EZSP environment). If you are using EZSP, please refer to app/util/zigbee-framework/fragment-host.h for guidance on differences in the fragmentation API.
To add fragmentation, in your main file where the messaging is done, add the following inclusion:
#include "app/util/zigbee-framework/fragment.h"
We also recommend adding a state variable to make sure you don’t send more than one fragmented message at once since the library only maintains state for one collection of fragments:
boolean fragmentedMessageInProcess = FALSE;
In the place where you send the large message, do something like this:
EmberMessageBuffer masterBuffer; masterBuffer = emberFillLinkedBuffers(messageContents, messageLength); if (masterBuffer == EMBER_NULL_MESSAGE_BUFFER) { return EMBER_NO_BUFFERS; } status = emberSendFragmentedMessage(EMBER_OUTGOING_DIRECT, destination, &apsFrame, masterBuffer, maxFragmentSize); // we are now sending a fragmented message if (status == EMBER_SUCCESS) { fragmentedMessageInProcess = TRUE; } emberReleaseMessageBuffer(masterBuffer); return status;
In your main loop, add a call to service the fragmentation state machine:
emberFragmentTick();
In your incomingMessageHandler routine, add a check before running further processing on the message:
boolean isFragment; isFragment = emberIsIncomingFragment(apsFrame, message); if( isFragment ) return; // don't process these here
…Note that the Boolean return value of emberIsIncomingFragment() is not so much whether the processed buffer is a fragment but whether the fragmentation library code completely processed it (TRUE if yes; in which case the IncomingMessageHandler should not continue to process it after this subroutine completes). In particular, the last fragment is processed by this function but leads to a FALSE return value, since the fragment buffer is replaced by a concatenation of all received fragments as one large buffer chain, which the application is then expected to handle when IsIncomingFragment returns. So when you arrive back in top-level IncomingMessageHandler context, your buffer now represents the entire collection of received fragments as one very long message, which is why you should wait to compute the payload length until after the fragmentation check (IsIncomingFragment), as per this code:
// has to be after frag so that len of whole message is collected len = emberMessageBufferLength(message);
Then, on the outgoing side, add similar handling in your MessageSentHandler to delay processing until all fragments are handled:
boolean isFragment; isFragment = emberIsOutgoingFragment(apsFrame, message, status); if( isFragment ) return; // don't process these here
Finally, set up code to handle the completion of the fragmented delivery:
void emberFragmentedMessageSentHandler(EmberStatus status) { // the fragmented message is no longer in process fragmentedMessageInProcess = FALSE; // Add any other code here you want to execute when all fragments are done }
- Login to post comments









