7.1 概述
传感器类的终端设备可以使用属性上报API把数据上报到协调器中,例如温湿度传感器把采集到温湿度数据上报、人体红外传感器检测到有人时上报这个信息等。
本节课将以实验的方式讲解基于ZCL的属性上报技术,主要的实验设备包括一个协调器设备和一个终端(或路由器)设备,实验内容是:
- 终端设备定期地上报数据给协调器。
 - 协调器接收到数据并显示到屏幕上。
 
7.2 终端设备开发
终端设备开发内容主要有以下这几部分:
#ifdef ZDO_COORDINATOR#else/** 此处省略了部分代码*/#define SAMPLEAPP_REPORT_EVT 0x0040#define SAMPLEAPP_REPORT_PERIOD 3000#endif
在zcl_samplesw.c文件中的应用层初始化函数zclSample_Init中添加启动属性上报事件代码:
osal_start_timerEx(zclSampleSw_TaskID,SAMPLEAPP_REPORT_EVT,//事件SAMPLEAPP_REPORT_PERIOD);//延迟处理事件的时间长度
定义事件处理函数
定义事件后,需要添加事件处理函数。打开zcl_samplesw.c文件找到事件处理函数zclSampleSw_event_loop,添加如下代码:
#ifdef ZDO_COORDINATOR#else/** 此处省略了部分代码*/if ( events & SAMPLEAPP_REPORT_EVT ){zclSampleSw_ReportTest();//属性上报事件的处理函数//启动下一个属性上报事件osal_start_timerEx(zclSampleSw_TaskID,SAMPLEAPP_REPORT_EVT,SAMPLEAPP_REPORT_PERIOD);return ( events ^ SAMPLEAPP_REPORT_EVT );}#endif
属性上报API 简介
只需调用属性上报API即可完成属性上报功能。在zcl.c文件中,可以找到属性上报API,代码如下:
/** 上报一个或多个属性值*/extern ZStatus_t zcl_SendReportCmd(uint8 srcEP, //源端点号afAddrType_t *dstAddr, //目标设备地址信息uint16 realClusterID, //属性所属Cluster IDzclReportCmd_t *reportCmd,//描述待上报的属性值uint8 direction, //通信方向uint8 disableDefaultRsp, //是否关闭默认响应(目标设备的响应)uint8 seqNum); //数据包标号,由开发者自定义
属性上报处理函数
学习完API后,即可编写属性上报事件处理函数zclSampleSw_ReportTest,其代码定义如下:
/** 数据上报事件的处理函数,用于上报数据*/static void zclSampleSw_ReportTest(void){static uint8 seqNum = 0;zclReportCmd_t *reportCmd;//目标设备的地址信息afAddrType_t destAddr;destAddr.addrMode = afAddr16Bit;destAddr.endPoint = SAMPLESW_ENDPOINT;destAddr.addr.shortAddr = 0x0000;//0x0000表示协调器的网络地址reportCmd = (zclReportCmd_t *)osal_mem_alloc(sizeof(zclReportCmd_t)+sizeof(zclReport_t));//申请内存空间if(reportCmd == NULL)//判断内存空间是否申请成功return;reportCmd->attrList[0].attrData = (uint8 *)osal_mem_alloc(sizeof(uint8));//申请内存空间if(reportCmd->attrList[0].attrData == NULL)//判断内存空间是否申请成功return;reportCmd->numAttr = 1;//属性数量为1reportCmd->attrList[0].attrID = ATTRID_ON_OFF_SWITCH_TYPE;//属性IDreportCmd->attrList[0].dataType = ZCL_DATATYPE_ENUM8;//数据类型*((uint8 *)(reportCmd->attrList[0].attrData)) = seqNum;//属性值//上报数据zcl_SendReportCmd(SAMPLESW_ENDPOINT,//源端点号&destAddr,//地址信息ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG,//Cluster IDreportCmd,ZCL_FRAME_CLIENT_SERVER_DIR,//通信方向为从客户端到服务端TRUE,//关闭默认响应(目标设备的响应)seqNum++ );//数据包标号,每上报一次数据seqNum的值就会增加1HalLcdWriteStringValue("Report: ", (seqNum-1), 10, 4);//显示// 释放内存空间!osal_mem_free(reportCmd->attrList[0].attrData);osal_mem_free(reportCmd);}
启用对应的宏定义
最后,还需要开启一个宏定义ZCL_REPORTING_DEVICE,如下图所示。
7.3 协调器设备开发
协调器设备开发内容主要有一下这几部分:
- 接收和处理属性数据。
 - 启用对应的宏定义。
接收和处理属性数据
与读写命令类似,协调器在接收到上报信息后,就会发生系统事件ZCL_INCOMING_MSG。打开在zcl_samplesw.c文件中的zdSampleSw_event_loop函数,可以找到ZCL_INCOMING_MSG的事件处理函数zclSamplesw_ProcessIncomingMsg,其中的部分代码如下: 
1.static void zclSampleSw_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )2.{3. switch ( pInMsg->zclHdr.commandID )4. {5. ...... // 不展开6.7.#ifdef ZCL_REPORT8. ...... // 不展开9. case ZCL_CMD_REPORT://属性上报10. zclSampleSw_ProcessInReportCmd( pInMsg ); //属性上报处理函数11. break;12.#endif13. ...... // 不展开14. }15. if ( pInMsg->attrCmd )16. osal_mem_free( pInMsg->attrCmd );17.}
其中的属性上报处理函数zclSampleSw_ProcessInReportCmd,由笔者自定义,代码如下:
#ifdef ZCL_REPORTstatic uint8 zclSampleSw_ProcessInReportCmd( zclIncomingMsg_t *pInMsg ){zclReportCmd_t *reportCmd;uint8 i;reportCmd = (zclReportCmd_t *)pInMsg->attrCmd;for ( i = 0; i < reportCmd->numAttr; i++ )//reportCmd->numAttr为属性数量{if( pInMsg- >clusterId == ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG//Cluster ID&& reportCmd->attrList[i].attrID == ATTRID_ON_OFF_SWITCH_TYPE)//属性ID{int8 attrDat = *(reportCmd->attrList[i].attrData);//读取属性值HalLcdWriteStringValue("Rx Value:", attrDat, 10, 4);//显示属性值}}return ( TRUE );}#endif // ZCL_REPORT
启用对应的宏定义
最后,需要开启两个宏:ZCL_REPORT_DESTINATION_DEVICE 和 ZCL_REPORT,如下图所示。
7.4 仿真调试
- 分别编译协调器和终端(路由器)工程,然后分别下载到两个开发板中。
 - 终端(路由器)设备加入到ZigBee网络中后,可以看到协调器屏幕显示如下提示信息。


 
 
