Z-stack终端加入网络与阅读协议栈的方法
来源:互联网 发布:淘宝上怎样收藏店铺 编辑:程序博客网 时间:2024/06/14 14:33
终端加入网络,学习ZgiBee已经有两个月了;如何读像协议栈这种大量的代码;
NUM_DISC_ATTEMPTS 这个参数觉得了发送beancon的次数,默认值是2,发送3次(扫描三次网络后)加入网络。
1、加入网络的过程得回调函数ZDO_NetworkDiscoveryConfirmCB()开始说明
ZDO_NetworkDiscoveryConfirmCB();
这是终端的回调函数
ZStatus_t ZDO_NetworkDiscoveryConfirmCB(uint8 status)
{
osal_event_hdr_t msg;
// If Scan is initiated by ZDO_MGMT_NWK_DISC_REQ
// Send ZDO_MGMT_NWK_DISC_RSP back
#if/**/defined ( ZDO_MGMT_NWKDISC_RESPONSE )
if ( zdappMgmtNwkDiscReqInProgress )
{
zdappMgmtNwkDiscReqInProgress = false;
ZDO_FinishProcessingMgmtNwkDiscReq();
}
else
#endif
{
// Pass the confirm to another task if it registers the callback
// Otherwise, pass the confirm to ZDApp.
if (zdoCBFunc[ZDO_NWK_DISCOVERY_CNF_CBID] != NULL )
{
zdoCBFunc[ZDO_NWK_DISCOVERY_CNF_CBID]( (void*)&status );
}
else
{//前面的不太懂,但是这并没有我需要的内容,单步调试走到这里,接着跳到其函数
// Otherwise, send scan confirm to ZDApp task to proceed
msg.status = ZDO_SUCCESS;
ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_DISC_CNF, sizeof(osal_event_hdr_t), (uint8 *)&msg );
}
}
return (ZSuccess);
} // ZDO_NetworkDiscoveryConfirmCB
2、跳到了ZDA的loop函数,
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,//跳到这里了
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
SerialApp_ProcessEvent,
NodeMgmtApp_ProcessEvent //131204zcl:节点管理应用 事件处理函数
};
UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
uint8 *msg_ptr;
if ( events & SYS_EVENT_MSG )
{
while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )
{
ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );
// Release the memory
osal_msg_deallocate( msg_ptr );
}
// Return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
case ZDO_NWK_DISC_CNF://从ZDO_NetworkDiscoveryConfirmCB()跳过来
if (devState != DEV_NWK_DISC)
break;
if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
{
// Process the network discovery scan results and choose a parent
// device to join/rejoin itself
networkDesc_t *pChosenNwk;
if ( ( (pChosenNwk = ZDApp_NwkDescListProcessing()) != NULL ) && (zdoDiscCounter > NUM_DISC_ATTEMPTS) )//我们首先判断是否有合适的网络,网络的此时是否大于2次,这样子才对网络进行判断。
{
if ( devStartMode == MODE_JOIN )
{
devState = DEV_NWK_JOINING;
ZDApp_NodeProfileSync( pChosenNwk->stackProfile);
if ( NLME_JoinRequest( pChosenNwk->extendedPANID, pChosenNwk->panId,
pChosenNwk->logicalChannel,
ZDO_Config_Node_Descriptor.CapabilityFlags,
pChosenNwk->chosenRouter, pChosenNwk->chosenRouterDepth ) != ZSuccess )
{
ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
+ ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
}
} // if ( devStartMode == MODE_JOIN )
else if ( devStartMode == MODE_REJOIN )
{
ZStatus_t rejoinStatus;
devState = DEV_NWK_REJOIN;
// Before trying to do rejoin, check if the device has a valid short address
// If not, generate a random short address for itself
if ( _NIB.nwkDevAddress == INVALID_NODE_ADDR )
{
uint16 commNwkAddr;
// Verify if the Network address has been commissioned by external tool
if ( ( osal_nv_read( ZCD_NV_COMMISSIONED_NWK_ADDR, 0,
sizeof(commNwkAddr),
(void*)&commNwkAddr ) == ZSUCCESS ) &&
( commNwkAddr != INVALID_NODE_ADDR ) )
{
_NIB.nwkDevAddress = commNwkAddr;
// clear Allocate address bit because device has a commissioned address
_NIB.CapabilityFlags &= ~CAPINFO_ALLOC_ADDR;
}
else
{
_NIB.nwkDevAddress = osal_rand();
}
ZMacSetReq( ZMacShortAddress, (byte*)&_NIB.nwkDevAddress );
}
// Check if the device has a valid PanID, if not, set it to the discovered Pan
if ( _NIB.nwkPanId == INVALID_PAN_ID )
{
_NIB.nwkPanId = pChosenNwk->panId;
ZMacSetReq( ZMacPanId, (byte*)&(_NIB.nwkPanId) );
}
tmp = true;
ZMacSetReq( ZMacRxOnIdle, &tmp ); // Set receiver always on during rejoin
// Perform Secure or Unsecure Rejoin depending on available configuration
if ( ZG_SECURE_ENABLED && ( ZDApp_RestoreNwkKey() == TRUE ) )
{
rejoinStatus = NLME_ReJoinRequest( ZDO_UseExtendedPANID, pChosenNwk->logicalChannel);
}
else
{
rejoinStatus = NLME_ReJoinRequestUnsecure( ZDO_UseExtendedPANID, pChosenNwk->logicalChannel);
}
if ( rejoinStatus != ZSuccess )
{
ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
+ ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
}
} // else if ( devStartMode == MODE_REJOIN )
// The receiver is on, turn network layer polling off.
if ( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE )
{
// for an End Device with NO Child Table Management process or for a Router
if ( ( ZG_DEVICE_RTR_TYPE ) ||
#if/**/defined ( ZIGBEE_CHILD_AGING )
( (ZG_DEVICE_ENDDEVICE_TYPE) && ( zgChildAgingEnable == FALSE ) ) )
#else
(ZG_DEVICE_ENDDEVICE_TYPE) )
#endif // ZIGBEE_CHILD_AGING
{
NLME_SetPollRate( 0 );
NLME_SetQueuedPollRate( 0 );
NLME_SetResponseRate( 0 );
}
}
else
{
if ( (ZG_SECURE_ENABLED) && (devStartMode == MODE_JOIN) )
{
ZDApp_SavedPollRate = zgPollRate;
NLME_SetPollRate( zgRejoinPollRate );
}
}
}
else
{
//HalLedSet ( HAL_LED_2, HAL_LED_MODE_FLASH ); // 20131118zcl:闪烁黄灯指示发现网络失败
//HalLedBlink ( HAL_LED_2, 100, 50, 500 );
if ( continueJoining )
{
#if/**/defined ( MANAGED_SCAN )
ZDApp_NetworkInit( MANAGEDSCAN_DELAY_BETWEEN_SCANS );
#else
zdoDiscCounter++;
if(zdoDiscCounter < 11)
{
ZDApp_NetworkInit( (uint16)(BEACON_REQUEST_DELAY
+ ((uint16)(osal_rand()& BEACON_REQ_DELAY_MASK))) );
}
#endif
}
}
}
break;
3、进入ZDApp_NwkDescListProcessing()这个函数
networkDesc_t* ZDApp_NwkDescListProcessing(void)
{
networkDesc_t *pNwkDesc;
uint8 i, ResultCount = 0;
uint8 stackProfile;
uint8 stackProfilePro;
uint8 selected;
// Count the number of nwk descriptors in the list
pNwkDesc = nwk_getNwkDescList();
while (pNwkDesc)
{
ResultCount++;
pNwkDesc = pNwkDesc->nextDesc;
}//将所有网络的信息放进去了,找到我们所需要的信息,看是否有一个网络,还是两个网络,OK我们来测试一下
// process discovery results
stackProfilePro = FALSE;
selected = FALSE;
for ( stackProfile = 0; stackProfile < STACK_PROFILE_MAX; stackProfile++ )
{
pNwkDesc = nwk_getNwkDescList();
for ( i = 0; i < ResultCount; i++, pNwkDesc = pNwkDesc->nextDesc )
{
/*140215zcl:取消掉扩展PANID的判断。这样路由设备的终端子节点才不会在父节点改变PANID后跟过去。
接下来判断了Bencon Paylodad的内容,
从他的PANID开始判断,依次往后进行判断,Dev.Cap,Dev.Depth 等等依次判断。
问题就来了:为什么它没有从物理层开始那,没有判断Superframe specification那?
首先要知道TI的协议栈并不是完全开源的协议栈,那么这些判断都是在低层就完成的。
if ( nwk_ExtPANIDValid( ZDO_UseExtendedPANID ) == true )
{
If the extended Pan ID is commissioned to a non zero value
Only join the Pan that has match EPID
if ( osal_ExtAddrEqual( ZDO_UseExtendedPANID, pNwkDesc->extendedPANID) == false )
continue;
}
else */if ( zgConfigPANID != 0xFFFF )
{
// PAN Id is preconfigured. check if it matches
if ( pNwkDesc->panId != zgConfigPANID )
continue;
}
// check that network is allowing joining
if ( ZSTACK_ROUTER_BUILD )
{
if ( stackProfilePro == FALSE )
{
if ( !pNwkDesc->routerCapacity )
{
continue;
}
}
else
{
if ( !pNwkDesc->deviceCapacity )
{
continue;
}
}
}
else if ( ZSTACK_END_DEVICE_BUILD )
{
if ( !pNwkDesc->deviceCapacity )
{
continue;
}
}
// check version of zigbee protocol
if ( pNwkDesc->version != _NIB.nwkProtocolVersion )
continue;
// check version of stack profile
if ( pNwkDesc->stackProfile != zgStackProfile )
{
if ( ((zgStackProfile == HOME_CONTROLS) && (pNwkDesc->stackProfile == ZIGBEEPRO_PROFILE))
|| ((zgStackProfile == ZIGBEEPRO_PROFILE) && (pNwkDesc->stackProfile == HOME_CONTROLS)) )
{
stackProfilePro = TRUE;
}
if ( stackProfile == 0 )
{
continue;
}
}
break;
}
if (i < ResultCount)
{
selected = TRUE;
break;
}
// break if selected or stack profile pro wasn't found
if ( (selected == TRUE) || (stackProfilePro == FALSE) )
{
break;
}
}
if ( i == ResultCount )
{
return (NULL); // couldn't find appropriate PAN to join !
}
else
{
return (pNwkDesc);//最后我们我们找到了一个网络。
}
}// ZDApp_NwkDescListProcessing()
这次是师傅带着我过完了终端加入网络过程,有很多的技巧需要注意。
1、Zstack是一个半开源的协议栈,有些数据包的解析(特别是低层数据包的解析),我们往往是看不到的,我们看到的是从网络层的数据包看的,那么我们应该如何去学习那?
答案:刚开始认为编程应该是一句一句的读懂, 这样子做事没错的,但这是学习裸机的方法,而面对这上万行的代码,又有人说我们就是看API,这种说法也是很片面的,只看API你觉得你有信心看完吗?有意思吗?
正确的方式应该是结合这我们的捕包工具的数据包,来分析一包数据是有谁发起的,函数是在哪里执行的,在哪里把值給判断出来的,缩小范围到几个API函数,进而对着几个API函数分析,有时API函数也会非常的复杂,我们可以通过设置端点,观察状态值(我们认为的),观察结构体(里面所有的数据都在里面),结合逻辑去分析。
当你在看一个简单的函数时,你需要看懂每一个标志位,一步一步的走通;
当你在看一个协议栈时,你更应该从协议栈的总体高度去分析问题,从功能性上分析实现的过程,而不是仅仅的去考虑函数的具体实现,寄存器的值的。
0 0
- Z-stack终端加入网络与阅读协议栈的方法
- Zigbee协议栈--Z-Stack的使用
- Z-stack协议栈中路由与普通节点的区别
- Z-stack协议栈中路由与普通节点的区别
- Z-Stack中SimpleApp开关结点加入网络流程
- 揭开ZigBee 2006协议栈Z-Stack的”开源“面纱
- 学习z-stack协议栈的serialApp例子(1)
- ZigBee协议栈Z-Stack开发指南的一些翻译
- 揭开ZigBee 协议栈Z-Stack的”开源“面纱
- 学习z-stack协议栈的serialApp例子(1)
- TI z-stack协议栈 sampleApp分析
- ZigBee协议栈TI Z-Stack分析
- ZigBee协议栈TI Z-Stack分析
- z-stack 协议栈修改按
- TI Z-Stack协议栈架构分析
- ZigBee协议栈Z-Stack开发指南(翻译的TI的手册Z-Stack Developer's Guide.pdf)
- 揭开ZigBee 2006协议栈Z-Stack的”开源“面纱 以及其它的开源协议
- Zstack协议栈中CC2530协调器掉电重启后重新加入之前网络的方法
- android开发training之actionbar之2
- Linux搭建Git服务器 windwos下 Git Bash, TortoiseGit 的使用
- ie8不支持transform: translateY,ie9支持不友好
- appears to have started a thread named [startQuertz_xxx] but has failed to stop it. This is very...
- js图片滚动实例
- Z-stack终端加入网络与阅读协议栈的方法
- C# DataSet和DataTable详解
- Python初学之导入Numpy函数库
- Node入门
- 关于ActiveMQ使用
- 单片机 远程开关量电压转换
- node.js 里面执行shell命令如何escape string
- python 函数-enumerate的用法
- 伟大程序员必须具备的7个好习惯