Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf7e0d1aa9 | ||
|
|
17874cfdc1 | ||
|
|
e12a371093 | ||
|
|
7e74b8c549 | ||
|
|
cdf64823ef | ||
|
|
5d195fc299 | ||
|
|
fd932926e7 | ||
|
|
38159a536c | ||
|
|
7e2ca5a97e | ||
|
|
b95dcd0f9b | ||
|
|
73f0f8fe43 | ||
|
|
16f3e884fc | ||
|
|
c5e6b9dd13 | ||
|
|
cae5d1a004 | ||
|
|
85375ffbae | ||
|
|
43fc66c436 | ||
|
|
5718cd0157 | ||
|
|
dd6e34a152 | ||
|
|
1ddf60bef0 | ||
|
|
6ff3954b71 | ||
|
|
6dd2926a1d | ||
|
|
5970e498f3 | ||
|
|
dcd81cbbf2 | ||
|
|
9e5fb04314 | ||
|
|
d324a91a5f | ||
|
|
fcfeac81e4 | ||
|
|
c44816efee | ||
|
|
86f19affa1 | ||
|
|
e21bfc1567 | ||
|
|
329c290505 | ||
|
|
b624a8ccad | ||
|
|
a43cd5a864 | ||
|
|
5f6b37bf83 | ||
|
|
653dfc7b6f | ||
|
|
aa87443c95 | ||
|
|
f5a5668359 | ||
|
|
5f2e93f64d | ||
|
|
7cd30a3a05 | ||
|
|
34a3e3c00b | ||
|
|
28e32884d9 | ||
|
|
dda2e064b2 | ||
|
|
9605e724e1 | ||
|
|
6912f8108d | ||
|
|
3c0e784afb | ||
|
|
be50d650a4 | ||
|
|
a5057ac101 | ||
|
|
72a74d7dc1 | ||
|
|
dccdc5aafa | ||
|
|
6dd60c09bf | ||
|
|
4ec905efca | ||
|
|
f62eabcb6d | ||
|
|
fd2cf41f0f | ||
|
|
755d101738 | ||
|
|
6fdd58be8a | ||
|
|
26083a62d9 | ||
|
|
30b35e7272 | ||
|
|
f6c01a02c9 | ||
|
|
35b9e6204d | ||
|
|
84f9d09b3f | ||
|
|
f260bf974b | ||
|
|
a2ea9c548f | ||
|
|
932a66a5c4 | ||
|
|
3d0541a32d | ||
|
|
3bb1f0f10b | ||
|
|
85b042ac25 | ||
|
|
f1fe1edb49 | ||
|
|
70d177485d | ||
|
|
fd44537984 | ||
|
|
dc20816043 | ||
|
|
c6d09df01a | ||
|
|
74cdde23b9 | ||
|
|
57aefe477d | ||
|
|
d5a3ce3871 | ||
|
|
92de1ca942 | ||
|
|
6f477c2923 | ||
|
|
5453c082c4 | ||
|
|
07fbc1b9a3 | ||
|
|
afeed4f372 | ||
|
|
2a197a4ba8 | ||
|
|
5e4e6d81de | ||
|
|
faede151f3 | ||
|
|
ea4aaf2cfa | ||
|
|
ac94b95bba | ||
|
|
708c497614 | ||
|
|
bd8aaea767 | ||
|
|
ac4ca88b8a | ||
|
|
8651fd7162 | ||
|
|
03ff4e6e5a | ||
|
|
3bc2ec8c79 | ||
|
|
c4804e574e | ||
|
|
5d3461c4c6 | ||
|
|
9380bbcadf | ||
|
|
3a0fe60b22 | ||
|
|
a1eea76dd4 | ||
|
|
69e805c882 | ||
|
|
0fe3a9b45c | ||
|
|
ecf64c8058 | ||
|
|
d3f705162d | ||
|
|
bd8282a41a | ||
|
|
82e87d563e | ||
|
|
d6c2b536ee | ||
|
|
919178840f | ||
|
|
84593a55ee | ||
|
|
1b8154bac1 | ||
|
|
8a133de1d1 | ||
|
|
75dddf462e |
@@ -1,8 +1,13 @@
|
||||
Unsupported device
|
||||
First check: https://koenkk.github.io/zigbee2mqtt/how_tos/how_to_support_new_devices.html
|
||||
Did you read the FAQ?
|
||||
https://koenkk.github.io/zigbee2mqtt/information/FAQ.md
|
||||
|
||||
Unsupported device?
|
||||
https://koenkk.github.io/zigbee2mqtt/how_tos/how_to_support_new_devices.html
|
||||
|
||||
Bug report
|
||||
A question?
|
||||
Read the documentation: https://koenkk.github.io/zigbee2mqtt/
|
||||
|
||||
Bug report:
|
||||
- First make sure your on the latest version of zigbee2mqtt.
|
||||
- Make sure you are running the latest CC253X firmware from https://github.com/koenkk/z-stack-firmware.
|
||||
- Provide a clear description of the problem.
|
||||
|
||||
@@ -8,6 +8,12 @@ services:
|
||||
node_js:
|
||||
- "10"
|
||||
|
||||
before_install:
|
||||
- "echo '{\"experimental\": true}' | sudo tee /etc/docker/daemon.json"
|
||||
- sudo apt update -y
|
||||
- sudo apt install --only-upgrade docker-ce -y
|
||||
- sudo service docker restart
|
||||
|
||||
install:
|
||||
- npm install
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ tag_push() {
|
||||
}
|
||||
|
||||
build_and_push() {
|
||||
docker build --build-arg COMMIT=$(git rev-parse --short HEAD) -t $DOCKER_USERNAME/zigbee2mqtt:$1 -f $2 .
|
||||
docker build --platform=$3 --build-arg COMMIT=$(git rev-parse --short HEAD) -t $DOCKER_USERNAME/zigbee2mqtt:$1 -f $2 .
|
||||
docker push $DOCKER_USERNAME/zigbee2mqtt:$1
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ then
|
||||
login
|
||||
|
||||
# Push versioned images
|
||||
build_and_push "$TRAVIS_TAG" docker/Dockerfile.amd64
|
||||
build_and_push "$TRAVIS_TAG-arm32v6" docker/Dockerfile.arm32v6
|
||||
build_and_push "$TRAVIS_TAG-arm64v8" docker/Dockerfile.arm64v8
|
||||
build_and_push "$TRAVIS_TAG" docker/Dockerfile.amd64 amd64
|
||||
build_and_push "$TRAVIS_TAG-arm32v6" docker/Dockerfile.arm32v6 arm
|
||||
build_and_push "$TRAVIS_TAG-arm64v8" docker/Dockerfile.arm64v8 arm64
|
||||
|
||||
# Push latest images.
|
||||
tag_push "$TRAVIS_TAG-arm32v6" "arm32v6"
|
||||
@@ -35,9 +35,9 @@ elif [ "$TRAVIS_BRANCH" = "dev" -a "$TRAVIS_PULL_REQUEST" = "false" ]
|
||||
then
|
||||
echo "Updating docker images for dev branch!"
|
||||
login
|
||||
build_and_push latest-dev docker/Dockerfile.amd64
|
||||
build_and_push arm32v6-dev docker/Dockerfile.arm32v6
|
||||
build_and_push arm64v8-dev docker/Dockerfile.arm64v8
|
||||
build_and_push latest-dev docker/Dockerfile.amd64 amd64
|
||||
build_and_push arm32v6-dev docker/Dockerfile.arm32v6 arm
|
||||
build_and_push arm64v8-dev docker/Dockerfile.arm64v8 arm64
|
||||
else
|
||||
echo "Not updating docker images, triggered by pull request or not on master/dev branch"
|
||||
fi
|
||||
|
||||
@@ -4,7 +4,20 @@
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
<img src="https://img.shields.io/travis/Koenkk/zigbee2mqtt.svg">
|
||||
<div style="display: flex;">
|
||||
<a href="https://travis-ci.org/Koenkk/zigbee2mqtt/">
|
||||
<img src="https://img.shields.io/travis/Koenkk/zigbee2mqtt.svg">
|
||||
</a>
|
||||
<a href="https://github.com/Koenkk/zigbee2mqtt/releases">
|
||||
<img src="https://img.shields.io/github/release/koenkk/zigbee2mqtt.svg">
|
||||
</a>
|
||||
<a href="https://github.com/Koenkk/zigbee2mqtt/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/koenkk/zigbee2mqtt.svg">
|
||||
</a>
|
||||
<a href="https://www.paypal.me/koenkk">
|
||||
<img src="https://img.shields.io/badge/donate-PayPal-blue.svg">
|
||||
</a>
|
||||
</div>
|
||||
<h1>Zigbee2mqtt 🌉 🐝</h1>
|
||||
<p>
|
||||
Allows you to use your Zigbee devices <b>without</b> the vendors bridge or gateway.
|
||||
|
||||
@@ -18,6 +18,8 @@ use their documentation*
|
||||
## MQTT discovery
|
||||
**At least Home Assistant >= 0.84 is required!**
|
||||
|
||||
**NOTE:** Groups are not auto-discovered, see configuration below.
|
||||
|
||||
The easiest way to integrate Zigbee2mqtt with Home Assistant is by
|
||||
using [MQTT discovery](https://www.home-assistant.io/docs/mqtt/discovery/).
|
||||
This allows Zigbee2mqtt to automatically add devices to Home Assistant.
|
||||
@@ -37,6 +39,9 @@ mqtt:
|
||||
payload: 'offline'
|
||||
\`\`\`
|
||||
|
||||
Mind you that if you want to use the embedded broker of Home Assistant you
|
||||
have to [follow this guide](https://www.home-assistant.io/docs/mqtt/broker#embedded-broker).
|
||||
|
||||
Zigbee2mqtt is expecting Home Assistant to send it's birth/will
|
||||
messages to \`hass/status\`. Be sure to add this to your \`configuration.yaml\` if you want
|
||||
Zigbee2mqtt to resend the cached values when Home Assistant restarts
|
||||
@@ -80,6 +85,26 @@ automation:
|
||||
\`\`\`
|
||||
{% endraw %}
|
||||
|
||||
## Groups
|
||||
Groups are not auto-discovered. Use the following configuration:
|
||||
|
||||
{% raw %}
|
||||
|
||||
\`\`\`yaml
|
||||
- platform: mqtt
|
||||
schema: json
|
||||
name: MY_GROUP
|
||||
command_topic: "zigbee2mqtt/[GROUP_FRIENDLY_NAME]/set"
|
||||
state_topic: "zigbee2mqtt/[GROUP_FRIENDLY_NAME]/set"
|
||||
|
||||
// Modify according to features supported by all devices in group
|
||||
color_temp: true
|
||||
brightness: true
|
||||
rgb: true
|
||||
\`\`\`
|
||||
|
||||
{% endraw %}
|
||||
|
||||
## Controlling Zigbee2mqtt via Home Assistant
|
||||
The following Home Assistant configuration allows you to control Zigbee2mqtt from Home Assistant.
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ The values shown are the default ones.
|
||||
# Required: Home Assistant integration (MQTT discovery)
|
||||
homeassistant: false
|
||||
|
||||
# Required: allow new devices to join
|
||||
# Required: allow new devices to join.
|
||||
# WARNING: Disable this after all devices have been paired!
|
||||
permit_join: true
|
||||
|
||||
# Required: MQTT settings
|
||||
@@ -53,4 +54,14 @@ advanced:
|
||||
rtscts: true
|
||||
# Optional: soft reset ZNP after timeout (in seconds); 0 is disabled
|
||||
soft_reset_timeout: 0
|
||||
```
|
||||
# Optional: network encryption key, changing requires repairing of all devices.
|
||||
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, epoch
|
||||
last_seen: 'disable'
|
||||
# Optional: Add an elapsed attribute to MQTT messages, contains milliseconds since the previous msg
|
||||
elapsed: false
|
||||
# Availability timeout in seconds, disabled by default (0).
|
||||
# When enabled, devices will be checked if they are still online.
|
||||
availability_timeout: 0,
|
||||
```
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
# Device specific configuration
|
||||
The `configuration.yaml` allows to set device specific configuration. The following options are available:
|
||||
The `configuration.yaml` allows to set device specific configuration. The following options are available.
|
||||
|
||||
### All devices
|
||||
* `friendly_name`: Used in the MQTT topic of a device. By default this is the device ID (e.g. `0x00128d0001d9e1d2`).
|
||||
* `retain`: Retain MQTT messages of this device.
|
||||
* `occupancy_timeout`: Timeout (in seconds) after the `occupancy: false` message is sent, only available for occupany sensors. If not set, the timeout is `90` seconds. When set to `0` no `occupancy: false` is send.
|
||||
* `qos`: QoS level for MQTT messages of this device. [What is QoS?](https://www.npmjs.com/package/mqtt#about-qos)
|
||||
|
||||
Example:
|
||||
### Device type specific
|
||||
* `occupancy_timeout`: Timeout (in seconds) after the `occupancy: false` message is sent, only available for occupany sensors. If not set, the timeout is `90` seconds. When set to `0` no `occupancy: false` is send.
|
||||
* `temperature_precision`: Controls the precision of `temperature` values, e.g. `0`, `1` or `2`; default `2`.
|
||||
* `humidity_precision`: Controls the precision of `humidity` values, e.g. `0`, `1` or `2`; default `2`.
|
||||
* `pressure_precision`: Controls the precision of `pressure` values, e.g. `0` or `1`; default `1`.
|
||||
|
||||
### Example
|
||||
``` yaml
|
||||
devices:
|
||||
'0x00158d0001d82999':
|
||||
@@ -15,11 +22,11 @@ devices:
|
||||
qos: 1
|
||||
```
|
||||
|
||||
Once finished, restart Zigbee2mqtt.
|
||||
### Changing device type specific defaults
|
||||
The default values used for the device specific configuration can be overriden via e.g.:
|
||||
|
||||
The bridge will log the `friendly_name` on startup, e.g.:
|
||||
```yaml
|
||||
device_options:
|
||||
occupancy_timeout: 30
|
||||
temperature_precision: 1
|
||||
```
|
||||
Currently 2 devices are joined:
|
||||
switch_bedroom (0x00158d0001d8e1d2): WXKG01LM - Xiaomi MiJia wireless switch (EndDevice)
|
||||
sensor_bedroom (0x00158d0001b79111): WSDCGQ01LM - Xiaomi MiJia temperature & humidity sensor (EndDevice)
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
# Flashing the firmware on the CC2531 USB stick
|
||||
The CC2531 USB stick needs to be flashed with a custom firmware.
|
||||
|
||||
*NOTE: The following instructions assume you have a CC Debugger. In case you don't, see [Alternative firmware flashing methods](../useful_information/alternative-firmware-flashing-methods.md).*
|
||||
*NOTE: The following instructions assume you have a CC Debugger. In case you don't, see [Alternative firmware flashing methods](../information/alternative_flashing_methods.md).*
|
||||
|
||||
## Windows
|
||||
1. Install [SmartRF Flash programmer](http://www.ti.com/tool/FLASH-PROGRAMMER) (**NOT V2**). This software is free but requires a Texas Instruments account in order to download.
|
||||
@@ -19,10 +19,10 @@ The CC2531 USB stick needs to be flashed with a custom firmware.
|
||||
Credits to [@Frans-Willem](https://github.com/frans-Willem) for majority of instructions.
|
||||
|
||||
1. Install prerequisites for [CC-Tool](https://github.com/dashesy/cc-tool) using a package manager (e.g. [Homebrew](https://brew.sh/) for macOS)
|
||||
> Ubuntu: dh-autoreconf, libusb-1.0, libboost-all-dev
|
||||
> Fedora: dh-autoreconf, boost-devel, libusb1-devel
|
||||
> Archlinux: dh-autoreconf, libusb, boost
|
||||
> macOS: autoconf, automake, libusb, boost, pkgconfig, libtool
|
||||
* Ubuntu: dh-autoreconf, libusb-1.0, libboost-all-dev
|
||||
* Fedora: dh-autoreconf, boost-devel, libusb1-devel
|
||||
* Archlinux: dh-autoreconf, libusb, boost
|
||||
* macOS: brew install autoconf automake libusb boost pkgconfig libtool
|
||||
|
||||
2. Build cc-tool
|
||||
```bash
|
||||
@@ -43,4 +43,4 @@ sudo ./cc-tool -e -w CC2531ZNP-Prod.hex
|
||||
```
|
||||
|
||||
# What's next?
|
||||
[Running Zigbee2mqtt](running_zigbee2mqtt.md)
|
||||
[Running Zigbee2mqtt](running_zigbee2mqtt.md)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
**IMPORTANT:** Before you start, make sure that `permit_join: true` is set in your `configuration.yaml`. Otherwise new devices cannot join the network!
|
||||
It's equally important that `permit_join: false` is set in your `configuration.yaml` after initial setup is done to keep your Zigbee network safe and to avoid accidental joining of other Zigbee devices.
|
||||
|
||||
Start by checking if your Zigbee device is supported, see [Supported devices](../information/supported_devices.md).
|
||||
|
||||
@@ -29,6 +30,29 @@ I start with bulb on, then off, and then 6 “on’s”, where I kill the light
|
||||
|
||||
* To factory reset the TRADFRI drivers (ICPSHC24-10EU-IL-1 and ICPSHC24-30EU-IL-1) use a small pin or paperclip to push the reset button once.
|
||||
|
||||
### IKEA TRADFRI remote control (E1524)
|
||||
This device requires extra setup as it is meant to only control groups. Therefore it does not send any information directly to the coordinator. As the group ID is randomized upon factor reset we need to find out the group ID where it sends its commands to. This can be done by using Zigbee sniffing.
|
||||
|
||||
1. Pair the remote to Zigbee2mqtt by holding it close to the coordinator and pressing the button next to the battery 4 times. The red light on the remote will now flash a few times.
|
||||
2. Setup your Zigbee traffic sniffer by following [How to sniff Zigbee traffic](../how_tos/how_to_sniff_zigbee_traffic.md).
|
||||
3. Press the middle (power) button on the remote, this will produce the following message in Wireshark:
|
||||

|
||||
4. Retrieve the group from the message, which is `0xeb12` in the above example.
|
||||
5. Add the group to the device in `configuration.yaml`, example:
|
||||
```yaml
|
||||
devices:
|
||||
'0x000b57fffecb472d':
|
||||
friendly_name: '0x000b57fffecb472d'
|
||||
retain: false
|
||||
coordinator_group: 0xeb12
|
||||
```
|
||||
6. Restart Zigbee2mqtt, when everything went OK you will see:
|
||||
```
|
||||
zigbee2mqtt:info 1/8/2019, 8:42:40 PM Sucesfully applied coordinator group for IKEA TRADFRI remote control (0x000b57fffecb472d)
|
||||
```
|
||||
### Why is this needed?
|
||||
The TRADFRI remote sends the group ID using touchlink commissioning (while holding the reset button close to a bulb) but this is currently not supported by the firmware (Z-Stack 1.2 HA). Perhaps it will work in Z-Stack 3.0.
|
||||
|
||||
## Philips Hue
|
||||
Factory reset the light bulb see [HOWTO: Factory reset a Hue bulb](https://www.youtube.com/watch?v=qvlEAELiJKs). After resetting the bulb will automatically connect.
|
||||
|
||||
@@ -65,4 +89,11 @@ Factory reset by:
|
||||
(at the 3rd, the 10th, and the 15th second).
|
||||
- After releasing the Binding Key, press the Switch Key within 2 seconds. The network indicator
|
||||
will rapidly flash green.
|
||||
- After fast flashes, Z809A will reboot, and the restore is completed. The socket will automatically connect now.
|
||||
- After fast flashes, Z809A will reboot, and the restore is completed. The socket will automatically connect now.
|
||||
|
||||
## Gledopto
|
||||
Some of the Gledopto devices are not providing a `modelID`, in that case the modelID `undefined` is shown. Sometimes it helps to repair the device while keeping it close to the coordinator (less than one meter).
|
||||
|
||||
If this fails, the `modelID` has to be set manually in `data/database.db`. First find out the `modelID` of your devices from the [Supported devices page](../information/supported_devices.md). Then open `data/database.db` and add the `modelId` as highlighted in **bold** below.
|
||||
|
||||
*{"id":50,"type":"Router","ieeeAddr":"0x00124b0019c606cd","nwkAddr":10828,"manufId":0,"manufName":"GLEDOPTO","powerSource":"Mains (single phase)",**"modelId":"GL-S-007Z"**,"epList":[11,13],"status":"offline","joinTime":null,"endpoints":{"11":{"profId":49246,"epId":11,"devId":528,"inClusterList":[0,3,4,5,6,8,768],"outClusterList":[],"clusters":{"genBasic":{"dir":{"value":1},"attrs":{}},"genIdentify":{"dir":{"value":1},"attrs":{}},"genGroups":{"dir":{"value":1},"attrs":{}},"genScenes":{"dir":{"value":1},"attrs":{}},"genOnOff":{"dir":{"value":1},"attrs":{}},"genLevelCtrl":{"dir":{"value":1},"attrs":{}},"lightingColorCtrl":{"dir":{"value":1},"attrs":{}}}},"13":{"profId":49246,"epId":13,"devId":57694,"inClusterList":[4096],"outClusterList":[4096],"clusters":{"lightLink":{"dir":{"value":3},"attrs":{}}}}},"_id":"geCEMkRqlaMe6muE"}*
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# How to connect a CC2530 coordinator using a USB to serial adapter
|
||||
|
||||
## Confirmed working
|
||||
This how-to has been confirmed working with the following CC2530 based devices:
|
||||
|
||||
| Device| Image |
|
||||
| --- | --- |
|
||||
| **CC2530** |  |
|
||||
|
||||
and the following USB to serial adapters:
|
||||
|
||||
| Device| Image |
|
||||
| --- | --- |
|
||||
| **CP2102** |  |
|
||||
|
||||
## Flashing the firmware
|
||||
The required coordinator fimrware can be found here: [CC sniffer devices](../information/cc_sniffer_devices.md).
|
||||
|
||||
## Connecting
|
||||
Connect to CC2530 to the USB to serial adapter using the following mapping:
|
||||
|
||||
| USB-Serial Adaper | CC2530 |
|
||||
| :------------: |:---------------:|
|
||||
| 3V3 | VCC |
|
||||
| GND | GND |
|
||||
| TXD | P02 |
|
||||
| RXD | P03 |
|
||||
|
||||
Now plug in the USB-to-serial adapter in your USB port.
|
||||
|
||||
## Configuration
|
||||
Add the following to your Zigbee2mqtt `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
advanced:
|
||||
rtscts: false
|
||||
```
|
||||
|
||||
and start Zigbee2mqtt, enjoy!
|
||||
@@ -0,0 +1,68 @@
|
||||
# How to create a CC2530 router
|
||||
The CC2530 is highly suitable for serving as a router. It has an external antenna which will greatly improve the range of your Zigbee network. This tutorial will explain how to create a CC2530 router packed into a nice enclosure which can be powered via any regular outlet.
|
||||
|
||||
**DISCLAIMER:** The CC2530 router will use Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician!
|
||||
|
||||

|
||||
|
||||
## 1. What do I need?
|
||||
| Name | Price | Picture |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| CC2530 <br/> **OR** <br/> CC2530 + CC2591 <br/> *The CC2530 + CC2591 is more powerful but more expensive* | +-7.50$ on AliExpress <br/><br/> +-15$ on AliExpress | |
|
||||
| HLK-PM03 | +-2.20$ on AliExpress |  |
|
||||
| Enclosure (the one used has the following dimensions: 100x68x40mm) | +-2$ |  |
|
||||
| Power cable | +-2$ |  |
|
||||
| CC debugger | - |  |
|
||||
| 8 female to female jumper wires | - |  |
|
||||
|
||||
# 2. Flashing the CC2530
|
||||
The CC2530 has to be flashed with a router firmware which has to be done with a CC debugger using 6 female to female jumper wires. Pins have to connected as follows:
|
||||
|
||||
### CC debugger pin layout
|
||||
|
||||
<div style="float: right;">
|
||||
<img src="../images/ccdebugger_pins.png"/>
|
||||
</div>
|
||||
|
||||
| CC debugger | CC2530 |
|
||||
| ----------- | ------ |
|
||||
| 1 | GND |
|
||||
| 2 | VCC |
|
||||
| 3 | P2.2 |
|
||||
| 4 | P2.1 |
|
||||
| 7 | RST |
|
||||
| 9 | VCC |
|
||||
|
||||
### Pin layout of various CC2530 modules
|
||||
| Name | Pin layout | Picture |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| CC2530 |  | 
|
||||
| Webee CC2530 + CC2591 |  | 
|
||||
|
||||
### Flashing
|
||||
Now the CC2530 can be flashed using the same instructions as [Flashing the CC2531](../getting_started/flashing_the_cc2531.md). The router firmwares can be found [here](https://github.com/Koenkk/Z-Stack-firmware/tree/master/router).
|
||||
|
||||

|
||||
|
||||
# 3. Putting it in an enclosure
|
||||
The following steps have to be followed:
|
||||
- Drill 2 holes in the enclosure; one for the antenna, one for the power cable
|
||||
- Lay a knot in the power cable; this serves as strain relief
|
||||
- Solder the power cable on to the AC pins of the HLK-PM03
|
||||
- Use 2 female to female jumper wires to connect the VC+ pin of the HLK-PM03 to the VCC pin of the CC2530 and the VC- pin of the HLK-PM03 to the GND pin of the CC2530
|
||||
- Use double sided tape to fix the CC2530 and HLK-PM03 into the enclosure
|
||||
|
||||
### Result
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
# 4. Done!
|
||||
Now plug the CC2530 into a power outlet where it will automatically join your Zigbee network. (don't forget to set `permit_join: true` to enable joining of new devices). Enjoy your extended Zigbee network range! :smile:
|
||||
@@ -0,0 +1,16 @@
|
||||
# How to secure your Zigbee network
|
||||
By default your Zigbee network isn't as secured as possible. The following settings are recommeded to apply to your configuration.
|
||||
|
||||
## Disabled joining
|
||||
To disable joining it's important that `permit_join: false` is set in your `configuration.yaml`.
|
||||
|
||||
## Change Zigbee network encryption key
|
||||
**Changing the key requires repairing of all devices!**
|
||||
|
||||
Zigbee2mqtt uses a default encryption key. Therefore it is recommended to use a different one. To use a different encryption key add the following to you `configuration.yaml`:
|
||||
|
||||
**Do not use the following key.**
|
||||
```
|
||||
advanced:
|
||||
network_key: [7, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 11, 12, 13],
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# How to sniff Zigbee traffic
|
||||
Sniffing Zigbee traffic can be handy sometimes. E.g. when you want to analyze the commands used by a device.
|
||||
|
||||
## Prerequisites
|
||||
* Ubuntu machine (tested with 18.10)
|
||||
* CC2531 stick
|
||||
|
||||
## 1. Flashing the CC2531 stick
|
||||
The CC2531 needs to be flashed with a sniffer firmware. This firmware is included with [PACKET-SNIFFER](http://www.ti.com/tool/PACKET-SNIFFER) (not **PACKET-SNIFFER-2!**). Download and install PACKET-SNIFFER. The firmware can then be found here: `C:\Program Files (x86)\Texas Instruments\SmartRF Tools\Packet Sniffer\bin\general\firmware\sniffer_fw_cc2531.hex`. Flash the firmware using the instructions from [Flashing the CC2531](../getting_started/flashing_the_cc2531.md).
|
||||
|
||||
## 2. Installing required tools
|
||||
```bash
|
||||
cd /opt
|
||||
sudo apt-get install -y libusb-1.0-0-dev wireshark
|
||||
curl -L https://github.com/homewsn/whsniff/archive/v1.1.tar.gz | tar zx
|
||||
cd whsniff-1.1
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## 3. Sniffing traffic
|
||||
Start wireshark with `sudo whsniff -c ZIGBEE_CHANNEL_NUMBER | wireshark -k -i -`
|
||||
|
||||
Wireshark will start and log the Zigbee messages. As these messages are encrypted we need to add 2 encryption keys. The first one is the Trust Center link key, which is the same for (almost) every Zigbee network. The second on is the network encryption key.
|
||||
|
||||
Add the Trust Center link key by going to to Edit -> Preferences -> Protocols -> ZigBee. Set Security Level to *AES-128 Encryption, 32-bit Integrity Protection* and click on *Edit*. Click on *+* and add `5A:69:67:42:65:65:41:6C:6C:69:61:6E:63:65:30:39` with Byte Order Normal.
|
||||
|
||||
*NOTE: The Hue bridge uses a [different Trust Center link key](https://peeveeone.com/?p=166)*
|
||||
|
||||

|
||||
|
||||
Next we need to figure out the network encryption key. The network encryption key is exposed when a device joins the network. Pair a new device to the network (or repair an existing one) and grab the message where the Info is *Device Announcement....*. Open the message and expand *ZigBee Network Layer Data* -> *ZigBee Security Header*.
|
||||
|
||||

|
||||
|
||||
Copy the key value, as shown above and go to Edit -> Preferences -> Protocols -> ZigBee -> Edit and add the key with Byte Order Normal.
|
||||
|
||||
Now Wireshark is able to decrypt the messages. When e.g. turning on a light you will see a message similar to:
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 19 KiB |
@@ -25,10 +25,16 @@ Welcome to the Zigbee2mqtt documentation!
|
||||
* [How to support new devices](how_tos/how_to_support_new_devices.md)
|
||||
* [How to debug](how_tos/how_to_debug.md)
|
||||
* [How to support new devices on Hass.io](how_tos/how_to_support_new_devices_on_hassio.md)
|
||||
* [How to sniff Zigbee traffic](how_tos/how_to_sniff_zigbee_traffic.md)
|
||||
* [How to create a CC2530 router](how_tos/how_to_create_a_cc2530_router.md)
|
||||
* [How to secure your Zigbee network](how_tos/how_to_secure_network.md)
|
||||
* [How to connect a CC2530 coordinator using a USB to serial adapter](how_tos/how_to_connect_a_cc2530_coordinator_using_a_usb_to_serial_adapter.md)
|
||||
|
||||
### Information
|
||||
* [Supported devices](information/supported_devices.md)
|
||||
* [MQTT topics and message structure](information/mqtt_topics_and_message_structure.md)
|
||||
* [Groups](information/groups.md)
|
||||
* [Binding](information/binding.md)
|
||||
* [Docker](information/docker.md)
|
||||
* [Zigbee network](information/zigbee_network.md)
|
||||
* [3D cases](information/3d_cases.md)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Frequently asked questions
|
||||
|
||||
## Can Zigbee stick X be supported?
|
||||
Unless the stick supports Texas Instruments Z-Stack, no. Zigbee2mqtt is based on zigbee-shepherd, zigbee-shepherd is based on Texas Instruments Z-Stack which means that only Z-Stack based device can be supported.
|
||||
|
||||
## I read that zigbee2mqtt has a limit of 15 devices, is this true?
|
||||
Definitely not! The default zigbee2mqtt firmware indeed supports 15 devices connected **directly** to the coordinator. However, by having routers in your network (probably all AC powered devices e.g. bulbs, you can even use another [CC2530/CC2531 as a router](../cc_sniffer_devices.md)) the network size can be extended. Various zigbee2mqtt users have reported that networks of 40+ nodes work without problems. Don't want to buy a router? No problem! In that case an [alternative firmware](https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/CC2531/alternatives/max_devices) can be used which supported 44 devices **directly** connected to the coordinator.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Binding
|
||||
*This is an experimental feature, ongoing discussion can be found here: https://github.com/Koenkk/zigbee2mqtt/issues/782*
|
||||
|
||||
Zigbee has support for binding which makes it possible that devices can directly control each other without the intervention of zigbee2mqtt or any home automation software.
|
||||
|
||||
## When to use this
|
||||
A use case for this is e.g. the TRADFRI wireless dimmer. Binding the dimmer directly to a bulb or group has the following advantages:
|
||||
- Smoothness; this will greatly improve the dimming feedback as the dimmer directly dims the bulb and thus does not have to make the MQTT/home automation software roundtrip.
|
||||
- It will work even when home automation software, zigbee2mqtt or the coordinator is down.
|
||||
|
||||
## Commands
|
||||
Binding can be configured using the following topics:
|
||||
|
||||
- `zigbee2mqtt/bridge/bind/[SOURCE_DEVICE_FRIENDLY_NAME]` with payload `TARGET_DEVICE_FRIENDLY_NAME` will bind the source device to the target device. In the above example, the TRADFRI wireless dimmer would be the source device and the bulb the target device.
|
||||
- `zigbee2mqtt/bridge/unbind/[SOURCE_DEVICE_FRIENDLY_NAME]` with payload `TARGET_DEVICE_FRIENDLY_NAME` will unbind the devices.
|
||||
@@ -17,3 +17,10 @@ For more information about a coordinator and routers can be found [here](zigbee_
|
||||
| **CC2530 + CC2591** | Serial connected Zigbee sniffer based on CC2530 with CC2591 RF frontend and external antenna. A more expensive option with increased range (~50-60m line of sight) and higher sensitivity. More difficult to connect unless paired with serial-USB | [Coordinator firmware](https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/CC2530_CC2591/bin) <br/><br/> [Router firmware](https://github.com/Koenkk/Z-Stack-firmware/tree/master/router/CC2530_CC2591/bin) | | [Aliexpress](http://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20181213104521&SearchText=cc2530+cc2591) |
|
||||
| **CC2530 with RFX2401** | Serial connected Zigbee sniffer based on CC2530 with RFX2401 RF frontend and external antenna. A more expensive option with increased range (~50-60m line of sight) and higher sensitivity. More difficult to connect unless paired with serial-USB (such as the example shown). **Note** that for the GBAN unit shown it is necessary to connect P04, P06 and P20 to GND - see [here](https://github.com/Koenkk/zigbee2mqtt/issues/52#issuecomment-391115143)| [Coordinator firmware (same as CC2530 + CC2591)](https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/CC2530_CC2591/bin) <br/><br/> [Router firmware (same as CC2530 + CC2591)](https://github.com/Koenkk/Z-Stack-firmware/tree/master/router/CC2530_CC2591/bin) |  | [GBAN](http://www.gban.cn/en/product_show.asp?id=43)<br/><br/>[Aliexpress](http://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20181213104722&SearchText=cc2530+rf) |
|
||||
|
||||
|
||||
NOTE: When using a CC2530 based device the following configuration is necessary:
|
||||
|
||||
```yaml
|
||||
advanced:
|
||||
rtscts: false
|
||||
```
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Groups
|
||||
*Ongoing discussion can be found here: https://github.com/Koenkk/zigbee2mqtt/issues/764*
|
||||
|
||||
Zigbee2mqtt has support for Zigbee groups. By using Zigbee groups you can control multiple devices simultaneously with one command.
|
||||
|
||||
**NOTE:** to use groups, at least firmware version `20181224` is required! (available [here](https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator))
|
||||
|
||||
## Configuration
|
||||
Add the following to your `configuration.yaml`.
|
||||
|
||||
```yaml
|
||||
groups:
|
||||
# ID, each group should have a different numerical ID
|
||||
'1':
|
||||
# Name which will be used to control the group
|
||||
friendly_name: group_1
|
||||
```
|
||||
|
||||
## Commands
|
||||
The group of a node can be configured using the following commands:
|
||||
|
||||
- `zigbee2mqtt/bridge/group/[GROUP_FRIENDLY_NAME]/add` with payload `DEVICE_FRIENDLY_NAME` will add a device to a group.
|
||||
- `zigbee2mqtt/bridge/group/[GROUP_FRIENDLY_NAME]/remove` with payload `DEVICE_FRIENDLY_NAME` will remove a device from a group.
|
||||
- `zigbee2mqtt/bridge/group/[GROUP_FRIENDLY_NAME]/remove_all` with payload `DEVICE_FRIENDLY_NAME` will remove a device from **all** groups.
|
||||
|
||||
## Controlling
|
||||
Controlling a group is similar to controlling a single device. For example to turn on all devices that are part of group send a MQTT message to `zigbee2mqtt/[GROUP_FRIENDLY_NAME]/set` with payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"state": "ON",
|
||||
}
|
||||
```
|
||||
|
||||
## How do groups work?
|
||||
By using the above `add` command above, a device will be added to a group. The device itself is responsible for storing to which groups it belongs. Others, e.g. the coordinator, do not have knowledge to which device a groups belongs.
|
||||
|
||||
When using the `set` command, e.g. to turn on all devices in a group, a broadcast request is send to **all* devices in the network. The device itself then determines if it belongs to that group and if it should execute the command.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# MQT topics and message structure
|
||||
# MQTT topics and message structure
|
||||
|
||||
This page describes which MQTT topics are used by Zigbee2mqtt. Note that the base topic (by default `zigbee2mqtt`) is configurable in the [Zigbee2mqtt `configuration.yaml`](../configuration/configuration.md).
|
||||
|
||||
@@ -12,6 +12,7 @@ zigbee2mqtt will output log to this endpoint. Message are always in the form of
|
||||
* `"pairing"`: logging when device is connecting to the network.
|
||||
* `"device_connected"`: send when a new device connects to the network.
|
||||
* `"device_removed"`: send when a device is removed from the network.
|
||||
* `"device_banned"`: send when a device is banned from the network.
|
||||
* `"devices"`: a list of all devices, this message can be triggered by sending a message to `zigbee2mqtt/bridge/config/devices` (payload doesn't matter).
|
||||
|
||||
## zigbee2mqtt/bridge/config/permit_join
|
||||
@@ -25,6 +26,9 @@ Allows you to switch the `log_level` during runtime. This is not persistent (wil
|
||||
## zigbee2mqtt/bridge/config/remove
|
||||
Allows you to remove devices from the network. Payload should be the `friendly_name`, e.g. `0x00158d0001b79111`. On successful remove a [`device_removed`](https://koenkk.github.io/zigbee2mqtt/information/mqtt_topics_and_message_structure.html#zigbee2mqttbridgelog) message is send.
|
||||
|
||||
## zigbee2mqtt/bridge/config/ban
|
||||
Allows you to ban devices from the network. Payload should be the `friendly_name`, e.g. `0x00158d0001b79111`. On successful ban a [`device_banned`](https://koenkk.github.io/zigbee2mqtt/information/mqtt_topics_and_message_structure.html#zigbee2mqttbridgelog) message is send.
|
||||
|
||||
## zigbee2mqtt/bridge/config/rename
|
||||
Allows you to change the `friendly_name` of a device on the fly.
|
||||
Format should be: `{"old": "OLD_FRIENDLY_NAME", "new": "NEW_FRIENDLY_NAME"}`.
|
||||
@@ -32,6 +36,12 @@ Format should be: `{"old": "OLD_FRIENDLY_NAME", "new": "NEW_FRIENDLY_NAME"}`.
|
||||
## zigbee2mqtt/bridge/networkmap
|
||||
Allows you to retrieve a map of your zigbee network. Possible payloads are `raw`, `graphviz`. Zigbee2mqtt will send the networkmap to `zigbee2mqtt/bridge/networkmap/[graphviz OR raw]`.
|
||||
|
||||
## zigbee2mqtt/bridge/groups/[friendly_name]/(add|remove|remove_all)
|
||||
See [Groups](groups.md)
|
||||
|
||||
## zigbee2mqtt/bridge/(bind|unbind)/[friendly_name]
|
||||
See [Binding](binding.md)
|
||||
|
||||
## zigbee2mqtt/[DEVICE_ID]
|
||||
Where `[DEVICE_ID]` is E.G. `0x00158d0001b79111`. Message published to this topic are **always** in a JSON format. Each device produces a different JSON message, **some** examples:
|
||||
|
||||
@@ -66,10 +76,18 @@ Where `[DEVICE_ID]` is E.G. `0x00158d0001b79111`. Message published to this topi
|
||||
}
|
||||
```
|
||||
|
||||
**Xiaomi Aqara curtain motor (ZNCLDJ11LM)**
|
||||
```
|
||||
{
|
||||
"position": 60, // Value between 0 and 100, (0 - closed / 100 - open)
|
||||
"running": true, // Curtain is moving
|
||||
}
|
||||
```
|
||||
|
||||
## zigbee2mqtt/[DEVICE_ID]/set
|
||||
Publishing messages to this topic allows you to control your Zigbee devices via MQTT. Only accepts JSON messages. An example to control a Philips Hue Go (7146060PH).
|
||||
|
||||
```json
|
||||
```
|
||||
{
|
||||
"state": "ON", // Or "OFF", "TOGGLE"
|
||||
"brightness": 255,
|
||||
@@ -84,7 +102,18 @@ Publishing messages to this topic allows you to control your Zigbee devices via
|
||||
// RGB color
|
||||
"r": 46,
|
||||
"g": 102,
|
||||
"b": 193
|
||||
"b": 193,
|
||||
|
||||
// OR
|
||||
|
||||
// HEX color
|
||||
"hex": "#547CFF",
|
||||
|
||||
// OR
|
||||
|
||||
// Hue and/or saturation color
|
||||
"hue": 360,
|
||||
"saturation": 100
|
||||
},
|
||||
|
||||
// Blinks the bulbs, possible values:
|
||||
@@ -108,19 +137,48 @@ Only used when `homeassistant: true` in `configuration.yaml`. Required for [Home
|
||||
## Device specific
|
||||
Device specific commands are always send to the topic: `zigbee2mqtt/[DEVICE_ID]/set`. Below you will find the possible payloads.
|
||||
|
||||
### Philips Hue power-on behavior
|
||||
Sets the Philips Hue power-on behavior which was introduced with the November/December '18 firmware update.
|
||||
```
|
||||
{
|
||||
"hue_power_on_behavior": "on", //default, on, off, recover, default = on
|
||||
"hue_power_on_brightness": 125, //default, same values as brightness, default = 255
|
||||
"hue_power_on_color_temperature": 280, //default, same values as color_temp, default = 366
|
||||
}
|
||||
```
|
||||
Attribute Value | Description
|
||||
----------------|-----------------------------------------------
|
||||
default | reset to factory default value
|
||||
on | lamps on after power loss with configured brightness, color-temperature, color (to-do)
|
||||
off | lamps off after power loss
|
||||
recover | last running state after power loss
|
||||
|
||||
### Philips Hue motion detector (SML001)
|
||||
Sets the sensors timeout between last motion detected
|
||||
and sensor reports occupance false
|
||||
```
|
||||
{
|
||||
// Value >= 0,
|
||||
// 0 - 10: 10sec (min possible timeout)
|
||||
// > 10: timeout in sec
|
||||
// (must be written to (default) endpoint 2)
|
||||
"occupancy_timeout": 0,
|
||||
}
|
||||
```
|
||||
|
||||
### Xiaomi Aqara vibration sensor (DJT11LM)
|
||||
Set the sensitivity of the sensor. **NOTE:** As this device is sleeping most of the time, right before sending this command press the button on the device.
|
||||
```json
|
||||
```
|
||||
{
|
||||
"sensitivity": "medium" // Possible values: 'low', 'medium', 'high'
|
||||
"sensitivity": "medium" // Possible values: 'low', 'medium', 'high'
|
||||
}
|
||||
```
|
||||
|
||||
### Xiaomi MiJia gas leak detector (JTQJBF01LMBW)
|
||||
Set/read the sensitivity of the sensor.
|
||||
```json
|
||||
```
|
||||
{
|
||||
"sensitivity": "medium" // Possible values; to set: 'low', 'medium', 'high'; to read: 'read'
|
||||
"sensitivity": "medium" // Possible values; to set: 'low', 'medium', 'high'; to read: 'read'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -131,10 +189,173 @@ Execute selftest
|
||||
}
|
||||
```
|
||||
|
||||
### Xiaomi Aqara curtain motor (ZNCLDJ11LM)
|
||||
Set the state of the curtain.
|
||||
```
|
||||
{
|
||||
"state": "open" // Possible values to set: 'open', 'close', 'stop'
|
||||
}
|
||||
```
|
||||
|
||||
Set the position of the curtain.
|
||||
```
|
||||
{
|
||||
"position": 50 // Possible values to set: 0 - 100 (0 - closed / 100 - open)
|
||||
}
|
||||
```
|
||||
|
||||
### SmartThings arrival sensor (STS-PRS-251)
|
||||
Let the device beep.
|
||||
```json
|
||||
{
|
||||
"beep": 5
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### eCozy Smart heating thermostat (1TST-EU), Bitron Wireless wall thermostat with relay (AV2010/32)
|
||||
Get local temperature in degrees Celsius (in the range 0x954d to 0x7fff, i.e. -273.15°C to 327.67 ºC)
|
||||
```json
|
||||
{
|
||||
"local_temperature": ""
|
||||
}
|
||||
```
|
||||
|
||||
Get or set offset added to/subtracted from the actual displayed room temperature to NUMBER, in steps of 0.1°C
|
||||
```
|
||||
{
|
||||
"local_temperature_calibration": "NUMBER" // Possible values: –2.5 to +2.5; leave empty to read
|
||||
}
|
||||
```
|
||||
|
||||
Set temperature display mode
|
||||
```
|
||||
{
|
||||
"temperature_display_mode": "" // Possible values: 0 to set °C or 1 so set °F
|
||||
}
|
||||
```
|
||||
|
||||
Get room occupancy. Specifies whether the heated/cooled space is occupied or not. If 1, the space is occupied, else it is unoccupied.
|
||||
```json
|
||||
{
|
||||
"thermostat_occupancy": ""
|
||||
}
|
||||
```
|
||||
|
||||
Get or set occupied heating setpoint to NUMBER in degrees Celsius.
|
||||
```
|
||||
{
|
||||
"occupied_heating_setpoint": "NUMBER" // Possible values: MinHeatSetpointLimit to MaxHeatSetpointLimit, i.e. 7 to 30 by default; leave empty to read
|
||||
}
|
||||
```
|
||||
|
||||
Get or set unoccupied heating setpoint to NUMBER in degrees Celsius
|
||||
```
|
||||
{
|
||||
"unoccupied_heating_setpoint": "NUMBER" // Possible values: MinHeatSetpointLimit to MaxHeatSetpointLimit, i.e. 7 to 30 by default; leave empty to read
|
||||
}
|
||||
```
|
||||
|
||||
Increase or decrease heating setpoint by NUMBER degrees in °C.
|
||||
```
|
||||
{
|
||||
"setpoint_raise_lower": {
|
||||
"mode": "0x00", // Possible values: see table below
|
||||
"amount": "NUMBER" // Possible values: signed 8-bit integer that specifies the amount the setpoint(s) are to be increased (or decreased) by, in steps of 0.1°C
|
||||
}
|
||||
}
|
||||
```
|
||||
Attribute Value | Description
|
||||
----------------|-----------------------------------------------
|
||||
0x00 | Heat (adjust Heat Setpoint)
|
||||
0x01 | Cool (adjust Cool Setpoint)
|
||||
0x02 | Both (adjust Heat Setpoint and Cool Setpoint)
|
||||
|
||||
Get or set whether the local temperature, outdoor temperature and occupancy are being sensed by internal sensors or remote networked sensors
|
||||
```
|
||||
{
|
||||
"remote_sensing": "NUMBER" // Possible values: see table below; leave empty to read
|
||||
}
|
||||
```
|
||||
Bit Number | Description
|
||||
-----------|-----------------------------------------
|
||||
0 | 0 – local temperature sensed internally <br> 1 – local temperature sensed remotely
|
||||
1 | 0 – outdoor temperature sensed internally <br> 1 – outdoor temperature sensed remotely
|
||||
2 | 0 – occupancy sensed internally <br> 1 – occupancy sensed remotely
|
||||
|
||||
Get or set control sequence of operation
|
||||
```
|
||||
{
|
||||
"control_sequence_of_operation": "VALUE" // Possible values: see table below; leave empty to read
|
||||
}
|
||||
```
|
||||
Values | Possible Values of SystemMode
|
||||
------------------------------------------|-------------------------------------
|
||||
`cooling only` | Heat and Emergency are not possible
|
||||
`cooling with reheat` | Heat and Emergency are not possible
|
||||
`heating only` | Cool and precooling are not possible
|
||||
`heating with reheat` | Cool and precooling are not possible
|
||||
`cooling and heating 4-pipes` | All modes are possible
|
||||
`cooling and heating 4-pipes with reheat` | All modes are possible
|
||||
|
||||
Get or set system mode
|
||||
```
|
||||
{
|
||||
"system_mode": "VALUE" // Possible values: see table below; leave empty to read
|
||||
}
|
||||
```
|
||||
| Values
|
||||
|------------------
|
||||
| `off`
|
||||
| `auto`
|
||||
| `cool`
|
||||
| `heat`
|
||||
| `emergency heating`
|
||||
| `precooling`
|
||||
| `fan only`
|
||||
| `dry`
|
||||
| `sleep`
|
||||
|
||||
Get running state
|
||||
```
|
||||
{
|
||||
"running_state": "" // leave empty when reading
|
||||
}
|
||||
```
|
||||
Possible values:
|
||||
| Values
|
||||
|------------------
|
||||
| `off`
|
||||
| `cool`
|
||||
| `heat`
|
||||
|
||||
Get or set weekly schedule
|
||||
```
|
||||
{
|
||||
"weekly_schedule": {
|
||||
"TemperatureSetpointHold": "0x00", // 0x00 setpoint hold off or 0x01 on
|
||||
"TemperatureSetpointHoldDuration": "0xffff", // 0xffff to 0x05a0
|
||||
"ThermostatProgrammingOperationMode": "00xxxxxx" //see table below
|
||||
} // leave empty to read
|
||||
}
|
||||
```
|
||||
Attribute Value | Description
|
||||
----------------|---------------------------------------------------------------------------
|
||||
0 | 0 – Simple/setpoint mode. This mode means the thermostat setpoint is altered only by manual up/down changes at the thermostat or remotely, not by internal schedule programming. <br> 1 – Schedule programming mode. This enables or disables any programmed weekly schedule configurations. <br> Note: It does not clear or delete previous weekly schedule programming configurations.
|
||||
1 | 0 - Auto/recovery mode set to OFF <br> 1 – Auto/recovery mode set to ON
|
||||
2 | 0 – Economy/EnergyStar mode set to OFF <br> 1 – Economy/EnergyStar mode set to ON
|
||||
|
||||
Clear weekly schedule
|
||||
```json
|
||||
{
|
||||
"clear_weekly_schedule": ""
|
||||
}
|
||||
```
|
||||
<!--
|
||||
Coming soon:
|
||||
Get weekly schedule response
|
||||
tz.thermostat_weekly_schedule_rsp
|
||||
Get relay status log
|
||||
tz.thermostat_relay_status_log
|
||||
Get relay status log response
|
||||
tz.thermostat_relay_status_log_rsp
|
||||
-->
|
||||
|
||||
@@ -2,22 +2,37 @@
|
||||
|
||||
*NOTE: This file has been generated, do not edit this file manually!*
|
||||
|
||||
Currently **144** devices are supported from **30** different vendors.
|
||||
Currently **191** devices are supported from **39** different vendors.
|
||||
|
||||
In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
[How to support new devices](https://koenkk.github.io/zigbee2mqtt/how_tos/how_to_support_new_devices.html).
|
||||
|
||||
### AduroSmart
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 81809 | AduroSmart ERIA colors and white shades smart light bulb A19 (on/off, brightness, color temperature, color xy) |  |
|
||||
|
||||
### Airam
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 4713407 | Airam LED OP A60 ZB 9W/827 E27 (on/off, brightness) |  |
|
||||
| AIRAM-CTR.U | Airam CTR.U remote (can only be used to control the Airam 4713407 bulb) (on/off) |  |
|
||||
|
||||
### Belkin
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| F7C033 | Belkin WeMo smart LED bulb (on/off, brightness) |  |
|
||||
|
||||
### Bitron Home
|
||||
### Bitron
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| AV2010/22 | Bitron Home Wireless motion detector (occupancy) |  |
|
||||
| AV2010/22 | Bitron Wireless motion detector (occupancy) |  |
|
||||
| AV2010/25 | Bitron Video wireless socket (on/off, power measurement) |  |
|
||||
| AV2010/32 | Bitron Wireless wall thermostat with relay (temperature, heating/cooling system control) |  |
|
||||
|
||||
### Calex
|
||||
|
||||
@@ -58,6 +73,7 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| Mega23M12 | Dresden Elektronik ZigBee Light Link wireless electronic ballast (on/off, brightness, color temperature, color xy) |  |
|
||||
| XVV-Mega23M12 | Dresden Elektronik ZigBee Light Link wireless electronic ballast color temperature (on/off, brightness, color temperature) |  |
|
||||
|
||||
### EDP
|
||||
|
||||
@@ -65,12 +81,21 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| PLUG EDP RE:DY | EDP re:dy plug (on/off, power measurement) |  |
|
||||
|
||||
### EcoSmart
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| D1821 | EcoSmart A19 RGB bulb (on/off, brightness, color temperature, color xy) |  |
|
||||
| D1531 | EcoSmart A19 bright white bulb (on/off, brightness) |  |
|
||||
| D1532 | EcoSmart A19 soft white bulb (on/off, brightness) |  |
|
||||
|
||||
### GE
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 22670 | GE Link smart LED light bulb, BR30 soft white (2700K) (on/off, brightness) |  |
|
||||
| 45852GE | GE ZigBee plug-in smart dimmer (on/off, brightness) |  |
|
||||
| 45856GE | GE In-wall smart switch (on/off) |  |
|
||||
| 45857GE | GE ZigBee in-wall smart dimmer (on/off, brightness) |  |
|
||||
|
||||
### Gledopto
|
||||
@@ -78,6 +103,13 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| GL-C-008 | Gledopto Zigbee LED controller RGB + CCT / RGBW / WWCW / Dimmer (on/off, brightness, color temperature, color xy) |  |
|
||||
| GL-C-006 | Gledopto Zigbee LED controller WW/CW Dimmer (on/off, brightness, color temperature) |  |
|
||||
| GL-S-007Z | Gledopto Smart RGBW GU10 (on/off, brightness, color temperature, color xy) |  |
|
||||
| GL-B-007Z | Gledopto Smart 6W E27 RGB / CW LED bulb (on/off, brightness, color temperature, color xy) |  |
|
||||
| GL-B-008Z | Gledopto Smart 12W E27 RGB / CW LED bulb (on/off, brightness, color temperature, color xy) |  |
|
||||
| GL-D-003Z | Gledopto LED RGB + CCT downlight (on/off, brightness, color temperature, color xy) |  |
|
||||
| GL-S-003Z | Gledopto Smart RGBW GU10 (on/off, brightness, color temperature, color xy) |  |
|
||||
| GD-CZ-006 | Gledopto Zigbee LED Driver (on/off, brightness) |  |
|
||||
|
||||
### HEIMAN
|
||||
|
||||
@@ -86,13 +118,16 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| HS1SA | HEIMAN Smoke detector (smoke) |  |
|
||||
| HS3SA | HEIMAN Smoke detector (smoke) |  |
|
||||
| HS1DS | HEIMAN Door sensor (contact) |  |
|
||||
| HS1DS-E | HEIMAN Door sensor (contact) |  |
|
||||
| HS1WL | HEIMAN Water leakage sensor (water leak) |  |
|
||||
|
||||
### Hive
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| HALIGHTDIMWWE27 | Hive Active light dimmable (on/off, brightness) |  |
|
||||
| HALIGHTDIMWWE27 | Hive Active smart bulb white LED (E27) (on/off, brightness) |  |
|
||||
| HALIGHTDIMWWB22 | Hive Active smart bulb white LED (B22) (on/off, brightness) |  |
|
||||
| 1613V | Hive Active plug (on/off, power measurement) |  |
|
||||
|
||||
### IKEA
|
||||
|
||||
@@ -113,7 +148,9 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| L1527 | IKEA FLOALT LED light panel, dimmable, white spectrum (30x30 cm) (on/off, brightness, color temperature) |  |
|
||||
| L1529 | IKEA FLOALT LED light panel, dimmable, white spectrum (60x60 cm) (on/off, brightness, color temperature) |  |
|
||||
| L1528 | IKEA FLOALT LED light panel, dimmable, white spectrum (30x90 cm) (on/off, brightness, color temperature) |  |
|
||||
| L1531 | IKEA SURTE door light panel, dimmable, white spectrum (38x64 cm) (on/off, brightness, color temperature) |  |
|
||||
| E1603 | IKEA TRADFRI control outlet (on/off) |  |
|
||||
| E1524 | IKEA TRADFRI remote control (toggle, arrow left/right click/hold/release, brightness up/down click/hold/release (**[requires additional setup!](https://github.com/Koenkk/zigbee2mqtt/blob/dev/docs/getting_started/pairing_devices.md)**)) |  |
|
||||
|
||||
### Innr
|
||||
|
||||
@@ -124,6 +161,7 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| RB 285 C | Innr E27 Bulb RGBW (on/off, brightness, color temperature, color xy) |  |
|
||||
| RB 165 | Innr E27 Bulb (on/off, brightness) |  |
|
||||
| RB 175 W | Innr E27 Bulb warm dimming (on/off, brightness) |  |
|
||||
| RB 178 T | Innr Smart bulb tunable white E27 (on/off, brightness, color temperature) |  |
|
||||
| RS 125 | Innr GU10 Spot (on/off, brightness) |  |
|
||||
| RS 128 T | Innr GU10 Spot 350 lm, dimmable, white spectrum (on/off, brightness, color temperature) |  |
|
||||
| RB 145 | Innr E14 Candle (on/off, brightness) |  |
|
||||
@@ -144,7 +182,7 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 3210-L | Iris Smart plug (on/off) |  |
|
||||
| 3326-L | Iris Motion sensor (occupancy and temperature) |  |
|
||||
| 3326-L | Iris Motion and temperature sensor (occupancy and temperature) |  |
|
||||
| 3320-L | Iris Contact sensor (contact) |  |
|
||||
|
||||
### JIAWEN
|
||||
@@ -159,6 +197,13 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| KS-SM001 | Ksentry Electronics [Zigbee OnOff Controller](http://ksentry.manufacturer.globalsources.com/si/6008837134660/pdtl/ZigBee-module/1162731630/zigbee-on-off-controller-modules.htm) (on/off) |  |
|
||||
|
||||
### Müller Licht
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 404000/404005/404012 | Müller Licht Tint LED bulb GU10/E14/E27 350/470/806 lumen, dimmable, color, opal white (on/off, brightness, color temperature, color xy) |  |
|
||||
| 404006/404008/404004 | Müller Licht Tint LED bulb GU10/E14/E27 350/470/806 lumen, dimmable, opal white (on/off, brightness, color temperature) |  |
|
||||
|
||||
### Nanoleaf
|
||||
|
||||
| Model | Description | Picture |
|
||||
@@ -177,6 +222,7 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| FB56+ZSW05HG1.2 | Nue ZigBee one gang smart switch (on/off) |  |
|
||||
| MG-AUWS01 | Nue ZigBee Double GPO (on/off) |  |
|
||||
| HGZB-01A | Nue ZigBee smart light controller (on/off, brightness) |  |
|
||||
|
||||
### OSRAM
|
||||
|
||||
@@ -200,6 +246,14 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| AB35996 | OSRAM Smart+ Spot GU10 Multicolor (on/off, brightness, color temperature, color xy) |  |
|
||||
| AC08562 | OSRAM SMART+ Candle E14 Dimmable White (on/off, brightness) |  |
|
||||
| AC01353010G | OSRAM SMART+ Motion Sensor (occupancy and temperature) |  |
|
||||
| AC03648 | OSRAM SMART+ spot GU5.3 tunable white (on/off, brightness, color temperature) |  |
|
||||
| AC0251100NJ | OSRAM Smart+ switch mini (on/off, brightness) |  |
|
||||
|
||||
### Paul Neuhaus
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 100.424.11 | Paul Neuhaus Q-INIGO LED ceiling light (on/off, brightness, color temperature) |  |
|
||||
|
||||
### Paulmann
|
||||
|
||||
@@ -212,26 +266,35 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 7299760PH | Philips Hue Bloom (on/off, brightness, color xy) |  |
|
||||
| 7146060PH | Philips Hue Go (on/off, brightness, color temperature, color xy) |  |
|
||||
| 433714 | Philips Hue Lux A19 bulb E27 (on/off, brightness) |  |
|
||||
| 9290011370 | Philips Hue white A60 bulb E27 (on/off, brightness) |  |
|
||||
| 8718696449691 | Philips Hue White Single bulb B22 (on/off, brightness) |  |
|
||||
| 7299355PH | Philips Hue white and color ambiance LightStrip (on/off, brightness, color xy) |  |
|
||||
| 915005106701 | Philips Hue white and color ambiance LightStrip plus (on/off, brightness, color temperature, color xy) |  |
|
||||
| 9290012573A | Philips Hue white and color ambiance E26/E27/E14 (on/off, brightness, color temperature, color xy) |  |
|
||||
| 9290002579A | Philips Hue white and color ambiance BR30 (on/off, brightness, color temperature, color xy) |  |
|
||||
| 8718696485880 | Philips Hue white and color ambiance GU10 (on/off, brightness, color temperature, color xy) |  |
|
||||
| 915005733701 | Philips Hue White and color ambiance Play Lightbar (on/off, brightness, color temperature, color xy) |  |
|
||||
| 8718696695203 | Philips Hue white ambiance E14 (on/off, brightness, color temperature) |  |
|
||||
| 8718696598283 | Philips Hue white ambiance GU10 (on/off, brightness, color temperature) |  |
|
||||
| 8718696548738 | Philips Hue white ambiance E26/E27 (on/off, brightness, color temperature) |  |
|
||||
| 3261030P7 | Philips Hue Being (on/off, brightness, color temperature) |  |
|
||||
| 3216331P5 | Philips Philips Hue White ambiance Aurelle Rectangle Panel Light (on/off, brightness, color temperature) |  |
|
||||
| 7199960PH | Philips Hue Iris (on/off, brightness, color xy) |  |
|
||||
| 7299760PH | Philips Hue Bloom (on/off, brightness, color xy, power-on behavior) |  |
|
||||
| 7146060PH | Philips Hue Go (on/off, brightness, color temperature, color xy, power-on behavior) |  |
|
||||
| 433714 | Philips Hue Lux A19 bulb E27 (on/off, brightness, power-on behavior) |  |
|
||||
| 9290011370 | Philips Hue white A60 bulb E27 (on/off, brightness, power-on behavior) |  |
|
||||
| 8718696449691 | Philips Hue White Single bulb B22 (on/off, brightness, power-on behavior) |  |
|
||||
| 7299355PH | Philips Hue white and color ambiance LightStrip (on/off, brightness, color xy, power-on behavior) |  |
|
||||
| 915005106701 | Philips Hue white and color ambiance LightStrip plus (on/off, brightness, color temperature, color xy, power-on behavior) |  |
|
||||
| 9290012573A | Philips Hue white and color ambiance E26/E27/E14 (on/off, brightness, color temperature, color xy, power-on behavior) |  |
|
||||
| 9290002579A | Philips Hue white and color ambiance BR30 (on/off, brightness, color temperature, color xy, power-on behavior) |  |
|
||||
| 8718696485880 | Philips Hue white and color ambiance GU10 (on/off, brightness, color temperature, color xy, power-on behavior) |  |
|
||||
| 915005733701 | Philips Hue White and color ambiance Play Lightbar (on/off, brightness, color temperature, color xy, power-on behavior) |  |
|
||||
| 464800 | Philips Hue white ambiance BR30 flood light (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 8718696695203 | Philips Hue white ambiance E14 (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 8718696598283 | Philips Hue white ambiance GU10 (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 8718696548738 | Philips Hue white ambiance E26/E27 (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 3261030P7 | Philips Hue Being (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 3261331P7 | Philips Hue white ambiance Still (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 3216331P5 | Philips Hue white ambiance Aurelle rectangle panel light (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 3216431P5 | Philips Hue white ambiance Aurelle round panel light (on/off, brightness, color temperature, power-on behavior) |  |
|
||||
| 7199960PH | Philips Hue Iris (on/off, brightness, color xy, power-on behavior) |  |
|
||||
| 324131092621 | Philips Hue dimmer switch (on/off) |  |
|
||||
| 9290012607 | Philips Hue motion sensor (occupancy, temperature, illuminance) |  |
|
||||
|
||||
### Salus
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| SP600 | Salus Smart plug (on/off, power measurement) |  |
|
||||
|
||||
### Sengled
|
||||
|
||||
| Model | Description | Picture |
|
||||
@@ -241,13 +304,24 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| Z01-CIA19NAE26 | Sengled Element Touch (A19) (on/off, brightness) |  |
|
||||
| Z01-A19NAE26 | Sengled Element Plus (A19) (on/off, brightness, color temperature) |  |
|
||||
| E11-N1EA | Sengled Element Plus Color (A19) (on/off, brightness, color temperature, color xy) |  |
|
||||
| E12-N14 | Sengled Element Classic (BR30) (on/off, brightness) |  |
|
||||
| E1ACA4ABE38A | Sengled Element downlight smart LED bulb (on/off, brightness) |  |
|
||||
|
||||
### Smart Home Pty
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| HGZB-07A | Smart Home Pty RGBW Downlight (on/off, brightness, color temperature, color xy) |  |
|
||||
| HGZB-20-DE | Smart Home Pty Power plug (on/off) |  |
|
||||
|
||||
### SmartThings
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| STSS-MULT-001 | SmartThings SmartSense multi sensor (contact) |  |
|
||||
| STS-PRS-251 | SmartThings SmartThings arrival sensor (presence) |  |
|
||||
| STSS-MULT-001 | SmartThings Multipurpose sensor (contact) |  |
|
||||
| STS-PRS-251 | SmartThings Arrival sensor (presence) |  |
|
||||
| 3325-S | SmartThings Motion sensor (2015 model) (occupancy and temperature) |  |
|
||||
| 3321-S | SmartThings Multi Sensor (2015 model) (contact and temperature) |  |
|
||||
|
||||
### Sylvania
|
||||
|
||||
@@ -259,23 +333,28 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| 74283 | Sylvania LIGHTIFY LED soft white dimmable A19 (on/off, brightness) |  |
|
||||
| 74696 | Sylvania LIGHTIFY LED soft white dimmable A19 (on/off, brightness) |  |
|
||||
| 72922-A | Sylvania SMART+ Smart Plug (on/off) |  |
|
||||
| 71831 | Sylvania Smart Home adjustable white A19 LED bulb (on/off, brightness, color temperature) |  |
|
||||
| 74282 | Sylvania Smart Home adjustable white MR16 LED bulb (on/off, brightness, color temperature) |  |
|
||||
| LTFY004 | Sylvania LIGHTIFY LED gardenspot mini RGB (on/off, brightness, color xy) |  |
|
||||
|
||||
### Trust
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| ZLED-2709 | Trust Smart Dimmable LED Bulb (on/off, brightness) |  |
|
||||
| ZPIR-8000 | Trust Motion Sensor (occupancy) |  |
|
||||
| ZCTS-808 | Trust Wireless contact sensor (contact) |  |
|
||||
|
||||
### Xiaomi
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| ZNLDP12LM | Xiaomi Aqara smart LED bulb (on/off, brightness, color temperature) |  |
|
||||
| WXKG01LM | Xiaomi MiJia wireless switch (single, double, triple, quadruple, many, long, long_release click) |  |
|
||||
| WXKG11LM | Xiaomi Aqara wireless switch (single, double click (and triple, quadruple, hold, release depending on model)) |  |
|
||||
| WXKG12LM | Xiaomi Aqara wireless switch (with gyroscope) (single, double, shake, hold, release) |  |
|
||||
| WXKG03LM | Xiaomi Aqara single key wireless wall switch (single click) |  |
|
||||
| WXKG02LM | Xiaomi Aqara double key wireless wall switch (left, right and both click) |  |
|
||||
| WXKG03LM | Xiaomi Aqara single key wireless wall switch (single, double, hold, release and long click) |  |
|
||||
| WXKG02LM | Xiaomi Aqara double key wireless wall switch (left, right, both click (and double, long click for left, right and both depending on model)) |  |
|
||||
| QBKG04LM | Xiaomi Aqara single key wired wall switch (on/off) |  |
|
||||
| QBKG11LM | Xiaomi Aqara single key wired wall switch (on/off, power measurement) |  |
|
||||
| QBKG03LM | Xiaomi Aqara double key wired wall switch (release/hold, on/off) |  |
|
||||
@@ -294,6 +373,19 @@ In case you own a Zigbee device which is **NOT** listed here, please see
|
||||
| JTQJ-BF-01LM/BW | Xiaomi MiJia gas leak detector (gas) |  |
|
||||
| A6121 | Xiaomi Vima Smart Lock (inserted, forgotten, key error) |  |
|
||||
| DJT11LM | Xiaomi Aqara vibration sensor (drop, tilt and touch) |  |
|
||||
| ZNCLDJ11LM | Xiaomi Aqara curtain motor (open, close, stop, position) |  |
|
||||
|
||||
### eCozy
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| 1TST-EU | eCozy Smart heating thermostat (temperature, occupancy, un-/occupied heating, schedule) |  |
|
||||
|
||||
### iCasa
|
||||
|
||||
| Model | Description | Picture |
|
||||
| ------------- | ------------- | -------------------------- |
|
||||
| ICZB-IW11D | iCasa Zigbee 3.0 Dimmer (on/off, brightness) |  |
|
||||
|
||||
### ilux
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ const ExtensionDeviceConfigure = require('./extension/deviceConfigure');
|
||||
const ExtensionDeviceReceive = require('./extension/deviceReceive');
|
||||
const ExtensionMarkOnlineXiaomi = require('./extension/markOnlineXiaomi');
|
||||
const ExtensionBridgeConfig = require('./extension/bridgeConfig');
|
||||
const ExtensionGroups = require('./extension/groups');
|
||||
const ExtensionDeviceAvailability = require('./extension/deviceAvailability');
|
||||
const ExtensionBind = require('./extension/bind');
|
||||
const ExtensionCoordinatorGroup = require('./extension/coordinatorGroup');
|
||||
|
||||
class Controller {
|
||||
constructor() {
|
||||
@@ -38,6 +42,9 @@ class Controller {
|
||||
new ExtensionRouterPollXiaomi(this.zigbee, this.mqtt, this.state, this.publishDeviceState),
|
||||
new ExtensionMarkOnlineXiaomi(this.zigbee, this.mqtt, this.state, this.publishDeviceState),
|
||||
new ExtensionBridgeConfig(this.zigbee, this.mqtt, this.state, this.publishDeviceState),
|
||||
new ExtensionGroups(this.zigbee, this.mqtt, this.state, this.publishDeviceState),
|
||||
new ExtensionBind(this.zigbee, this.mqtt, this.state, this.publishDeviceState),
|
||||
new ExtensionCoordinatorGroup(this.zigbee, this.mqtt, this.state, this.publishDeviceState),
|
||||
];
|
||||
|
||||
if (settings.get().homeassistant) {
|
||||
@@ -51,6 +58,12 @@ class Controller {
|
||||
this.zigbee, this.mqtt, this.state, this.publishDeviceState
|
||||
));
|
||||
}
|
||||
|
||||
if (settings.get().advanced.availability_timeout) {
|
||||
this.extensions.push(new ExtensionDeviceAvailability(
|
||||
this.zigbee, this.mqtt, this.state, this.publishDeviceState
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
onMQTTConnected() {
|
||||
@@ -91,7 +104,7 @@ class Controller {
|
||||
let mappedDevice = null;
|
||||
|
||||
// Check if message has a device
|
||||
if (message.endpoints && message.endpoints[0].device) {
|
||||
if (message.endpoints && message.endpoints.length && message.endpoints[0].device) {
|
||||
device = message.endpoints[0].device;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
const utils = require('../util/utils');
|
||||
const Queue = require('queue');
|
||||
|
||||
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/(bind|unbind)/.+$`);
|
||||
const foundationCfg = {manufSpec: 0, disDefaultRsp: 0};
|
||||
const clusteReportCfg = {
|
||||
6: {direction: 0, attrId: 0, dataType: 16, minRepIntval: 0, maxRepIntval: 1000, repChange: 0},
|
||||
8: {direction: 0, attrId: 0, dataType: 32, minRepIntval: 0, maxRepIntval: 1000, repChange: 0},
|
||||
};
|
||||
|
||||
const allowedClusters = [
|
||||
5, // genScenes
|
||||
6, // genOnOff
|
||||
8, // genLevelCtrl
|
||||
768, // lightingColorCtrl
|
||||
];
|
||||
|
||||
class Bind {
|
||||
constructor(zigbee, mqtt, state, publishDeviceState) {
|
||||
this.zigbee = zigbee;
|
||||
this.mqtt = mqtt;
|
||||
this.state = state;
|
||||
this.publishDeviceState = publishDeviceState;
|
||||
|
||||
// Setup queue
|
||||
this.queue = new Queue();
|
||||
this.queue.concurrency = 1;
|
||||
this.queue.autostart = true;
|
||||
}
|
||||
|
||||
onMQTTConnected() {
|
||||
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/bind/+`);
|
||||
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/unbind/+`);
|
||||
}
|
||||
|
||||
parseTopic(topic) {
|
||||
if (!topic.match(topicRegex)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove base from topic
|
||||
topic = topic.replace(`${settings.get().mqtt.base_topic}/bridge/`, '');
|
||||
|
||||
// Parse type from topic
|
||||
const type = topic.split('/')[0];
|
||||
|
||||
// Remove type from topic
|
||||
topic = topic.replace(`${type}/`, '');
|
||||
|
||||
return {ID: topic, type: type};
|
||||
}
|
||||
|
||||
onMQTTMessage(topic, message) {
|
||||
topic = this.parseTopic(topic);
|
||||
|
||||
if (!topic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find source; can only be a device.
|
||||
const sourceEntity = utils.resolveEntity(topic.ID);
|
||||
const source = this.zigbee.findDevice(sourceEntity.ID);
|
||||
|
||||
if (!source) {
|
||||
logger.error(`Failed to find device '${sourceEntity.ID}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find target; can be a device or group.
|
||||
const targetEntity = utils.resolveEntity(message.toString());
|
||||
let target = null;
|
||||
|
||||
if (targetEntity.type === 'device') {
|
||||
target = this.zigbee.findDevice(targetEntity.ID);
|
||||
|
||||
if (!target) {
|
||||
logger.error(`Failed to find target device '${targetEntity.ID}'`);
|
||||
return false;
|
||||
}
|
||||
} else if (targetEntity.type === 'group') {
|
||||
target = targetEntity.ID;
|
||||
}
|
||||
|
||||
// Find which clusters are supported by both the source and target.
|
||||
// Groups are assumed to support all clusters (as we don't know which devices are in)
|
||||
let supported = [];
|
||||
if (targetEntity.type === 'device') {
|
||||
supported = target.getSimpleDesc().inClusterList.filter((cluster) => {
|
||||
return allowedClusters.includes(cluster);
|
||||
});
|
||||
} else if (targetEntity.type === 'group') {
|
||||
supported = allowedClusters;
|
||||
}
|
||||
|
||||
const clusters = source.getSimpleDesc().outClusterList.filter((cluster) => {
|
||||
return supported.includes(cluster);
|
||||
});
|
||||
|
||||
// Bind
|
||||
clusters.forEach((cluster) => {
|
||||
this.queue.push((queueCallback) => {
|
||||
logger.debug(`${topic.type}ing cluster '${cluster}' from ${sourceEntity.ID}' to '${targetEntity.ID}'`);
|
||||
|
||||
source[topic.type](cluster, target, (error) => {
|
||||
if (error) {
|
||||
logger.error(
|
||||
`Failed to ${topic.type} cluster '${cluster}' from ${sourceEntity.ID}' to ` +
|
||||
`'${targetEntity.ID}' (${error})`
|
||||
);
|
||||
} else {
|
||||
logger.info(
|
||||
`Successfully ${topic.type === 'bind' ? 'bound' : 'unbound'} cluster '${cluster}' from ` +
|
||||
`${sourceEntity.ID}' to '${targetEntity.ID}'`
|
||||
);
|
||||
|
||||
/**
|
||||
* As the target device is now directly controllled by the source device
|
||||
* zigbee2mqtt won't receive any updates of the target device when directly
|
||||
* changed by the source device.
|
||||
* Configure reporting on the target device.
|
||||
* This is not supported for groups yet.
|
||||
*/
|
||||
if (targetEntity.type === 'device' && topic.type === 'bind') {
|
||||
this.setupReporting(target, cluster);
|
||||
}
|
||||
}
|
||||
|
||||
queueCallback();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setupReporting(ep, cluster) {
|
||||
this.queue.push((queueCallback) => {
|
||||
if (clusteReportCfg[cluster]) {
|
||||
ep.foundation(cluster, 'configReport', [clusteReportCfg[cluster]], foundationCfg, (error) => {
|
||||
if (error) {
|
||||
logger.error(
|
||||
`Failed to setup reporting for cluster '${cluster}' of device '${ep.device.ieeeAddr}'`
|
||||
);
|
||||
} else {
|
||||
logger.info(
|
||||
`Configured reporting for cluster '${cluster}' of device '${ep.device.ieeeAddr}'`
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.warn(`Don't know how to setup reporting for '${cluster}', skipping..`);
|
||||
}
|
||||
|
||||
queueCallback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Bind;
|
||||
@@ -18,6 +18,7 @@ class BridgeConfig {
|
||||
this.devices = this.devices.bind(this);
|
||||
this.rename = this.rename.bind(this);
|
||||
this.remove = this.remove.bind(this);
|
||||
this.ban = this.ban.bind(this);
|
||||
|
||||
// Set supported options
|
||||
this.supportedOptions = {
|
||||
@@ -26,6 +27,7 @@ class BridgeConfig {
|
||||
'devices': this.devices,
|
||||
'rename': this.rename,
|
||||
'remove': this.remove,
|
||||
'ban': this.ban,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,6 +91,14 @@ class BridgeConfig {
|
||||
}
|
||||
|
||||
remove(topic, message) {
|
||||
this.removeOrBan(false, message);
|
||||
}
|
||||
|
||||
ban(topic, message) {
|
||||
this.removeOrBan(true, message);
|
||||
}
|
||||
|
||||
removeOrBan(ban, message) {
|
||||
message = message.toString();
|
||||
const IDByFriendlyName = settings.getIeeeAddrByFriendlyName(message);
|
||||
const deviceID = IDByFriendlyName ? IDByFriendlyName : message;
|
||||
@@ -101,17 +111,17 @@ class BridgeConfig {
|
||||
// Remove from state
|
||||
this.state.remove(deviceID);
|
||||
|
||||
logger.info(`Successfully removed ${deviceID}`);
|
||||
this.mqtt.log('device_removed', message);
|
||||
logger.info(`Successfully ${ban ? 'banned' : 'removed'} ${deviceID}`);
|
||||
this.mqtt.log(ban ? 'device_banned' : 'device_removed', message);
|
||||
};
|
||||
|
||||
// Remove from zigbee network.
|
||||
if (device) {
|
||||
this.zigbee.removeDevice(deviceID, (error) => {
|
||||
this.zigbee.removeDevice(deviceID, ban, (error) => {
|
||||
if (!error) {
|
||||
cleanup();
|
||||
} else {
|
||||
logger.error(`Failed to remove ${deviceID}`);
|
||||
logger.error(`Failed to ${ban ? 'ban' : 'remove'} ${deviceID}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
const zigbeeShepherdConvertersDevices = require('zigbee-shepherd-converters').devices;
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
|
||||
// IKEA TRADFRI remote control
|
||||
const E1524 = zigbeeShepherdConvertersDevices.find((d) => d.model === 'E1524');
|
||||
|
||||
const devices = [E1524];
|
||||
|
||||
/**
|
||||
* This extensions adds the coordinator to a group which is required for some devices to work properly.
|
||||
*/
|
||||
class CoordinatorGroup {
|
||||
constructor(zigbee, mqtt, state, publishDeviceState) {
|
||||
this.zigbee = zigbee;
|
||||
this.mqtt = mqtt;
|
||||
this.state = state;
|
||||
this.publishDeviceState = publishDeviceState;
|
||||
}
|
||||
|
||||
onZigbeeStarted() {
|
||||
this.zigbee.getAllClients().forEach((device) => {
|
||||
devices.forEach((mappedDevice) => {
|
||||
if (mappedDevice.zigbeeModel.includes(device.modelId)) {
|
||||
this.setup(mappedDevice, device);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setup(mappedDevice, device) {
|
||||
const deviceLog = `${mappedDevice.vendor} ${mappedDevice.description} (${device.ieeeAddr})`;
|
||||
|
||||
// Check if there is a coordinator_group defined for this device.
|
||||
const deviceSettings = settings.getDevice(device.ieeeAddr);
|
||||
if (!deviceSettings || !deviceSettings.coordinator_group) {
|
||||
logger.error(
|
||||
`Device ${deviceLog} requires extra configuration!` +
|
||||
` Please see https://github.com/Koenkk/zigbee2mqtt/blob/dev/docs/getting_started/pairing_devices.md`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the coordinator to the group, first check if it's already in the group.
|
||||
const findPayload = {endpoint: 1, groupid: deviceSettings.coordinator_group};
|
||||
this.zigbee.shepherd.controller.request('ZDO', 'extFindGroup', findPayload, (error, data) => {
|
||||
if (error) {
|
||||
const addPayload = {endpoint: 1, groupid: deviceSettings.coordinator_group, namelen: 0, groupname: ''};
|
||||
this.zigbee.shepherd.controller.request('ZDO', 'extAddGroup', addPayload, (error, data) => {
|
||||
if (!error) {
|
||||
logger.info(`Successfully applied coordinator group for ${deviceLog}`);
|
||||
} else {
|
||||
logger.error(`Failed to apply coordinator group for ${deviceLog}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
logger.info(`Successfully applied coordinator group for ${deviceLog}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CoordinatorGroup;
|
||||
@@ -0,0 +1,125 @@
|
||||
const logger = require('../util/logger');
|
||||
const settings = require('../util/settings');
|
||||
const utils = require('../util/utils');
|
||||
const Queue = require('queue');
|
||||
const zigbeeShepherdConverters = require('zigbee-shepherd-converters');
|
||||
|
||||
// Some EndDevices should be pinged
|
||||
// e.g. E11-G13 https://github.com/Koenkk/zigbee2mqtt/issues/775#issuecomment-453683846
|
||||
const pingableDevices = [
|
||||
zigbeeShepherdConverters.devices.find((d) => d.model === 'E11-G13'),
|
||||
];
|
||||
|
||||
/**
|
||||
* This extensions set availability based on optionally polling router devices
|
||||
* and optionally check device publish with attribute reporting
|
||||
*/
|
||||
class DeviceAvailabilityHandler {
|
||||
constructor(zigbee, mqtt, state, publishDeviceState) {
|
||||
this.zigbee = zigbee;
|
||||
this.mqtt = mqtt;
|
||||
this.availability_timeout = settings.get().advanced.availability_timeout;
|
||||
this.timers = {};
|
||||
this.pending = [];
|
||||
|
||||
/**
|
||||
* Setup command queue.
|
||||
* The command queue ensures that only 1 command is executed at a time.
|
||||
* This is to avoid DDoSiNg of the coordinator.
|
||||
*/
|
||||
this.queue = new Queue();
|
||||
this.queue.concurrency = 1;
|
||||
this.queue.autostart = true;
|
||||
}
|
||||
|
||||
isPingable(device) {
|
||||
if (pingableDevices.find((d) => d.zigbeeModel.includes(device.modelId))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return device.type === 'Router' && (device.powerSource && device.powerSource !== 'Battery');
|
||||
}
|
||||
|
||||
getAllPingableDevices() {
|
||||
return this.zigbee.getAllClients().filter((d) => this.isPingable(d));
|
||||
}
|
||||
|
||||
onMQTTConnected() {
|
||||
// As some devices are not checked for availability (e.g. battery powered devices)
|
||||
// we mark all device as online by default.
|
||||
this.zigbee.getDevices()
|
||||
.filter((d) => d.type !== 'Coordinator')
|
||||
.forEach((device) => this.publishAvailability(device.ieeeAddr, true));
|
||||
|
||||
// Start timers for all devices
|
||||
this.getAllPingableDevices().forEach((device) => this.setTimer(device.ieeeAddr));
|
||||
}
|
||||
|
||||
handleInterval(ieeeAddr) {
|
||||
// Check if a job is already pending.
|
||||
// This avoids overflowing of the queue in case the queue is not able to catch-up with the jobs being added.
|
||||
if (this.pending.includes(ieeeAddr)) {
|
||||
logger.debug(`Skipping ping for ${ieeeAddr} becuase job is already in queue`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.pending.push(ieeeAddr);
|
||||
|
||||
this.queue.push((queueCallback) => {
|
||||
this.zigbee.ping(ieeeAddr, (error) => {
|
||||
if (error) {
|
||||
logger.debug(`Failed to ping ${ieeeAddr}`);
|
||||
} else {
|
||||
logger.debug(`Successfully pinged ${ieeeAddr}`);
|
||||
}
|
||||
|
||||
this.publishAvailability(ieeeAddr, !error);
|
||||
|
||||
// Remove from pending jobs.
|
||||
const index = this.pending.indexOf(ieeeAddr);
|
||||
if (index !== -1) {
|
||||
this.pending.splice(index, 1);
|
||||
}
|
||||
|
||||
this.setTimer(ieeeAddr);
|
||||
queueCallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setTimer(ieeeAddr) {
|
||||
if (this.timers[ieeeAddr]) {
|
||||
clearTimeout(this.timers[ieeeAddr]);
|
||||
}
|
||||
|
||||
this.timers[ieeeAddr] = setTimeout(() => {
|
||||
this.handleInterval(ieeeAddr);
|
||||
}, utils.secondsToMilliseconds(this.availability_timeout));
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.queue.stop();
|
||||
|
||||
this.zigbee.getDevices()
|
||||
.filter((d) => d.type !== 'Coordinator')
|
||||
.forEach((device) => this.publishAvailability(device.ieeeAddr, false));
|
||||
}
|
||||
|
||||
publishAvailability(ieeeAddr, available) {
|
||||
const deviceSettings = settings.getDevice(ieeeAddr);
|
||||
const name = deviceSettings ? deviceSettings.friendly_name : ieeeAddr;
|
||||
const topic = `${name}/availability`;
|
||||
const payload = available ? 'online' : 'offline';
|
||||
this.mqtt.publish(topic, payload, {retain: true, qos: 0});
|
||||
}
|
||||
|
||||
onZigbeeMessage(message, device, mappedDevice) {
|
||||
// When a zigbee message from a device is received we know the device is still alive.
|
||||
// => reset the timer.
|
||||
if (device && this.isPingable(this.zigbee.getDevice(device.ieeeAddr))) {
|
||||
this.setTimer(device.ieeeAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DeviceAvailabilityHandler;
|
||||
@@ -32,13 +32,14 @@ class DeviceConfigure {
|
||||
|
||||
if (!this.configured.includes(ieeeAddr) && mappedDevice.configure) {
|
||||
const friendlyName = settings.getDevice(ieeeAddr) ? settings.getDevice(ieeeAddr).friendly_name : 'unknown';
|
||||
logger.debug(`Configuring ${friendlyName} (${ieeeAddr}) ...`);
|
||||
|
||||
// Call configure function of this device.
|
||||
mappedDevice.configure(ieeeAddr, this.zigbee.shepherd, this.zigbee.getCoordinator(), (ok, msg) => {
|
||||
if (ok) {
|
||||
logger.info(`Succesfully configured ${friendlyName} ${ieeeAddr}`);
|
||||
logger.info(`Succesfully configured ${friendlyName} (${ieeeAddr})`);
|
||||
} else {
|
||||
logger.error(`Failed to configure ${friendlyName} ${ieeeAddr}`);
|
||||
logger.error(`Failed to configure ${friendlyName} (${ieeeAddr}) ('${msg}')`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -3,11 +3,20 @@ const settings = require('../util/settings');
|
||||
const zigbeeShepherdConverters = require('zigbee-shepherd-converters');
|
||||
const Queue = require('queue');
|
||||
const logger = require('../util/logger');
|
||||
const utils = require('../util/utils');
|
||||
|
||||
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/.+/(set|get)$`);
|
||||
const postfixes = ['left', 'right', 'center', 'bottom_left', 'bottom_right', 'top_left', 'top_right'];
|
||||
const postfixes = ['left', 'right', 'center', 'bottom_left', 'bottom_right', 'top_left', 'top_right', 'white', 'rgb'];
|
||||
const maxDepth = 20;
|
||||
|
||||
const groupConverters = [
|
||||
zigbeeShepherdConverters.toZigbeeConverters.on_off,
|
||||
zigbeeShepherdConverters.toZigbeeConverters.light_brightness,
|
||||
zigbeeShepherdConverters.toZigbeeConverters.light_colortemp,
|
||||
zigbeeShepherdConverters.toZigbeeConverters.light_color,
|
||||
zigbeeShepherdConverters.toZigbeeConverters.ignore_transition,
|
||||
];
|
||||
|
||||
class DevicePublish {
|
||||
constructor(zigbee, mqtt, state, publishDeviceState) {
|
||||
this.zigbee = zigbee;
|
||||
@@ -61,9 +70,9 @@ class DevicePublish {
|
||||
topic = topic.replace(`/${postfix}`, '');
|
||||
}
|
||||
|
||||
const deviceID = topic;
|
||||
const ID = topic;
|
||||
|
||||
return {type: type, deviceID: deviceID, postfix: postfix};
|
||||
return {type: type, ID: ID, postfix: postfix};
|
||||
}
|
||||
|
||||
onMQTTMessage(topic, message) {
|
||||
@@ -73,22 +82,38 @@ class DevicePublish {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Map friendlyName to ieeeAddr if possible.
|
||||
const ieeeAddr = settings.getIeeeAddrByFriendlyName(topic.deviceID) || topic.deviceID;
|
||||
// Resolve the entity
|
||||
const entity = utils.resolveEntity(topic.ID);
|
||||
|
||||
// Get device
|
||||
const device = this.zigbee.getDevice(ieeeAddr);
|
||||
if (!device) {
|
||||
logger.error(`Failed to find device with ieeAddr: '${ieeeAddr}'`);
|
||||
return;
|
||||
}
|
||||
// Get entity details
|
||||
let endpoint = null;
|
||||
let converters = null;
|
||||
let device = null;
|
||||
|
||||
// Map device to a model
|
||||
const model = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
|
||||
if (!model) {
|
||||
logger.warn(`Device with modelID '${device.modelId}' is not supported.`);
|
||||
logger.warn(`Please see: https://koenkk.github.io/zigbee2mqtt/how_tos/how_to_support_new_devices.html`);
|
||||
return;
|
||||
if (entity.type === 'device') {
|
||||
device = this.zigbee.getDevice(entity.ID);
|
||||
if (!device) {
|
||||
logger.error(`Failed to find device with ieeAddr: '${entity.ID}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Map device to a model
|
||||
const model = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
|
||||
if (!model) {
|
||||
logger.warn(`Device with modelID '${device.modelId}' is not supported.`);
|
||||
logger.warn(`Please see: https://koenkk.github.io/zigbee2mqtt/how_tos/how_to_support_new_devices.html`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine endpoint to publish to.
|
||||
if (model.hasOwnProperty('ep')) {
|
||||
const eps = model.ep(device);
|
||||
endpoint = eps.hasOwnProperty(topic.postfix) ? eps[topic.postfix] : null;
|
||||
}
|
||||
|
||||
converters = model.toZigbee;
|
||||
} else if (entity.type === 'group') {
|
||||
converters = groupConverters;
|
||||
}
|
||||
|
||||
// Convert the MQTT message to a Zigbee message.
|
||||
@@ -100,22 +125,19 @@ class DevicePublish {
|
||||
json = {state: message.toString()};
|
||||
}
|
||||
|
||||
// Determine endpoint to publish to.
|
||||
let endpoint = null;
|
||||
if (model.hasOwnProperty('ep')) {
|
||||
const eps = model.ep(device);
|
||||
endpoint = eps.hasOwnProperty(topic.postfix) ? eps[topic.postfix] : null;
|
||||
}
|
||||
|
||||
// When brightness is present skip state; brightness also handles state.
|
||||
if (json.hasOwnProperty('brightness') && json.hasOwnProperty('state')) {
|
||||
logger.debug(`Skipping 'state' because of 'brightness'`);
|
||||
delete json.state;
|
||||
}
|
||||
|
||||
// Ensure that state and brightness are executed before other commands.
|
||||
const keys = Object.keys(json);
|
||||
keys.sort((a, b) => (['state', 'brightness'].includes(a) ? -1 : 1));
|
||||
|
||||
// For each key in the JSON message find the matching converter.
|
||||
Object.keys(json).forEach((key) => {
|
||||
const converter = model.toZigbee.find((c) => c.key.includes(key));
|
||||
keys.forEach((key) => {
|
||||
const converter = converters.find((c) => c.key.includes(key));
|
||||
if (!converter) {
|
||||
logger.error(`No converter available for '${key}' (${json[key]})`);
|
||||
return;
|
||||
@@ -130,7 +152,8 @@ class DevicePublish {
|
||||
// Add job to queue
|
||||
this.queue.push((queueCallback) => {
|
||||
this.zigbee.publish(
|
||||
ieeeAddr,
|
||||
entity.ID,
|
||||
entity.type,
|
||||
converted.cid,
|
||||
converted.cmd,
|
||||
converted.cmdType,
|
||||
@@ -139,32 +162,34 @@ class DevicePublish {
|
||||
endpoint,
|
||||
(error, rsp) => {
|
||||
// Devices do not report when they go off, this ensures state (on/off) is always in sync.
|
||||
if (topic.type === 'set' && !error && (key.startsWith('state') || key === 'brightness')) {
|
||||
if (entity.type === 'device' && topic.type === 'set' &&
|
||||
!error && (key.startsWith('state') || key.startsWith('brightness'))) {
|
||||
const msg = {};
|
||||
const _key = topic.postfix ? `state_${topic.postfix}` : 'state';
|
||||
msg[_key] = key === 'brightness' ? 'ON' : json['state'];
|
||||
msg[_key] = key.startsWith('brightness') ? 'ON' : json['state'];
|
||||
this.publishDeviceState(device, msg, true);
|
||||
}
|
||||
|
||||
queueCallback();
|
||||
}
|
||||
);
|
||||
|
||||
setTimeout(() => queueCallback(), 100);
|
||||
});
|
||||
|
||||
// When there is a transition in the message the state of the device gets out of sync.
|
||||
// Therefore; at the end of the transition, read the new state from the device.
|
||||
if (topic.type === 'set' && converted.zclData.transtime) {
|
||||
const time = converted.zclData.transtime * 100;
|
||||
const getConverted = converter.convert(json[key], json, 'get');
|
||||
// It's possible for devices to get out of sync when writing an attribute that's not reportable.
|
||||
// So here we re-read the value after a specified timeout, this timeout could for example be the
|
||||
// transition time of a color change.
|
||||
if (topic.type === 'set' && entity.type === 'device'
|
||||
&& converted.hasOwnProperty('readAfterWriteTime') && converted.readAfterWriteTime !== 0) {
|
||||
const getConverted = converter.convert(key, json[key], json, 'get');
|
||||
setTimeout(() => {
|
||||
// Add job to queue
|
||||
this.queue.push((queueCallback) => {
|
||||
this.zigbee.publish(
|
||||
ieeeAddr, getConverted.cid, getConverted.cmd, getConverted.cmdType,
|
||||
entity.ID, entity.type, getConverted.cid, getConverted.cmd, getConverted.cmdType,
|
||||
getConverted.zclData, getConverted.cfg, endpoint, () => queueCallback()
|
||||
);
|
||||
});
|
||||
}, time);
|
||||
}, converted.readAfterWriteTime);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -12,12 +12,22 @@ class DeviceReceive {
|
||||
this.mqtt = mqtt;
|
||||
this.state = state;
|
||||
this.publishDeviceState = publishDeviceState;
|
||||
this.coordinator = null;
|
||||
this.elapsed = {};
|
||||
}
|
||||
|
||||
onZigbeeStarted() {
|
||||
this.coordinator = this.zigbee.getCoordinator().device.ieeeAddr;
|
||||
}
|
||||
|
||||
onZigbeeMessage(message, device, mappedDevice) {
|
||||
if (message.type == 'devInterview' && !settings.getDevice(message.data)) {
|
||||
logger.info('Connecting with device...');
|
||||
this.mqtt.log('pairing', 'connecting with device');
|
||||
if (message.type == 'devInterview') {
|
||||
if (!settings.getDevice(message.data)) {
|
||||
logger.info('Connecting with device...');
|
||||
this.mqtt.log('pairing', 'connecting with device');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type == 'devIncoming') {
|
||||
@@ -30,6 +40,11 @@ class DeviceReceive {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device.ieeeAddr === this.coordinator) {
|
||||
logger.debug('Ignoring message from coordinator');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a new device.
|
||||
if (!settings.getDevice(device.ieeeAddr)) {
|
||||
logger.info(`New device with address ${device.ieeeAddr} connected!`);
|
||||
@@ -84,30 +99,55 @@ class DeviceReceive {
|
||||
// - If a payload is returned publish it to the MQTT broker
|
||||
// - If NO payload is returned do nothing. This is for non-standard behaviour
|
||||
// for e.g. click switches where we need to count number of clicks and detect long presses.
|
||||
converters.forEach((converter) => {
|
||||
const publish = (payload) => {
|
||||
// Don't cache messages with following properties:
|
||||
let cache = true;
|
||||
dontCacheProperties.forEach((property) => {
|
||||
if (payload.hasOwnProperty(property)) {
|
||||
cache = false;
|
||||
}
|
||||
});
|
||||
const publish = (payload) => {
|
||||
// Don't cache messages with following properties:
|
||||
let cache = true;
|
||||
dontCacheProperties.forEach((property) => {
|
||||
if (payload.hasOwnProperty(property)) {
|
||||
cache = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Add device linkquality.
|
||||
if (message.hasOwnProperty('linkquality')) {
|
||||
payload.linkquality = message.linkquality;
|
||||
// Add device linkquality.
|
||||
if (message.hasOwnProperty('linkquality')) {
|
||||
payload.linkquality = message.linkquality;
|
||||
}
|
||||
|
||||
// Add last seen timestamp
|
||||
const now = Date.now();
|
||||
switch (settings.get().advanced.last_seen) {
|
||||
case 'ISO_8601':
|
||||
payload.last_seen = new Date(now).toISOString();
|
||||
break;
|
||||
case 'epoch':
|
||||
payload.last_seen = now;
|
||||
break;
|
||||
}
|
||||
|
||||
if (settings.get().advanced.elapsed) {
|
||||
if (this.elapsed[device.ieeeAddr]) {
|
||||
payload.elapsed = now - this.elapsed[device.ieeeAddr];
|
||||
}
|
||||
|
||||
this.publishDeviceState(device, payload, cache);
|
||||
};
|
||||
this.elapsed[device.ieeeAddr] = now;
|
||||
}
|
||||
|
||||
const payload = converter.convert(mappedDevice, message, publish, settings.getDevice(device.ieeeAddr));
|
||||
this.publishDeviceState(device, payload, cache);
|
||||
};
|
||||
|
||||
if (payload) {
|
||||
publish(payload);
|
||||
let payload = {};
|
||||
converters.forEach((converter) => {
|
||||
const options = {...settings.get().device_options, ...settings.getDevice(device.ieeeAddr)};
|
||||
const converted = converter.convert(mappedDevice, message, publish, options);
|
||||
|
||||
if (converted) {
|
||||
payload = {...payload, ...converted};
|
||||
}
|
||||
});
|
||||
|
||||
if (Object.keys(payload).length) {
|
||||
publish(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
|
||||
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/.+/(remove|add|remove_all)$`);
|
||||
|
||||
class Groups {
|
||||
constructor(zigbee, mqtt, state, publishDeviceState) {
|
||||
this.zigbee = zigbee;
|
||||
this.mqtt = mqtt;
|
||||
this.state = state;
|
||||
this.publishDeviceState = publishDeviceState;
|
||||
}
|
||||
|
||||
onMQTTConnected() {
|
||||
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/+/remove`);
|
||||
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/+/add`);
|
||||
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/+/remove_all`);
|
||||
}
|
||||
|
||||
parseTopic(topic) {
|
||||
if (!topic.match(topicRegex)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove base from topic
|
||||
topic = topic.replace(`${settings.get().mqtt.base_topic}/bridge/group/`, '');
|
||||
|
||||
// Parse type from topic
|
||||
const type = topic.substr(topic.lastIndexOf('/') + 1, topic.length);
|
||||
|
||||
// Remove type from topic
|
||||
topic = topic.replace(`/${type}`, '');
|
||||
|
||||
return {friendly_name: topic, type: type};
|
||||
}
|
||||
|
||||
onMQTTMessage(topic, message) {
|
||||
topic = this.parseTopic(topic);
|
||||
|
||||
if (!topic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find ID of this group.
|
||||
const groupID = settings.getGroupIDByFriendlyName(topic.friendly_name);
|
||||
if (!groupID) {
|
||||
logger.error(`Group with friendly_name '${topic.friendly_name}' doesn't exist`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Map message to ieeeAddr and check if device exist.
|
||||
message = message.toString();
|
||||
const ieeeAddr = settings.getIeeeAddrByFriendlyName(message) || message;
|
||||
if (!this.zigbee.getDevice(ieeeAddr)) {
|
||||
logger.error(`Failed to find device '${message}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send command to the device.
|
||||
let payload = null;
|
||||
let cmd = null;
|
||||
if (topic.type === 'add') {
|
||||
payload = {groupid: groupID, groupname: ''};
|
||||
cmd = 'add';
|
||||
} else if (topic.type === 'remove') {
|
||||
payload = {groupid: groupID};
|
||||
cmd = 'remove';
|
||||
} else if (topic.type === 'remove_all') {
|
||||
payload = {};
|
||||
cmd = 'removeAll';
|
||||
}
|
||||
|
||||
const callback = (error, rsp) => {
|
||||
if (error) {
|
||||
logger.error(`Failed to ${topic.type} ${ieeeAddr} from ${topic.friendly_name}`);
|
||||
} else {
|
||||
logger.info(`Successfully ${topic.type} ${ieeeAddr} to ${topic.friendly_name}`);
|
||||
}
|
||||
};
|
||||
|
||||
this.zigbee.publish(
|
||||
ieeeAddr, 'device', 'genGroups', cmd, 'functional',
|
||||
payload, null, null, callback,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Groups;
|
||||
@@ -84,7 +84,6 @@ const configurations = {
|
||||
unit_of_measurement: 'lx',
|
||||
device_class: 'illuminance',
|
||||
value_template: '{{ value_json.illuminance }}',
|
||||
json_attributes: ['linkquality', 'battery', 'voltage'],
|
||||
},
|
||||
},
|
||||
'sensor_humidity': {
|
||||
@@ -94,7 +93,6 @@ const configurations = {
|
||||
unit_of_measurement: '%',
|
||||
device_class: 'humidity',
|
||||
value_template: '{{ value_json.humidity }}',
|
||||
json_attributes: ['linkquality', 'battery', 'voltage'],
|
||||
},
|
||||
},
|
||||
'sensor_temperature': {
|
||||
@@ -104,7 +102,6 @@ const configurations = {
|
||||
unit_of_measurement: '°C',
|
||||
device_class: 'temperature',
|
||||
value_template: '{{ value_json.temperature }}',
|
||||
json_attributes: ['linkquality', 'battery', 'voltage'],
|
||||
},
|
||||
},
|
||||
'sensor_pressure': {
|
||||
@@ -114,7 +111,6 @@ const configurations = {
|
||||
unit_of_measurement: 'hPa',
|
||||
device_class: 'pressure',
|
||||
value_template: '{{ value_json.pressure }}',
|
||||
json_attributes: ['linkquality', 'battery', 'voltage'],
|
||||
},
|
||||
},
|
||||
'sensor_click': {
|
||||
@@ -123,7 +119,6 @@ const configurations = {
|
||||
discovery_payload: {
|
||||
icon: 'mdi:toggle-switch',
|
||||
value_template: '{{ value_json.click }}',
|
||||
json_attributes: ['linkquality', 'battery', 'voltage', 'action', 'duration'],
|
||||
force_update: true,
|
||||
},
|
||||
},
|
||||
@@ -134,7 +129,6 @@ const configurations = {
|
||||
unit_of_measurement: 'Watt',
|
||||
icon: 'mdi:flash',
|
||||
value_template: '{{ value_json.power }}',
|
||||
json_attributes: ['linkquality', 'voltage', 'temperature', 'consumption', 'current', 'power_factor'],
|
||||
},
|
||||
},
|
||||
'sensor_action': {
|
||||
@@ -143,10 +137,6 @@ const configurations = {
|
||||
discovery_payload: {
|
||||
icon: 'mdi:gesture-double-tap',
|
||||
value_template: '{{ value_json.action }}',
|
||||
json_attributes: [
|
||||
'linkquality', 'battery', 'voltage', 'angle', 'side', 'from_side', 'to_side', 'brightness',
|
||||
'angle_x_absolute', 'angle_y_absolute', 'angle_z', 'angle_y', 'angle_x', 'unknown_data',
|
||||
],
|
||||
force_update: true,
|
||||
},
|
||||
},
|
||||
@@ -157,7 +147,6 @@ const configurations = {
|
||||
unit_of_measurement: 'brightness',
|
||||
icon: 'mdi:brightness-5',
|
||||
value_template: '{{ value_json.brightness }}',
|
||||
json_attributes: ['linkquality'],
|
||||
},
|
||||
},
|
||||
'sensor_lock': {
|
||||
@@ -166,24 +155,39 @@ const configurations = {
|
||||
discovery_payload: {
|
||||
icon: 'mdi:lock',
|
||||
value_template: '{{ value_json.inserted }}',
|
||||
json_attributes: ['linkquality', 'forgotten', 'keyerror'],
|
||||
},
|
||||
},
|
||||
'sensor_battery': {
|
||||
type: 'sensor',
|
||||
object_id: 'battery',
|
||||
discovery_payload: {
|
||||
unit_of_measurement: '%',
|
||||
device_class: 'battery',
|
||||
value_template: '{{ value_json.battery }}',
|
||||
json_attributes: ['linkquality', 'voltage', 'action', 'sensitivity'],
|
||||
},
|
||||
},
|
||||
'sensor_linkquality': {
|
||||
type: 'sensor',
|
||||
object_id: 'linkquality',
|
||||
discovery_payload: {
|
||||
unit_of_measurement: '-',
|
||||
value_template: '{{ value_json.linkquality }}',
|
||||
json_attributes: ['description', 'type', 'rssi'],
|
||||
},
|
||||
},
|
||||
'sensor_gas_density': {
|
||||
type: 'sensor',
|
||||
object_id: 'gas_density',
|
||||
discovery_payload: {
|
||||
value_template: '{{ value_json.gas_density }}',
|
||||
icon: 'mdi:google-circles-communities',
|
||||
},
|
||||
},
|
||||
'sensor_cover': {
|
||||
type: 'sensor',
|
||||
object_id: 'cover',
|
||||
discovery_payload: {
|
||||
value_template: '{{ value_json.position }}',
|
||||
icon: 'mdi:view-array',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -240,6 +244,16 @@ const configurations = {
|
||||
command_topic: true,
|
||||
},
|
||||
},
|
||||
|
||||
// Cover
|
||||
'cover': {
|
||||
type: 'cover',
|
||||
object_id: 'cover',
|
||||
discovery_payload: {
|
||||
command_topic: true,
|
||||
optimistic: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const switchWithPostfix = (postfix) => {
|
||||
@@ -252,22 +266,24 @@ const switchWithPostfix = (postfix) => {
|
||||
value_template: `{{ value_json.state_${postfix} }}`,
|
||||
command_topic: true,
|
||||
command_topic_prefix: postfix,
|
||||
json_attributes: ['linkquality', `button_${postfix}`],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// Map homeassitant configurations to devices.
|
||||
const mapping = {
|
||||
'WXKG01LM': [configurations.sensor_click],
|
||||
'WXKG11LM': [configurations.sensor_click],
|
||||
'WXKG12LM': [configurations.sensor_click],
|
||||
'WXKG03LM': [configurations.sensor_click],
|
||||
'WXKG02LM': [configurations.sensor_click],
|
||||
'WXKG01LM': [configurations.sensor_click, configurations.sensor_battery],
|
||||
'WXKG11LM': [configurations.sensor_click, configurations.sensor_battery],
|
||||
'WXKG12LM': [configurations.sensor_click, configurations.sensor_battery],
|
||||
'WXKG03LM': [configurations.sensor_click, configurations.sensor_battery],
|
||||
'WXKG02LM': [configurations.sensor_click, configurations.sensor_battery],
|
||||
'QBKG04LM': [configurations.switch],
|
||||
'QBKG03LM': [switchWithPostfix('left'), switchWithPostfix('right')],
|
||||
'WSDCGQ01LM': [configurations.sensor_temperature, configurations.sensor_humidity],
|
||||
'WSDCGQ11LM': [configurations.sensor_temperature, configurations.sensor_humidity, configurations.sensor_pressure],
|
||||
'WSDCGQ01LM': [configurations.sensor_temperature, configurations.sensor_humidity, configurations.sensor_battery],
|
||||
'WSDCGQ11LM': [
|
||||
configurations.sensor_temperature, configurations.sensor_humidity, configurations.sensor_pressure,
|
||||
configurations.sensor_battery,
|
||||
],
|
||||
'RTCGQ01LM': [configurations.binary_sensor_occupancy, configurations.sensor_battery],
|
||||
'RTCGQ11LM': [
|
||||
configurations.binary_sensor_occupancy, configurations.sensor_illuminance,
|
||||
@@ -276,7 +292,7 @@ const mapping = {
|
||||
'MCCGQ01LM': [configurations.binary_sensor_contact, configurations.sensor_battery],
|
||||
'MCCGQ11LM': [configurations.binary_sensor_contact, configurations.sensor_battery],
|
||||
'SJCGQ11LM': [configurations.binary_sensor_water_leak, configurations.sensor_battery],
|
||||
'MFKZQ01LM': [configurations.sensor_action],
|
||||
'MFKZQ01LM': [configurations.sensor_action, configurations.sensor_battery],
|
||||
'ZNCZ02LM': [configurations.switch, configurations.sensor_power],
|
||||
'QBCZ11LM': [configurations.switch, configurations.sensor_power],
|
||||
'LED1545G12': [configurations.light_brightness_colortemp],
|
||||
@@ -295,6 +311,7 @@ const mapping = {
|
||||
'4058075816718': [configurations.light_brightness_colortemp_colorxy],
|
||||
'AA69697': [configurations.light_brightness_colortemp_colorxy],
|
||||
'HALIGHTDIMWWE27': [configurations.light_brightness],
|
||||
'HALIGHTDIMWWB22': [configurations.light_brightness],
|
||||
'AB3257001NJ': [configurations.switch],
|
||||
'8718696449691': [configurations.light_brightness],
|
||||
'RB 185 C': [configurations.light_brightness_colortemp_colorxy],
|
||||
@@ -304,7 +321,7 @@ const mapping = {
|
||||
'73742': [configurations.light_brightness_colortemp],
|
||||
'73740': [configurations.light_brightness_colortemp],
|
||||
'22670': [configurations.light_brightness],
|
||||
'ICTC-G-1': [configurations.sensor_brightness],
|
||||
'ICTC-G-1': [configurations.sensor_brightness, configurations.sensor_battery],
|
||||
'ICPSHC24-30EU-IL-1': [configurations.light_brightness],
|
||||
'45852GE': [configurations.light_brightness],
|
||||
'E11-G13': [configurations.light_brightness],
|
||||
@@ -314,6 +331,7 @@ const mapping = {
|
||||
'L1527': [configurations.light_brightness_colortemp],
|
||||
'L1529': [configurations.light_brightness_colortemp],
|
||||
'L1528': [configurations.light_brightness_colortemp],
|
||||
'L1531': [configurations.light_brightness_colortemp],
|
||||
'RB 165': [configurations.light_brightness],
|
||||
'RB 175 W': [configurations.light_brightness],
|
||||
'RS 125': [configurations.light_brightness],
|
||||
@@ -340,7 +358,7 @@ const mapping = {
|
||||
'8718696598283': [configurations.light_brightness_colortemp],
|
||||
'8718696695203': [configurations.light_brightness_colortemp],
|
||||
'73693': [configurations.light_brightness_colortemp_colorxy],
|
||||
'324131092621': [configurations.sensor_action],
|
||||
'324131092621': [configurations.sensor_action, configurations.sensor_battery],
|
||||
'9290012607': [
|
||||
configurations.binary_sensor_occupancy, configurations.sensor_temperature,
|
||||
configurations.sensor_illuminance, configurations.sensor_battery,
|
||||
@@ -348,8 +366,10 @@ const mapping = {
|
||||
'GL-C-008': [configurations.light_brightness_colortemp_colorxy],
|
||||
'STSS-MULT-001': [configurations.binary_sensor_contact, configurations.sensor_battery],
|
||||
'E11-G23/E11-G33': [configurations.light_brightness],
|
||||
'E1ACA4ABE38A': [configurations.light_brightness],
|
||||
'AC03645': [configurations.light_brightness_colortemp_colorxy],
|
||||
'AC03641': [configurations.light_brightness],
|
||||
'AC03648': [configurations.light_brightness_colortemp],
|
||||
'FB56+ZSW05HG1.2': [configurations.switch],
|
||||
'72922-A': [configurations.switch],
|
||||
'AC03642': [configurations.light_brightness_colortemp],
|
||||
@@ -366,7 +386,10 @@ const mapping = {
|
||||
'Z01-CIA19NAE26': [configurations.light_brightness],
|
||||
'E11-N1EA': [configurations.light_brightness_colortemp_colorxy],
|
||||
'74283': [configurations.light_brightness],
|
||||
'JTQJ-BF-01LM/BW': [configurations.binary_sensor_gas, configurations.sensor_battery],
|
||||
'JTQJ-BF-01LM/BW': [
|
||||
configurations.binary_sensor_gas, configurations.sensor_battery,
|
||||
configurations.sensor_gas_density,
|
||||
],
|
||||
'50045': [configurations.light_brightness],
|
||||
'AV2010/22': [configurations.binary_sensor_occupancy, configurations.sensor_battery],
|
||||
'3210-L': [configurations.switch],
|
||||
@@ -377,7 +400,8 @@ const mapping = {
|
||||
'A6121': [configurations.sensor_lock],
|
||||
'433714': [configurations.light_brightness],
|
||||
'3261030P7': [configurations.light_brightness_colortemp],
|
||||
'DJT11LM': [configurations.sensor_action],
|
||||
'3216431P5': [configurations.light_brightness_colortemp],
|
||||
'DJT11LM': [configurations.sensor_action, configurations.sensor_battery],
|
||||
'E1603': [configurations.switch],
|
||||
'7199960PH': [configurations.light_brightness_colorxy],
|
||||
'74696': [configurations.light_brightness],
|
||||
@@ -412,6 +436,48 @@ const mapping = {
|
||||
'HS1DS': [configurations.binary_sensor_contact],
|
||||
'HS1WL': [configurations.binary_sensor_water_leak],
|
||||
'421786': [configurations.light_brightness],
|
||||
'ICZB-IW11D': [configurations.light_brightness],
|
||||
'HGZB-01A': [configurations.light_brightness],
|
||||
'3321-S': [configurations.binary_sensor_contact, configurations.sensor_temperature],
|
||||
'ZPIR-8000': [configurations.binary_sensor_occupancy],
|
||||
'ZCTS-808': [configurations.binary_sensor_contact],
|
||||
'ZNLDP12LM': [configurations.light_brightness_colortemp],
|
||||
'D1821': [configurations.light_brightness_colortemp_colorxy],
|
||||
'ZNCLDJ11LM': [configurations.cover, configurations.sensor_cover],
|
||||
'LTFY004': [configurations.light_brightness_colorxy],
|
||||
'GL-S-007Z': [configurations.light_brightness_colortemp_colorxy],
|
||||
'3325-S': [configurations.sensor_temperature, configurations.binary_sensor_occupancy],
|
||||
'4713407': [configurations.light_brightness],
|
||||
'464800': [configurations.light_brightness_colortemp],
|
||||
'3261331P7': [configurations.light_brightness_colortemp],
|
||||
'GL-B-008Z': [configurations.light_brightness_colortemp_colorxy],
|
||||
'AV2010/25': [configurations.switch, configurations.sensor_power],
|
||||
'E12-N14': [configurations.light_brightness],
|
||||
'1TST-EU': [],
|
||||
'RB 178 T': [configurations.light_brightness_colortemp],
|
||||
'45856GE': [configurations.switch],
|
||||
'GL-D-003Z': [configurations.light_brightness_colortemp_colorxy],
|
||||
'GD-CZ-006': [configurations.light_brightness],
|
||||
'AIRAM-CTR.U': [],
|
||||
'HGZB-20-DE': [configurations.switch],
|
||||
'D1531': [configurations.light_brightness],
|
||||
'D1532': [configurations.light_brightness],
|
||||
'AV2010/32': [],
|
||||
'HGZB-07A': [configurations.light_brightness_colortemp_colorxy],
|
||||
'E1524': [configurations.sensor_action],
|
||||
'GL-C-006': [configurations.light_brightness_colortemp],
|
||||
'100.424.11': [configurations.light_brightness_colortemp],
|
||||
'AC0251100NJ': [configurations.sensor_click, configurations.sensor_brightness, configurations.sensor_battery],
|
||||
'71831': [configurations.light_brightness_colortemp],
|
||||
'404000/404005/404012': [configurations.light_brightness_colortemp_colorxy],
|
||||
'404006/404008/404004': [configurations.light_brightness_colortemp],
|
||||
'GL-S-003Z': [configurations.light_brightness_colortemp_colorxy],
|
||||
'HS1DS-E': [configurations.binary_sensor_contact],
|
||||
'SP600': [configurations.switch, configurations.sensor_power],
|
||||
'1613V': [configurations.switch, configurations.sensor_power],
|
||||
'XVV-Mega23M12': [configurations.light_brightness_colortemp],
|
||||
'GL-B-007Z': [configurations.light_brightness_colortemp_colorxy],
|
||||
'81809': [configurations.light_brightness_colortemp_colorxy],
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -457,7 +523,12 @@ class HomeAssistant {
|
||||
const topic = `${config.type}/${ieeeAddr}/${config.object_id}/config`;
|
||||
const payload = {...config.discovery_payload};
|
||||
payload.state_topic = `${settings.get().mqtt.base_topic}/${friendlyName}`;
|
||||
payload.availability_topic = `${settings.get().mqtt.base_topic}/bridge/state`;
|
||||
|
||||
// Set json_attributes_topic for types which support this
|
||||
// https://github.com/Koenkk/zigbee2mqtt/issues/840
|
||||
if (['binary_sensor', 'sensor'].includes(config.type)) {
|
||||
payload.json_attributes_topic = payload.state_topic;
|
||||
}
|
||||
|
||||
// Set (unique) name
|
||||
payload.name = `${friendlyName}_${config.object_id}`;
|
||||
@@ -474,6 +545,24 @@ class HomeAssistant {
|
||||
manufacturer: mappedModel.vendor,
|
||||
};
|
||||
|
||||
// Set availability payload
|
||||
// When using availability_timeout each device has it's own availability topic.
|
||||
// If not, use the availability topic of zigbee2mqtt.
|
||||
if (settings.get().advanced.availability_timeout) {
|
||||
payload.availability_topic = `${settings.get().mqtt.base_topic}/${friendlyName}/availability`;
|
||||
} else {
|
||||
payload.availability_topic = `${settings.get().mqtt.base_topic}/bridge/state`;
|
||||
}
|
||||
|
||||
// Add precision to value_template
|
||||
if (settings.getDevice(ieeeAddr).hasOwnProperty(`${config.object_id}_precision`)) {
|
||||
const precision = settings.getDevice(ieeeAddr)[`${config.object_id}_precision`];
|
||||
let template = payload.value_template;
|
||||
template = template.replace('{{ ', '').replace(' }}', '');
|
||||
template = `{{ (${template} | float) | round(${precision}) }}`;
|
||||
payload.value_template = template;
|
||||
}
|
||||
|
||||
if (payload.command_topic) {
|
||||
payload.command_topic = `${settings.get().mqtt.base_topic}/${friendlyName}/`;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class NetworkMap {
|
||||
|
||||
graphviz(zigbee, topology) {
|
||||
let text = 'digraph G {\nnode[shape=record];\n';
|
||||
const lqiDevices = new Map(topology.map((d) => [d.ieeeAddr, d]));
|
||||
let devStyle = '';
|
||||
|
||||
zigbee.getDevices().forEach((device) => {
|
||||
const labels = [];
|
||||
@@ -68,18 +68,27 @@ class NetworkMap {
|
||||
// Add the device status (online/offline)
|
||||
labels.push(device.status);
|
||||
|
||||
// Shape the record according to device type
|
||||
if (device.type == 'Coordinator') {
|
||||
devStyle = 'style="bold"';
|
||||
} else if (device.type == 'Router') {
|
||||
devStyle = 'style="rounded"';
|
||||
} else {
|
||||
devStyle = 'style="rounded, dashed"';
|
||||
}
|
||||
|
||||
// Add the device with its labels to the graph as a node.
|
||||
text += ` "${device.ieeeAddr}" [label="{${labels.join('|')}}"];\n`;
|
||||
text += ` "${device.ieeeAddr}" [`+devStyle+`, label="{${labels.join('|')}}"];\n`;
|
||||
|
||||
/**
|
||||
* Add an edge between the device and its parent to the graph
|
||||
* NOTE: There are situations where a device is NOT in the topology, this can be e.g.
|
||||
* due to not responded to the lqi scan. In that case we do not add an edge for this device.
|
||||
*/
|
||||
const lqiDevice = lqiDevices.get(device.ieeeAddr);
|
||||
if (lqiDevice != undefined) {
|
||||
text += ` "${device.ieeeAddr}" -> "${lqiDevice.parent}" [label="${lqiDevice.lqi}"]\n`;
|
||||
}
|
||||
topology.filter((e) => e.ieeeAddr === device.ieeeAddr).forEach((e) => {
|
||||
const lineStyle = (e.lqi==0) ? `style="dashed", ` : ``;
|
||||
text += ` "${device.ieeeAddr}" -> "${e.parent}" [`+lineStyle+`label="${e.lqi}"]\n`;
|
||||
});
|
||||
});
|
||||
|
||||
text += '}';
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const utils = require('../util/utils');
|
||||
const interval = utils.secondsToMilliseconds(60);
|
||||
const Queue = require('queue');
|
||||
const logger = require('../util/logger');
|
||||
|
||||
/**
|
||||
* This extensions polls Xiaomi Zigbee routers to keep them awake.
|
||||
@@ -8,6 +10,15 @@ class RouterPollXiaomi {
|
||||
constructor(zigbee, mqtt, state, publishDeviceState) {
|
||||
this.zigbee = zigbee;
|
||||
this.timer = null;
|
||||
|
||||
/**
|
||||
* Setup command queue.
|
||||
* The command queue ensures that only 1 command is executed at a time.
|
||||
* This is to avoid DDoSiNg of the coordinator.
|
||||
*/
|
||||
this.queue = new Queue();
|
||||
this.queue.concurrency = 1;
|
||||
this.queue.autostart = true;
|
||||
}
|
||||
|
||||
onZigbeeStarted() {
|
||||
@@ -27,15 +38,30 @@ class RouterPollXiaomi {
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.queue.stop();
|
||||
this.clearTimer();
|
||||
}
|
||||
|
||||
ping(ieeeAddr) {
|
||||
this.queue.push((queueCallback) => {
|
||||
this.zigbee.ping(ieeeAddr, (error) => {
|
||||
if (error) {
|
||||
logger.debug(`Failed to ping ${ieeeAddr}`);
|
||||
} else {
|
||||
logger.debug(`Successfully pinged ${ieeeAddr}`);
|
||||
}
|
||||
|
||||
queueCallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleInterval() {
|
||||
this.zigbee.getAllClients()
|
||||
.filter((d) => utils.isXiaomiDevice(d)) // Filter Xiaomi devices
|
||||
.filter((d) => d.type === 'Router') // Filter routers
|
||||
.filter((d) => d.powerSource && d.powerSource !== 'Battery') // Remove battery powered devices
|
||||
.forEach((d) => this.zigbee.ping(d.ieeeAddr)); // Ping devices.
|
||||
.forEach((d) => this.ping(d.ieeeAddr)); // Ping devices.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ const defaults = {
|
||||
mqtt: {
|
||||
include_device_information: false,
|
||||
},
|
||||
groups: {},
|
||||
device_options: {},
|
||||
advanced: {
|
||||
log_directory: path.join(data.getPath(), 'log', '%TIMESTAMP%'),
|
||||
log_level: process.env.DEBUG ? 'debug' : 'info',
|
||||
@@ -19,6 +21,9 @@ const defaults = {
|
||||
baudrate: 115200,
|
||||
rtscts: true,
|
||||
|
||||
// Availability timeout in seconds, disabled by default.
|
||||
availability_timeout: 0,
|
||||
|
||||
/**
|
||||
* Home Assistant requires ALL attributes to be present in ALL MQTT messages send by the device.
|
||||
* https://community.home-assistant.io/t/missing-value-with-mqtt-only-last-data-set-is-shown/47070/9
|
||||
@@ -28,6 +33,25 @@ const defaults = {
|
||||
* https://koenkk.github.io/zigbee2mqtt/configuration/configuration.html
|
||||
*/
|
||||
cache_state: true,
|
||||
|
||||
/**
|
||||
* Add a last_seen attribute to mqtt messages, contains date/time of zigbee message arrival
|
||||
* "ISO_8601": ISO 8601 format
|
||||
* "epoch": milliseconds elapsed since the UNIX epoch
|
||||
* "disable": no last_seen attribute (default)
|
||||
*/
|
||||
last_seen: 'disable',
|
||||
|
||||
// Optional: Add an elapsed attribute to MQTT messages, contains milliseconds since the previous msg
|
||||
elapsed: false,
|
||||
|
||||
/**
|
||||
* https://github.com/Koenkk/zigbee2mqtt/issues/685#issuecomment-449112250
|
||||
*
|
||||
* Network key will serve as the encryption key of your network.
|
||||
* Changing this will require you to repair your devices.
|
||||
*/
|
||||
network_key: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -72,6 +96,16 @@ function getIeeeAddrByFriendlyName(friendlyName) {
|
||||
);
|
||||
}
|
||||
|
||||
function getGroupIDByFriendlyName(friendlyName) {
|
||||
if (!settings.groups) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Object.keys(settings.groups).find((ID) =>
|
||||
settings.groups[ID].friendly_name === friendlyName
|
||||
);
|
||||
}
|
||||
|
||||
function changeFriendlyName(old, new_) {
|
||||
const ieeeAddr = getIeeeAddrByFriendlyName(old);
|
||||
|
||||
@@ -93,5 +127,6 @@ module.exports = {
|
||||
removeDevice: (ieeeAddr) => removeDevice(ieeeAddr),
|
||||
|
||||
getIeeeAddrByFriendlyName: (friendlyName) => getIeeeAddrByFriendlyName(friendlyName),
|
||||
getGroupIDByFriendlyName: (friendlyName) => getGroupIDByFriendlyName(friendlyName),
|
||||
changeFriendlyName: (old, new_) => changeFriendlyName(old, new_),
|
||||
};
|
||||
|
||||