ZigBee按键允许入网

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nicole088/article/details/52458772
1.前言
在德州仪器在线技术支持社区看到有zigbee怎么加入指定网络的讨论,TI员工讲到:“像智能家居等个人消费产品,从安全性考虑,正常运行时一般会关闭网络的允许加入功能,有新设备需要加入时,才打开该功能。另外,这些产品一般都会使能网络加密的功能。” 我们可以通过按键来控制Coordinator允许入网;控制Enddevice加入网络。

2.实验方法
一、
Coordinator:
step1.  开启组网 (协调器上电后,网络创建成功,不发送网络信息广播,也不允许任何节点加入网络,只有当连按3次协调器的按键,或者上位机发送准许入网的指令,这时候协调器才发送网络信息广播,准许设备加入网络)
setp2. 控制是否允许节点进入网络 (这里有个时间窗,时间窗内所有的节点都允许正常进入的)

协调器首次上电流程图:


Enddevice:
step1. 开启网络发现 (连按3次按键,设备开启网络发现模式,如果有网络则加入网络)

协调器/网关流程图:

二、
通过串口给协调器"11",协调器收到"11"后通过无线发送给终端或者路由器控制终端的LED灯亮起;终端或者路由器收到"11"后,应答协议器AA
通过串口给协调器"10",协调器收到"10"后通过无线发送给终端或者路由器控制终端的LED灯熄灭;终端或者路由器收到"10"后,同样应答协议器AA

3.代码
Coordinator:
<span style="font-family:Comic Sans MS;"><span style="font-family:Courier New;"><strong><span style="font-size:14px;"></span>
<span style="font-family:Comic Sans MS;">case ZDO_STATE_CHANGE: 
    if(GenericApp_NwkState==DEV_ZB_COORD)
          {
             GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;   
             GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;

             //地址设置为广播地址,数据将广播给网络中的所有节点
             GenericApp_DstAddr.addr.shortAddr = 0xffff;

             //禁止节点加入
             <span style="background-color: rgb(255, 255, 51);">NLME_PermitJoiningRequest(0);</span>
          }
   break; </span>
<span style="font-family:Comic Sans MS;"></span><span style="font-size: 16px;"> </span></strong></span></span>
分析: 在网络状态改变事件里判断如果是协调器 GenericApp_NwkState==DEV_ZB_COORD 地址设置为广播地址, 禁止所有设备入网。
<span style="font-family:Comic Sans MS;"><span style="font-family:Courier New;font-size:14px;"><strong></span>
<span style="font-family:Comic Sans MS;">if ( keys & HAL_KEY_SW_6 )
    {
       DB_KEY_CNT ++;
       if(DB_KEY_CNT == 3)
       {
          DB_KEY_CNT = 0;
          if(GenericApp_NwkState == DEV_ZB_COORD) //网络是协调器
          {
             NLME_PermitJoiningRequest(60);        //开启入网: 1分钟
             osal_start_timerEx( GenericApp_TaskID,
                                 PermitJOIN_TIMEOUT_EVT,
                                 60000 );
             HalLedBlink ( HAL_LED_1, 0, 50, 500 ); //led 闪烁
             HalUARTWrite( MT_UART_DEFAULT_PORT, "允许入网\r\n", 10);
          }
         else
          {
             static uint8 flag = 0;
             if(flag)
             {
               NLME_LeaveReq_t req;
               req.extAddr = NULL;
               req.rejoin = TRUE;
               req.removeChildren = FALSE;
               req.silent = FALSE;
               NLME_LeaveReq( &req );
               HalLedSet (HAL_LED_1, HAL_LED_MODE_ON);
               HalUARTWrite( MT_UART_DEFAULT_PORT, "离开网络\r\n", 10);
             }else
             {
               devState = DEV_HOLD;
               ZDOInitDevice( 0 );               //加入网络
               HalLedBlink ( HAL_LED_1, 0, 50, 500 ); //led 闪烁
               HalUARTWrite( MT_UART_DEFAULT_PORT, "尝试入网中\r\n", 12);
             }
             flag = !flag;
          }
       }
       osal_start_timerEx( GenericApp_TaskID,KEY_TIMEOUT_EVT,KEY_INTERVAL_MONITOR_TIME );
    }</span>
<span style="font-family:Comic Sans MS;"></strong></span></span>
分析:在按键事件处理函数中首先,判断按键的次数,如果为3次;再次判断网络是否为协调器,如果是协调器开启入网时窗;否则认为是终端或者路由器。然后,通过flag 标记是否为第一次入网。

req.rejoin = TRUE; //TRUE允许设备重新加入网络;FALSE不允许设备重新加入网络
req.removeChildren =FALSE; //TRUE 子设备也脱离,FALSE只脱离当前设备

NLME_PermitJoiningRequest(byte  PermitDuration)
PermitDuration=0xFF:允许其他设备加入本协调器建立的网络 
PermitDuration=0x00:禁止
API使用说明:
NLME_PermitJoiningRequest只管本节点是否允许其他设备加入,管不了整个网络。
所以多级组网或者设备很多的时候,不但协调器的Permit需要打开,下面Router的Permit也要打开,否则一旦设备和协调器之间无法直接通信,或者协调器直接挂载的设备数已经达到最大值,都会导致设备无法入网。
同样,设备退网的时候,也需要将整个网络的Permit都关掉,不然的话,设备一退网,如果发入网请求的话,又会加回来,这就是有人说的设备退不了网的情况。
NLME_PermitJoiningRequest   是让协调器自己关掉入网(是对于自己而言,开启或者关闭本地端,允许其他设备入网)。
ZDP_MgmtPermitJoinReq   是让协调器关掉附件路由的入网,地址就是路由器的地址,一般发个广播就行(是通过地址,告诉某个设备或者所有路由开启或者关闭,允许其他设备网)。
注意:如果通信是加密的, 那么 就必须有一个trust center。 一般是协调器,因为我上面的通信是加密的, 关了协调器 就没有了 trust center,导致了 终端只能association  不能入网。

Enddevice:
<span style="font-family:Comic Sans MS;"><strong><span style="font-family:Courier New;font-size:14px;"></span>
<span style="font-family:Comic Sans MS;">case ZDO_STATE_CHANGE:         //net state change
     GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
     if(GenericApp_NwkState == DEV_END_DEVICE)
     {
          GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
          GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;
          GenericApp_DstAddr.addr.shortAddr = 0x0;
          HalUARTWrite( MT_UART_DEFAULT_PORT, (uint8*)END_CODD, sizeof(END_CODD));
     }
 break;</span>
<span style="font-family:Comic Sans MS;"></span></strong></span>
按键事件处理函数中 加入网络。
<span style="font-family:Comic Sans MS;"><span style="font-family:Courier New;font-size:14px;"><strong></span>
<span style="font-family:Comic Sans MS;">devState = DEV_HOLD;
ZDOInitDevice( 0 );               //加入网络
HalLedBlink ( HAL_LED_1, 0, 50, 500 ); //led 闪烁
HalUARTWrite( MT_UART_DEFAULT_PORT, "尝试入网中\r\n", 12);</span>
<span style="font-family:Comic Sans MS;"></strong></span></span>

硬件连接


猜你喜欢

转载自blog.csdn.net/nicole088/article/details/52458772