ZigBee开发(15)--组网实验点播

时间:2024-02-16 11:49:42

/***考试周,我抓紧把ZigBee的记录补一下,其实早就做了,被学院的事情耽搁了,博客一直没写,这两天给他补上************/

前言: Zigbee 的通讯方式主要有三种点播、组播、广播。点播,顾名思义就是点对点通信,也就是 2 个设备之间的通讯,不容许有第三个设备收到信息;组播,就是把网络中的节点分组,每一个组员发出的信息只有相同组号的组员才能收到。广播,最广泛的也就是 1 个设备上发出的信息所有设备都能接收到。这也是 ZigBee 通信的基本方式。
点播(点对点通讯)

点播描述的就是网络中 2 个节点相互通信的过程。确定通信对象的就是节点的 16bit 短地址。

首先,在AF.H文件中,可以看到这段代码

1 typedef enum
2 {
3   afAddrNotPresent = AddrNotPresent,
4   afAddr16Bit      = Addr16Bit,
5   afAddr64Bit      = Addr64Bit,
6   afAddrGroup      = AddrGroup,
7   afAddrBroadcast  = AddrBroadcast
8 } afAddrMode_t;

该类型是一个枚举类型:
addrMode= Addr16Bit 时,对应点播方式;
addrMode= AddrGroup 时,对应组播方式;
addrMode= AddrBroadcast 时,对应广播方式;
打开SampleApp.c加入点对点通信定义

afAddrType_t Point_To_Point_DstAddr;//点对点通信定义
//go to definition of afAddrType_t 可以找到刚才的枚举内容

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 = 0x0000; //发给协调器

第三行的意思是点播的发送对象是 0x0000,也就是协调器的地址。节点和协调器点对点通讯。 

添加自己的点对点发送函数,在 SampleAPP.c 最后加入下面代码

void SampleApp_SendPointToPointMessage( void )
{
  uint8 data[]="Hello Tian!";
  if ( AF_DataRequest( &Point_To_Point_DstAddr,
                       &SampleApp_epDesc,
                       SAMPLEAPP_POINT_TO_POINT_CLUSTERID,
                       sizeof(data),
                       data,
                       &SampleApp_TransID,
                       AF_DISCV_ROUTE,
                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }
}

/***********************添加完之后记得在SampleApp.c文件开头添加函数声明****************/

加入 SAMPLEAPP_POINT_TO_POINT_CLUSTERID 的定义如所示:

#define SAMPLEAPP_POINT_TO_POINT_CLUSTERID 3//传输编号

添加接收函数

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  uint16 flashTime;

  switch ( pkt->clusterId )
  {
    case SAMPLEAPP_POINT_TO_POINT_CLUSTERID:
      HalUARTWrite(0,"I get data\n",11);//用于提示有数据
      HalUARTWrite(0, &pkt->cmd.Data[0],10); //打印收到数据
      HalUARTWrite(0,"\n",1);  //回车换行,便于观察
      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;
  }
}

注册周期发送事件

 SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
          if ( //(SampleApp_NwkState == DEV_ZB_COORD)|| //协调器不给自己点播
               (SampleApp_NwkState == DEV_ROUTER)
              || (SampleApp_NwkState == DEV_END_DEVICE) )
          {
            // Start sending the periodic message in a regular interval.
            osal_start_timerEx( SampleApp_TaskID,
                              SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
                              SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
          }
          else
          {
            // Device is no longer in the network
          }
/*由于协调器不允许给自己点播,故周期性点播初始化时协调器不能初始化*/
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
  {
     SampleApp_SendPointToPointMessage();//周期性发送函数
     
    // 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);
  }

将修改后的程序分别以协调器、路由器、终端的方式下载到 3 个节点设备中,连接串口。可以看到只有协调器在一个周期内收到信息。也就是说路由器和终端均与地址为 0x00(协调器)的设备通信,不与其他设备通信。实现点对点传输。