Zigbee网络中进行数据通信主要有三种类型:单播、组播、广播。那这三种方式如何设置呢,在哪里设置呢,

一、 广播

当应用程序需要将数据包发送给网络的每一个设备时,使用这种模式。广播的短地址有三种

0xFFFF: 广播数据发送至所有设备,包括睡眠节点;
0xFFFD: 广播数据发送至正在睡眠的所有设备;
0xFFFC: 广播数据发送至所有协调器和路由器;

具体说明广播通信,假设终端发“0123456789”数据给协调器,当协调器收到数据后,通过串口发给电脑,电脑上的串口调试助手显示接收到的字符串,具体的流程如下图所示:左边为协调器的工作流程,右边为终端的工作流程,其中黑色阴影部分为SampleApp_Init函数完成的工作,橙色阴影部分为SampleApp_ProcessEvent函数完成的工作,蓝色阴影部分为SampleApp_MessageMSGCB和SampleApp_SendPeriodicMessage处理函数完成的工作,省略号表示其他代码。

1 应用初始化函数,即完成一些初始化工作,如果是协调器,则实现注册串口,填充端点描述符并注册端点描述符;如果是终端,则实现建立广播目的地址,填充端点描述符并注册端点描述符等。

void SampleApp_Init( uint8 task_id )
{
  ............................................................................. //注册串口
MT_UartInit(); //串口初始化
  MT_UartRegisterTaskID(task_id); //注册串口任务
  HalUARTWrite(,"UartInit OK\n", sizeof("UartInit OK\n"));//提示信息
..............................................................................
//建立广播目的地址
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//设置为广播模式
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; //配置端点
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF; //指定广播地址
//填充端点描述符
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs; // 注册端点描述符
afRegister( &SampleApp_epDesc ); ..................................................................................
}

(2)任务处理函数,即处理应用事件函数。

首先当分别启动协调器和终端后,协调器实现组网和终端加入该网络,此后将分别触发系统事件SYS_EVENT_MSG中的网络状态改变ZDO_STATE_CHANGE事件。当网络状态改变后,令终端每隔5ms发送一次SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,即设置定时任务osal_start_timerEx。当时间到达后,将触发SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,在该事件中,终端发送广播信息 SampleApp_SendPeriodicMessage并重新设置定时任务osal_start_timerEx,这样周而复始,即终端每隔5ms周期性的发送事件。

其次,当终端发送SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件后,协调器将收到SYS_EVENT_MSG事件中的AF_INCOMING_MSG_CMD事件,这样协调器执行SampleApp_MessageMSGCB接收数据任务。

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG )
{//从信息列表中获取SampleApp_TaskID相关的信息
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )//不为空,说明有信息
{
switch ( MSGpkt->hdr.event )
{
// Received when a key is pressed
..............................................................
// 系统消息命令到来
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break; // 网络状态改变
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) )
{
// 设置定时任务
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
.........................................................
} // Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available//在列表中检索下一条信息
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
} // return unprocessed events
return (events ^ SYS_EVENT_MSG);
} // 触发定时任务
// (setup in SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// 发送广播信息
SampleApp_SendPeriodicMessage(); //重新设置定时任务
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); // return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
} ...........................................................................
}

(3)接收消息函数

当协调器收到消息后,将通过判断协议号SAMPLEAPP_PERIODIC_CLUSTERID决定是否是由终端发送的周期性广播包,如果是,则通过串口发送到PC。

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) //接收数据
{
uint16 flashTime; switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID://判断协议镞类型,并发送串口数据
HalUARTWrite(, "Rx:", ); //提示信息
HalUARTWrite(, pkt->cmd.Data, pkt->cmd.DataLength); //输出接收到的数据
HalUARTWrite(, "\n", ); //回车换行
break; .....................................
}
}

(4)发送广播函数

首先,函数是ZigBee协议的发送数据函数,其中参数1规定了数据的通信方式,即广播通信模式,通过短地址为0xFFFF(见SampleApp_Init函数);参考3定义了该广播数据的协议族号;参数4为发送数据的长度,参考5为发送的具体数据。

void SampleApp_SendPeriodicMessage( void )
{
//发送广播数据
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
,
(uint8*)&SampleAppPeriodicCounter,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
..............................................................
}

二、组播

具体说明组播通信,假设终端发“0123456789”数据给同一组的协调器,当协调器收到数据后,D1闪烁并通过串口发给电脑,电脑上的串口调试助手显示接收到的字符串,具体的流程如下图所示:左边为协调器的工作流程,右边为终端的工作流程,其中黑色阴影部分为SampleApp_Init函数完成的工作,橙色阴影部分为SampleApp_ProcessEvent函数完成的工作,蓝色阴影部分为SampleApp_MessageMSGCB和SampleApp_SendPeriodicMessage处理函数完成的工作,省略号表示其他代码。

