起因

由于家中多个小米ZigBee设备,每次的操作都会有日志记录,并且小米可以读取到(可参考2019年初米家APP中个人年度报告),所以萌生了自建ZigBee网关,将所有数据本地化。

2019年11月偶然发现一个开源项目 z2m_partner 可自行搭建ZigBee网关

在项目实施过程中遇到很多爱好者的无私指导 特此感谢@老妖 @一只菜鸡【Debian】@盐巴 @Huex

目的

使用z2m_partner项目并自己焊接元件 ,通过zigbee2mqtt,最终将ZigBee设备接入到Node-RED中。

环境说明:使用z2m_partner ver 2.1,zigbee2mqtt ver 1.7.1,Node-RED ver 1.0.3

制作硬件

z2m_parther开源了完整pcb,所以我们只需要做成电路板,并焊接相应的元件。

PCB打板

个人使用了嘉立创进行打板,首先官网下载嘉立创助手。

将项目中project/gerber目录打包为zip/rar格式

将zip/rar文件拖入助手相应位置

板子厚度选为1.0,其他选项默认,凡是有不需要的选项一律勾选不需要。

板子数量按个人需求来,推荐选择5片/5元包邮。

元件采购

在制作PCB的同时可以采购元件,本文使用立创商城采购,bom可在z2m_parther项目中project/bom看到。

商品编号 名称 封装规格 数量
C26000 5.1KΩ ±5% 0603 2
C181158 S8050 SOT-23(SOT-23-3) 2
C149620 100nF(104) ±10% 50V 0603 10
C22790 12KΩ ±1% 0603 2
C369933 AMS1117-3.3 SOT-223 1
C385912 0Ω ±1% 0402 1
C221895 轻触开关4.2mm*3.2mm,400gf 4.2*3.2mm 1
C17313 0.5A 15V 自恢复保险丝 1812 1
C6521 CD4052BM96 SOIC-16_150mil 1
C113518 SN74LVC1G66DCKR SC-70-5 2
C128257 10uF(106) ±10% 16V CASE-B_3528 2
C84681 CH340C SOP-16_150mil 1
C165948 TYPE-C-31-M-12 母座 12P/16P 贴片 8.94*7.3mm 1
C81770 ESP-WROOM-02 QFN 1
C15401 10KΩ ±5% 0603 8
C108551 E18-MS1PA1-IPX CC2530芯片 SMD 1
C221896 PTS810SJK250SMTRLFS SMD 1

注1:由于ZigBee芯片不含天线,所以需另外采购2.4g天线,以上列表中不含天线。

注2:商品编号存在波动,以上数据采集为2019-12-12后续不会维护!

焊接元件

由于本人技术太菜,焊坏了一堆元件,总结了几点经验,老手略过吧。

助焊剂,和低温焊锡丝是必备的,烙铁头选细一点。

相信在不懈的努力下,一定可以成功。

刷写硬件

type-c链接到电脑

ESP Firmware 选择 firmware/bin/espFW/ser2net.bin

CClib Firmware 选择 firmware/bin/espFW/cclib.bin

Zigbee Firmware 选择 firmware/bin/zigbeeFW/normal_21db/CC2530ZNP-Prod.hex

ssid填写WiFi名,passwd填写WiFi密码,hostname填写z2mp,tcp port填写8880

最后点击Flash列All选项,约20分钟可以完成刷机

软件配置

由于个人使用root账号,相关命令操作会有些出入,Node-RED安装不在本文范围内。

搭建zigbee2mqtt环境

本文使用虚拟环境,其他安装形式不在本文范围之内,可参考官方网站 zigbee2mqtt官网

安装zigbee2mqtt

# 克隆仓库到本地
git clone https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt

# 进入目录
cd /opt/zigbee2mqtt

# 安装Python env
python3 -m venv .

# 激活环境
source /opt/zigbee2mqtt/bin/activate

# 升级  pip, wheel, setuptools
pip install --upgrade pip wheel setuptools

# 安装node env
pip install nodeenv

# 初始化node环境
nodeenv -p -n 10.15.1

# 安装依赖关系, 若非root用户 去掉sudo
sudo npm i

# 停用环境
deactivate

启动zigbee2mqtt

# 进入目录
cd /opt/zigbee2mqtt

# 激活环境
source /opt/zigbee2mqtt/bin/activate

