6.1 ZCL 属性读写 API
一句话理解
属性就是设备的数据项。要远程读/写它,只需要:① 在属性列表里定义好属性 → ② 用 zcl_SendRead() / zcl_SendWrite() 发命令 → ③ 在 ZCL_INCOMING_MSG 事件里处理响应。
添加属性:在属性列表里"建档"
设备用到的所有属性都要在属性列表中定义。打开 zcl_samplesw_data.c,属性列表 zclSampleSw_Attrs 里有这样一个元素:
{
ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG, // 添加到的 Cluster
{ // Attribute record(属性记录)
ATTRID_ON_OFF_SWITCH_ACTIONS, // 属性 ID:开关动作
ZCL_DATATYPE_ENUM8, // 数据类型:8 位枚举
ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, // 访问权限:可读可写
(void *)&zclSampleSw_OnOffSwitchActions // 属性值存储位置
}
}以属性 ATTRID_ON_OFF_SWITCH_ACTIONS 为例:
- 数据类型是 8 位枚举(
ZCL_DATATYPE_ENUM8); - 权限是可读可写(
ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE); - 它被添加进
ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG这个簇。
类比
属性列表就像员工档案柜:每个档案注明"属于哪个部门(Cluster)、叫什么(属性ID)、什么类型、谁能看谁能改(权限)"。
属性读写命令 API
打开 zcl.h,找到属性读写 API:
#ifdef ZCL_READ
// 发送一个"读取属性"命令
extern ZStatus_t zcl_SendRead(
uint8 srcEP, // 源端点号
afAddrType_t *dstAddr, // 目标设备地址
uint16 realClusterID, // Cluster ID(属性属于哪个簇)
zclReadCmd_t *readCmd, // "读"信息(读哪些属性)
uint8 direction, // 通信方向
uint8 disableDefaultRsp, // 是否关闭默认响应
uint8 seqNum ); // 数据包序号(自增)
#endif // ZCL_READ
#ifdef ZCL_WRITE
// 发送一个"写入属性"命令
#define zcl_SendWrite(a,b,c,d,e,f,g) \
(zcl_SendWriteRequest( (a), (b), (c), (d), ZCL_CMD_WRITE, (e), (f), (g) ))
#endif // ZCL_WRITE注意:使用前要开启宏 ZCL_READ 和 ZCL_WRITE(工程 Options → Defined symbols)。
命令处理:响应来了怎么办
客户端发命令后,服务端会返回响应,并产生系统事件 ZCL_INCOMING_MSG。在 zclSampleSw_event_loop() 中:
case ZCL_INCOMING_MSG:
// Incoming ZCL Foundation command/response messages
zclSampleSw_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
break;zclSampleSw_ProcessIncomingMsg() 里按命令 ID 分流:
static void zclSampleSw_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
{
switch ( pInMsg->zclHdr.commandID )
{
#ifdef ZCL_READ
case ZCL_CMD_READ_RSP: // 读命令响应
zclSampleSw_ProcessInReadRspCmd( pInMsg );
break;
#endif
#ifdef ZCL_WRITE
case ZCL_CMD_WRITE_RSP: // 写命令响应
zclSampleSw_ProcessInWriteRspCmd( pInMsg );
break;
#endif
case ZCL_CMD_DEFAULT_RSP: // 默认响应
zclSampleSw_ProcessInDefaultRspCmd( pInMsg );
break;
default:
break;
}
if ( pInMsg->attrCmd )
osal_mem_free( pInMsg->attrCmd ); // 释放消息内存
}三种响应:搞懂"回执"的含义
小结
属性读写三步走:
- 建档:属性列表里定义属性(Cluster + 属性ID + 类型 + 权限);
- 发令:
zcl_SendRead()/zcl_SendWrite(); - 收据:在
ZCL_INCOMING_MSG里处理读/写响应。
内容来源:紫甲 IoT《ZigBee 3.0 开发指南》第四部分·6.1 ZCL 属性读写 API,原站链接
本章自测
一、单项选择题(每题 4 分,共 40 分)
在属性列表
zclSampleSw_Attrs中定义一个属性时,不需要给出的信息是(A. 属性所属的 Cluster B. 属性 ID 与数据类型 C. 访问权限与属性值存储位置 D. 发送命令的周期) 答案:D示例属性
ATTRID_ON_OFF_SWITCH_ACTIONS的数据类型是(A.ZCL_DATATYPE_UINT8B.ZCL_DATATYPE_ENUM8(8 位枚举) C.ZCL_DATATYPE_CHAR_STRD.ZCL_DATATYPE_BOOLEAN) 答案:B示例属性的访问权限设置为(A. 只读
ACCESS_CONTROL_READB. 只写ACCESS_CONTROL_WRITEC.ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE(可读可写) D. 不可访问) 答案:C示例属性被添加进哪个簇(A.
ZCL_CLUSTER_ID_GEN_ON_OFFB.ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIGC.ZCL_CLUSTER_ID_GEN_BASICD.ZCL_CLUSTER_ID_GEN_LEVEL_CTRL) 答案:B客户端要远程读取设备属性,使用哪个 API(A.
zcl_SendWrite()B.zcl_SendRead()C.zcl_SendCommand()D.zcl_registerAttrList()) 答案:B宏
zcl_SendWrite(a,b,c,d,e,f,g)展开后最终调用的函数与命令字是(A.zcl_SendReadRequestB.zcl_SendWriteRequest(),命令字为ZCL_CMD_WRITEC.zcl_SendCommand()D.zclGeneral_RegisterCmdCallbacks()) 答案:B客户端发出属性读写命令后,服务端返回响应时在客户端产生哪个系统事件(A.
ZDO_CB_MSGB.ZCL_INCOMING_MSGC.AF_DATA_CONFIRM_CMDD.SYS_EVENT_MSG) 答案:B在
zclSampleSw_ProcessIncomingMsg()的switch中,读命令响应对应哪个case(A.ZCL_CMD_WRITE_RSPB.ZCL_CMD_READ_RSPC.ZCL_CMD_DEFAULT_RSPD.ZCL_CMD_REPORT) 答案:B使用属性读/写 API 前,工程预编译宏中必须开启(A.
ZCL_READ和ZCL_WRITEB.ZCL_ON_OFFC.ZCL_GROUPSD.ZCL_SCENES) 答案:A关于三种"回执",下列说法错误的是(A. 默认响应用于让客户端确认服务端确实收到了命令 B. 读响应返回属性是否读成功以及属性值 C. 写响应返回属性值是否写入成功 D. 写响应中必须携带属性当前值) 答案:D
二、问答题(每题 20 分,共 60 分)
- 题干:请按页面"小结"列出 ZCL 属性读写的三步流程,并说明每一步做什么。 参考答案要点:
- 第一步"建档":在属性列表
zclSampleSw_Attrs(zcl_samplesw_data.c)中定义属性,注明所属 Cluster、属性 ID、数据类型、访问权限和属性值存储位置; - 第二步"发令":客户端用
zcl_SendRead()发读命令、用zcl_SendWrite()发写命令; - 第三步"收据":响应到达时产生
ZCL_INCOMING_MSG事件,在zclSampleSw_ProcessIncomingMsg()中按commandID分流到zclSampleSw_ProcessInReadRspCmd()/zclSampleSw_ProcessInWriteRspCmd()处理;处理完释放pInMsg->attrCmd内存。
- 题干:一条属性记录(Attribute record)包含哪些关键信息?请以
ATTRID_ON_OFF_SWITCH_ACTIONS为例说明。 参考答案要点:
- 所属 Cluster:
ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG; - 属性 ID:
ATTRID_ON_OFF_SWITCH_ACTIONS(开关动作); - 数据类型:
ZCL_DATATYPE_ENUM8(8 位枚举); - 访问权限:
ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE(可读可写); - 属性值存储位置:
(void *)&zclSampleSw_OnOffSwitchActions。
- 题干:默认响应、读响应(READ_RSP)、写响应(WRITE_RSP)三者各自的含义是什么? 参考答案要点:
- 默认响应:发送命令时可指定是否需要,客户端据此确认"服务端确实收到了命令";
- 读响应(READ_RSP):服务端返回读取结果,包括属性是否读成功以及读到的属性值;
- 写响应(WRITE_RSP):服务端返回写入结果,即属性值是否写入成功。