ZigBee 协议栈网络管理内容主要是对新加入的设备节点的设备管理。

我们都知道每个 CC2530 芯片出厂时候都有一个全球唯一的 32 位 MAC 地址。


实验现象: 路由器(编号 1)、终端设备(编号 2)发送自己的定义的设备号给协调器, 协调器通过接收到的设备号判断设备类型,并且获取设备的短地址,通过串口打印出来。 

要实现协调器收集数据的功能,可以使用点播方式传输数据, 点播地址为协调器地址( 0x0000), 避免了路由器和终端之间的互传,减少网络数据拥塞。

在点播程序的基础上完成本实验。

========================================== 初始化串口(参考协议栈串口实验)

1、

SampleApp.c

#include  "MT_UART.h" //串口头文件引用 


2、 ​SampApp.c



SampApp_Init()

SampApp_TransID() = 0;

MT_UartInit();


3、 ​void MT_UartInit()


uartConfig.baudRate             =MT_UART_DEFAULT_BAUDRATE;

uartConfig.flowControl          = MT_UART_DEFAULT_OVERFLOW;

#define MT_UART_DEFAULT_BAUDRATE         HAL_UART_BR_115200 //38400  #define MT_UART_DEFAULT_OVERFLOW       FALSE //TRUE  4、 用 ZTOOL,串口 0。我们可以在 option——C/C++ 的 CompilerPreprocessor 里面看到,已经默认添加 ZTOOL_P1 预编译。

5、

void SampleApp_Init( uint8 task_id )

MT_UartInit();

MT_UartRegisterTaskID(task_id);//登记任务号


至此,就可以使用  HalUARTWrite(0, "Hello,world\n", 12); //(串口, 字符, 字符个数)  发送数据了。 ========================================== 点播部分(参考网络通讯--点播) 1、 afAddrType_t SampleApp_Periodic_DstAddr;

afAddrType_t SampleApp_Flash_DstAddr;


按照格式在组播和广播下面添加自己的点播: ---------------

afAddrType_t   Point_To_Point_DstAddr;//点对点通信定义

---------------

2、 void SampleApp_Init( uint8 task_id ) 里面, 对 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;    //发给协调器


---------------

3、 在SampleApp.c中

添加头文件声明  void SampleApp_SendPointToPointMessage( void ); 定义该函数 void SampleApp_SendPointToPointMessage( void )

{

  uint8 data[10]={'0','1','2','3','4','5','6','7','8','9'};

  if ( AF_DataRequest( &Point_To_Point_DstAddr,

                       &SampleApp_epDesc,

                       SAMPLEAPP_POINT_TO_POINT_CLUSTERID,  //点播传输编号

                       10,

                       data,

                       &SampleApp_TransID,

                       AF_DISCV_ROUTE,

                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )

  {

  }

}

4、 在SampleApp.h中声明SAMPLEAPP_POINT_TO_POINT_CLUSTERID #define SAMPLEAPP_MAX_CLUSTERS       3 //2

#define SAMPLEAPP_PERIODIC_CLUSTERID 1

#define SAMPLEAPP_FLASH_CLUSTERID    2

#define SAMPLEAPP_POINT_TO_POINT_CLUSTERID  3

5、 周期性点播发送数据 uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )

if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )

// Send the periodic message

//SampleApp_SendPeriodicMessage();//周期性发送函数

SampleApp_SendPointToPointMessage();//此处替换成点播函数


6、 接收 ID 我们在原来基础上改成我们刚定义的 SAMPLEAPP_POINT_TO_POINT_CLUSTERID。 void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )

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;


7、

由于协调器不允许给自己点播,故​周期性点播初始化​时协调器不能初始化。

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )

case ZDO_STATE_CHANGE:

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 );

}

==========================================

---------------------------------------------------------------

发送方:修改SampleApp_SendPointToPointMessage() SampleApp.c

void SampleApp_SendPointToPointMessage( void )

{

uint8 device;      //设备类型变量

if ( SampleApp_NwkState == DEV_ROUTER)

device=0x01;  //编号1表示路由器  

else if (SampleApp_NwkState == DEV_END_DEVICE)

device=0x02;  //编号2表示终端  

else

device=0x03;  //编号3表示出错


if ( AF_DataRequest( &Point_To_Point_DstAddr,  //发送设备类型编号   点播

                       &SampleApp_epDesc,

                       SAMPLEAPP_POINT_TO_POINT_CLUSTERID,

                       1,

                       &device,

                       &SampleApp_TransID,

                       AF_DISCV_ROUTE,

                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )

{

}

else

{

// Error occurred in request to send.

}

}



数据接收: 我们对接收到的数据进行判断,区分路由器和终端设备。然后在数据包中取出 16 位短地址。通过串口打印出来。 短地址在数据包里的存放位置。依次是 pkt--- srcAddr---shortAddr

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )


typedef struct

{

afAddrType_t  srcAddr;     /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,

                               it's an InterPAN message */

} afIncomingMSGPacket_t;


typedef struct

{

  union

  {

    uint16      shortAddr;

    ZLongAddr_t extAddr;

  } addr;

  afAddrMode_t addrMode;


} afAddrType_t;


SampleApp.cpp

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )

{


uint16  flashTime,  temp;


//16进制转ASCII码表

uint8 asc_16[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};


switch ( pkt->clusterId )

{

case SAMPLEAPP_POINT_TO_POINT_CLUSTERID:  

temp=pkt->srcAddr.addr.shortAddr; //读出数据包的16位短地址

if( pkt->cmd.Data[0]==1 ) //路由器        

HalUARTWrite(0,"ROUTER ShortAddr:0x",19); //提示接收到数据

if( pkt->cmd.Data[0]==2 ) //终端

HalUARTWrite(0,"ENDDEVICE ShortAddr:0x",22); //提示接收到数据 


/****将短地址分解,ASC码打印*****/

      HalUARTWrite(0,&asc_16[temp/4096],1);

      HalUARTWrite(0,&asc_16[temp%4096/256],1);

      HalUARTWrite(0,&asc_16[temp%256/16],1);

      HalUARTWrite(0,&asc_16[temp%16],1);      

      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;

}

}


将修改后的程序分别以协调器、路由器、终端的方式下载到 3 个 或以上设备,协调器连接到 PC 机。上电后每个设备往协调器发送自身编号,协调器通过串口打印出来。


利用同样的方法可以将 MAC 地址、 PANID 等读取出来。或者自行设定预定义节点编号进行网络管理。 

例如读取  PANID 

  panTemp= pkt->srcAddr.panId;

HalUARTWrite(0,"PAN ID:0x",9);



HalUARTWrite(0,&asc_16[panTemp/4096],1);


HalUARTWrite(0,&asc_16[panTemp%4096/256],1);


HalUARTWrite(0,&asc_16[panTemp%256/16],1);


HalUARTWrite(0,&asc_16[panTemp%16],1);


HalUARTWrite(0,"\n",1);

 MAC 地址

pkt->srcAddr.addr.extAddr