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. SQL Server int类型值最大2147483647(2^31 - 1)

    突发奇想,一个字增字段,假设每天增加1000条记录,多少年之后写不进int类型的字段了2147483647 / 1000 / 365 = 5883.51684109589041095890410958 ...

  2. app控件获取之uiautomatorviewer

    初探 在Android的SDk提供了以下的工具来支持我们进行UI自动化测试: uiautomatorviewer:用来扫描和分析Android应用程序的UI控件的工具. uiautomator:一个包 ...

  3. XGBoost参数

    XGBoost参数 转自http://blog.csdn.net/zc02051126/article/details/46711047 在运行XGboost之前,必须设置三种类型成熟:general ...

  4. nginx 代理配置文件实例

    安装NGINX前要先安装PCRE正则表达式库: ./configure --prefix=/usr/local/pcre 出现以下错误  (一般./configure即可, 笔者这里是直接./conf ...

  5. IP一些基础知识

    1.主机IP地址 IP地址:internet上的每一台计算机都被赋予了唯一的32位Internet地址,简称ip地址. (1)IP地址的组成 IP地址由两部分组成,如图1 网络地址(net-ID) 主 ...

  6. [oracle] listener.ora 、sqlnet.ora 、tnsnames.ora

    路径 $ORACLE_HOME/network/admin sqlnet.ora(客户及服务器端) 作用类似于linux或者其他unix的nsswitch.conf文件,通过这个文件来决定怎么样找一个 ...

  7. css显示出三角形

    其实非常简单,就是设置一个div 让div的宽度和高度都设置为0, 然后为div设置一个border 因为角部位,比如我设置border-left和border-top 角部分是各自占用一半, 所以当 ...

  8. math对象和date对象

    math对象的函数方法,记住Math首字母要大写 console.log(Math.abs(-5)); //取绝对值 console.log(Math.ceil(1.1)); //向上取舍 conso ...

  9. android大项目运行中出现问题汇总

    Android 项目中,特别是当项目文件和规模达到一定的程度后,会引发一些平常不常见的问题. 下面对遇到的一些问题做一个汇总和总结. scenario 1: 在项目中,我们采用了chromimum内核 ...

  10. TCP/IP详解学习笔记(12)-- TCP:传输控制协议

    1.概述      TCP提供了一种可靠的面向连接的字节流运输层服务.      TCP将用户数据打包成报文段,它发送后启动一个定时器,另一端收到的数据进行确认,对失序的数据重新排序,丢弃重复数据,T ...