一、功能需求
1、協調器創建網絡,並加入一個組,向組內成員組播數據“I am coordinator device \n”
2、終端1加入網絡,並加入與協調器相同的組,收到協調器發送而來的數據
2、終端2加入網絡,並加入另外一個組,不能收到協調器發來的數據
二、實現過程
1、複製工程模板,並重命名
2、加入串口通信代碼
3、配置組播
三、具體操作
1、仍然是我們熟悉的第一步,在我們的工程模板中添加我們的頭文件
打開sampleAPP.c文件
添加我們的兩個頭文件
#include string.h
#include mt_uart.h
2、還是老套的流程,搞一搞串口初始化以及函數打印
以及關閉我們的流控,並設置我們的波特率爲115200
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
MT_UartInit ();
HalUARTWrite ( 0, "uart0 is ok\n", strlen("uart0 is ok\n"));
#if !defined( MT_UART_DEFAULT_OVERFLOW )
#define MT_UART_DEFAULT_OVERFLOW FALSE
#endif
#if !defined MT_UART_DEFAULT_BAUDRATE
#define MT_UART_DEFAULT_BAUDRATE HAL_UART_BR_115200
#endif
3、完成了這些老套的配置,終於正式進入了我們新的組播的環節了,記得把不用的廣播代碼註釋掉
下面進入組播的配置
首先當然是模式端口的基礎配置了
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; //選中組播模式
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; //端口號的確認
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; //組播地址
//go to 進去,可以看到我們組播的地址爲0X0001 ,注意 組播地址必須與組的ID一致
//端口描述符的一些成員複製
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
既然是組播,那麼我們的小組必然要有自己的ID,以及組名,下面我們進行一下配置
SampleApp_Group.ID = 0x0001; //對結構體成員變量賦值 ,這裏我們可以看到與組播地址一致
osal_memcpy( SampleApp_Group.name, "Group 1", 7 ); //將Group 1賦值給SampleApp_Group裏的name數組
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); //將相應的端口加入這個組
我們進入SampleApp_Group 這個結構體來看一下
typedef struct
{
uint16 ID; //組的ID,組號
uint8 name[APS_GROUP_NAME_LEN]; //數組,name 肯定是我們的組名,但是注意name數組的首元素是數組長度
} aps_Group_t;
串口和組播的初始化到此完成,主要做的一些地址的填充,接下來我們進入事件輪詢
如果協調器創建網絡成功,他的網絡狀態也會由初始狀態變爲DEV_ZB_COORD這一狀態
首先,還是在事件組SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);這裏獲取網絡狀態,然後再來判斷是否爲協調器狀態
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);//首先還是在這裏獲取網絡狀態
if (SampleApp_NwkState == DEV_ZB_COORD) //然後判斷是否爲協調器狀態
{
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT, //如果是協調器,我們就用定時器觸發這一事件,週期性的發送數據
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
else
{
}
break;
仍然是我們熟悉的週期性發送數據
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
SampleApp_SendPeriodicMessage();//下面我們go to進入發送消息的配置
// Setup to send message again in normal period (+ a little jitter)
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
協調器發送消息完成了
void SampleApp_SendPeriodicMessage( void )
{
uint8 *buff = "I am coordinator device \n"; //發送數據
if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc, //這裏地址改爲我們組播的地址,在上面的模式選擇裏有
SAMPLEAPP_PERIODIC_CLUSTERID, //命令號不變
strlen(buff), //修改數據長度
buff, //數據
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
發送數據完成之後,我們進入終端的接收數據
進入事件輪詢的,接收到新的消息
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break;
進入消息處理函數
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
switch ( pkt->clusterId ) //首先判斷是哪一個命令號
{
case SAMPLEAPP_PERIODIC_CLUSTERID: //如果是這個命令號,那麼我們通過串口將消息打印到終端上
HalUARTWrite ( 0, pkt->cmd.Data,pkt->cmd.DataLength);
break;
case SAMPLEAPP_FLASH_CLUSTERID:
flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );
HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );
break;
}
}
需要注意的一點是,在我們的模板中,默認讓我們的終端處於低功耗模式,處於休眠狀態,定時的喚醒終端來接收消息
而休眠模式不能接收組播發送的消息,因爲他的接收器沒有打開,我們要讓他的接收器一直打開,那麼我們這樣操作
將代碼的 FALSE 改爲TRUE,就可以讓我們的接收器一直處於打開的狀態
最後進行非組播終端的修改
1、將地址改爲 0X0002
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; //選中組播模式
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; //端口號的確認
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; //組播地址
//這裏go to 進去改
SampleApp_Group.ID = 0x0002; //對結構體成員變量賦值 ,這裏我們可以看到與組播地址一致
osal_memcpy( SampleApp_Group.name, "Group 2", 7 ); //將Group 1賦值給SampleApp_Group裏的name數組
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); //將相應的端口加入這個組
2、組名改爲Group 2
然後編譯即可