在SampleApp中利用SendPeriodicMessage实现终端节点定时向汇聚节

更新时间:2024-06-23 00:10:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

在SampleApp中利用SendPeriodicMessage实现终端节点

定时向汇聚节点发送消息

在SampleApp中,SendPeriodicMessage是所有节点的定时消息,即在(一个周期+随机时间)的时间间隔内,所有工作节点向外广播一个消息。在星型网络中,我们可以修改这个定时消息,实现终端节点向汇聚节点定时发送一个消息,这个消息当然可以包含有传感器的信息。下面以发送一个字符串“Hello ZB”为例来说明这个过程。 1、 由于原来这个消息的发送目的地址是广播地址,所以要将其广播地址改为汇聚节点的地址。在一个网络形成之后,汇聚节点的地址为0x0000,这个地址是固定的,所以在初始化函数SampleApp_Init中找到这个目的地址并改成0x0000: //默认为0xFFFF,即广播地址,这里改成了0x000

SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0000;//源程序为0xFFFF,即广播地址 2、单单改了这个地址还不够,需要将地址模式也要修改,就在上述语句的上面有这么一条语句:

// Broadcast to everyone ---------地址模式

SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;

很明显,地址模式为广播地址模式,我们将其修改为16位短地址模式,程序如下: SampleApp_Periodic_DstAddr.addrMode= (afAddrMode_t)Addr16Bit;// 原为AddrBroadcast; 2、 完成上述两步之后,就实现了所有节点都能向汇聚节点发送消息,当然也包括汇聚节点所以我们要将汇聚节点去掉。在函数SampleApp_ProcessEvent中,有如下一段程序:

//如果是三种状态之一则按正常间隔启动定时器

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 }

break;

我们只需要终端节点向汇聚节点发消息,故把if条件中的协调器和路由器两个选项去掉,如下所示:

if ( 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 }

这样,就实现了终端节点定时消息的产生,因为它每次都调用osal_start_timerEx为系统任务中添加一次定时消息。 3、 定时消息中发送字符串。在函数SampleApp_SendPeriodicMessage中,首先定义一个buf,

内容就为要发送的字符串,然后在AF_DataRequest发送消息函数的第4个参数改为buf的长度,第5个参数改为buff的地址(指针)即可实现数据发送。详细程序如下所示: void SampleApp_SendPeriodicMessage( void ) {

int8 buf[8]={'H','E','L','L','O',' ','Z','B'};

if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 8,//发送的数据长度 buf,//字符串的首地址 &SampleApp_TransID, AF_DISCV_ROUTE,

AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )//发送成功 {

P1_0=!P1_0;//发送成功后,灯P1_0取反。用于标示消息是否发送成功 } else {

// Error occurred in request to send. } }

4、 汇聚节点接收周期消息并处理。前面已经将周期消息发送方定为了终端节点,接收方定为了汇聚节点,故当汇聚节点收到周期消息后会运行到SampleApp_ProcessEvent函数中的下面一段: ??

case AF_INCOMING_MSG_CMD://有消息进来,直接转入SampleApp_MessageMSGCB函数。 SampleApp_MessageMSGCB( MSGpkt );//消息处理。 break; ??

然后我们在SampleApp_MessageMSGCB函数中修改汇聚节点接收到周期消息后要做的处理:

在下面的处理中,汇聚节点收到了消息,然后将收到的消息直接发送到串口中。具体如何实现串口发送,请参考其他资料。

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) {

uint16 flashTime;

devStates_t NwkState;

switch ( pkt->clusterId )//判断族ID {

case SAMPLEAPP_PERIODIC_CLUSTERID://如果是周期性消息 //在这里加入所要处理的事件

//接收数据,显示在显示屏,并发送到串口。

/**********************下面这段代码是ninesuns加的************************/ NwkState = (devStates_t)(pkt->hdr.status); // if (NwkState == DEV_END_DEVICE) {

P1_1=!P1_1; //闪灯,标示汇聚节点收到了数据

//从串口发出。

HalUARTWrite(0,pkt->cmd.Data,8); }

/**********************加入的程序结束*********************************/ break;

case SAMPLEAPP_FLASH_CLUSTERID://如果是flash消息

flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); //小灯闪烁四次

HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); break; } }

5、 最简单也是最关键的,给汇聚节点下载程序时,一定要将工程选为:CoordinatorEB,给终端节点下载程序时,一定要将工程选为:EndDevicedEB。如果要实现自动建网的话,在option?C/C++compiler 中选择Preprocessor选项,在defined symbols 中注意要将HOLD_AUTO_START(禁止网络自启动)去掉。消息发送周期可以在SampleApp.h中修改。

总结:如果将发送的消息改为传感器的数据,用定时发送消息功能,就可很容易实现传感器数据的主动上传。

本文来源:https://www.bwwdw.com/article/ttf3.html

Top