[silicon][EmberZnet]router响应write attribute命令并读取存储的attribute值

前言

最近在研究芯科平台zigbee cluster的扩展,之所以要扩展标准的cluster,是因为我司的zigbee开关需要做一些定制的功能,扩展的方案大致如下:

clusterattributenametypeRangeAccessDefaultreset Keep
0x00060x8000Modeuint80x00-0xffRW0x00yes
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>

img

但是升级完后,每次coordinator下发一个write attribute的命令,router都无法正常响应:

write attribute:

命令类似如下

  • zcl global write 0x06 0x8000 0x20 {01}
  • send 0x7F07 1 1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rR2eC0UF-1605170456462)(C:\Users\lijiaming\AppData\Roaming\Typora\typora-user-images\image-20201103174907627.png)]

response:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WyXwBePL-1605170456463)(C:\Users\lijiaming\AppData\Roaming\Typora\typora-user-images\image-20201103174950374.png)]

每次都响应一个"[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了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MDwpQmIK-1605170456465)(C:\Users\lijiaming\AppData\Roaming\Typora\typora-user-images\image-20201103175633029.png)]

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到现在都不是很流行的原因,因为各大厂家都是自己玩自己的,不过这是其它的话题了,这里不详细展开。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值