本周日,苏州开源盛宴,一起聊聊:Devops、K8s、数据库建模、SoLiD、.Net Core、微信开发、去中心化… 点击占座。
Watch 1 Star 3 Fork 0

erabbit / OpenIoT

加入码云
与超过 300 万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
基于公有云的IoT实践,以JavaScript作为主要开发语言 展开 收起

克隆/下载
lighting-zha-dongle.md 22.20 KB
一键复制 编辑 Web IDE 原始数据 按行查看 历史
erabbit 提交于 2016-10-06 12:00 . fix format for zha dongle doc#4

ZHA USB dongle使用介绍

概述

智能照明管理项目中使用的USB dongle基于TI CC2530芯片设计,支持标准Zigbee Home Automation(ZHA)协议。 CC2530通过串口收发控制命令,串口在dongle上通过CP2102芯片转为USB接口连接至网关。 对于Linux和OS X系统,dongle对应的串口设备一般为/dev/ttyUSB0,如果没有,可能需要安装CP2102的驱动程序。
USB dongle作为协调器建立和维护Zigbee网络,灯具作为节点加入此网络。 正常工作时,Zigbee网络是关闭的,为了使新节点能够加入,需要先打开网络。 节点入网时协调器为其分配两字节的网络地址,随后与节点的通信均通过网络地址进行。 网络地址可能随着网络结构的变化而改变,而节点本身的MAC地址是不变的,因此网关需维护节点MAC地址与网络地址的对应关系,在每次启动和节点主动上报地址信息时更新。

串口参数

串口波特率为115200,8位数据位,1位停止位,无奇偶校验。

数据帧格式

网关向dongle发送的命令应符合以下格式,dongle的回应也符合此格式:

  • 帧头:1字节,内容为0xFE
  • 帧长:1字节,整帧数据长度,范围是0x0A~0x7F
  • 命令层级:1字节,详见命令列表
  • 命令代码:1字节,详见命令列表
  • 地址模式:1字节
    • 0x01:组播
    • 0x02:使用网络地址单播
    • 0x03:使用MAC地址单播
    • 0x0F:广播
  • 目标设备网络地址:2字节,低字节在前
  • 端点:1字节,与节点设备的厂家有关,使用Philips HUE灯泡时,应为0x0B
  • 帧序号:1字节,内容由网关定义
  • 数据:n字节(n>=0)
  • 校验:1字节,之前所有字节按位异或

在下文的命令列表中,帧序号字段和校验字段填写的都是固定值,实际应用中须替换之。

命令发送和回应

当dongle收到来自网关的命令帧后,会向网关回应一条确认帧(ACK),其中命令代码字段为发送命令代码与0x40按位或。 确认帧中数据部分的第一个字节通常为【状态】字段,其值为0表示操作成功,为1表示操作失败。
如果网关所请求的数据可以由dongle直接返回,则回应中还包含数据。
如果命令是发往节点的,dongle将根据网络地址向节点转发命令,当dongle收到来自节点的数据后,会向网关回应数据帧,其中命令代码字段为发送命令代码与0x80按位或。
确认帧和数据帧中的帧序号与命令帧一致。

(1)dongle直接回应网关
网关 -------CMD------> dongle
网关 <----CMD|0x40---- dongle

(2)dongle先回应网关ACK帧,收到节点数据后再回应网关数据帧
网关 -------CMD------> dongle ------------> 节点
网关 <----CMD|0x40---- dongle
网关 <----CMD|0x80---- dongle <------------ 节点

命令列表

以下命令前的数字为命令层级和命令代码,如“5.1 开/关灯”表示这条命令的命令层级是5,命令代码是1。

系统命令

  • 1.0 协调器初始化成功
    网关无需发送这条命令,在协调器初始化成功后由dongle主动发给网关:
帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 硬件版本 软件版本 校验
0xFE 0x0D 0x01 0x80 0x02 0x00 0x00 0x00 0x88 0x01 0x00 0x01 0xFF
  • 1.1 查询协调器固件版本号

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 校验
0xFE 0x0A 0x01 0x01 0x02 0x00 0x00 0x00 0x88 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 硬件版本 软件版本 校验
0xFE 0x0D 0x01 0x41 0x02 0x00 0x00 0x00 0x88 0x01 0x00 0x01 0xFF
  • 1.2 重启协调器
    在重启完成后网关会收到“1.0 协调器初始化成功”消息
帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 校验
0xFE 0x0A 0x01 0x02 0x02 0x00 0x00 0x00 0x88 0xFF
  • 1.3 将协调器恢复出厂设置并重启
    在重启完成后网关会收到“1.0 协调器初始化成功”消息
帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 配置选项 校验
0xFE 0x0B 0x01 0x03 0x02 0x00 0x00 0x00 0x88 0x03 0xFF
  • 1.4 读取和配置协调器网络参数
    • 读信道

      命令:

      帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 读/写 配置ID 校验
      0xFE 0x0C 0x01 0x04 0x02 0x00 0x00 0x00 0x88 0x00 0x01 0xFF

      回应:

      帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 读/写 配置ID 状态 信道 校验
      0xFE 0x0E 0x01 0x44 0x02 0x00 0x00 0x00 0x88 0x00 0x01 0x00 0x0B 0xFF
    • 配置信道

      命令:

      帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 读/写 配置ID 信道 校验
      0xFE 0x0D 0x01 0x04 0x02 0x00 0x00 0x00 0x88 0x01 0x01 0x0B 0xFF

      其中,【信道】的取值范围是0x0B~0x1A。

      回应:

      帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 读/写 配置ID 状态 校验
      0xFE 0x0D 0x01 0x44 0x02 0x00 0x00 0x00 0x88 0x01 0x01 0x00 0xFF
    • 读EPID

      命令:

      帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 读/写 配置ID 校验
      0xFE 0x0C 0x01 0x04 0x02 0x00 0x00 0x00 0x88 0x00 0x03 0xFF

      回应:

      帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 读/写 配置ID 状态 EPID 校验
      0xFE 0x15 0x01 0x44 0x02 0x00 0x00 0x00 0x88 0x00 0x03 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0xFF

网络管理命令

  • 2.1 打开/关闭网络

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 【时间】 校验
0xFE 0x0B 0x02 0x01 0x02 0x00 0x00 0x00 0x88 0x3C 0xFF

其中:

【时间】 含义
0x00 关闭网络
0xFF 一直打开网络,直到收到关闭命令
其他值 指定打开网络的持续时间,单位是秒,时间到后自动关闭

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 校验
0xFE 0x0B 0x02 0x41 0x02 0x00 0x00 0x00 0x88 0x00 0xFF
  • 2.2 设备地址信息
    网关无需发送这条命令,在节点加入网络或上线时由dongle主动发给网关。
帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 网络地址 MAC地址 设备类型 校验
0xFE 0x15 0x02 0x82 0x02 0x34 0x12 0x00 0x88 0x34 0x12 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x01 0xFF
  • 2.5 根据MAC地址查询网络地址

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 MAC地址 请求类型 起始索引 校验
0xFE 0x14 0x02 0x05 0x03 0x00 0x00 0x00 0x88 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00 0x00 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 MAC地址 校验
0xFE 0x13 0x02 0x85 0x02 0x34 0x12 0x00 0x88 0x00 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0xFF
  • 2.6 根据网络地址查询MAC地址

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 请求类型 起始索引 校验
0xFE 0x0C 0x02 0x06 0x02 0x34 0x12 0x00 0x88 0x00 0x00 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 MAC地址 校验
0xFE 0x13 0x02 0x86 0x02 0x34 0x12 0x00 0x88 0x00 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0xFF
  • 2.21 离网设备上报
    网关不需要发送此命令,当远端设备离开网络时,由dongle发送给网关:
帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 MAC地址 校验
0xFE 0x13 0x02 0x95 0x02 0x34 0x12 0x00 0x88 0x00 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0xFF
  • 2.22 从网络中移除设备并将其恢复出厂设置

命令:

帧头|帧长|命令层级|命令代码|地址模式|网络地址|端点|帧序号|MAC地址|校验 ----|-----|-----|-----|-----|-----------|-----|-----|-----|-----------------------------------------------|----- 0xFE| 0x12| 0x02| 0x16| 0x02| 0x34 0x12| 0x00| 0x88| 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01| 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 校验
0xFE 0x0B 0x02 0x56 0x02 0x34 0x12 0x00 0x88 0x00 0xFF

若操作成功,网关还将收到一条“2.21 离网设备上报”消息。

