z-stack组网分:协调器建立网络、路由器和终端加入网络

暂时只记录第一次上电建立网络的过程,至于开启NV_RESTORE后,恢复原有的网络则暂时不分析。

一、协调器建立网络:

1、ZDO层的ZDApp_Init中有如下函数:

  if ( devState != DEV_HOLD )     // 如果不希望自动启动,则可以在这个函数调用前,把devState设置为DEV_HOLD,然后在需要启动的时候设置为DEV_INIT
{
ZDOInitDevice( ); // 启动设备,里面就包含了组网
}
else
{
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, , , );
}

2、ZDOInitDevice()中如果定义了NV_RESTORD,则可以通过按键选择是新建一个网络,或者是读取NV中的网络进行恢复,我们这里假设NV_RESTORE没有定义,直接新建一个网络。

  if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )   // 判断是新建一个网络
{
ZDAppDetermineDeviceType(); // 确定当前设备类型为NODETYPE_COORDINATOR协调器,设备启动模式为MODE_HARD // Only delay if joining network - not restoring network state
extendedDelay = (uint16)((NWK_START_DELAY + startDelay)
+ (osal_rand() & EXTENDED_JOINING_RANDOM_MASK));
} // Initialize the security for type of device
ZDApp_SecInit( networkStateNV ); // Trigger the network start
ZDApp_NetworkInit( extendedDelay ); // 开始网络初始化,我们这里协调器开始建立网络 // set broadcast address mask to support broadcast filtering
NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );

3、ZDApp_NetworkInit()函数,设置了一个事件定时器,当事件达到,触发ZDO_NETWORK_INIT事件

void ZDApp_NetworkInit( uint16 delay )
{
if ( delay )
{
// Wait awhile before starting the device
osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );
}
else
{
osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
}
}

4、ZDApp_event_loop则检测ZDO层的任务,当发现ZDO_NETWORK_INIT事件后,会执行如下:

  if ( events & ZDO_NETWORK_INIT )
{
// Initialize apps and start the network
devState = DEV_INIT;

// 以前面确定的节点类型NODETYPE_COORDINATOR(协调器),启动方式MODE_HARD启动设备
ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER ); // Return unprocessed events
return (events ^ ZDO_NETWORK_INIT);
}

5、ZDO_StartDevice()函数调用如下函数开始形成网络:

  if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )
{
if ( startMode == MODE_HARD )
{
devState = DEV_COORD_STARTING; // 把设备状态更改为协调器启动中,并且开始建立网络
// 调用网络形成函数开始建立网络,需要的信息需要我们设置的主要包括PANID,信道
ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,
zgDefaultStartingScanDuration, beaconOrder,
superframeOrder, false );
}

6、NLME_NetworkFormationRequest()函数是通过网络层像空间发送建立网络请求,其中通过抓包软件发现,他会想空间发送一个BEACON信号,来获取空间中的网络情况,然后建立自己的网络,如果自己的网络和空间中的网络的PANID相同,则会在此PANID上+1,
7、NLME_NetworkFormationRequest()函数发出request请求后会得到一个confirm,这个confirm函数为ZDO_NetworkFormationConfirmCB(),如果status的值为ZSUCCESS,则此网络成功建立,网络建立成功或者失败,都需要告知ZDO层,ZDO层好根据情况作出相应的合适的处理。

/*********************************************************************
* @fn ZDO_NetworkFormationConfirmCB
*
* @brief This function reports the results of the request to
* initialize a coordinator in a network.
*
* @param Status - Result of NLME_NetworkFormationRequest()
*
* @return none
*/
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )
{
nwkStatus = (byte)Status; if ( Status == ZSUCCESS )
{
// LED on shows Coordinator started
HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON ); // LED off forgets HOLD_AUTO_START
HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF); #if defined ( ZBIT )
SIM_SetColor(0xd0ffd0);
#endif if ( devState == DEV_HOLD )
{
// Began with HOLD_AUTO_START
devState = DEV_COORD_STARTING;
}
}
#if defined(BLINK_LEDS)
else
{
HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure
}
#endif osal_set_event( ZDAppTaskID, ZDO_NETWORK_START ); // 通知ZDO层,设置一个ZDO_NETWORK_START事件
}

8、ZDApp_event_loop处理上面触发的ZDO_NETWORK_START事件

    if ( events & ZDO_NETWORK_START )
{
ZDApp_NetworkStartEvt(); // Return unprocessed events
return (events ^ ZDO_NETWORK_START);
}

9、ZDO_NETWORK_START事件调用了ZDApp_NetworkStartEvt()函数,如果之前网络已经建立成功则设置ZDO_STATE_CHANGE_EVT事件,否则增大发射功率再次设置ZDO_NETWORK_INIT事件,重新开始建立网络,具体函数如下:

void ZDApp_NetworkStartEvt( void )
{
if ( nwkStatus == ZSuccess )
{
// Successfully started a ZigBee network
if ( devState == DEV_COORD_STARTING )
{
devState = DEV_ZB_COORD;
} osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
}
else
{
// Try again with a higher energy threshold !!
if ( ( NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT ) < 0xff )
{
NLME_SetEnergyThreshold( (uint8)(NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT) );
osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
}
else
{
// Failed to start network. Enter a dormant state (until user intervenes)
devState = DEV_INIT;
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
}
}
}

