zigbee學習筆記十二—組播通信

一、功能需求

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
然後編譯即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章