# 启动,若非root用户去掉sudo
sudo npm start

# ctrl + c 退去程序

# 停用环境
deactivate

系统服务守护运行(可选)

要将zigbee2mqtt作为后台程序运行 并在开机启动时自动启动,需使用systemctl运行zigbee2mqtt

# 创建zigbee2mqtt的systemctl文件
sudo nano /etc/systemd/system/zigbee2mqtt.service

添加以下内容到zigbee2mqtt.service文件,需注意 若非root用户需修改User,及去掉ExecStart中的sudo

[Unit]
Description=zigbee2mqtt
After=network.target

[Service]
ExecStart=/bin/bash -c 'source /opt/zigbee2mqtt/bin/activate; sudo /opt/zigbee2mqtt/bin/npm start'
WorkingDirectory=/opt/zigbee2mqtt
StandardOutput=inherit
StandardError=inherit
Restart=always
User=root

[Install]
WantedBy=multi-user.target

使用方法

# 停止zigbee2mqtt服务
systemctl stop zigbee2mqtt

# 启动zigbee2mqtt服务
systemctl start zigbee2mqtt

# 查看zigbee2mqtt服务状态
systemctl status zigbee2mqtt

zigbee2mqtt配置文件

强烈建议参考官方文档,以下为2019年12月12日转载,仅供参考以官方为准。

# Required: Home Assistant integration (MQTT discovery) (default: false)
homeassistant: false

# Required: allow new devices to join.
# WARNING: Disable this after all devices have been paired! (default: false)
permit_join: true

# Required: MQTT settings
mqtt:
  # Required: MQTT base topic for zigbee2mqtt MQTT messages
  base_topic: zigbee2mqtt
  # Required: MQTT server URL (use mqtts:// for SSL/TLS connection)
  server: 'mqtt://localhost:1883'
  # Optional: absolute path to SSL/TLS certificate of CA used to sign server and client certificates (default: nothing)
  ca: '/etc/ssl/mqtt-ca.crt'
  # Optional: absolute paths to SSL/TLS key and certificate for client-authentication (default: nothing)
  key: '/etc/ssl/mqtt-client.key'
  cert: '/etc/ssl/mqtt-client.crt'
  # Optional: MQTT server authentication user (default: nothing)
  user: my_user
  # Optional: MQTT server authentication password (default: nothing)
  password: my_password
  # Optional: MQTT client ID (default: nothing)
  client_id: 'MY_CLIENT_ID'
  # Optional: disable self-signed SSL certificates (default: false)
  reject_unauthorized: true
  # Optional: Include device information to mqtt messages (default: false)
  include_device_information: true

# Required: serial settings
serial:
  # Required: location of the adapter (e.g. CC2531).
  # To autodetect the port, set 'port: null'.
  port: /dev/ttyACM0
  # Optional: disable LED of the adapter if supported (default: false)
  disable_led: false

# Optional: ban devices from the network (by ieeeAddr) (default: empty)
ban:
  - '0x000b57fffec6a5b2'

# Optional: whitelist devices from the network (by ieeeAddr)
# Note that when devices are whitelisted, all device which are not whitelisted will be removed from the network.
# (default: empty)
whitelist:
  - '0x000b57fffec6a5b3'

