7.1 概述

传感器类的终端设备可以使用属性上报API把数据上报到协调器中,例如温湿度传感器把采集到温湿度数据上报、人体红外传感器检测到有人时上报这个信息等。

本节课将以实验的方式讲解基于ZCL的属性上报技术,主要的实验设备包括一个协调器设备和一个终端(或路由器)设备,实验内容是:

  • 终端设备定期地上报数据给协调器。
  • 协调器接收到数据并显示到屏幕上。

7.2 终端设备开发

终端设备开发内容主要有以下这几部分:

  • 定义和启动属性上报事件。
  • 定义事件处理函数,进行属性上报。
  • 启用对应的宏定义。

    定义和启动属性上报事件

    在zcl_samplesw.h文件中添加事件定义和事件发生时间定义,代码如下:
  1. #ifdef ZDO_COORDINATOR
  2. #else
  3. /*
  4. * 此处省略了部分代码
  5. */
  6. #define SAMPLEAPP_REPORT_EVT 0x0040
  7. #define SAMPLEAPP_REPORT_PERIOD 3000
  8. #endif

在zcl_samplesw.c文件中的应用层初始化函数zclSample_Init中添加启动属性上报事件代码:

  1. osal_start_timerEx(zclSampleSw_TaskID,
  2. SAMPLEAPP_REPORT_EVT,//事件
  3. SAMPLEAPP_REPORT_PERIOD);//延迟处理事件的时间长度

定义事件处理函数

定义事件后,需要添加事件处理函数。打开zcl_samplesw.c文件找到事件处理函数zclSampleSw_event_loop,添加如下代码:

  1. #ifdef ZDO_COORDINATOR
  2. #else
  3. /*
  4. * 此处省略了部分代码
  5. */
  6. if ( events & SAMPLEAPP_REPORT_EVT )
  7. {
  8. zclSampleSw_ReportTest();//属性上报事件的处理函数
  9. //启动下一个属性上报事件
  10. osal_start_timerEx(zclSampleSw_TaskID,
  11. SAMPLEAPP_REPORT_EVT,
  12. SAMPLEAPP_REPORT_PERIOD);
  13. return ( events ^ SAMPLEAPP_REPORT_EVT );
  14. }
  15. #endif

属性上报API 简介

只需调用属性上报API即可完成属性上报功能。在zcl.c文件中,可以找到属性上报API,代码如下:

  1. /*
  2. * 上报一个或多个属性值
  3. */
  4. extern ZStatus_t zcl_SendReportCmd(
  5. uint8 srcEP, //源端点号
  6. afAddrType_t *dstAddr, //目标设备地址信息
  7. uint16 realClusterID, //属性所属Cluster ID
  8. zclReportCmd_t *reportCmd,//描述待上报的属性值
  9. uint8 direction, //通信方向
  10. uint8 disableDefaultRsp, //是否关闭默认响应(目标设备的响应)
  11. uint8 seqNum); //数据包标号,由开发者自定义

属性上报处理函数

学习完API后,即可编写属性上报事件处理函数zclSampleSw_ReportTest,其代码定义如下:

  1. /*
  2. * 数据上报事件的处理函数,用于上报数据
  3. */
  4. static void zclSampleSw_ReportTest(void)
  5. {
  6. static uint8 seqNum = 0;
  7. zclReportCmd_t *reportCmd;
  8. //目标设备的地址信息
  9. afAddrType_t destAddr;
  10. destAddr.addrMode = afAddr16Bit;
  11. destAddr.endPoint = SAMPLESW_ENDPOINT;
  12. destAddr.addr.shortAddr = 0x0000;//0x0000表示协调器的网络地址
  13. reportCmd = (zclReportCmd_t *)osal_mem_alloc(sizeof(zclReportCmd_t)+sizeof(zclReport_t));//申请内存空间
  14. if(reportCmd == NULL)//判断内存空间是否申请成功
  15. return;
  16. reportCmd->attrList[0].attrData = (uint8 *)osal_mem_alloc(sizeof(uint8));//申请内存空间
  17. if(reportCmd->attrList[0].attrData == NULL)//判断内存空间是否申请成功
  18. return;
  19. reportCmd->numAttr = 1;//属性数量为1
  20. reportCmd->attrList[0].attrID = ATTRID_ON_OFF_SWITCH_TYPE;//属性ID
  21. reportCmd->attrList[0].dataType = ZCL_DATATYPE_ENUM8;//数据类型
  22. *((uint8 *)(reportCmd->attrList[0].attrData)) = seqNum;//属性值
  23. //上报数据
  24. zcl_SendReportCmd(SAMPLESW_ENDPOINT,//源端点号
  25. &destAddr,//地址信息
  26. ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG,//Cluster ID
  27. reportCmd,
  28. ZCL_FRAME_CLIENT_SERVER_DIR,//通信方向为从客户端到服务端
  29. TRUE,//关闭默认响应(目标设备的响应)
  30. seqNum++ );//数据包标号,每上报一次数据seqNum的值就会增加1
  31. HalLcdWriteStringValue("Report: ", (seqNum-1), 10, 4);//显示
  32. // 释放内存空间!
  33. osal_mem_free(reportCmd->attrList[0].attrData);
  34. osal_mem_free(reportCmd);
  35. }