HA标准命令

  • 4.3 闪烁设备
    设置远端设备闪烁指定的时间,用于在现场寻找一个特定的设备。

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 闪烁时间 校验
0xFE 0x0B 0x04 0x03 0x02 0x34 0x12 0x0B 0x88 0x05 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 校验
0xFE 0x0B 0x04 0x83 0x02 0x34 0x12 0x0B 0x88 0x00 0xFF

HA照明类命令

  • 5.1 开/关灯

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 【操作命令】 校验
0xFE 0x0B 0x05 0x01 0x02 0x34 0x12 0x0B 0x88 0x01 0xFF

其中:

【操作命令】 含义
0x00 关灯
0x01 开灯
0x02 切换开/关状态
  • 5.2 调亮度

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 操作命令 【亮度】 【调光时间】 校验
0xFE 0x0E 0x05 0x02 0x02 0x34 0x12 0x0B 0x88 0x04 0x7F 0x02 0x00 0xFF

其中:
【亮度】的取值范围是0~255
【调光时间】表示灯用多长时间达到指定状态,单位是秒

  • 5.3 调色调和饱和度

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 操作命令 【色调】 【饱和度】 【调光时间】 校验
0xFE 0x0E 0x05 0x02 0x02 0x34 0x12 0x0B 0x88 0x07 0x7F 0x40 0x02 0x00 0xFF

其中:
【色调】与【饱和度】的取值范围都是0~254
【调光时间】表示灯用多长时间达到指定状态,单位是秒

  • 5.4 调色温

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 【色温】 【调光时间】 校验
0xFE 0x0E 0x05 0x02 0x02 0x34 0x12 0x0B 0x88 0x99 0x40 0x02 0x00 0xFF

其中,【色温】为双字节,低字节在前,取值范围是1~65279,对应的实际色温值 = 1000,000/【色温】,单位是K(Kelvin)
其中,【调光时间】表示灯用多长时间达到指定状态,单位是秒

  • 5.5 查询灯的开/关状态

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 属性ID 校验
0xFE 0x0C 0x05 0x05 0x02 0x34 0x12 0x0B 0x88 0x00 0x00 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 开关状态 校验
0xFE 0x0C 0x05 0x85 0x02 0x34 0x12 0x0B 0x88 0x00 0x01 0xFF
  • 5.6 查询灯的亮度

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 属性ID 校验
0xFE 0x0C 0x05 0x06 0x02 0x34 0x12 0x0B 0x88 0x00 0x00 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 亮度 校验
0xFE 0x0C 0x05 0x86 0x02 0x34 0x12 0x0B 0x88 0x00 0x7F 0xFF
  • 5.7 查询灯的色调和饱和度

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 属性ID 校验
0xFE 0x0C 0x05 0x07 0x02 0x34 0x12 0x0B 0x88 0x00 0x00 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 色调 饱和度 校验
0xFE 0x0D 0x05 0x87 0x02 0x34 0x12 0x0B 0x88 0x00 0x7F 0x40 0xFF
  • 5.8 查询灯的色温

命令:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 属性ID 校验
0xFE 0x0C 0x05 0x08 0x02 0x34 0x12 0x0B 0x88 0x00 0x00 0xFF

回应:

帧头 帧长 命令层级 命令代码 地址模式 网络地址 端点 帧序号 状态 色温 校验
0xFE 0x0D 0x05 0x88 0x02 0x34 0x12 0x0B 0x88 0x00 0x01 0x01 0xFF

使用lighting-gw网关程序测试

lighting-gw网关程序中已经实现了以上各条命令,如果您的程序也用JavaScript编写,可以直接使用lighting-gw的代码。
如果您使用其他语言,则可以按照下文的介绍,通过在lighting-gw的主程序内输入命令执行操作,然后查看接收和发送的数据,作为参考。

  1. 首先,请确认您已经安装了nodejs和npm,建议您使用6.5.0或以上版本的nodejs:

$ node -v
v6.5.0

  1. 下载OpenIoT工程:

$ git clone https://git.oschina.net/erabbit/OpenIoT.git OpenIoT
$ cd OpenIoT/gw
$ mkdir data

  1. 运行主程序(由于要使用串口,此处可能需要sudo权限):

$ src/main.js

