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