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>