(1)初始化函数

即完成一些初始化工作,如果是协调器,则实现注册串口,填充端点描述符并注册端点描述符,接着任务组初始化,并将终端加入到组中,值得注意的是,任务组的ID号要和终端的目的地址的短地址号SAMPLEAPP_FLASH_GROUP一致;如果是终端,则实现建立组播目的地址,填充端点描述符并注册端点描述符等。

void SampleApp_Init( uint8 task_id )
{
..................................................................................................
//串口初始化
MT_UartInit(); //串口初始化
MT_UartRegisterTaskID(task_id); //注册串口任务
HalUARTWrite(,"UartInit OK\n", sizeof("UartInit OK\n"));//提示信息 ............................
// 建立组目的地址
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; //组号1
//SampleApp_Flash_DstAddr.addr.shortAddr = 0x0002; //组号2 /填充端点描述符
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs; //注册端点
afRegister( &SampleApp_epDesc ); ................................
// 初始化组并将端点加入到组中
SampleApp_Group.ID = 0x0001;
//SampleApp_Group.ID = 0x0002;
osal_memcpy( SampleApp_Group.name, "Group 1", );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); ...............................
}

(2)任务处理函数

处理函数的分析与广播类似,区别在于定时时间到达后,响应的是组播发送函数 SampleApp_SendFlashMessage。

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )//不为空,说明有信息
{
switch ( MSGpkt->hdr.event )
{
.............................................................
// 系统消息命令到来
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break; // 网络状态改变
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) )
{
// 启动定时任务
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
...................................................................................
} ........................................................................................
}
...................................................................................
} // 由定时器触发定时任务
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// 发送组播信息
SampleApp_SendFlashMessage();
// 重新建立组播定时任务
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); .........................................................................................
} // Discard unknown events
return ;
}

(3)接收函数设置

分析与广播类似,区别是收到组播信息后,发送完串口数据,命令协调器的D1闪烁。

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint8 data; switch ( pkt->clusterId )
{
.............................................
case SAMPLEAPP_FLASH_CLUSTERID: //
HalUARTWrite(, "Rx:", ); //提示信息
HalUARTWrite(, pkt->cmd.Data, pkt->cmd.DataLength); //输出接收到的数据
HalUARTWrite(, "\n", ); //回车换行
HalLedBlink( HAL_LED_4, , , (flashTime / ) );
break; ..............................................
}

(4)发送函数设置

分析与广播类似,区别在于参数1包含了组播信息,即通信方式为组播,且短地址为目的地址组(协调器)的ID号,参考3规定为组播协议族。

void SampleApp_SendFlashMessage( uint16 flashTime )
{
uint8 data[]="";
if ( AF_DataRequest( &SampleApp_Flash_DstAddr,
&SampleApp_epDesc,
SAMPLEAPP_FLASH_CLUSTERID,
,
data,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
..........................................................................
}

三、点播

具体说明广播通信,假设终端发“0123456789”数据给协调器,当协调器收到数据后,通过串口发给电脑,电脑上的串口调试助手显示接收到的字符串,具体的流程如下图所示:左边为协调器的工作流程,右边为终端的工作流程,其中黑色阴影部分为SampleApp_Init函数完成的工作,橙色阴影部分为SampleApp_ProcessEvent函数完成的工作,蓝色阴影部分为SampleApp_MessageMSGCB和SampleApp_SendPeriodicMessage处理函数完成的工作,省略号表示其他代码。

(1)初始化函数配置

void SampleApp_Init( uint8 task_id )
{
...................................................................
MT_UartInit(); //串口初始化
MT_UartRegisterTaskID(task_id); //注册串口任务
.............................................................................
SampleApp_P2P_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //点播
SampleApp_P2P_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_P2P_DstAddr.addr.shortAddr = 0x0000; //发给协调器 // 填充端点描述符
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs; // 注册端点描述符
afRegister( &SampleApp_epDesc ); ..........
}

(2)任务处理函数设置

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )//不为空,说明有信息
{
switch ( MSGpkt->hdr.event )
{
................................................................................................ // 系统消息命令到来
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break; // 网络状态改变
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) )
{
// 设置定时任务
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
.........................................................................................
} ............................................................................
}
................................................................................
} // 触发定时任务
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// 发送点播信息
SampleApp_Send_P2P_Message();
// 重新设置定时任务
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); .........................................................................
} // Discard unknown events
return ;
}

(3)接收函数设置

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime; switch ( pkt->clusterId )
{
case SAMPLEAPP_P2P_CLUSTERID:
HalUARTWrite(, "Rx:", ); //提示接收到数据
HalUARTWrite(, pkt->cmd.Data, pkt->cmd.DataLength); //串口输出接收到的数据
HalUARTWrite(, "\n", ); // 回车换行
break;
.............................
}
}

