基于zigbee光照感应系统之节点广播通信
在zigbee通信本系列第一章就介绍了协调器通过获取串口助手的数据,然后通过广播的方式发送给路由器下面我们就来详细讲解协调器是如何通过广播的方式发送数据的,路由器是怎样接收到数据的
首先,配置接收方(路由器)为广播方式,地址为0XFFFF,0xFFFF代表全部节点都可以接受到此协调器发送的数据。
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
第二步,配置发送方(协调器),配置任务号、端点号等配置。
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
第三步,组网:小伙伴们都知道协调器、路由器之间可以相互收发数据就要组网,为了判断是否组网成功我们需要在组网成功后添加一些标识语句来判断是否组网成功,以本项目为例:添加LED闪烁语句和串口打印语句来判断是否组网成功
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)
)
{
//LS164_BYTE(8);//数码管显示0-9
// Start sending the periodic message in a regular interval.
// osal_start_timerEx( SampleApp_TaskID,
// SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
// SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
//协调器双闪三次
HalLedBlink(0x03,3,50,1000);
HalUARTWrite(0,"I am CoordinatorEB\n",sizeof("I am CoordinatorEB\n"));
}
else
{
// Device is no longer in the network
}
break;
看到这里细心的朋友们已经发现我在组网成功后语句注释掉了osal_start_timerEx定时器函数,为什么要注释掉定时器函数呢?因为我们在通过协调器广播发送函数不是自动的发送数据,而是通过串口助手手动的发送不同的数据,而不是每次自动发送相同的数据,于是我们就可以把定时器函数给注释掉。
第四步,还记得我在本项目第二篇文章添加的void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg)函数吗,现在就用到了此函数,我本项目所希望的效果是通过串口助手上发送数据给协调器,协调器获取到串口助手上的字符串,通过广播的方式发送给路由器,为了达到这样的效果我们可以直接在void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg)函数下添加广播发送函数。
void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg)
{
//uint8 i;
uint8 *str=NULL;
uint8 ch;
str=cmdMsg->msg; //指向数据开头
/********打印出串口接收到的数据,用于提示*********/
ch=str[1];
if(1==*str){
if(AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
1,
&ch,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS )== afStatus_SUCCESS)
HalUARTWrite(0,"success\n",sizeof("success\n"));
else
HalUARTWrite(0,"fail\n",sizeof("fail\n"));
}
else{
//LS164_BYTE(16);//数码管全灭
HalUARTWrite(0,"error\n",sizeof("error\n"));
}
HalUARTWrite(0,str+1,str[0]);
HalUARTWrite(0,"\n",1);//换行
}
可能朋友们看了我添加的发送数据函数有点懵逼,为什么要增加一个if判断语句,下面我来解释一下,我先定义一个8位的字符,然后通过str=cmdMsg->msg;ch=str[1];两条语句赋值给ch,因为str[0]也就是str第零位数据是指的是串口助手发送过来的字符长度而不是字符内容,所以我为了方便添加一个if语句,来限定串口助手一次只能发送一个字符给协调器否则则发送失败,因为ch=str[1];代表ch是串口助手那边发送过来的字符,然后我们通过发送数据函数把ch,发送给路由器。
第五步,路由器通过接受协调器的数据。
在SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )函数里
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
if(*(pkt->cmd.Data)=='1'){
HalLedSet (0x01, HAL_LED_MODE_ON);
HalLedSet (0x02, HAL_LED_MODE_OFF);
HalUARTWrite(0,"1",1);
HalUARTWrite(0,"\n",1);
}else if(*(pkt->cmd.Data)=='0'){
HalLedSet (0x02, HAL_LED_MODE_ON);
HalLedSet (0x01, HAL_LED_MODE_OFF);
HalUARTWrite(0,"0",1);
HalUARTWrite(0,"\n",1);
}else{
HalLedSet (0x03, HAL_LED_MODE_OFF);
HalUARTWrite(0,"fail\n",sizeof("fail\n"));
HalUARTWrite(0,"\n",1);
}
HalUARTWrite(0,pkt->cmd.Data,pkt->cmd.DataLength);
break;
在接收路由器接受数据函数中我添加了几个if语句可以忽略,最重要的语句是HalUARTWrite(0,pkt->cmd.Data,pkt->cmd.DataLength);此语句将接收到的数据通过串口助手打印出来。
完成以上步骤协调器就可以通过广播方式发送给路由器了。