This is a smart lighting gateway based on AWS IoT, which communicates to Zigbee Home Automation network via USB dongle.
serial port opened!
on command: networkParam
sent: FE 0C 01 04 02 00 00 00 01 00 03 F7 
failed to open devices file due to error: Error: ENOENT: no such file or directory, open 'data/devices.json'
received:
<Buffer fe 15 01 44 02 00 00 00 01 00 03 00 86 13 96 02 00 4b 12 00 f6>
parse rx message: FE 15 01 44 02 00 00 00 01 00 03 00 86 13 96 02 00 4B 12 00 F6 
got Ack for command: networkParam
{ operation: 0,
 configuration: 3,
 status: 0,
 value: <Buffer 86 13 96 02 00 4b 12 00> }
epid updated: 86139602004B1200
如上文,可将epid用作dongle的唯一标识。
  1. 打开网络,以搜索设备:

network.switchNetwork {"duration":"on"}

onUserCommand network.switchNetwork: {"duration":"on"}
on command: switchNetwork
sent: FE 0B 02 01 02 00 00 00 02 FF 09 
received:
<Buffer fe 0b 02 41 02 00 00 00 02 00 b6>
parse rx message: FE 0B 02 41 02 00 00 00 02 00 B6 
got Ack for command: switchNetwork
{ status: 0 }

received:
<Buffer fe 15 02 82 02 02 e3 00 00 02 e3 0d 83 dd 01 00 4b 12 00 01 63 fe 15 02 82 02 02 e3 00 01 02 e3 0d 83 dd 01 00 4b 12 00 01 62>
parse rx message: FE 15 02 82 02 02 E3 00 00 02 E3 0D 83 DD 01 00 4B 12 00 01 63 
got Response for command: updateAddress
{ nwkAddr: 58114,
 macAddr: <Buffer 0d 83 dd 01 00 4b 12 00>,
 deviceType: 1 }
found new light: {"id":"Light1","uid":"0D83DD01004B1200"}
on command: getPower
sent: FE 0C 05 05 02 02 E3 0B 03 00 00 19 
parse rx message: FE 15 02 82 02 02 E3 00 01 02 E3 0D 83 DD 01 00 4B 12 00 01 62 
got Response for command: updateAddress
{ nwkAddr: 58114,
 macAddr: <Buffer 0d 83 dd 01 00 4b 12 00>,
 deviceType: 1 }
got nwkAddr: e302 of Light1
on command: getPower
sent: FE 0C 05 05 02 02 E3 0B 04 00 00 1E 
received:
<Buffer fe 0b 05 45 02 02 e3 0b 03 00 5e fe 0b 05 45 02 02 e3 0b 04 00 59>
parse rx message: FE 0B 05 45 02 02 E3 0B 03 00 5E 
got Ack for command: getPower
parse rx message: FE 0B 05 45 02 02 E3 0B 04 00 59 
got Ack for command: getPower
received:
<Buffer fe 0c 05 85 02 02 e3 0b 03 00 00 99 fe 0c 05 85 02 02 e3 0b 04 00 00 9e>
parse rx message: FE 0C 05 85 02 02 E3 0B 03 00 00 99 
got Response for command: getPower
{ status: 0, power: 0 }
light power updated: {"id":"Light1","power":"off"}
parse rx message: FE 0C 05 85 02 02 E3 0B 04 00 00 9E 
got Response for command: getPower
{ status: 0, power: 0 }
light power updated: {"id":"Light1","power":"off"}
如上文,搜索到了一个设备,其id(程序自动生成)是"Light1",uid(唯一标识)是"0D83DD01004B1200"(实际是设备的Zigbee MAC地址)。  
接下来关闭网络,以防无关设备加入:

network.switchNetwork {"duration":"off"}

onUserCommand network.switchNetwork: {"duration":"off"}
on command: switchNetwork
sent: FE 0B 02 01 02 00 00 00 05 00 F1 
received:
<Buffer fe 0b 02 41 02 00 00 00 05 00 b1>
parse rx message: FE 0B 02 41 02 00 00 00 05 00 B1 
got Ack for command: switchNetwork
{ status: 0 }
  1. 控制设备

light.power {"id":"Light1","operation":"on"}

onUserCommand light.power: {"id":"Light1","operation":"on"}
on command: power
sent: FE 0B 05 01 02 02 E3 0B 06 01 1E 
received:
<Buffer fe 0b 05 41 02 02 e3 0b 06 00 5f>
parse rx message: FE 0B 05 41 02 02 E3 0B 06 00 5F 
got Ack for command: power

light.lum {"id":"Light1","lum":50,"duration":2}

