點播、組播、廣播
一、基礎知識補充
Zigbee的通信方式主要有三種:點播、組播、廣播。
點播就是點對點通信,也就是兩個設備之間的通信,不允許第三個設備收到信息。
組播就是把網絡中的節點分組,每一個組員發出的信息只有相同組號的組員才能收到。
廣播,最廣泛的就是1個設備上發出的信息所以設備都能接收到。
二、點播實驗步驟
因為要將收到的數據通過串口顯示在屏幕上,所以在程序開始之前先把串口初始化吧~設置波特率和關閉流控不要忘記!完成后就開始點播實驗吧~
- 打開AF.h,找到圖1所示代碼段。該類型是枚舉類型。
圖1
我們需要知道的是Addr16Bit表示點播,AddrGroup表示組播,AddrBroadcast表示廣播。
打開SampleApp.c聲明一個結構體變量(如圖2)
afAddrType_t Point_To_Point_DstAddr;
圖2
這個是點對點通信的定義。查看afAddrType_t的定義就可以知道其中包含哪些內容。這個結構體是用於選擇你將要進行哪種方式的通信。在后面發送數據的函數中會用到。
2. 聲明了結構體變量就要對其進行初始化對吧?初始化的代碼一般都寫在初始化函數SampleApp_Init()中。我們現在來對Point_To_Point_DstAddr進行配置吧。
代碼如下:
Point_To_Point_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//點播 Point_To_Point_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; Point_To_Point_DstAddr.addr.shortAddr = 0x00; //發送給協調器
圖3
注意最后一個值是0x0000,這個是協調器的地址,這樣配置我們就可以確保只發送給協調器啦。如圖3我們還可以看到另外兩個同結構體類型的初始化配置。它們的通信方式分別是廣播和組播。廣播的發送地址是0xFFFF,這個是指發送給全部的設備。組播的發送地址從變量名就可以看出是發送給同一組內成員噠。
3. 在SampleApp.c下添加自己的點對點發送函數。