启用对应的宏定义

最后,还需要开启一个宏定义ZCL_REPORTING_DEVICE,如下图所示。
第7章:基于ZCL的属性上报实验 - 图1

7.3 协调器设备开发

协调器设备开发内容主要有一下这几部分:

  • 接收和处理属性数据。
  • 启用对应的宏定义。

    接收和处理属性数据

    与读写命令类似,协调器在接收到上报信息后,就会发生系统事件ZCL_INCOMING_MSG。打开在zcl_samplesw.c文件中的zdSampleSw_event_loop函数,可以找到ZCL_INCOMING_MSG的事件处理函数zclSamplesw_ProcessIncomingMsg,其中的部分代码如下:
  1. 1.static void zclSampleSw_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
  2. 2.{
  3. 3. switch ( pInMsg->zclHdr.commandID )
  4. 4. {
  5. 5. ...... // 不展开
  6. 6.
  7. 7.#ifdef ZCL_REPORT
  8. 8. ...... // 不展开
  9. 9. case ZCL_CMD_REPORT://属性上报
  10. 10. zclSampleSw_ProcessInReportCmd( pInMsg ); //属性上报处理函数
  11. 11. break;
  12. 12.#endif
  13. 13. ...... // 不展开
  14. 14. }
  15. 15. if ( pInMsg->attrCmd )
  16. 16. osal_mem_free( pInMsg->attrCmd );
  17. 17.}

其中的属性上报处理函数zclSampleSw_ProcessInReportCmd,由笔者自定义,代码如下:

  1. #ifdef ZCL_REPORT
  2. static uint8 zclSampleSw_ProcessInReportCmd( zclIncomingMsg_t *pInMsg )
  3. {
  4. zclReportCmd_t *reportCmd;
  5. uint8 i;
  6. reportCmd = (zclReportCmd_t *)pInMsg->attrCmd;
  7. for ( i = 0; i < reportCmd->numAttr; i++ )//reportCmd->numAttr为属性数量
  8. {
  9. if( pInMsg- >clusterId == ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG//Cluster ID
  10. && reportCmd->attrList[i].attrID == ATTRID_ON_OFF_SWITCH_TYPE)//属性ID
  11. {
  12. int8 attrDat = *(reportCmd->attrList[i].attrData);//读取属性值
  13. HalLcdWriteStringValue("Rx Value:", attrDat, 10, 4);//显示属性值
  14. }
  15. }
  16. return ( TRUE );
  17. }
  18. #endif // ZCL_REPORT

启用对应的宏定义

最后,需要开启两个宏:ZCL_REPORT_DESTINATION_DEVICE 和 ZCL_REPORT,如下图所示。
第7章:基于ZCL的属性上报实验 - 图2

7.4 仿真调试

  • 分别编译协调器和终端(路由器)工程,然后分别下载到两个开发板中。
  • 终端(路由器)设备加入到ZigBee网络中后,可以看到协调器屏幕显示如下提示信息。
    第7章:基于ZCL的属性上报实验 - 图3
    第7章:基于ZCL的属性上报实验 - 图4