onUserCommand light.lum: {"id":"Light1","lum":50,"duration":2}
on command: lum
sent: FE 0E 05 02 02 02 E3 0B 07 04 32 02 00 2C 
received:
<Buffer fe 0b 05 42 02 02 e3 0b 07 00 5d>
parse rx message: FE 0B 05 42 02 02 E3 0B 07 00 5D 
got Ack for command: lum

light.hueSaturation {"id":"Light1","hue":0,"saturation":254,"duration":2}

onUserCommand light.hueSaturation: {"id":"Light1","hue":0,"saturation":254,"duration":2}
on command: hueSaturation
sent: FE 0F 05 03 02 02 E3 0B 08 07 00 FE 02 00 EC 
received:
<Buffer fe 0b 05 43 02 02 e3 0b 08 00 53>
parse rx message: FE 0B 05 43 02 02 E3 0B 08 00 53 
got Ack for command: hueSaturation
  1. 使用Ctrl+C结束程序,查看OpenIoT/gw/data目录,会发现设备信息已经被写入到文件:

$ cat data/devices.json
[{"id":"Light1","uid":"0D83DD01004B1200"}]

再次打开程序,将自动加载设备信息并刷新其开关状态:

$ src/main.js

This is a smart lighting gateway based on AWS IoT, which communicates to Zigbee Home Automation network via USB dongle.
serial port opened!
on command: networkParam
sent: FE 0C 01 04 02 00 00 00 01 00 03 F7 
on command: getNwkAddrByMac
sent: FE 14 02 05 03 00 00 00 02 0D 83 DD 01 00 4B 12 00 00 00 E7 
received:
<Buffer fe 15 01 44 02 00 00 00 01 00 03 00 86 13 96 02 00 4b 12 00 f6 fe 0b 02 45 03 00 00 00 02 00 b3>
parse rx message: FE 15 01 44 02 00 00 00 01 00 03 00 86 13 96 02 00 4B 12 00 F6 
got Ack for command: networkParam
{ operation: 0,
  configuration: 3,
  status: 0,
  value: <Buffer 86 13 96 02 00 4b 12 00> }
epid updated: 86139602004B1200
parse rx message: FE 0B 02 45 03 00 00 00 02 00 B3 
got Ack for command: getNwkAddrByMac
received:
<Buffer fe 13 02 85 02 22 88 00 0c 00 0d 83 dd 01 00 4b 12 00 c5>
parse rx message: FE 13 02 85 02 22 88 00 0C 00 0D 83 DD 01 00 4B 12 00 C5 
got Response for command: getNwkAddrByMac
{ status: 0, macAddr: <Buffer 0d 83 dd 01 00 4b 12 00> }
got nwkAddr: 8822 of Light1
on command: getPower
sent: FE 0C 05 05 02 22 88 0B 03 00 00 52 
received:
<Buffer fe 0b 05 45 02 22 88 0b 03 00 15>
parse rx message: FE 0B 05 45 02 22 88 0B 03 00 15 
got Ack for command: getPower
received:
<Buffer fe 0c 05 85 02 22 88 0b 03 00 01 d3>
parse rx message: FE 0C 05 85 02 22 88 0B 03 00 01 D3 
got Response for command: getPower
{ status: 0, power: 1 }
light power updated: {"id":"Light1","power":"on"}
  1. 从网络中删除设备并使其恢复出厂设置:

network.detachDevice {"macAddr":"0D83DD01004B1200"}

onUserCommand network.detachDevice: {"macAddr":"0D83DD01004B1200"}
on command: detachDevice
sent: FE 12 02 16 02 00 00 00 09 0D 83 DD 01 00 4B 12 00 F8 
received:
<Buffer fe 0b 02 56 02 00 00 00 09 00 aa>
parse rx message: FE 0B 02 56 02 00 00 00 09 00 AA 
got Ack for command: detachDevice
received:
<Buffer fe 13 02 95 02 02 e3 00 fe 00 0d 83 dd 01 00 4b 12 00 6c>
parse rx message: FE 13 02 95 02 02 E3 00 FE 00 0D 83 DD 01 00 4B 12 00 6C 
got Response for command: detached
{ status: 0, macAddr: <Buffer 0d 83 dd 01 00 4b 12 00> }
device detached: {"id":"Light1","uid":"0D83DD01004B1200"}

评论 ( 0 )

你可以在登录后,发表评论

搜索帮助

14_float_left_people 14_float_left_close