6.6ZigBee多跳组播在实际生活应用中,读者可能会遇到这样的问题:需要对特定的工程对象实现分组管理。如在医院中的医疗病房中,病人患病情况类型是不同的,年龄组分布也不尽相同。如果需要对特定分组的患者利用ZigBee网络通知相关消息,组播技术可以很方便地完成上述任务。ZigBee网络中的节点分组,只有相同组号的组员才能收到每一个组员发出的消息。即工作组内设备可以接收组播数据包,而组外设备将无法接收,可实现对特定设备的分组管理。本节我们在TI官方例程SampleApp的基础上,定义了两个不同的分组对象。设备可以通过按键选择加入特定分组,并且可以同时存在两个分组中。当组内设备接收到按键组播消息后,连接在设备上的蜂鸣器发出“滴滴滴滴”的声音,并且LED灯闪烁,表示接收到组播消息。实验目的与器材1)实验目的学习ZigBee协议的组播技术。加深对Z-Stack2007/Pro协议栈的应用层流程认识。学会使用蜂鸣器,并利用LED灯控制函数控制蜂鸣器。2)实验器材4个CC2530开发套件(1个协调器模块,3个路由器模块)。4个蜂鸣器。实验原理与步骤1.硬件介绍1)蜂鸣器蜂鸣器是一种结构非常简单的电子讯响器,采用直流电压供电,常被用于电子产品中的发声器件。图蜂鸣器实物图及电路连接图如图所示,蜂鸣器的工作原理非常简单,主要由发声器、三极管和电阻组成。单片机I/O驱动能力不能够使蜂鸣器发音。所以,三极管用来放大驱动电流。如果电阻R输出是高电平,三极管导通,集电极的电流能够使得蜂鸣器发声。当输出为低电平,三极管截止,蜂鸣器没有电流通过,不会发声。如果输出为方波,通过控制方波的频率,蜂鸣器也能够产生简单的音乐。2.程序流程组播通信寻址使用16位多播组ID完成。多播组是所有已登记在同一个多播组ID下节点的集合。一个多播信息发送给一个特定的目标组,即多播表中该组ID所列的所有设备。组播数据帧既可以由目标多播组的成员在网络中传播,也可以由非目标多播组成员在网络中传播。数据包发送由数据包的一个地址模式标志指明,确定转发到下一跳的方式。如果原始信息由组的成员创建,就被视为处于“成员模式”,按广播方式转发。如果原始信息不是组成员设备创建,就被视为处于“非成员模式”,按单播方式转发一个组成员。如果一个非成员信息到达目标组的任何成员,不管下一个数据包由哪个设备进行转发,就会立即转换为成员模式类型。实现组播通信,首先,要对组对象进行定义和初始化,将设备加入到特定组中,然后,向特定设备组发送组播消息,最后组内成员接收到消息后,进行相应消息处理。1)组对象初始化组播网络中,设备发出的消息经过组寻址才会发到具有相同组号的组员设备中。组号用来标记设备所属的组,而组寻址需要定义组播地址。(1).在SampleApp.h中定义两者的组ID,以标记设备所属的组。#defineSAMPLEAPP_FLASH_GROUP10x0001#defineSAMPLEAPP_FLASH_GROUP20x0002(2)在程序SampleApp.c文件的SampleApp_Init函数中定义两个组对象并进行简单初始化,主要包括组的ID和组名字。aps_Group_tSampleApp_Group1;//定义组1和组2对象aps_Group_tSampleApp_Group2;//组1初始化SampleApp_Group1.ID=0x0001;osal_memcpy(SampleApp_Group1.name,Group1,7);//组2初始化SampleApp_Group2.ID=0x0002;//osal_memcpy(SampleApp_Group2.name,Group2,7);(3)组播地址定义。组播通信过程中,网络中节点是通过使用组地址进行网络寻址,并能够向特定分组节点传递消息。组播数据包应该具有设备寻址的地址模式、所属任务的端点号和组号。组1地址定义以及初始化为://定义组1地址afAddrType_tSampleApp_Flash_DstAddr_Group1;//设置地址模式为组播SampleApp_Flash_DstAddr_Group1.addrMode=(afAddrMode_t)afAddrGroup;SampleApp_Flash_DstAddr_Group1.endPoint=SAMPLEAPP_ENDPOINT;//设置组地址为组1ID号SampleApp_Flash_DstAddr_Group1.addr.shortAddr=SAMPLEAPP_FLASH_GROUP1;2)设备入组/离开组(1).在ZigBee网络实现组播通信时,设备加入组是通过设备端点加入到工作组中。aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp_Group);初始情况下,编者将设备都加入到了组1和组2中:aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp_Group1);aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp_Group2);#ifdefined(LCD_SUPPORTED)HalLcdWriteString(GROUP1+2,HAL_LCD_LINE_6);#endif(2).将一个设备从工作组中移除,将该端点依据组ID号将其从组中移除。aps_RemoveGroup(SAMPLEAPP_ENDPOINT,SAMPLEAPP_FLASH_GROUP);(3).使用aps_FindGroup函数判断一设备端点SAMPLEAPP_ENDPOINT是否在组ID号为SAMPLEAPP_FLASH_GROUP的组中。grp=aps_FindGroup(SAMPLEAPP_ENDPOINT,SAMPLEAPP_FLASH_GROUP);读者可以在按键函数(SampleApp_HandleKeys)中利用这三个函数实现设备入组、退组、以及组间切换。3)向特定组发送消息设备在按键函数中调用SampleApp_SendFlashMessage()函数来发送消息。本例中,为了实现对不同分组函数控制,编者加入了组号“SAMPLEAPP_FLASH_GROUP”参数:SampleApp_SendFlashMessage(uint16flashTime,uint8SAMPLEAPP_FLASH_GROUP)该函数中调用AF_DataRequest()函数进行数据收发,下面是向组1设备发送消息的语句:if(AF_DataRequest(&SampleApp_Flash_DstAddr_Group1,&SampleApp_epDesc,SAMPLEAPP_FLASH_CLUSTERID,3,buffer,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS)==afStatus_SUCCESS){}AF_DataRequest()函数中需要定义ZigBee设备完整地址,包括网络地址以及端点地址、源端点描述符、发送端ClusterID、数据以及数据长度等。4)组设备接收到消息,并进行相应处理节点接收到其他节点设备到来的数据后,应用层任务事件处理函数调用SampleApp_MessageMSGCB()回调函数将进行处理。回调函数根据到来数据包的ClusterID判断数据类型,如果ClusterID为SAMPLEAPP_FLASH_CLUSTERID,设备蜂鸣器和LED会进行相关数据包接收指示操作:SampleApp_MessageMSGCB(afIncomingMSGPacket_t*pkt){switch(pkt-clusterId){caseSAMPLEAPP_FLASH_CLUSTERID:flashTime=BUILD_UINT16(pkt-cmd.Data[1],pkt-cmd.Data[2]);HalLedBlink(HAL_LED_4,4,50,(flashTime/4));//蜂鸣器HalLedBlink(HAL_LED_2,4,50,(flashTime/4));//LED灯闪}}这里,编者并没有针对蜂鸣器编写驱动函数,而是直接利用LED4Blink函数进行操作。与LED灯闪类似,蜂鸣器会响四次,每次周期蜂鸣器响的百分比为50%,每个周期时间为flashTime/4。这是由于LED灯和蜂鸣器工作都是由于电平使能的。原来芯片引脚到LED4的电平加到蜂鸣器的引脚上。由此,读者可以联想下单片机基本的编程操作方式。3)实验步骤组播实验使用四个节点设备,分别编号为节点1,2,3,4。首先将蜂鸣器接到节点模块上,与原来连接灯LED4的芯片引脚P10相连。节点初始时,节点既加入到组1,又加入到组2中。经过按键选择分组后,节点1为协调器,既在组1,又在组2中。节点2在组1中,节点3在组2中,节点4既在组1,又在组2中。第一步:按照程序说明将源代码目录下的SampleApp.c和SampleApp.h替换SampleApp目录下的同名文件。CoordinatorEB下载到节点1,RouterEB下载到节点2,3,4中。第二步:1)按下节点1(协调器)的重启键,LCD屏会显示网络号,LED3(黄灯)长亮时说明网络建立成功;2)分别按下节点2,3,4的重启键。等到LED3(黄灯)长亮,并且屏幕上出现设备类型和地址时,说明已与协调器节点建立连接。3)连续按节点2的SW2(右键),直到节点屏幕上出现“GROUP1”字样,代表节点2只加入到组1中。4)连续按节点3的SW2(右键),节点屏幕上出现“GROUP2”字样,代表节点3只加入到组2中。5)节点4不用按键,节点4默认在组1和组2中。第三步:按节点1(协调器)的SW1(上键),节点1屏幕上出现“MSG2GROUP1”字样,代表向组1中发送按键消息。这时,节点2和节点4的蜂鸣器会发出“滴滴滴滴”的声音,并且其LED2闪亮四次。第四步:按节点1的SW3(下键),节点1的屏幕上出现“MSG2GROUP2”字样,代表向组2中发送按键消息。这时,节点3和节点4的蜂鸣器会发出“滴滴滴滴”的声音,并且其LED2闪亮四次。4)程序清单清单6.1按键处理函数/*******************************************************************************函数名SampleApp_HandleKeys*描述按键处理函数,主要完成组消息发送,组间切换。*参数uint16flashTime:灯每次闪烁,蜂鸣器每次响的周期*uint8SAMPLEAPP_FLASH_GROUP发送消息的组号*返回值无*****************************************************************************/voidSampleApp_HandleKeys(uint8shift,uint8keys){(void)shift;//Intentionallyunreferencedparameterif(keys&HAL_KEY_SW_1)//上键,向组1发送消息{SampleApp_SendFlashMessage(SAMPLEAPP_FLASH_DURATION,SAMPLEAPP_FLASH_GROUP1);}if(keys&HAL_KEY_SW_3)//下键,向组2发送消息{SampleApp_SendFlashMessage(SAMPLEAPP_FLASH_DURATION,SAMPLEAPP_FLASH_GROUP2);}if(keys&HAL_KEY_SW_2)//组切换,如果设备当前在1组,则转入到2组。//如果当前在2组,则转入到1组。//如果当前既在1组,又在2组,则只在2组。{aps_Group_t*grp1;grp1=aps_FindGroup(SAMPLEAPP_ENDPOINT,S