10、ZDO_STATE_CHANGE_EVT事件调用函数ZDO_UpdateNwkStatue()函数,此函数会把该网络变化情况通知给所有的应用层端点,以便用户根据此通知做相应处理,具体函数如下:

void ZDO_UpdateNwkStatus(devStates_t state)
{
epList_t *pItem = epList; while (pItem != NULL)
{
if (pItem->epDesc->endPoint != ZDO_EP)
{
// 发送消息给所有的应用层任务和端点
zdoSendStateChangeMsg(state, *(pItem->epDesc->task_id));
} pItem = pItem->nextDesc;
}
#if defined MT_ZDO_CB_FUNC
zdoSendStateChangeMsg(state, MT_TaskID);
#endif ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
}

11、至此协调器成功建立网络并且告知应用层。路由器和终端加入网络的过程在下一节继续分析。

z-stack组网过程的更多相关文章

  1. FastDFS配置过程

    在我的生产环境中利用FastDFS实现动静分离的方案

  2. [ZOJ 4016] Mergable Stack

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4016 直接用栈爆内存,看网上大神用数组实现的,构思巧妙,学习了! ...

  3. 算法之美--2.3.1 Z字形编排问题

    2016-12-08   00:23:11 写在前面的话:万事贵在坚持,万事开头难,有很多的东西要学,要知道主次,讲究效率,大的方向对就行!坚持........ 一.图像压缩编码中的Z字排序 JPEG ...

  4. KMP&Z函数详解

    KMP 一些简单的定义: 真前缀:不是整个字符串的前缀 真后缀:不是整个字符串的后缀 当然不可能这么简单的,来个重要的定义 前缀函数: 给定一个长度为\(n\)的字符串\(s\),其 \(前缀函数\) ...

  5. 基于ZigBee的家居控制系统的设计与应用

    基于ZigBee的家居控制系统的设计与应用 PPT简介:http://pan.baidu.com/s/1i38PC6D 摘  要 智能家居是未来家居的发展方向,其利用先进的网络技术.计算机技术和无线通 ...

  6. [转][C/C++]函数名字修饰(Decorated Name)方式

    1.C/C++函数修饰名: 对于我们的C/C++源程序而言,函数名只是函数的一小部分,函数还有调用方式(参数入栈方式).返回值类型.参数个数和各参数类型等信息,对于C++类成员函数,还有更多信息.这些 ...

  7. Java设计模式----解释器模式

    计算器中,我们输入“20 + 10 - 5”,计算器会得出结果25并返回给我们.可你有没有想过计算器是怎样完成四则运算的?或者说,计算器是怎样识别你输入的这串字符串信息,并加以解析,然后执行之,得出结 ...

  8. 算法语言Scheme修订6报告 R6RS简体中文翻译

    算法语言Scheme修订6报告 R6RS简体中文翻译 来源 https://r6rs.mrliu.org/   MICHAEL SPERBERR. KENT DYBVIG, MATTHEW FLATT ...

  9. ufldl学习笔记与编程作业:Multi-Layer Neural Network(多层神经网络+识别手写体编程)

    ufldl学习笔记与编程作业:Multi-Layer Neural Network(多层神经网络+识别手写体编程) ufldl出了新教程,感觉比之前的好,从基础讲起,系统清晰,又有编程实践. 在dee ...

随机推荐

  1. vtk多线程简单测试

    vtkMultithreader is a class that provides support for multithreaded execution using sproc() on an SG ...

  2. Oracle函数组的使用

    --1.组函数--COUNT():用来统计记录的条数 如果没有记录,返回 0--COUNT函数可以根据一列或多列进行计算,没有排重功能--统计EMP表一共有多少条记录select count(empn ...

  3. C#进阶目录

    一.Sql语句的性能优化 二.Quartz.NET的介绍 三.Log4.Net的介绍 四.Topshelf的介绍 五.Git的使用 六.IEnumerable接口迭代原理 七.Lambada表达式的演 ...

  4. 小明的密码-初级DP解法

    #include #include #include using namespace std; int visited[5][20][9009];// 访问情况 int dp[5][20][9009] ...

  5. sublime text快捷键

    Ctrl+Shift+V:粘贴并格式化Ctrl+D:选择单词,重复可增加选择下一个相同的单词Ctrl+L:选择行,重复可依次增加选择下一行Ctrl+M:跳转到对应括号Ctrl+K+B:开关侧栏Ctrl ...

  6. 【Network】修改docker启动默认网桥docker0为自定义网桥

    自定义网桥 除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器. 在启动 Docker 服务的时候,使用 -b BRIDGE或--bridge=BRIDGE 来指定使用的网桥. 如果服 ...

  7. caffe_实战之两个简单的例子(物体分类和人脸检测)

    一.物体分类: 这里使用的是caffe官网中自带的例子,我这里主要是对代码的解释~ 首先导入一些必要的库: import caffe import numpy as np import matplot ...

  8. Devils never rest

    一个人 练习一个人 书名 看到就被吸引了,然后亚马逊下手 作者很文艺,我很喜欢作者内心的那份宁静. 我一个人吃饭 旅行 到处走走停停 也一个人看书 写信 自己对话谈心 依然是心内一片寂静,总是不由自主 ...

  9. 安卓真机调试 出现Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE....

    [2016-08-20 14:38:39 - hybrid-android] Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE[2016-0 ...

  10. CentOS7 学习笔记

    1.首先centos7 采用了systemd管理系统服务的启动 systemd结合了以前红帽子的service 与chkconfig systemctl [command] [unit]   comm ...