1 void SampleApp_SendPointToPointMessage(void) 2 3 { 4 5 uint8 data[10] = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’}; 6 7 if ( AF_DataRequest( &Point_To_Point_DstAddr, &SampleApp_epDesc, 8 9 SAMPLEAPP_POINT_TO_POINT_CLUSTERID, 10 11 10, 12 13 &data[0], 14 15 &SampleApp_TransID, 16 17 AF_DISCV_ROUTE, 18 19 AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) 20 21 { 22 23 } 24 25 else 26 27 { 28 29 // Error occurred in request to send. 30 31 } 32 33 }
這個格式應該看着挺熟悉了吧,之前好幾次有涉及過,這里就不解釋啦。就注意一點,函數的傳遞參數沒有的話要加void,不然可能會報錯哦。
函數寫好了不要忘記在文件開頭加上函數聲明呢,不然程序會找不到......
4. 剛才寫的函數不知道你們有沒有仔細看,其實里面有一個參數是還沒有定義過的哦。就是SAMPLEAPP_POINT_TO_POINT_CLUSTERID啦。這個類型的參數應該也挺眼熟的吧......打開SampleApp.h,找到它們的同類,在后面加上一句:
#define SAMPLEAPP_FLASH_CLUSTERID 3
同時不要忘了把SAMPLEAPP_MAX_CLUSTERS的值改3!
圖4
5. 寫完發送函數就要把它用上!找到事件處理函數SampleApp_ProcessEvent();找到里面的if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )語句(因為我們要周期性發送數據,所以就選它啦),發現里面已經有一個廣播的發送函數啦。我們要做的就是用點播的函數把它替換掉!(如圖5)
圖5
這樣我們就可以實現周期性點播發送函數啦。
6. 發送處理完就要考慮接收啦。在SampleApp.c下找到發送函數SampleApp_MessageMSGCB();我們在其中把發送的代碼寫上,同時把廣播發送的代碼刪除。(如圖6)
圖6
7. 由於協調器不能給自己點播,我們需要在周期性點播初始化的地方把它注釋掉。(如圖7)
圖7
三、點播實驗結果
將編譯好的程序分別以協調器、路由器、終端的方式下載到3個節點設備中。連接串口后可以看到只有協調器收到了信息。
圖8
四、點播實驗流程總結
圖9
五、組播實驗步驟
一開始先串口初始化!
- 來看下SampleApp.c關於組播的定義。之前我們就知道組播afAddrType_t的類型變量已經定義好的了,變量名是SampleApp_Flash_DstAddr。
然后,注意看,該定義下面還有一行關於組播的代碼
aps_Group_t SampleApp_Group;
這行代碼是關於分組內容的。
圖10
2. 再看組播參數的配置。其實已經給我們配置好了。在同一個函數里面再往下看,可以看到有關於分組的配置。為了以后操作方便(其實我沒覺得方便...),可以稍微修改一下。我們可以看到現在配置的分組ID是0x0001,我們把這個改成SAMPLEAPP_FLASH_GROUP,這樣以后該分組只要在SAMPLEAPP_FLASH_GROUP定義里面修改就可以了。看吧,其實沒有方便......
圖11
3. 然后我們就可以開始添加自己的組播發送函數啦。代碼如下:

1 void SampleApp_SendGroupMessage(void) 2 3 { 4 5 uint8 data[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; 6 7 if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc, 8 9 SAMPLEAPP_FLASH_CLUSTERID, 10 11 10, 12 13 data, 14 15 &SampleApp_TransID, 16 17 AF_DISCV_ROUTE, 18 19 AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) 20 21 { 22 23 } 24 25 else 26 27 { 28 29 // Error occurred in request to send. 30 31 } 32 33 }
這里對代碼不再做解釋啦(我懶...),也不需要再加定義什么的,就是不要忘了在文件開頭加上函數聲明。
4. 把事件處理函數里面原有的組播函數換成我們自己寫的。(如圖12)
圖12
5. 然后就到接收部分啦。在接收到組播信息部分,修改代碼如下:
1 case SAMPLEAPP_FLASH_CLUSTERID: 2 3 HalUARTWrite(0, "I get data:", 11); 4 5 HalUARTWrite(0, &pkt->cmd.Data[0], pkt->cmd.DataLength); 6 7 HalUARTWrite(0, "\n", 1); 8 9 //flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); 10 11 //HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); 12 13 break;
圖13
六、組播實驗結果
程序分別下載到一個協調器,兩個路由器。其中協調器和路由器1組號為0x0001,路由器2組號為0x0002。(如圖14)
圖14
連接串口,可以看到只有協調器和路由器1相互發送信息。
七、廣播實驗步驟
廣播實驗就更方便了......不過還是要初始化串口!
- 看到廣播參數的配置
// Setup for the periodic message's destination address // Broadcast to everyone SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
0xFFFF是廣播地址
廣播地址有3種類型:
0xFFFF——數據包將被傳送到網絡上的所以設備
0xFFFD——數據包將被傳送到網絡上的所有在空閑時打開接收的設備,即除睡眠中的所以設備
0xFFFC——數據包發送給所有的路由器,包括協調器
2. 找到自帶廣播發送函數,修改代碼如下:

void SampleApp_SendPeriodicMessage( void ) { uint8 data[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 10, data, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { } else { // Error occurred in request to send. } }
3. 修改接收的代碼:
1 case SAMPLEAPP_PERIODIC_CLUSTERID: 2 3 HalUARTWrite(0, "I get data:", 11); 4 5 HalUARTWrite(0, &pkt->cmd.Data[0], pkt->cmd.DataLength); 6 7 HalUARTWrite(0, "\n", 1); 8 9 break;
八、廣播實驗結果
把程序分別下載到協調器、路由器、終端。可以看到各個設備都在廣播發送信息,同時接收廣播信息。