[silicon][EmberZnet]router响应write attribute命令并读取存储的attribute值
前言
最近在研究芯科平台zigbee cluster的扩展,之所以要扩展标准的cluster,是因为我司的zigbee开关需要做一些定制的功能,扩展的方案大致如下:
cluster | attribute | name | type | Range | Access | Default | reset Keep |
---|---|---|---|---|---|---|---|
0x0006 | 0x8000 | Mode | uint8 | 0x00-0xff | RW | 0x00 | yes |
Mode attribute
-
用来描述继电器是否跟随开关动作的值:
0 = 继电器模式(按下开关,控制继电器,然后上报状态)
1 = 遥控模式(按下开关,继电器不工作(保持闭合),只上报状态)
熟悉zigbee cluster的同学应该知道,上述是基于on/off这个cluster进行扩展的,添加了一个新的attribute,attribute ID为0x8000。这个attribute主要用来描述开关的模式,0代表按下开关的时候,通过继电器控制连接的灯;1代表按下开关后,只上报当前开关按键的状态值,不再控制继电器的闭合。
其实这个扩展是基于以下这种场景的一个开发需求:
假如一个开关(router)通过继电器控制一个同样支持zigbee的灯(router),然后这两个设备都通过zigbee的方式连接了coordinator。一般情况下,我们都是习惯通过开关来控制灯的亮灭。但是现在这种场景下,如果把开关闭合了,那么相当于直接把灯断电了,这时候coordinator就以为灯是离线了,而不会觉得这个是关闭的状态,所以coordinator上看到的状态就不对。
所以如果灯是支持zigbee的话,开关就不再通过继电器来控制灯,而是简单的上报一个状态值告诉coordinator,由coordinator去控制相应的灯,这样各个设备的状态值就正常了。
就是基于以上的需求,我们的开关需要一个attribute来记录此时处于一个什么模式,这个模式值由coordinator来下发一个write attribute命令来改变。
正文
1、扩展标准cluster
其实扩展标准的cluster,芯科官方有给出指导:
https://github.com/MarkDing/IoT-Developer-Boot-Camp/wiki/Zigbee-Custom-Clusters-CN
在完全按照指导文档来扩展的文件如下:
<configurator>
<domain name="Test" />
<!-- Use the cluster extension Extend the on/off cluster -->
<clusterExtension code="0x0006">
<attribute side="server" code="0x8000"
define="SWITCH_Mode"
type="INT8U" min="0x0000" max="0xFFFF" writable="true"
default="0x0000" optional="true"
manufacturerCode="0x128e">Mode</attribute>
</clusterExtension>
</configurator>
但是升级完后,每次coordinator下发一个write attribute的命令,router都无法正常响应:
write attribute:
命令类似如下
- zcl global write 0x06 0x8000 0x20 {01}
- send 0x7F07 1 1
response:
每次都响应一个"[0x86] unsupported attribute"的错误码,在芯科的论坛咨询后,如果想用通用的命令就不能定义私有的manufactureCode:
<configurator>
<domain name="Test" />
<!-- Use the cluster extension Extend the on/off cluster -->
<clusterExtension code="0x0006">
<attribute side="server" code="0x8000"
define="SWITCH_Mode"
type="INT8U" min="0x0000" max="0xFFFF" writable="true"
default="0x0000" optional="true" >Mode</attribute>
<command source="client" code="0x00"
name="ModeChange" optional="true" manufacturerCode="0x128e">
<description>Change the switch mode. 0=switch mode, 1=remote control mode.</description>
</command>
</clusterExtension>
</configurator>
之后router就能正常respond了:
2、读取自身的attribute值
既然coordinator下发了一个attribute值到router,那么router怎么能读到这个值呢?SDK的代码肯定也是提供了相应的接口给开发者使用的。在我们的开关代码中,当按下开关我们就会去读取一下Mode这个attribute值,来判断此时处于什么模式下:
void emberAfHalButtonIsrCallback(uint8_t button, uint8_t state)
{
uint8_t readLength;
if (button == BSP_BUTTON1_PIN) {
if (state == PRESS) {
emberAfReadAttribute(1,ZCL_ON_OFF_CLUSTER_ID,ZCL_SWITCH_Mode_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &readLength, sizeof(readLength), NULL);
}
}
}
其实就是一个简单的接口,把读取到的数据保存到定义的变量readLength中:
EmberAfStatus emberAfReadAttribute(uint8_t endpoint,
EmberAfClusterId cluster,
EmberAfAttributeId attributeID,
uint8_t mask,
uint8_t *dataPtr,
uint8_t readLength,
EmberAfAttributeType *dataType);
结语
说实话,扩展标准的cluster来定制自己的私有协议并不是一个很好的方案,毕竟私有的协议只有你自己家的产品能用,并不通用。这也是zigbee到现在都不是很流行的原因,因为各大厂家都是自己玩自己的,不过这是其它的话题了,这里不详细展开。
本文地址:https://blog.csdn.net/lee_jimmy/article/details/109647514
上一篇: STM32F103 串口DMA + 空闲中断 实现不定长数据收发
下一篇: nginx必会知识点