# Optional: advanced settings
advanced:
  # Optional: ZigBee pan ID (default: shown below)
  pan_id: 0x1a62
  # Optional: Zigbee extended pan ID (default: shown below)
  ext_pan_id: [0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD]
  # Optional: ZigBee channel, changing requires re-pairing of all devices. (Note: use a ZLL channel: 11, 15, 20, or 25 to avoid Problems)
  # (default: 11)
  channel: 11
  # Optional: state caching, MQTT message payload will contain all attributes, not only changed ones.
  # Has to be true when integrating via Home Assistant (default: true)
  cache_state: true
  # Optional: Logging level, options: debug, info, warn, error (default: info)
  log_level: info
  # Optional: Location of log directory (default: shown below)
  log_directory: data/log/%TIMESTAMP%
  # Optional: Baudrate for serial port (default: shown below)
  baudrate: 115200
  # Optional: RTS / CTS Hardware Flow Control for serial port (default: true)
  rtscts: true
  # Optional: soft reset ZNP after timeout (in seconds); 0 is disabled (default: 0)
  soft_reset_timeout: 0
  # Optional: network encryption key, will improve security (Note: changing requires repairing of all devices) (default: shown below)
  network_key: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13]
  # Optional: Add a last_seen attribute to MQTT messages, contains date/time of last Zigbee message
  # possible values are: disable (default), ISO_8601, ISO_8601_local, epoch (default: disable)
  last_seen: 'disable'
  # Optional: Add an elapsed attribute to MQTT messages, contains milliseconds since the previous msg (default: false)
  elapsed: false
  # Optional: Availability timeout in seconds, disabled by default (0).
  # When enabled, devices will be checked if they are still online.
  # Only AC powered routers are checked for availability. (default: 0)
  availability_timeout: 0
  # Optional: Blacklist devices from being checked for availability (default: empty)
  availability_blacklist:
    - DEVICE_FRIENDLY_NAME
  # Optional: Enables report feature (see information -> report for more details) (default: false)
  report: true
  # Optional: Home Assistant discovery topic (default: shown below)
  homeassistant_discovery_topic: 'homeassistant'
  # Optional: Home Assistant status topic (default: shown below)
  homeassistant_status_topic: 'hass/status'

# Optional: networkmap options
map_options:
  graphviz:
    # Optional: Colors to be used in the graphviz network map (default: shown below)
    colors:
      fill:
        enddevice: '#fff8ce'
        coordinator: '#e04e5d'
        router: '#4ea3e0'
      font:
        coordinator: '#ffffff'
        router: '#ffffff'
        enddevice: '#000000'
      line:
        active: '#009900'
        inactive: '#994444'

# Optional: Queue settings, useful when your zigbee stick get's
# unstable when executing many commands
queue:
  # Optional: Delay in ms between each command (default: shown below)
  delay: 250
  # Optional: Max no. of simultaneously running commands (default: shown below)
  simultaneously: 5

# Optional: Device specific options
device_options:
  # See 'Device specific configuration' below

搭建socat环境

由于zigbee2mqtt v1.7.1 不支持tcp形式连接,需使用socat将tcp转发为串口。

据说后续版本将直接tcp不在需要此步操作,请关注版本及更新日志。

# 启动
# 按需修改link及tcp连接信息
$ socat PTY,raw,echo=0,link=/tmp/ttyVUSB0 tcp:192.168.1.2:5000

系统服务守护运行(可选)

[Unit]
Description=socat-vusb
After=network-online.target

[Service]
User=%i
ExecStart=/usr/bin/socat PTY,raw,echo=0,link=/tmp/ttyVUSB0 tcp:192.168.1.2:5000
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

搭建MQTT服务器

# 添加源到软件仓库
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa

# 更新软件仓库列表
sudo apt-get update

# 安装mosquitto
sudo apt-get install mosquitto

运行

# 查看运行状态
sudo service mosquitto status

# 启动服务
sudo service mosquitto start

# 停止服务
sudo service mosquitto stop

添加Node-RED节点

新建mqtt节点 topics(主题) 填写 zigbee2mqtt/bridge/log 并链接debug节点,当新设备连接/解除时,会有日志打出

完整topics方法可在官网获取 MQTT topics and message structure

添加设备至网关

先从米家中删除设备,然后重置设备,即可连接到新网关

注:如是电池设备,请注意电量,实测电量15%时,无法配对新网关

获取设备状态

新建mqtt节点 topics(主题) 填写 zigbee2mqtt/[FRIENDLY_NAME]

FRIENDLY_NAME 在加入网关后,有一串0x开头的字符,就是FRIENDLY_NAME

注1:需将mqtt节点输出改为a parsed JSON object,默认会打印出字符串

注2:若是传感器,最好持久化保存数据,因为无法主动获取数据

写在最后

由于Node-RED接入部分比较简单,所以只是概括描述。

对于设备的设定/获取操作 可查看 Supported devices 支持设备中对应的设备

对于系统相关设置 可查看 MQTT topics and message structure

zigbee2mqtt 配置文件configuration.yaml 中 permit_join: true是允许添加设备,注意及时修改状态,避免乱入设备。

参考

[1] z2m_partner

[2] zigbee2mqtt

[3] 自己动手做zigbee网关,和小米网关说拜拜

[4] zigbeeV2.0网关刷机教程

[5] Request: Support TCP Connections to CC2530