7.3 协调器设备开发
一句话理解
协调器侧只需两件事:接收上报命令 → 解析属性值显示到屏幕;外加开启对应宏。
协调器设备开发内容
- 接收和处理属性数据;
- 启用对应的宏定义。
接收和处理属性数据
与读写命令类似,协调器收到上报信息后,产生系统事件 ZCL_INCOMING_MSG。在 zclSampleSw_event_loop() 中:
case ZCL_INCOMING_MSG:
// Incoming ZCL Foundation command/response messages
zclSampleSw_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
break;在 zclSampleSw_ProcessIncomingMsg() 中,添加上报命令分支:
static void zclSampleSw_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
{
switch ( pInMsg->zclHdr.commandID )
{
...... // 省略其他分支
#ifdef ZCL_REPORT
case ZCL_CMD_REPORT: // 属性上报命令
zclSampleSw_ProcessInReportCmd( pInMsg ); // 上报处理函数
break;
#endif
...... // 省略其他分支
}
if ( pInMsg->attrCmd )
osal_mem_free( pInMsg->attrCmd );
}属性上报处理函数
zclSampleSw_ProcessInReportCmd() 是自定义函数:
#ifdef ZCL_REPORT
static 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 &&
reportCmd->attrList[i].attrID == ATTRID_ON_OFF_SWITCH_TYPE )
{
int8 attrDat = *(reportCmd->attrList[i].attrData); // 读取属性值
HalLcdWriteStringValue( "Rx Value:", attrDat, 10, 4 ); // 显示属性值
}
}
return ( TRUE );
}
#endif // ZCL_REPORT启用对应的宏定义
协调器侧需要开启两个宏:ZCL_REPORT_DESTINATION_DEVICE 和 ZCL_REPORT。
工程 Options → C/C++ Compiler → Preprocessor → Defined symbols:
ZCL_ON_OFF
ZCL_GROUPS
ZCL_REPORT_DESTINATION_DEVICE
ZCL_REPORT为什么宏不同?
- 终端侧开
ZCL_REPORTING_DEVICE:表示"我是上报方"; - 协调器侧开
ZCL_REPORT_DESTINATION_DEVICE+ZCL_REPORT:表示"我是接收方,允许处理上报命令"。
宏决定协议栈编译哪些代码,两边各开各的。
小结
协调器侧 = 接事件(ZCL_INCOMING_MSG)→ 分流(ZCL_CMD_REPORT)→ 解析显示 + 开宏。至此,上报链路"终端 → 协调器"就完整了。
内容来源:紫甲 IoT《ZigBee 3.0 开发指南》第四部分·7.3 协调器设备开发,原站链接
本章自测
一、单项选择题(每题 4 分,共 40 分)
协调器设备开发主要包括哪两项内容(A. 定义上报事件 + 周期调用上报 API B. 接收和处理属性数据 + 启用对应宏 C. 烧录协调器 + 烧录终端 D. 组网 + 绑定) 答案:B
协调器收到终端的上报信息后,产生的系统事件是(A.
SAMPLEAPP_REPORT_EVTB.ZCL_INCOMING_MSGC.ZDO_STATE_CHANGE_EVTD.KEY_CHANGE) 答案:B在
zclSampleSw_event_loop()中,ZCL_INCOMING_MSG事件被派发给哪个函数处理(A.zclSampleSw_ReportTest()B.zclSampleSw_ProcessIncomingMsg()C.zcl_SendReportCmd()D.zclSampleSw_Init()) 答案:B在
zclSampleSw_ProcessIncomingMsg()中,用于识别"这是一条属性上报命令"的判断依据是(A.pInMsg->clusterId == 0B.pInMsg->zclHdr.commandID == ZCL_CMD_REPORTC.pInMsg->attrCmd == NULLD.pInMsg->srcAddr == 0x0000) 答案:B真正负责解析上报属性值并显示到屏幕的自定义函数是(A.
zclSampleSw_ProcessInReportCmd()B.zclSampleSw_ReportTest()C.zcl_SendReportCmd()D.zclSampleSw_event_loop()) 答案:A在
zclSampleSw_ProcessInReportCmd()中,遍历属性记录的循环次数由哪个变量决定(A.pInMsg->clusterIdB.reportCmd->numAttrC.seqNumD.SAMPLEAPP_REPORT_PERIOD) 答案:B为了确认收到的正是本实验关心的属性,处理函数中做了哪两项匹配(A. 匹配 Cluster ID 和 attrID B. 匹配短地址和端点 C. 匹配 seqNum 和 numAttr D. 匹配 dataType 和 direction) 答案:A
在解析完成后,函数通过哪个函数把属性值显示到协调器屏幕上(A.
printf()B.HalLcdWriteStringValue()C.UART_Write()D.osal_start_timerEx()) 答案:B在
zclSampleSw_ProcessIncomingMsg()末尾,对pInMsg->attrCmd做的操作是(A. 再次发送 B.osal_mem_free释放内存 C. 清零 D. 复制到新缓冲区) 答案:B协调器侧需要开启的两个宏是(A.
ZCL_REPORTING_DEVICE和ZCL_ON_OFFB.ZCL_REPORT_DESTINATION_DEVICE和ZCL_REPORTC.ZCL_GROUPS和HAL_LED=TRUED.ZCL_READ和ZCL_WRITE) 答案:B
二、问答题(每题 20 分,共 60 分)
- 协调器收到一条属性上报命令后,代码层面的处理流程是怎样的?参考答案要点:
- 产生
ZCL_INCOMING_MSG事件,进入zclSampleSw_event_loop(); - 调用
zclSampleSw_ProcessIncomingMsg(),按pInMsg->zclHdr.commandID分流; - 当 commandID 等于
ZCL_CMD_REPORT时,调用自定义函数zclSampleSw_ProcessInReportCmd(); - 在该函数中按
numAttr遍历attrList,匹配 Cluster ID 与 attrID,读取 attrData; - 通过
HalLcdWriteStringValue()把值显示到屏幕,最后在ProcessIncomingMsg末尾osal_mem_free(pInMsg->attrCmd)释放内存。
- 为什么终端侧和协调器侧开启的宏不同?分别说明两边宏的含义。参考答案要点:
- 终端侧开
ZCL_REPORTING_DEVICE:表示"我是上报方",协议栈编译发送上报命令相关代码; - 协调器侧开
ZCL_REPORT_DESTINATION_DEVICE+ZCL_REPORT:表示"我是接收方,允许处理上报命令"; - 宏决定协议栈到底编译哪部分代码,两边各开各的;
- 若宏开错或漏开,对应的上报/接收分支不会被编译进去,链路就不工作。
- 在
zclSampleSw_ProcessInReportCmd()中,为什么要同时判断clusterId和attrID?只判断其中一个行不行?参考答案要点:
- ZigBee 节点上同一时刻可能存在多个 Cluster,且一个 Cluster 内可能有多个属性;
- 必须同时匹配 Cluster ID(
ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG)和 attrID(ATTRID_ON_OFF_SWITCH_TYPE),才能确认收到的正是本实验关心的那一个属性值; - 只匹配一个会把其他 Cluster/其他属性的上报误当成本实验数据显示;
- 匹配成功后才读取
attrData并通过 LCD 打印 "Rx Value:"。