(4)发送函数设置

void SampleApp_Send_P2P_Message( void )
{
uint8 data[]=""; if ( AF_DataRequest( &SampleApp_P2P_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_P2P_CLUSTERID,
,
data,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
....................................................
}

四、参考链接

【1】Zigbee单播、组播、广播网络通信

【2】zigbee单播、组播、广播

Ztack学习笔记(6)-广播组播点播的更多相关文章

  1. Linux IPC socket 广播,组播

    getsockopt()/setsockopt() //获得sockfd指向的socket的属性 int getsockopt(int sockfd, int level, int optname, ...

  2. TCP/IP详解学习笔记(7)-广播和多播,IGMP协议

    1.单播,多播,广播的介绍 1.1.单播(unicast) 单播是说,对特定的主机进行数据传送.例如给某一个主机发送IP数据包.这时候,数据链路层给出的数据头里面是非常具体的目的地址,对于以太网来 说 ...

  3. 网络编程--广播&组播

    广播 1.广播地址 如果用{netid, subnetid, hostid}( {网络ID,子网ID,主机ID})表示IPv4地址.那么有四种类型的广播地址,我们用-1表示所有比特位均为1的字段: 1 ...

  4. Android学习笔记之图片轮播...

    PS:一个bug又折腾了一个下午....哎... 学习内容: 1.Android利用ViewPager和PagerAdapter实现图片轮播... 2.使用反射机制获取Android的资源信息... ...

  5. Android 学习笔记 BroadcastReceiver广播...

    PS:不断提升自己,是件好事... 学习内容: 1.BroadcastReceiver的使用.. 2.通过BroadcastReceiver去启动Service... 1.BroadcastRecei ...

  6. Linux学习笔记---用户管理---组group

    组管理: (1)/etc/group 格式: 组名:密码:GID:组员

  7. Ztack学习笔记(4)-系统网络分析

    协调器的组网,终端设备和路由设备发现网络以及加入网络 //第一步:Z-Stack 由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统 ...

  8. Ztack学习笔记(1)-初识Ztack

    一.Zigbee协议 Zigbee是IEEE 802.15.4协议的代名词,是一种短距离.低功耗的无线通信技术.这一名称来源于蜜蜂的八字舞,因为蜜蜂(bee)是靠飞翔和“嗡嗡”(zig)地抖动翅膀的“ ...

  9. Android学习笔记(广播机制)

    1.Android的广播机制介绍 收听收音机也是一种广播,在收音机中有很多个广播电台,每个广播电台播放的内容都不相同.接受广播时广播(发送方)并不在意我们(接收方)接收到广播时如何处理.好比我们收听交 ...

随机推荐

  1. C和C++头文件的不同

    #include <IOSTREAM.h>void main(){    std::cout<<"Hello,World!"<<std::end ...

  2. win7-opengl开发环境的搭建

    1. glut的安装: 下载glutdlls37beta.zip,下载链接直接opengl.org上找. 把glut.h 复制到include下: glut.lib, glut32.lib复制到C:\ ...

  3. 手写堆_C++

    一般主程序中拿堆顶元素 x=h[]; h[]=h[top--]; down(); 在堆尾加入元素 h[++top]=x; up(top); 上浮下沉操作 inline void up(int x) { ...

  4. 浅析人脸检测之Haar分类器方法

    一.Haar分类器的前世今生 人脸检测属于计算机视觉的范畴,早期人们的主要研究方向是人脸识别,即根据人脸来识别人物的身份,后来在复杂背景下的人脸检测需求越来越大,人脸检测也逐渐作为一个单独的研究方向发 ...

  5. How to deploy JAVA Application on Azure Service Fabric

    At this moment, Azure Service Fabric does not support JAVA application natively (but it's on the sup ...

  6. vss error reading from file 解决方法

    vss error reading from file 解决方法 1 若服务器中存在 vss/data/backup目录,请将该目录删掉2 运行cmd cd.. cd C:\Program Files ...

  7. php文件大小单位转换GB MB KB

    private function formatBytes($size){ $units = array('字节','K','M','G','T'); $i = 0; for( ; $size>= ...

  8. WPF学习系列之七 (样式与行为)

    样式(Styles)是组织和重用格式化选项的重要工具.不是使用重复的标记填充XAML,以设置诸如边距.颜色及字体等细节,而可以创建一系列封装所有这些细节的样式.然后可以在需要之处通过一个属性应用样式. ...

  9. Java之注解

    package com.demo.test; import java.lang.annotation.Documented; import java.lang.annotation.ElementTy ...

  10. solr5.5教程-solrconfig.xml,加载schema.xml

    布署完成后,接下来要更深入的研究solr的原理和使用. 首先进入testcore这个文件夹下面,发现这个core的conf里并没有schema.xml.那么数据格式是在哪里定义的呢? 打开 solr_ ...