ZigBee学习(6)————ZigBee无线传感器网络获取网络拓扑

目录

要获取网络的拓扑信息,需要知道每个网络节点的网路地址以及父节点的网路地址。可考虑如下思路来获取拓扑信息:节点上电后,将自身的网络地址以及父节点的网络地址发送给协调器,通过串口给协调器发送命令,协调器收到命令后,将各个节点的网络地址以及父节点的网络地址发送给PC机


ZigBee学习(6)————ZigBee无线传感器网络获取网络拓扑_第1张图片

系统上电后,各个节点需要将自身设备类型,网络地址,父节点网络地址发送给协调器,设计一个数据结构,如下:

 

协调器编程:

//Coordinator.c
typedef struct RFTXBUF
{
    uint8 type[3];
    uint8 myNWK[4];
    uint8 pNWK[4];
}RFTX;

该结构体用于存放节点对的信息:设备类型,网络地址,父节点网络地址

 

//Coordinator.c
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{

  switch ( pkt->clusterId )
  {
    case GENERICAPP_CLUSTERID:
      osal_memcpy(&nodeinfo[nodenum++],pkt->cmd.Data,11);
      break;
  }
}

static void rxCB(uint8 port,uint8 event)
{
  unsigned char changeline[2]={0x0A,0x0D};
  uint8 buf[8];
  uint8 uartbuf[16];
  uint8 i=0;
  HalUARTRead(0,buf,8);
  if(osal_memcmp(buf,"topology",8))
  {
        for(i=0;i<3;i++)
        {
            HalUARTWrite(0,nodeinfo[i].type,3);      //输出设备类型
            
            HalUARTWrite(0," NWK: ",6);
            HalUARTWrite(0,nodeinfo[i].myNWK,4);     //输出网络地址
            
            HalUARTWrite(0," pNWK: ",7);
            HalUARTWrite(0,nodeinfo[i].pNWK,4);      //输出父节点网络地址
            
            HalUARTWrite(0,changeline,2);
        }
  }
}

串口回调函数,当串口缓冲区有数据时,会调用这个函数,读取串口缓冲区的数据,使用osal_memcmp()函数,判断是否收到“topology”

 

终端节点和路由器编程:

//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 ZDO_STATE_CHANGE:             
          GenericApp_NwkState=(devStates_t)(MSGpkt->hdr.status);
          if((GenericApp_NwkState == DEV_END_DEVICE)
                || (GenericApp_NwkState == DEV_ROUTER))   
          {
            osal_set_event(GenericApp_TaskID,SEND_DATA_EVENT);
          }
          break;
        default:
          break;
      }
      osal_msg_deallocate( (uint8 *)MSGpkt );  //释放内存
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }

    return (events ^ SYS_EVENT_MSG);
  }
  if(events & SEND_DATA_EVENT)
  {
      SendInfo();
      return (events ^ SEND_DATA_EVENT);
  }
  return 0;
}

当成功加入网络后,设置SEND_DATA_EVENT事件,在该事件处理函数中,调用SendInfo()函数,向协调器发送设备信息
 

//Enddevice.c
void SendInfo( void )
{
  RFTX rftx;
  uint16 nwk;
  if(GenericApp_NwkState == DEV_END_DEVICE)             //判断是否为终端节点
  {
      osal_memcpy(rftx.type,"END",3);
  }
  if(GenericApp_NwkState == DEV_ROUTER)                 //判断是否是路由器
  {
      osal_memcpy(rftx.type,"ROU",3);
  }
  
  nwk = NLME_GetShortAddr();
  To_string(rftx.myNWK,(uint8 *)&nwk,2);
  
  nwk = NLME_GetCoordShortAddr();
  To_string(rftx.pNWK,(uint8 *)&nwk,2);
  
  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,
                       11,
                       (uint8 *)&rftx,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
}

void To_string(uint8 *dest,char *src,uint8 length)
{
    uint8 *xad;
    uint8 i=0;
    uint8 ch;
    xad = src + length-1;
    for(i=0;i> 4) & 0x0F;
        dest[i<<1] = ch + ((ch<10) ? '0' : '7');
        ch = *xad & 0x0F;
        dest[(i<<1) + 1] = ch + ((ch<10) ? '0' : '7');
    }
}

如果设备类型是终端节点,则在设备类型字段填充“END”;如果设备类型是路由器,则在设备类型字段填充“RND”。使用NLME_GetCoordShortAddr()函数获得父节点网络地址。

 

测试:

打开串口调试助手,发送topology命令,此时会输出网络的拓扑信息

 

可见,网络中有一个路由器,网络地址为0x0001,还有两个终端节点,网络地址分别为0x796F,0x7970。网络拓扑如下:

ZigBee学习(6)————ZigBee无线传感器网络获取网络拓扑_第2张图片

 

你可能感兴趣的:(ZigBee)