相关系列文章
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(-)-Z3GatewayHost应用搭建
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(二)-使用gateway-management-ui
概要
Host-NCP环境搭建好后,怎么测试验证zigbee功能,怎么将Host集成到自己的应用中,应该是大部分使用者关心的问题。芯科公司为此提供了一套基于Nodejs和ReactJS的Web应用例子“gateway-management-ui”来指引开发。如下图所示,通过web可视化界面,使用者可以简单、快捷地体验ZigBee的各种功能,主要包括:网络配置、网络开放、设备加入、设备信息查看、设备控制、设备属性读取、设备应用绑定等;大部分功能都是基于芯科ZigBee 插件应用实现的,稳定性和可用性都比较高,“久经考验”。
本人觉得使用“gateway-management-ui”,对使用者来说,有以下几点意义:
1.理解Host作为外部应用和ZigBee应用之间的一座桥梁,应当怎么为上层应用提供服务能力;(从整体架构设计的角度,理解Host的定位)
2.理解应用如何从依赖于callback回调的编程模式,转变为通过mqtt方式实现“订阅“-“发布”的编程模式;(移动互联网、云端应用的概念)
3.有助于使用者更加快速地将应用与各大物联网平台对接。(微信、阿里等)
软件架构
在《ug129-zigbee-gateway-ref-design-guide.pdf》文档中的第4章节,有具体的描述。
软件安装
1.gateway-management-ui最新版本可以在https://github.com/SiliconLabs/gateway-management-ui获取;
2.gateway-management-ui运行,需要nodejs、npm环境,而且对版本可能有一点要求(nodejs版本过高,可能运行失败)。
目前,在本人电脑上能正确运行的环境如下:
NodeJS: v10.15.0
npm:6.4.1
3.下载代码后,需要分别进入nodeserver目录、reactui目录进行依赖安装和应用部署(和大部分node应用一样),具体可以参考文档4.2.2章节,如下图所示
特别注意:npm 安装gulp时,需要带上版本号@3.9.0;因为现在gulp最新版本4.x为,在语法上和3.x有较大出入;reactui中用到的是3.x的语法,所以只能安装旧版gulp
备注:如果后续调整了reactui中的资源文件(页面、js或图片等),都要执行sudo npm run build命令,重新build一下reactui项目。
软件配置
几个重要的配置文件:
1.mqtt服务地址和端口配置:位于nodeserver\src\common\routes\GatewayInterface.js文件中,如下图所示
var mqttBrokerPort = 1883;
var mqttBrokerAddress = "127.0.0.1";
2.nodeserver与reactui间socket通讯的配置:位于nodeserver\src\common\routes\SocketInterface.js文件中,如下图所示
备注1:socket端口需要与reactui\src\js\Config.js文件中的端口保持一致,如下所示
备注2:socketio默认使用polling方式,如果需要支持微信小程序通讯,需要采用websocket方式,而且客户端需要使用支持微信小程序的socketio版本
var Config = {}
Config.gatewayAddress = window.location.hostname + ':9010';
module.exports = Config;
3.nodeserver\src\common\Constants.js配置了日志目录、ota文件存放目录、外部程序目录(包括installcode生成key的外部程序路径),如下图所示
ZigBee功能验证
1.网络配置
点击网络配置按钮
设置好网络参数(通道、PANID),accept后,可以看到新的网络生效。(界面显示先停止已有网络,然后新的网络生效)
在Z3GatewayHost的命令行面板可以到以下日志:
说明Host收到mqtt的命令后,转换为调用对应插件命令,在配置网络的操作中,主要的mqtt命令为
{"commands":[{"command":"plugin device-table clear"},{"command":"plugin command-relay clear","postDelayMs":100},{"command":"plugin ias-zone-client clear-all","postDelayMs":100},{"command":"plugin groups-server clear","postDelayMs":100},{"command":"plugin scenes clear","postDelayMs":100}]}
{"commands":[{"command":"network leave","postDelayMs":1000},{"command":"plugin network-creator form 0x1 0x6D17 -2 0x14"}]}
2.设备入网
点击新增ZigBee设备按钮,打开网络。(界面提示设备180秒的入网倒计时)
让终端设备按正常进行加网请求,可以看到设备正常入网,Z3GatewayHost日志如下:
设备加入网络后的展示
在Z3GatewayHost 的命令行下,通过plugin device-tables print命令可以看到已经加入的设备
在抓包软件中可以看到整个入网流程日志
在设备入网的操作中,主要的mqtt命令为
{"commands":[{"command":"plugin network-creator-security open-network","postDelayMs":100}]}
3.设备属性读取
ZigBee一个优势是在传感器领域指定了一套规范,包括对设备属性的读写、对设备的控制等,从而能实现不同厂家设备间“互联互通、数据共享”(理论上)。而其中zcl是实现这些功能的最主要手段。
在gateway-management-ui中可以在“Home”标签页下面,看到相关设备的属性,例如下图所示的温度传感器显示的温度,终端的manufacturer name,这些属性都是通过标准的zcl方式进行读取。
无论你的模组是efr32的,还是cc2530的,或者其他厂家的;都能通过zcl进行设备控制。(后面专门写一篇cc2530和efr32在实现同一个zigbee功能中的差异性)
所以,这里应当作为重点来分析掌握一下。
流程分析:reactUI界面-》node server-》host-》ncp
关键代码分析如下:
1)reactUI界面:gateway-management-ui\reactui\src\js\actions\ServerActions.js中的requestNodeAttribute方法。
从方法的实现可以看到,它是通过socket方式(前面提到的9010端口),发送请求和参数给nodeserver(json格式的socket调用,socketIO)
2)nodeserver:reactUI发送的socket请求,会在gateway-management-ui\nodeserver\src\common\controller\DeviceController.js中的onSocketAction方法j进行处理。
找到requestattribute,可以看到是调用ServerActions.GatewayInterface.zigbeeRequestAttribute方法。
zigbeeRequestAttribute方法位于gateway-management-ui\nodeserver\src\common\actions\ServerActions.js中,打开可以看到,它的实现是将命令和参数转换为json格式,然后通过mqtt发布到对应的topic上。
重点:reactUI和nodeserver中的ServerAction.js都是重要的入口和处理文件,大部分逻辑和实现,都可以在这里找到。
3)host:因为host在ncp启动后,会通过mqtt方式订阅commands主题(具体的代码分析,在后一章esp32移植中再详细描述),这个可以从host启动的日志看到:
Subscribing to topic "gw/60A423FFFE068C75/commands" using QoS2
Subscribing to topic "gw/60A423FFFE068C75/publishstate" using QoS2
Subscribing to topic "gw/60A423FFFE068C75/updatesettings" using QoS2
所以上面nodeserver发布的命令,host会通过mqtt接收到,然后通过调用插件方式或者底层api方式,将zcl命令发送给ncp(通过ezsp协议),进行zigbee操作(具体的代码分析,在后一章esp32移植中再详细描述)。
4)ncp:ncp收到命令,处理完后,返回处理结果给host(这个过程可能是异步的?);
那么,host怎么将结果通知给前端?答案,也是mqtt的“订阅”-“发布”
host通过mqtt方式,将处理ncp结果发布到zclresponse主题,所以只要是订阅了gw/60A423FFFE068C75/zclresponse的客户端(reactUI也好,VUE也好、微信小程序也好)都可以收到
如下图所示
在nodeserver后台,也可以看到对应的日志输出(nodeserver做了一些数据转换、格式化的工作)
在设备属性读取的操作中,主要的mqtt命令为
{"commands":[{"command" :"zcl global direction 0"},{"command":"zcl global read 1024 0"},{"command":"plugin device-table send {000B57FFFE097874} 1","postDelayMs":100}]}
调整的地方:
1)在调试中发现gateway-management-ui\nodeserver\src\common\actions\ServerActions.js中的publishCommandListThrottled方法,并没有真的把数据发送到mqtt,所以先调整为直接调用GatewayInterfaceSend.publishCommandList(commandlist);
2)当zclresponse返回属性的数据类型为String的时候,nodeserver处理不正确(例如:获取manufacturer name中的字符串值),先暂时改为调用自定义方法得到字符串
位于nodeserver中的DeviceController.js文件中的onAttributeUpdate方法
4.设备控制
设备控制主要指开、关这些常规的zcl操作,其实原理和上面设备属性读取一致,所以就不在这里详细描述了。
入口还是在reactUI的ServerAction.js中,它已经封装好比较细粒度的操作了,如下图所示。
在设备控制的操作中,主要的mqtt命令为:
{"commands":[{"command":"zcl on-off on"},{"command":"plugin device-table send {00124B00213CCA01} 0x8"}]}
5.设备report参数配置
在设备report中,有几个地方要注意:
1.设备终端要打开report功能,具体而言:
对于efr32要在plugin勾选Reporting插件,如下图所示
对应cc2530,要配置BDB_REPORTING编译条件
2.先将网关和reporting 终端绑定:
mqtt命令如下:
{"commands":[{"command" :"zdo bind 0x434C 1 1 0x0400 {000B57FFFE097874} {0022A30000115EDA }"},{"command ":"plugin device-table send {000B57FFFE097874} 1","postDelayMs":100}]}
备注:以上这些zcl命令、zdo命令格式,都可以在《ug129-zigbee-gateway-ref-design-guide.pdf》的第4.3 Z3GatewayMqtt Application章节找到
简单记录一下自己用到的命令
#######light 终端##############
// 绑定终端
// zdo bind 终端短地址 终端endpoint 网关endpoint 终端clusterid 终端eui 网关eui
zdo bind 0x3CEE 8 1 0x0006 {60A423FFFE091C85} {60A423FFFE0B648E}
// 设定终端属性上报配置
// zcl global send-me-a-report 终端clusterid 属性id 数据类型 最小上报周期 最大上报周期 变化值
zcl global send-me-a-report 0x0006 0x0000 0x10 0x0001 0x708 {00 01}
开关状态上报配置:最小上报时间1秒,最大上报时间1800秒 0x10代表ZCL_BOOLEAN_ATTRIBUTE_TYPE数据类型
plugin device-table send {60A423FFFE091C85} 8
######switch 终端#################
zcl global send-me-a-report 0x0402 0x0000 0x29 0x0001 0x3c {00}
温度值上报配置:最小上报时间1秒,最大上报时间60秒 0x29代表ZCL_INT16S_ATTRIBUTE_TYPE数据类型
plugin device-table send {60A423FFFE0B6A52} 8
查看设备绑定表
option binding-table print
相关抓包截图
6.设备OTA
需要了解efr32终端OTA的,可以参考以下文章(感谢相关文章作者的分享,在此借以引用参考,如有涉及版权问题,请及时联系我);
https://blog.csdn.net/weixin_42160773/article/details/101284109
在Z3GatewayHost项目的build/exe目录下,会自动生成一个终端ota文件存放的目录ota-files
这个目录的配置是在芯科SDK中protocol\zigbee\app\framework\plugin\ota-storage-posix-filesystem\ota-storage-linux.c文件中,如下图所示。
只要把终端的ota文件保存到放在这里,然后设备入网后过一段时间即可自动进行ota;也可以通过cli命令方式,指定终端开始ota操作
这里,只记录一下ota相关的一些命令;
#终端
plugin ota-client start
#host端
plugin ota-storage-common printImages
plugin ota-storage-common reload
后面esp32移植中再详细讲述怎么通过esp32到外网下载ota,存储在flash中,然后通知终端进行ota,并测试多终端一起ota的场景。
备注:
终端设备的bootloader类型需要选择“Local storage”,如果是默认配置,可能出现ota完后,设备不能自动重启的现象。
总结
- 通过使用gateway-management-ui,有助于了解整个Host-NCP架构;对于需要云端部署、对接互联网平台、对接第三方物联网平台的场景,有很好的参考价值;
- 在使用Host-NCP解决方案的时候应当遵循芯科的设计思想:优先使用“订阅”-“发布”的编程模式,减少对callback的依赖,要有面向云端和移动互联网的架构设计思想。专注于应用层面的使用,实现各层间的解耦和赋能。
- 芯科解决方案的优势,是它拥有很多“久经考验”的插件;我们在实现业务场景的时候应当尽量复用这些插件;而不是去大量调用底层的api(不要觉得自己写的代码比芯科的开发人员强);
- 用好Host-NCP比将Host移植到不同平台更加重要。