Hi,
I am using the ZigBee 3.0 stack from the FRM-KW41Z SDK v2.2.0, working off the dimmable_light_freertos example.
I want to pre-configure the network my devices use, so I'm looking into using the Orphan Rejoin functions.
My thought process was that the Routers can come on, do a ZPS_eAplZdoOrphanRejoinNetwork and connect to the configured network; if the network isn't up yet, they can retry this a little while later.
This works pretty well, if the network is up and running, even when my Coordinator comes up a little bit later than the Router.
However, when my Coordinator starts much later than my Router, something unexpected happens. After failing to connect for a while (as seen from the BDB/ZPS events), the calls to ZPS_eAplZdoOrphanRejoinNetwork itself will immediately fail with a code 0xe8.
According to the docs, this should be MAC_ENUM_INVALID_PARAMETER, "Out-of-range parameter in function", and shouldn't be a valid return value (only ZPS_E_SUCCESS and ZPS_APL_APS_E_ILLEGAL_REQUEST specified).
At this point, on the Router, I don't see any events generated, and I can't find how to properly reset the stack to make it accept those calls again.
What is the recommended way to keep attempting the Orphan Rejoins when the network isn't up yet?
Hello @TJvV,
Could you please help us with more details about your network? Is it a new network or was your device already registered on the network? Also, please update your SDK to the latest version available.
ZPS_eAplZdoOrphanRejoinNetwork function will attempt to join the network whose EPID has been pre-configured on the node. The function will only allow the node to join a parent that already has knowledge of the node (in the parent’s Neighbour table).
Regards,
Eduardo.
Hi,
I will see if I can upgrade to the latest SDK. Judging from the diff between sources, and the change notes, it feels like the upgrade won't change the behavior though.
At the moment, the network we're planning is a single Coordinator with a number of Routers in somewhat close proximity; I'm not quite sure if they'll all be single hop.
We have configured all nodes with the same EPID (currently fixed in software for testing, will be moved to EEPROM).
The idea was to configure the network before deploying the nodes. First we add the MAC address for all relevant Routers to the Coordinator using ZPS_eAplZdoDirectJoinNetwork. Next we start up the Routers, and have them join the network. Every Router will be within range of the Coordinator during this step. From what we can see, this gives us a working network.
The only issue we have, is that when we deploy the nodes, we have no control over when they will be powered. This brings us to the situation where the Routers may start up before the Coordinator has set up the network.
Hello,
Could you please help us with more details about the procedure you are following for orphan rejoin on your Coordinator and your Router?
Please, take a look at the ZigBee Pro Specification, Chapter 3.6.1.4 Joining a Network, section 3.6.1.4.3.1 describes Joining or Re-joining a Network Through Orphaning.
You can find more information about ZPS_eAplZdoOrphanRejoinNetwork in the ZigBee 3.0 Stack User Guide (inside KW41 SDK folder > docs > wireless > Zigbee).
Regards,
Eduardo.
Hi,
Sorry for the slow replies, I'm only working on this project on Tuesdays.
On my Router, this is the basic flow
void main_task(){
PDUM_vInitPools();
pdum_vAPduInit(s_asAPduPool, sizeof(s_asAPduPool)/sizeof(pdum_tsAPdu *));
[...]
ZPS_u32MacSetTxBuffers (4);
ZPS_eAplAfInit(); //Initialise ZBPro stack
APP_ZCL_vInitialise(); //Initialises ZCL related functions
[...]
if (sZllState.eState == 0) {
ZPS_vNwkNibSetPanId(ZPS_pvAplZdoGetNwkHandle(), (uint16) RND_u32GetRand(1, 0xfff0));
}
[...]
BDB_tsInitArgs sArgs;
sArgs.hBdbEventsMsgQ = &APP_msgBdbEvents;
BDB_vInit(&sArgs);
[...]
BDB_vStart();
while( 1 ){
test_task();
zps_taskZPS();
bdb_taskBDB();
ZTIMER_vTask();
}
}
void test_task(){
ZPS_teStatus status;
switch( connect_step ){
case connect_init:
status = = ZPS_eAplZdoOrphanRejoinNetwork();
if ( ZPS_E_SUCCESS != status) {
connect_result = result_failed;
}
connect_step = connect_wait;
break;
case connect_wait:
if (result_failed == connect_result) {
prev_connect_attempt = now_ms;
connect_step = connect_failed;
} else if (result_success == connect_result) {
connect_step = connect_active;
}
break;
case connect_failed:
if( diff(prev_connect_attempt, now_ms) >= 2000 ){
connect_step = connect_init;
}
break;
[...]
}
}
void vBdbCallback(BDB_tsBdbEvent *psBdbEvent){
BDB_tsZpsAfEvent zpsAfEvent = psBdbEvent->uEventData.sZpsAfEvent;
ZPS_teAfEventType zpsAfEventType = zpsAfEvent.sStackEvent.eType;
[...]
if (BDB_EVENT_REJOIN_FAILURE == psBdbEvent->eEventType) {
read_next_zps = true;
} else if (BDB_EVENT_REJOIN_SUCCESS == psBdbEvent->eEventType) {
read_next_zps = true;
}
if(read_next_zps && (BDB_EVENT_ZPSAF == psBdbEvent->eEventType)){
if (ZPS_EVENT_NWK_JOINED_AS_ROUTER == zpsAfEventType) {
connect_result = result_success;
} else if (ZPS_EVENT_NWK_FAILED_TO_JOIN == zpsAfEventType) {
connect_result = result_failed;
}
}
}
My Coordinator looks like this.
void main_task(){
[...]
PDUM_vInitPools();
pdum_vAPduInit(s_asAPduPool, sizeof(s_asAPduPool)/sizeof(pdum_tsAPdu *));
[...]
ZPS_u32MacSetTxBuffers ( 5 );
[...]
APP_vConfigureDevice ( u8DeviceType ); //configure device as Coordinator
ZPS_eAplAfInit();
[...]
sBDB.sAttrib.bbdbNodeIsOnANetwork = ( ( sZllState.eNodeState >= E_RUNNING ) ? ( TRUE ) : ( FALSE ) );
sBDB.sAttrib.bTLStealNotAllowed = !sBDB.sAttrib.bbdbNodeIsOnANetwork;
sArgs.hBdbEventsMsgQ = &APP_msgBdbEvents;
BDB_vInit ( &sArgs );
APP_ZCL_vInitialise();
[...]
BDB_vStart();
test_init();
while(1){
test_task();
zps_taskZPS();
bdb_taskBDB();
[...]
}
}
void test_init(){
start_network();
OSA_TimeDelay(10);
zb_add_mac(IEEE_NODE_1);
OSA_TimeDelay(10);
zb_add_mac(IEEE_NODE_2);
}
void zb_add_mac(uint64_t u64MacAddress) {
uint16_t u16NwkAddr = ZPS_u16AplZdoLookupAddr(u64MacAddress);
if ( ZPS_NWK_INVALID_NWK_ADDR == u16NwkAddr) {
for (u16NwkAddr = 10; u16NwkAddr < ZPS_NWK_INVALID_NWK_ADDR; u16NwkAddr++) {
uint64 volatile u64Mac = ZPS_u64AplZdoLookupIeeeAddr(u16NwkAddr);
if (0 == u64Mac) {
// Empty entry
break;
}
}
}
uint8_t u8Capability = 0x88;
ZPS_teStatus status = ZPS_eAplZdoDirectJoinNetwork(u64MacAddress, u16NwkAddr, u8Capability);
if( ZPS_E_SUCCESS != status ){
// log join failed
}
}The test_task in Coordinator simply waits for certain events, and logs them.
There's quite a bit of code omitted, but I'd be happy to go into more detail, if you can tell which part you're interested in.
Both devices have #define ZPS_APS_AIB_INIT_USE_EXTENDED_PANID 0x0000000000000001ULL set in app_zps_cfg.h, which should ensure they work with the same network, and the same ZPS_APS_AIB_INIT_CHANNEL_MASK.
Again, all of this works fine, until the Router runs into the 0xe8 status code.
I did notice, it will also keep returning this 0xe8 status code for other network related functions.
As this is a MAC code, I tried to reset the MAC layer as defined in the IEEE 802.15.4 MACPHY Application Developer's Guide, but that didn't help.
The only working solution I've found so far, is to simply reboot the Router when it fails to join.
Hello,
I truly apologize, I was not able to reproduce this behavior.
Regards.