ZigBee学习(4)————单播,组播和广播

目录

在ZigBee网络中进行数据通信主要有三种类型:广播(Broadcast),单播(Unicast)和组播(Multicast)。


 

广播描述的是一个节点发送的数据包,网络中的所有节点都可以收到,类似于开会时,领导讲话,每个开会者都可以听到

 

单播描述的是网络中两个节点之间进行数据包的收发过程,类似于任意两个与会者之间进行的讨论

 

组播又称为多播,描述的是一个节点发送的数据包,只有和该节点属于同一组的节点才能收到该数据包。类似于领导讲完话后,各小组进行讨论,只有本小组的成员才能听到该相关的讨论内容,不属于该小组的成员不需要听取相关的内容

 

 

  • 广播和单播通信:

协调器周期性以广播的形式向终端节点发送数据(每隔5s广播一次),终端节点收到数据后,使开发板上的LED状态翻转,同时向协调器发送字符串“Enddevice received!”,协调器收到终端节点发回的数据后,通过串口输出到PC机

 

协调器编程:

//Coordinator.c
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
        case AF_INCOMING_MSG_CMD:          //收到新数据事件
          GenericApp_MessageMSGCB( MSGpkt );
          break;
          
        case ZDO_STATE_CHANGE:             //建立网络后,设置事件
          GenericApp_NwkState=(devStates_t)(MSGpkt->hdr.status);
          if(GenericApp_NwkState == DEV_ZB_COORD)
          {
              osal_start_timerEx(GenericApp_TaskID,SEND_TO_ALL_EVENT,5000);
          }
          break;
          
        default:
          break;
      }

      osal_msg_deallocate( (uint8 *)MSGpkt );
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }
    return (events ^ SYS_EVENT_MSG);
  }
  
  if(events & SEND_TO_ALL_EVENT)    //数据发送事件处理
  {
    GenericApp_SendTheMessage();
    osal_start_timerEx(GenericApp_TaskID,SEND_TO_ALL_EVENT,5000);
    return (events ^ SEND_TO_ALL_EVENT);
  }
  return 0;
}

当网络状态发生变化时,启动定时器定时5s,定时时间到达后,设置SEND_TO_ALL事件,在SEND_TO_ALL事件处理函数中,调用发送数据函数GenericApp_SendTheMessage(),发送完数据后,再次启动定时器,定时5s.......

 

Coordinator.c
#define SEND_TO_ALL_EVENT     0x01        //定义发送事


void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  char buf[20];
  unsigned char buffer[2]={0x0A,0x0D};                    //回车换行的ASCII码
  switch ( pkt->clusterId )
  {
    case GENERICAPP_CLUSTERID:
      osal_memcpy(buf,pkt->cmd.Data,20);
      HalUARTWrite(0,buf,20);
      HalUARTWrite(0,buffer,2);                          //输出回车换行符
      break;
  }
}

void GenericApp_SendTheMessage( void )
{
  unsigned char *theMessageData = "Coordinator send!";
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode= (afAddrMode_t)AddrBroadcast;
  my_DstAddr.endPoint= GENERICAPP_ENDPOINT;
  my_DstAddr.addr.shortAddr= 0xFFFF;
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       osal_strlen(theMessageData)+1,
                       theMessageData,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
}

当收到终端节点发回的数据后,读取该数据,然后发送到串口,使用广播方式发送数据

 

终端节点编程:

//Enddevice.c
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  char *recvbuf;
  switch ( pkt->clusterId )
  {
      case GENERICAPP_CLUSTERID:
        osal_memcpy(recvbuf,pkt->cmd.Data,osal_strlen("Coordinator send!")+1);
        if(osal_memcmp(recvbuf,"Coordinator send!",osal_strlen("Coordinator send!")+1))
        {
            GenericApp_SendTheMessage();
        }
        else
        {
            
        }
        break;
  }
}

void GenericApp_SendTheMessage( void )
{
  unsigned char *theMessageData = "EndDevice received!";
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode= (afAddrMode_t)Addr16Bit;
  my_DstAddr.endPoint= GENERICAPP_ENDPOINT;
  my_DstAddr.addr.shortAddr= 0x0000;
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       osal_strlen(theMessageData)+1,
                       theMessageData,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
  HalLedSet(HAL_LED_2,HAL_LED_MODE_TOGGLE);
}

当接收到协调器发送的字符串“Coordinator send!”时,调用函数GenericApp_SendTheMessage()发送返回消息,向协调器发送单播数据

 

最终出现如下现象:

 

  • 组播:

协调器周期性以组播的形式向路由器发送数据(每隔5s发送组播数据一次),路由器收到数据后,使开发板上的LED状态翻转,同时向协调器发送字符串“Router received!”,协调器收到路由器发回的数据后,通过串口输出到PC机

协调器编程:

//Coordinator.c
aps_Group_t GenericApp_Group;        //定义了一个aps_Group_t类型的变量GenericApp_Group


void GenericApp_Init( byte task_id )
{
  halUARTCfg_t  uartConfig;
  GenericApp_TaskID = task_id;
  GenericApp_TransID = 0;
  GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id = &GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq = noLatencyReqs;
  afRegister( &GenericApp_epDesc );
  
  uartConfig.configured        = TRUE;
  uartConfig.baudRate          = HAL_UART_BR_115200;
  uartConfig.flowControl       = FALSE;
  uartConfig.callBackFunc      = NULL;
  HalUARTOpen (0, &uartConfig);
  
  GenericApp_Group.ID = 0x0001;                                
  GenericApp_Group.name[0] = 6;                          
  osal_memcpy(&(GenericApp_Group.name[1]),"Group1",6);    
}

将组ID初始化为0x0001,将组名的长度写入name数组的第1个元素位置处,使用osal_memcpy()函数将组名“Group1”拷贝到name数组中,从第2个元素位置处开始存放数组名,这样就可以使用aps_AddGroup()函数使该端口加到组中

 

//Coordinator.c
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  char buf[17];
  unsigned char buffer[2]={0x0A,0x0D};                    //回车换行的ASCII码
  switch ( pkt->clusterId )
  {
    case GENERICAPP_CLUSTERID:
      osal_memcpy(buf,pkt->cmd.Data,17);
      HalUARTWrite(0,buf,17);
      HalUARTWrite(0,buffer,2);                          //输出回车换行符
      break;
  }
}


void GenericApp_SendTheMessage( void )
{
  unsigned char *theMessageData = "Coordinator send!";
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode= (afAddrMode_t)AddrGroup;
  my_DstAddr.endPoint= GENERICAPP_ENDPOINT;
  my_DstAddr.addr.shortAddr= GenericApp_Group.ID;
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       osal_strlen(theMessageData)+1,
                       theMessageData,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
}

当接收到路由器发送的回复消息后,读取并输出到串口;实现了组播发送,此时地址模式设置为AddrGroup,网络地址设置为组ID,即GenericApp_Group.ID。

 

路由器编程:

//Enddevice.c
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
        case AF_INCOMING_MSG_CMD:
          GenericApp_MessageMSGCB(MSGpkt);
          break;
        case ZDO_STATE_CHANGE:             //建立网络后,加入组中
          GenericApp_NwkState=(devStates_t)(MSGpkt->hdr.status);
          if(GenericApp_NwkState == DEV_ROUTER)   
          {
            //接收“该”消息。
              aps_AddGroup(GENERICAPP_ENDPOINT,&GenericApp_Group);
          }
          break;
        default:
          break;
      }
      osal_msg_deallocate( (uint8 *)MSGpkt );  //释放内存
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }

    return (events ^ SYS_EVENT_MSG);
  }
  return 0;
}

void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  char buf[18];
  switch ( pkt->clusterId )
  {
      case GENERICAPP_CLUSTERID:
        osal_memcpy(buf,pkt->cmd.Data,osal_strlen("Coordinator send!")+1);
        if(osal_memcmp(buf,"Coordinator send!",osal_strlen("Coordinator send!")+1))
        {
            GenericApp_SendTheMessage();
        }
        break;
  }
}

void GenericApp_SendTheMessage( void )
{
  unsigned char *theMessageData = "Router received!";
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode= (afAddrMode_t)Addr16Bit;
  my_DstAddr.endPoint= GENERICAPP_ENDPOINT;
  my_DstAddr.addr.shortAddr= 0x0000; 
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       osal_strlen(theMessageData)+1,
                       theMessageData,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
  HalLedSet(HAL_LED_2,HAL_LED_MODE_TOGGLE);
}

接收到协调器发送的数据后,判断是否是“Coordinator send!”,如果接收正确,则调用GenericApp_SendTheMessage()函数,以单播的方式向协调器发送数据"Router received!",发送完数据后,调用HalLedSet()函数使LED得状态翻转

 

最终出现如下现象:

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值