Compare commits

...
2065 Commits
Author SHA1 Message Date
Koen Kanters 7e63039144 chore(dev): release 1.33.1 (#19104) 2023-10-03 11:09:57 +02:00
Koen KantersandKoenkk b990ed9a60 fix(ignore): update zigbee-herdsman-converters to 15.86.1 (#19150)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-10-03 11:01:54 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ccc0f7ce53 chore: Bump alpine from 3.18.3 to 3.18.4 in /docker (#19116)
Bumps alpine from 3.18.3 to 3.18.4.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 10:58:37 +02:00
Rotzbua 83e331323c fix: Correct typos (#19143)
Credit to `codespell`.
2023-10-03 10:54:13 +02:00
Koen KantersandKoenkk 45ce494951 fix(ignore): update zigbee-herdsman-converters to 15.86.0 (#19149)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-10-03 08:45:18 +00:00
Koen KantersandKoenkk 1c7bb8fc24 fix(ignore): update dependencies (#19127)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-10-03 10:38:48 +02:00
Koen KantersandKoenkk 90763fd83f fix(ignore): update zigbee-herdsman-converters to 15.85.0 (#19102)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-28 10:42:33 +00:00
Koen KantersandKoenkk 7ccb4bcafe fix(ignore): update zigbee-herdsman-converters to 15.84.0 (#19096)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-27 18:59:28 +00:00
Koen KantersandKoenkk a7bb3fc9e8 fix(ignore): update zigbee-herdsman-converters to 15.83.0 (#19088)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-26 18:07:53 +00:00
Koen KantersandKoenkk 1190a342e9 fix(ignore): update zigbee-herdsman-converters to 15.82.0 (#19067)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-24 18:19:07 +00:00
Koen Kanters 31e4e8c552 chore: merge master to dev 2023-09-24 19:49:20 +02:00
koenkk 4d53ac4c84 chore: fix dev branch changelog link https://github.com/Koenkk/zigbee2mqtt/issues/19062 2023-09-24 19:48:55 +02:00
Koen KantersandKoenkk d99da63b89 fix(ignore): update dependencies (#19061)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-24 07:42:03 +02:00
Koen KantersandKoenkk 9a7aeaf62b fix(ignore): update zigbee-herdsman-converters to 15.81.1 (#19041)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-21 18:42:24 +00:00
Koen Kantersandnurikk 9b66ab1367 fix(ignore): update zigbee2mqtt-frontend to 0.6.136 (#19040)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-09-21 18:32:32 +00:00
Koen KantersandKoenkk e3d1c63463 Update zigbee-herdsman-converters to 15.81.0 (#19032)
* fix(ignore): update zigbee-herdsman-converters to 15.81.0

* fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-20 18:27:44 +00:00
Koen KantersandKoenkk af209b6f53 fix(ignore): update zigbee-herdsman-converters to 15.80.0 (#19023)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-19 18:14:44 +00:00
Koen KantersandKoenkk 7b558fef5f Update zigbee-herdsman-converters to 15.79.0 (#19003)
* fix(ignore): update zigbee-herdsman-converters to 15.79.0

* fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-18 17:35:36 +00:00
Koen KantersandKoenkk eac9240e06 fix(ignore): update zigbee-herdsman-converters to 15.78.0 (#18999)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-17 07:17:19 +00:00
Koen KantersandKoenkk 84f9950556 fix(ignore): update zigbee-herdsman to 0.19.0 (#18998)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-17 07:00:37 +00:00
Koen KantersandKoenkk 5477163727 fix(ignore): update dependencies (#18995)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-17 08:46:52 +02:00
Koen KantersandKoenkk 0a69bb54c8 fix(ignore): update zigbee-herdsman-converters to 15.77.0 (#18984)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-16 07:21:58 +00:00
Koen KantersandKoenkk 4040840d8e fix(ignore): update zigbee-herdsman-converters to 15.76.0 (#18978)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-14 19:16:23 +00:00
Koen KantersandKoenkk cc95c85969 fix(ignore): update zigbee-herdsman-converters to 15.75.0 (#18972)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-13 17:58:34 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 3b64ea9d92 chore: Bump docker/setup-qemu-action from 2 to 3 (#18956)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 19:44:07 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 08a1468dda chore: Bump docker/setup-buildx-action from 2 to 3 (#18955)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 19:43:43 +02:00
Koen KantersandKoenkk 6de7662ca8 fix(ignore): update zigbee-herdsman-converters to 15.74.0 (#18949)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-11 18:18:48 +00:00
Koen KantersandKoenkk 4daddfc5f7 Update dependencies (#18923)
* fix(ignore): update dependencies

* fix types/node

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-10 09:28:14 +02:00
Koen KantersandKoenkk d6ed0f45da fix(ignore): update zigbee-herdsman-converters to 15.73.0 (#18917)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-09 06:47:11 +00:00
Koen KantersandKoenkk ea8de2ba1e fix(ignore): update zigbee-herdsman-converters to 15.72.0 (#18901)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-07 19:00:33 +00:00
Koen KantersandKoenkk f509410189 fix(ignore): update zigbee-herdsman-converters to 15.71.0 (#18887)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-06 18:39:23 +00:00
Koen KantersandKoenkk 91a9e32a83 fix(ignore): update zigbee-herdsman-converters to 15.70.0 (#18866)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-04 19:00:31 +00:00
Koen KantersandKoenkk 914b4c6757 fix(ignore): update zigbee-herdsman to 0.18.7 (#18865)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-04 18:43:08 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 03f381fdc2 chore: Bump actions/checkout from 3 to 4 (#18863)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 20:09:44 +02:00
Koen KantersandKoenkk 3285850efa fix(ignore): update zigbee-herdsman-converters to 15.69.0 (#18835)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-03 06:54:30 +00:00
Koen KantersandKoenkk 6654c7f1a3 fix(ignore): update zigbee-herdsman to 0.18.6 (#18838)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-02 07:17:04 +00:00
Koen Kanters d280e5ef2b chore: merge master to dev 2023-09-02 09:08:31 +02:00
rbswift f224ef7b7c chore: Improve update script in case of local changes (#18837)
* Stash local changes to prevent update failing

Call git stash to stash any local changes that would prevent the update.sh script from failing

* Update update.sh

changed to git checkout package-lock.json
2023-09-02 09:08:09 +02:00
Koen Kanters 0543ad4b19 fix: Fix configuration.example.yaml missing from container (#18836) 2023-09-02 08:51:50 +02:00
koenkk 9165bbb7b4 chore: bump release-please bootstrap-sha 2023-09-02 08:50:33 +02:00
koenkk f4ef421d27 chore: promote to dev 2023-09-01 16:05:15 +02:00
Koen Kanters 7ee207fc0e chore(dev): release 1.33.0 (#18490) 2023-09-01 15:57:57 +02:00
Koen KantersandKoenkk e78aa3589b fix(ignore): update zigbee-herdsman-converters to 15.67.1 (#18817)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-01 15:50:16 +02:00
Koen KantersandKoenkk 68169f0e50 fix(ignore): update zigbee-herdsman to 0.18.5 (#18816)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-01 13:45:06 +00:00
Koen KantersandKoenkk 97f6a840e4 fix(ignore): update zigbee-herdsman-converters to 15.67.0 (#18815)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-09-01 13:35:18 +00:00
Koen Kantersandnurikk 9a6445a8a0 fix(ignore): update zigbee2mqtt-frontend to 0.6.135 (#18814)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-09-01 15:27:52 +02:00
Koen KantersandKoenkk 0ec68a4b71 fix(ignore): update zigbee-herdsman-converters to 15.66.1 (#18790)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-31 07:35:19 +00:00
Koen KantersandKoenkk 5084b1293e fix(ignore): update zigbee-herdsman-converters to 15.64.0 (#18784)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-29 06:46:11 +00:00
Koen Kantersandnurikk 4949a54d66 fix(ignore): update zigbee2mqtt-frontend to 0.6.134 (#18761)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-08-27 10:59:06 +00:00
Koen KantersandKoenkk b193d89042 fix(ignore): update zigbee-herdsman-converters to 15.63.0 (#18758)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-27 06:42:34 +00:00
Koen KantersandKoenkk bc17e6406b fix(ignore): update dependencies (#18755)
* fix(ignore): update dependencies

* lock version

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-27 08:36:28 +02:00
Yip Rui Fung d1e50ce534 fix: Use QOS1 for rarely sent discovery and availability messages (#18756)
* Use QOS1 for rarely sent messages

Specifically discovery and availability depending on the set up, it's possible for these messages to be silently discarded by the broker.

Sending them as QOS1 means the mqtt library used will resend them until it gets an ACK.
Ensuring delivery is particularly important for messages that are rarely sent like discovery or availability as they are only sent when there are changes, and nondelivery or dropped messages for them impede proper functioning in home assistant.

* Fix tests for discovery and availability using QOS1
2023-08-27 06:26:07 +00:00
koenkk 677db105e2 chore: remove duplicate object_id warning for function expose 2023-08-26 08:43:47 +02:00
Koen KantersandKoenkk 514d9f38b2 fix(ignore): update zigbee-herdsman-converters to 15.62.0 (#18742)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-26 06:02:23 +00:00
Koen Kanters 704ecf366e feat: Add Home Assistant origin to discovery (#18741) 2023-08-26 07:56:31 +02:00
Koen KantersandKoenkk 1439f4c6ac fix(ignore): update zigbee-herdsman to 0.18.4 (#18727)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-25 07:46:49 +00:00
Koen KantersandKoenkk 6a1b6a1403 fix(ignore): update zigbee-herdsman to 0.18.3 (#18714)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-24 08:27:14 +00:00
Koen KantersandKoenkk 239c8fc70c Update zigbee-herdsman-converters to 15.61.0 (#18713)
* fix(ignore): update zigbee-herdsman-converters to 15.61.0

* u

* u

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-24 08:20:28 +00:00
Artem Draft e33e335c0c feat: Use labels in Home Assistant entity naming (#18678)
* feat: Use labels in Home Assistant entity naming

* tweak comment
2023-08-22 08:07:23 +02:00
Koen KantersandKoenkk 71c4211d13 fix(ignore): update zigbee-herdsman-converters to 15.60.0 (#18672)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-20 15:58:16 +00:00
4b3a2c9f5a feat: Support scene renaming (#18667)
Co-authored-by: Frank van Viegen <frank@vanviegen.net>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-08-20 17:50:10 +02:00
Koen KantersandKoenkk 7185d9e501 fix(ignore): update zigbee-herdsman-converters to 15.59.0 (#18661)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-19 07:17:20 +00:00
Koen KantersandKoenkk dcbf4e5b0e fix(ignore): update zigbee-herdsman-converters to 15.58.1 (#18658)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-18 18:08:05 +00:00
Koen KantersandKoenkk db812cd729 fix(ignore): update zigbee-herdsman to 0.18.2 (#18648)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-17 19:59:06 +00:00
Koen KantersandKoenkk c214f83298 Update zigbee-herdsman-converters to 15.58.0 (#18647)
* fix(ignore): update zigbee-herdsman-converters to 15.58.0

* fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-17 19:24:20 +00:00
Koen KantersandKoenkk 3736b5901b fix(ignore): update zigbee-herdsman to 0.18.1 (#18627)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-15 18:38:11 +00:00
Koen Kanters 3af130a2c0 feat: Support coordinator check (#18599)
* feat: Support coordinator check

* add tests
2023-08-14 20:35:15 +02:00
Koen KantersandKoenkk 145bc05dc3 fix(ignore): update zigbee-herdsman-converters to 15.57.0 (#18616)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-14 17:02:24 +00:00
Koen KantersandKoenkk cc0536c5ab fix(ignore): update zigbee-herdsman to 0.18.0 (#18600)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-13 07:13:00 +00:00
Koen KantersandKoenkk 0d00a144f5 fix(ignore): update dependencies (#18598)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-13 08:45:32 +02:00
Koen Kanters aa021d988d feat: Support generating extended_pan_id (#18596)
* feat: Support generating extended_pan_id

* Update configuration.example.yaml
2023-08-12 15:07:30 +02:00
Koen KantersandKoenkk ea147900ab Update zigbee-herdsman-converters to 15.56.0 (#18593)
* fix(ignore): update zigbee-herdsman-converters to 15.56.0

* Update bridge.test.js

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-12 12:39:00 +00:00
Koen KantersandKoenkk b1796e3e1a fix(ignore): update zigbee-herdsman-converters to 15.55.3 (#18578)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-10 16:23:27 +00:00
koenkk b55cc0a037 fix(ignore): chore: Update dependencies (#18459) 2023-08-09 20:04:20 +02:00
Koen KantersandKoenkk 8675b1c9ed fix(ignore): update zigbee-herdsman-converters to 15.55.2 (#18566)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-09 18:00:54 +00:00
koenkk b09b8ec3d6 fix(ignore): Revert "chore: Update dependencies (#18459)"
This reverts commit 53cb42103c.
2023-08-09 07:33:27 +02:00
Koen KantersandKoenkk 7f05f31c72 fix(ignore): update zigbee-herdsman-converters to 15.55.1 (#18557)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-08 18:10:21 +00:00
Koen KantersandKoenkk 53cb42103c chore: Update dependencies (#18459)
* fix(ignore): update dependencies

* Make compatible with MQTT 5

* updates

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-08 20:04:22 +02:00
Koen KantersandKoenkk a892a1b898 fix(ignore): update zigbee-herdsman to 0.17.3 (#18556)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-08 17:49:39 +00:00
Koen Kanters 1f52faee39 feat: Drop Node.js 14 support (#18555) 2023-08-08 19:40:22 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> e0038380c7 chore: Bump alpine from 3.18.2 to 3.18.3 in /docker (#18554)
Bumps alpine from 3.18.2 to 3.18.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 19:37:05 +02:00
Koen KantersandKoenkk 6050428566 fix(ignore): update zigbee-herdsman-converters to 15.55.0 (#18547)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-07 17:03:41 +00:00
Koen KantersandKoenkk b5e9ed436c fix(ignore): update zigbee-herdsman-converters to 15.54.1 (#18537)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-06 07:14:43 +00:00
Koen Kanters cf313c503b fix: Generate pan_id for new installations (#18530) 2023-08-05 13:22:31 +02:00
Koen KantersandKoenkk abba8b3ba8 fix(ignore): update zigbee-herdsman-converters to 15.54.0 (#18527)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-05 06:40:44 +00:00
Koen KantersandKoenkk f08cd81ac0 fix(ignore): update zigbee-herdsman-converters to 15.53.0 (#18524)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-04 17:37:59 +00:00
Koen Kanters 68ec507e30 fix: Add secure default config (#18357)
* fix: Add secure default config. https://github.com/Koenkk/zigbee2mqtt/issues/16188

* Enable frontend by default
2023-08-03 20:48:23 +02:00
Koen KantersandKoenkk 0718ca162d fix(ignore): update zigbee-herdsman-converters to 15.52.0 (#18514)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-03 18:39:15 +00:00
Koen KantersandKoenkk 2d917a7d0d fix(ignore): update zigbee-herdsman-converters to 15.51.0 (#18501)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-02 18:09:54 +00:00
koenkk ed22ecedbf fix: Fix Home Assistant TypeError: object of type 'NoneType' has no len() error. https://github.com/Koenkk/zigbee2mqtt/issues/17861 2023-08-02 19:34:39 +02:00
Koen Kanters f6196107a7 fix: Fix Home Assistant `MQTT device name is equal to entity name in your config (#18491)
* fix: Fix Home Assistant `MQTT device name is equal to entity name in your config` error. https://github.com/Koenkk/zigbee2mqtt/issues/18445

* remove onlythis
2023-08-01 20:39:02 +02:00
koenkk 49920ce093 chore: use .md extension for changelog 2023-08-01 20:15:01 +02:00
koenkk 33543c8588 chore: use GH_TOKEN for gist edit 2023-08-01 20:07:05 +02:00
koenkk c1413afa04 chore: publish changelog in gist 2023-08-01 20:04:14 +02:00
Koen Kanters df93e4c8f9 feat: Let Home Assistant generate entity name when device_class is present (#18208) 2023-08-01 19:46:24 +02:00
koenkk 7709af8a5e chore: promote to dev 2023-08-01 19:25:37 +02:00
Koen Kanters 1ec1e57244 chore(dev): release 1.32.2 (#18486) 2023-08-01 19:18:26 +02:00
koenkk 758b8144a1 fix(ignore): fix commit-user-lookup cache 2023-08-01 18:29:22 +02:00
koenkk 590564c158 fix(ignore): Attempt 3 to fix commit-user-lookup 2023-08-01 18:23:24 +02:00
koenkk ea412cfe82 fix(ignore): Attempt 2 to fix cache saving 2023-08-01 18:17:11 +02:00
koenkk fa02bb5b74 fix(ignore): Attempt to fix cache not saving 2023-08-01 18:11:36 +02:00
Koen KantersandKoenkk 683d29f9f7 fix(ignore): update zigbee-herdsman-converters to 15.50.1 (#18487)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-01 18:00:02 +02:00
Koen KantersandKoenkk 3478e40017 fix(ignore): update zigbee-herdsman-converters to 15.50.0 (#18475)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-08-01 15:30:00 +00:00
koenkk ba0cc61965 fix(ignore): Fix failing test 2023-07-31 18:05:00 +02:00
Koen KantersandKoenkk 8139d7f1f4 fix(ignore): update zigbee-herdsman-converters to 15.49.0 (#18443)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-27 17:59:55 +00:00
Koen KantersandKoenkk d487f37a7a fix(ignore): update zigbee-herdsman-converters to 15.48.0 (#18438)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-26 19:42:36 +00:00
Koen KantersandKoenkk 087b85cb9f fix(ignore): update zigbee-herdsman-converters to 15.47.0 (#18430)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-25 18:10:45 +00:00
Ilya KirovandKoen Kanters 4bd281ce6c fix(ignore): Add ep l till 24 (#18422)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-07-25 17:53:31 +00:00
Koen KantersandKoenkk ced3d43dad fix(ignore): update zigbee-herdsman-converters to 15.46.0 (#18421)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-24 17:50:49 +00:00
Jorge Schrauwen 91f22f1230 fix(ignore): Add th1-th10 endpoints for Ubisys H10 (#18405)
See koenkk/zigbee2mqtt#18121
2023-07-23 18:37:56 +02:00
Koen KantersandKoenkk 57d031d54a fix(ignore): update zigbee-herdsman-converters to 15.45.0 (#18404)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-23 07:49:55 +00:00
Koen KantersandKoenkk 8e946623a9 fix(ignore): update dependencies (#18403)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-23 09:15:07 +02:00
Koen Kantersandnurikk e1d52ae43a fix(ignore): update zigbee2mqtt-frontend to 0.6.133 (#18390)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-07-21 15:53:43 +00:00
Koen Kanters f64cd7e8f3 fix: Fix socket error crashing Zigbee2MQTT (#18388) 2023-07-21 14:51:39 +00:00
Bruno Bierbaumer df8e1687b2 fix: Fix insecure Zigbee network encryption key generation (#18372) 2023-07-20 19:26:29 +02:00
Koen KantersandKoenkk 3408e3c05a fix(ignore): update zigbee-herdsman-converters to 15.44.0 (#18365)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-19 17:46:37 +00:00
Koen KantersandKoenkk 7a22cee639 fix(ignore): update zigbee-herdsman-converters to 15.43.0 (#18356)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-18 18:32:43 +00:00
koenkk dec91919bc fix: Fix 'dict object' has no attribute 'ir_code_to_send' error. https://github.com/Koenkk/zigbee2mqtt/issues/18180 2023-07-18 19:53:48 +02:00
Koen KantersandKoenkk 313865b0a3 fix(ignore): update zigbee-herdsman-converters to 15.42.0 (#18343)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-17 18:07:42 +00:00
Koen KantersandKoenkk ee1a5f0400 fix(ignore): update dependencies (#18260)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-16 09:05:30 +02:00
Koen Kanters 7f2803b020 chore: merge master to dev 2023-07-16 08:44:34 +02:00
koenkk 83205e43da chore: fix d22d45a697 2023-07-16 08:41:41 +02:00
Koen Kanters 45e127e22f chore: merge master to dev 2023-07-16 08:39:51 +02:00
koenkk d22d45a697 chore: don't update @types/ws package 2023-07-16 08:39:23 +02:00
Koen KantersandKoenkk 330a913e76 fix(ignore): update zigbee-herdsman-converters to 15.41.0 (#18328)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-15 07:18:43 +00:00
Koen KantersandKoenkk af0521b54c fix(ignore): update zigbee-herdsman-converters to 15.40.0 (#18314)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-13 18:20:52 +00:00
Koen Kanters 8cf8cc0231 chore: merge master to dev 2023-07-13 19:59:31 +02:00
arteck f5f5b037b8 chore: Add iobroker intergration (#18308)
* Update README.md

* Update README.md
2023-07-13 19:56:26 +02:00
Brandon Rothweiler 1252f10d39 fix: Use HA sensor device class atmospheric_pressure instead of pressure (#18306)
* Update homeassistant.ts

* Update tests
2023-07-13 19:55:19 +02:00
Koen KantersandKoenkk a3c8e1c3c9 fix(ignore): update zigbee-herdsman-converters to 15.39.1 (#18292)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-11 19:46:51 +02:00
Koen KantersandKoenkk 073989c7a4 fix(ignore): update zigbee-herdsman to 0.17.2 (#18291)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-11 19:45:58 +02:00
Koen Kantersandnurikk 05eff957eb fix(ignore): update zigbee2mqtt-frontend to 0.6.132 (#18289)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-07-11 12:56:33 +00:00
Koen KantersandKoenkk 3c855d2042 fix(ignore): update zigbee-herdsman-converters to 15.39.0 (#18282)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-10 20:06:48 +02:00
koenkk 0bdf663ca1 fix: Fix not all cluster unbound/bound when specified. https://github.com/Koenkk/zigbee2mqtt/issues/10740 2023-07-10 20:00:57 +02:00
Koen KantersandKoenkk 813dd49a41 fix(ignore): update zigbee-herdsman-converters to 15.38.0 (#18262)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-09 12:12:40 +00:00
koenkk dab7e6a1ae chore: Merge branch 'master' into dev 2023-07-08 09:36:24 +02:00
koenkk b73c3e3dfb Revert "fix(ignore): update zigbee-herdsman-converters to 15.33.1-hotfix.0 (#18247)"
This reverts commit 1046f0e74a.
2023-07-08 09:34:55 +02:00
koenkk 4ccfdfc6f4 chore: release 1.32.1 2023-07-08 09:32:42 +02:00
koenkk 15601d6339 fix(ignore): Update zigbee-herdsman-converters to 15.33.1-hotfix.0 2023-07-08 09:21:42 +02:00
Koen KantersandKoenkk 1046f0e74a fix(ignore): update zigbee-herdsman-converters to 15.33.1-hotfix.0 (#18247)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-08 07:18:57 +00:00
Koen KantersandKoenkk 032e5238b8 fix(ignore): update zigbee-herdsman-converters to 15.37.0 (#18244)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-07 18:52:01 +00:00
Koen KantersandKoenkk 5b3fdf7b9f fix(ignore): update zigbee-herdsman to 0.17.1 (#18234)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-06 20:00:03 +02:00
Koen KantersandKoenkk 0489e75e1e fix(ignore): update zigbee-herdsman to 0.17.0 (#18232)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-06 14:31:34 +00:00
Koen KantersandKoenkk eb655f17db fix(ignore): update zigbee-herdsman-converters to 15.36.0 (#18227)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-05 17:27:06 +00:00
Koen KantersandKoenkk d8c7c00ca2 fix(ignore): update zigbee-herdsman-converters to 15.35.1 (#18216)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-04 19:07:31 +00:00
Koen KantersandKoenkk 9aa7e1ec86 fix(ignore): update zigbee-herdsman-converters to 15.35.0 (#18215)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-04 17:24:31 +00:00
Koen Kantersandnurikk caa652b0ad fix(ignore): update zigbee2mqtt-frontend to 0.6.131 (#18194)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-07-03 10:08:04 +00:00
Koen Kanters 08e82e4980 chore: Add changelog to release PR (#18183) 2023-07-02 09:49:51 +02:00
Koen KantersandKoenkk 5067721fdf fix(ignore): update zigbee-herdsman-converters to 15.34.0 (#18181)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-02 09:19:51 +02:00
koenkk b014857a13 chore: promote to dev 2023-07-01 13:08:01 +02:00
koenkk eb7945248b chore: disable latest-dev version publishing 2023-07-01 13:07:46 +02:00
Koen Kanters 69638d7956 chore(dev): release 1.32.0 (#18163) 2023-07-01 12:50:40 +02:00
koenkk 953f3a232b chore: Fix release please 2023-07-01 12:25:11 +02:00
Koen KantersandKoenkk d1824f169b fix(ignore): update zigbee-herdsman-converters to 15.33.1 (#18161)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-07-01 06:37:59 +00:00
Koen KantersandKoenkk 81973c3a2a fix(ignore): update zigbee-herdsman-converters to 15.33.0 (#18156)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-30 17:05:35 +00:00
Koen Kanters 213e2b50d6 chore: merge master to dev 2023-06-30 18:52:54 +02:00
gruijter 0a63ae5376 chore: Added Homey Integration to README.md (#18152) 2023-06-30 18:52:33 +02:00
Koen KantersandKoenkk 61dd1dd96d fix(ignore): update zigbee-herdsman-converters to 15.32.0 (#18132)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-27 19:05:48 +00:00
Koen KantersandKoenkk ed85367e53 fix(ignore): update zigbee-herdsman-converters to 15.31.0 (#18125)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-26 17:47:42 +00:00
Koen KantersandKoenkk 38c2ea5bf7 fix(ignore): update zigbee-herdsman to 0.16.0 (#18124)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-26 17:40:00 +00:00
Koen KantersandKoenkk 2d62027e24 fix(ignore): update zigbee-herdsman to 0.15.3 (#18116)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-25 10:00:07 +02:00
Koen KantersandKoenkk a56719d19c fix(ignore): update zigbee-herdsman-converters to 15.30.0 (#18115)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-25 09:59:01 +02:00
Koen Kanters 94744525ba feat: Support settable Home Assistant text (#18114) 2023-06-25 09:23:13 +02:00
koenkk ea193f1938 Revert "fix(ignore): update dependencies (#18112)"
This reverts commit 57566c76ed.
2023-06-25 09:19:27 +02:00
koenkk 88339473ce fix(ignore): Fix DeviceMessage.meta type 2023-06-25 09:16:36 +02:00
github-actions[bot]andKoenkk 57566c76ed fix(ignore): update dependencies (#18112)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-25 08:12:19 +02:00
koenkk a09342836b chore: Improve changelog generator 2023-06-23 18:24:12 +02:00
Koen Kanters b3fbf78bec chore: Fix changelog generator cache (#18100)
* chore: Fix changelog

* u

* u

* u

* u

* u
2023-06-23 18:14:35 +02:00
Koen KantersandKoenkk a744838e9c fix(ignore): update zigbee-herdsman-converters to 15.29.0 (#18099)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-23 16:06:47 +00:00
koenkk 712c7bdbaf chore: Cache commit users in changelog generator 2023-06-22 21:10:10 +02:00
Koen KantersandKoenkk 6d3389b409 fix(ignore): update zigbee-herdsman-converters to 15.28.0 (#18092)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-22 18:46:31 +00:00
Koen KantersandKoenkk 03005b38c8 fix(ignore): update zigbee-herdsman to 0.15.2 (#18091)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-22 18:37:39 +00:00
Koen KantersandKoenkk 17cff2a26f fix(ignore): update zigbee-herdsman to 0.15.1 (#18080)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-21 17:32:24 +00:00
Koen KantersandKoenkk 5777d76e55 fix(ignore): update zigbee-herdsman-converters to 15.27.0 (#18075)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-20 17:18:43 +00:00
Koen KantersandKoenkk 91d67a0ef5 fix(ignore): update zigbee-herdsman-converters to 15.26.0 (#18067)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-19 19:09:38 +00:00
Grégoire SeuxandKoen Kanters e083a6bff7 feat: Support Home Assistant water device_class (#18066)
This should be sufficient for https://www.zigbee2mqtt.io/devices/ZVG1.html to be water_consumed sensor to be usable in Energy dashboard (water section).

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-06-19 19:21:43 +02:00
Koen KantersandKoenkk 57aaa5a85a fix(ignore): update zigbee-herdsman-converters to 15.25.0 (#18056)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-18 10:03:48 +00:00
koenkk 34bad92ec6 chore: fix update_deps 2023-06-18 11:00:53 +02:00
Koen Kanters b6a4acda9b Revert "fix(ignore): update dependencies (#18052)" (#18053)
This reverts commit 1dc0b24e9a.
2023-06-18 10:56:59 +02:00
github-actions[bot]andKoenkk 1dc0b24e9a fix(ignore): update dependencies (#18052)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-18 10:40:32 +02:00
dependabot[bot] 38de19bb2c chore: Bump alpine from 3.18.0 to 3.18.2 in /docker (#18030) 2023-06-15 18:56:06 +02:00
Koen KantersandKoenkk c47f5df021 fix(ignore): update zigbee-herdsman-converters to 15.24.0 (#18025)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-14 18:31:21 +00:00
Koen KantersandKoenkk 4ad838c114 fix(ignore): update zigbee-herdsman-converters to 15.23.0 (#18015)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-13 19:41:02 +00:00
Koen KantersandKoenkk b0b3aee648 fix(ignore): update zigbee-herdsman-converters to 15.22.0 (#18004)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-12 16:26:26 +00:00
koenkk 446dbbf1fc fix(ignore): Fix e10dd893ab 2023-06-12 18:22:15 +02:00
koenkk 11f0be55d8 fix: Fix Home Assistant truncate error when program is null. https://github.com/Koenkk/zigbee2mqtt/issues/16460 2023-06-12 18:10:45 +02:00
github-actions[bot]andKoenkk e10dd893ab fix(ignore): update dependencies (#17991)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-12 17:22:42 +02:00
Koen KantersandKoenkk 0dd899679d Update zigbee-herdsman-converters to 15.21.2 (#17967)
* fix(ignore): update zigbee-herdsman-converters to 15.21.2

* fix

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-08 21:42:29 +00:00
Koen KantersandKoenkk 05cab61e1f fix(ignore): update zigbee-herdsman to 0.15.0 (#17966)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-08 23:10:44 +02:00
Koen KantersandKoenkk 0c7e7e5089 fix(ignore): update zigbee-herdsman-converters to 15.20.0 (#17954)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-08 07:25:05 +00:00
koenkk 5f71776434 chore: improve changelog generator 2023-06-08 09:20:42 +02:00
Koen Kanters a7e02a7be8 fix(ignore): Better fix for #17891 (#17951)
* fix(ignore): Better fix for #17891

* remove onlythis
2023-06-08 09:04:14 +02:00
koenkk 7df6b2bab5 chore: Merge branch 'master' into dev 2023-06-07 20:24:57 +02:00
koenkk 21f51258a9 chore: release 1.31.2 2023-06-07 20:17:06 +02:00
koenkk c6904686c3 fix: Update zhc to 15.13.1-hotfix.1 2023-06-07 20:16:23 +02:00
koenkk a1bea8c5ab chore: Fix changelog generator 2023-06-07 16:48:26 +02:00
Koen KantersandKoenkk c23d244405 Update zigbee-herdsman-converters to 15.19.1 (#17941)
* fix(ignore): update zigbee-herdsman-converters to 15.19.1

* fix

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-07 14:30:11 +00:00
koenkk 86898e5ceb chore: Merge branch 'master' into dev 2023-06-07 14:57:48 +02:00
koenkk 3572c60770 chore: release 1.31.1 2023-06-07 14:55:08 +02:00
koenkk ffc7ab83a2 fix: Update zhc to 15.13.1-hotfix.0 2023-06-07 14:54:34 +02:00
Sean Kelly c12bedb3e5 fix: Fix HA entities unavailable after broker restart when broker does not persist retained messages (#17891)
* Fix race condition with bridge status message cancelling reinitialize after a reconnect to mqtt

* Fix tests
2023-06-07 09:16:11 +02:00
Koen KantersandKoenkk fd1622ba80 fix(ignore): update zigbee-herdsman-converters to 15.18.0 (#17917)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-05 08:44:21 +00:00
Koen KantersandKoenkk 7564019ecd fix(ignore): update zigbee-herdsman-converters to 15.17.0 (#17909)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-04 12:18:21 +00:00
koenkk 6d381da075 chore: fix ci.yml 2023-06-04 14:01:49 +02:00
github-actions[bot]andKoenkk b10aa83fc8 fix(ignore): update dependencies (#17903)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-04 13:47:46 +02:00
Koen KantersandKoenkk a7997a3cd4 fix(ignore): update zigbee-herdsman-converters to 15.16.0 (#17900)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-03 16:07:49 +00:00
Koen KantersandKoenkk 73c19bff71 fix(ignore): update zigbee-herdsman-converters to 15.15.1 (#17884)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-02 17:58:16 +00:00
Koen KantersandKoenkk 80aa21123c fix(ignore): update zigbee-herdsman-converters to 15.15.0 (#17872)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-02 07:52:26 +00:00
koenkk afd1760b6f chore: Fix changelog generator 2023-06-02 09:47:58 +02:00
Koen KantersandKoenkk ddcab827ad Update zigbee-herdsman-converters to 15.14.1 (#17859)
* fix(ignore): update zigbee-herdsman-converters to 15.14.1

* fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-01 14:29:42 +00:00
koenkk d0a41548fd chore: Exclude node_modules from TS compiler 2023-06-01 16:10:05 +02:00
koenkk ff8e6b9c66 chore: fix release_please.yml 2023-06-01 15:25:20 +02:00
koenkk 25f30a94f5 Revert "chore: promote to dev"
This reverts commit efe451df79.
2023-06-01 15:15:24 +02:00
Koenkk efe451df79 chore: promote to dev 2023-06-01 13:13:42 +00:00
koenkk b97a09c75b chore: improve release_please.yml 2023-06-01 14:39:25 +02:00
koenkk f3b8c689a9 chore: improve release_please.yml 2023-06-01 14:36:39 +02:00
koenkk 4d1a8ee873 chore: promote to dev 2023-06-01 11:30:16 +02:00
Koen Kanters f440c86019 chore(dev): release 1.31.0 (#17772) 2023-06-01 11:06:39 +02:00
Koen KantersandKoenkk 4b20dfafab fix(ignore): update zigbee-herdsman-converters to 15.13.1 (#17851)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-06-01 08:34:42 +00:00
Koen KantersandKoenkk b228d9daf6 fix(ignore): update zigbee-herdsman-converters to 15.13.0 (#17842)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-31 08:10:14 +00:00
Koen KantersandKoenkk be82b737be fix(ignore): update zigbee-herdsman-converters to 15.12.0 (#17837)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-30 09:50:17 +02:00
Koen Kanters d119f609de fix(ignore): Fix build (#17838) 2023-05-30 09:50:05 +02:00
github-actions[bot]andKoenkk a71857c723 fix(ignore): update dependencies (#17811)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-28 14:27:10 +02:00
Koen Kanters a404f9ff92 chore: merge master to dev 2023-05-27 16:36:37 +02:00
koenkk 0cbbf40040 chore: improve merge_master_to_dev.yml 2023-05-27 16:36:05 +02:00
Koen Kanters 277ac10e44 2023-05-27 16:32:16 +02:00
github-actions[bot]andKoenkk 2e8dfbb96e fix(ignore): update zigbee-herdsman-converters to 15.11.0 (#17808)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-27 16:30:07 +02:00
koenkk 366642cf71 chore: improve ci/cd 2023-05-27 16:29:57 +02:00
github-actions[bot]andKoenkk b7b3b51cfe fix(ignore): update zigbee-herdsman-converters to 15.10.0 (#17797)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-26 10:11:03 +02:00
koenkk e6f9aeda06 fix: Fix Home Assistant Payload is not supported (e.g. open, closed, opening, closing, stopped): STOP error. https://github.com/Koenkk/zigbee2mqtt/issues/17552 2023-05-26 09:32:29 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bad365b9a7 chore: Bump actions/download-artifact from 2 to 3 (#17793)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-26 09:10:58 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 1f8a68d4c9 chore: Bump actions/upload-artifact from 2 to 3 (#17794)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-26 09:10:44 +02:00
koenkk 443d5ea43c chore: fix ci.yml 2023-05-25 10:29:18 +02:00
koenkk af0cea0fb9 chore: fix release_please.yml 2023-05-25 10:25:27 +02:00
Koen Kanters 3701cce15e 2023-05-25 10:23:39 +02:00
github-actions[bot]andKoenkk 5b807c36ec fix(ignore): update zigbee-herdsman-converters to 15.9.0 (#17791)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-25 10:23:22 +02:00
koenkk 7cea62995c chore: fix ci.yml 2023-05-25 10:23:12 +02:00
koenkk 2a7d49b709 chore: automate releasing 2023-05-25 10:12:46 +02:00
Koen Kanters 1b7138e0c8 2023-05-25 09:19:40 +02:00
koenkk 0476b3362e Add merge_master_to_dev.yml 2023-05-25 09:19:05 +02:00
koenkk 3ed7ac90c9 chore: fix generateChangelog.js and ci.yml 2023-05-24 16:56:08 +02:00
github-actions[bot]andKoenkk 8b579b6533 fix(ignore): update zigbee-herdsman-converters to 15.8.2 (#17789)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-24 16:41:06 +02:00
koenkk 2d731ba1b6 chore: fix release_please.yml 2023-05-24 13:13:41 +02:00
koenkk 6a80d187fd Merge branch 'master' into dev 2023-05-24 13:11:44 +02:00
koenkk 1e8c3d05e5 chore: update ci config 2023-05-24 13:09:38 +02:00
koenkk ce7f09afc6 Update update_dependency.yml 2023-05-24 09:04:36 +02:00
koenkk c0e8efcde5 Add update_dependency.yml 2023-05-24 09:00:44 +02:00
github-actions[bot]andKoenkk 1344ae0616 feat(ignore): update zigbee-herdsman-converters to 15.7.0 (#17777)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-23 11:43:05 +00:00
github-actions[bot]andKoenkk 24baed3053 feat(ignore): update zigbee-herdsman-converters to 15.6.0 (#17774)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-23 12:45:35 +02:00
koenkk 8e95061fe5 Update release_please config 2023-05-23 12:17:48 +02:00
koenkk 626b2c47c1 Update config.yml 2023-05-23 12:15:15 +02:00
koenkk 95dff212e7 Update config.yml 2023-05-23 12:13:47 +02:00
koenkk c6416c9c61 Fix config.yml 2023-05-23 12:12:13 +02:00
koenkk 1898140f64 Update config.yml 2023-05-23 12:11:44 +02:00
github-actions[bot]andKoenkk 8457c3735b fix(ignore): update zigbee-herdsman to 0.14.117 (#17770)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-23 11:38:29 +02:00
koenkk 47c08b6cbd Merge branch 'master' into dev 2023-05-22 18:46:17 +02:00
koenkk b3de973af6 feat(ignore): update CI/CD 2023-05-22 18:45:47 +02:00
koenkk 0d17d26133 feat(ignore): update CI/CD 2023-05-22 18:38:28 +02:00
koenkk c802e776d6 Merge branch 'master' into dev 2023-05-22 16:56:42 +02:00
github-actions[bot]andKoenkk aa0f78269f chore: update zigbee-herdsman-converters to 15.5.0 (#17754)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-22 14:50:28 +00:00
koenkk 97b14cc2d4 Add release-please 2023-05-22 16:41:31 +02:00
github-actions[bot]andKoenkk d952ee60a9 Update dependencies (#17739)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-22 13:31:28 +02:00
github-actions[bot]andKoenkk 3d3bff88d7 Update zigbee-herdsman-converters to 15.0.117 (#17750)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-22 08:40:10 +00:00
github-actions[bot]andKoenkk c1cb4697f7 Update zigbee-herdsman-converters to 15.0.116 (#17736)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-20 12:55:49 +00:00
github-actions[bot]andKoenkk bfc51e0dc5 Update zigbee-herdsman-converters to 15.0.115 (#17700)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-16 17:55:56 +00:00
github-actions[bot]andKoenkk d339460269 Update zigbee-herdsman-converters to 15.0.114 (#17691)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-15 17:44:34 +00:00
Pierre-Gilles Leymarie fb60deeebc Add Gladys Assistant compatibility in README (#17686)
* Add Gladys Assistant integration in README

* Fix indentation

* Add <br> to align items

* Test with just one br
2023-05-15 17:22:13 +02:00
1b65ff5a65 Update zigbee-herdsman-converters to 15.0.113 (#17676)
* Update zigbee-herdsman-converters to 15.0.113

* Fix

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-05-14 18:01:04 +02:00
github-actions[bot]andKoenkk e3ebb1c5bc Update dependencies (#17672)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-14 17:09:02 +02:00
github-actions[bot]andKoenkk 099a8d35b0 Update zigbee-herdsman-converters to 15.0.112 (#17660)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-12 18:32:50 +00:00
github-actions[bot]andKoenkk 3085608a35 Update zigbee-herdsman-converters to 15.0.111 (#17646)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-11 18:29:49 +00:00
github-actions[bot]andKoenkk 307e0dcadd Update zigbee-herdsman-converters to 15.0.110 (#17631)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-10 18:08:42 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> aeb737012c Bump alpine from 3.17.3 to 3.18.0 in /docker (#17630)
Bumps alpine from 3.17.3 to 3.18.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-10 19:43:37 +02:00
github-actions[bot]andKoenkk dddd2bca88 Update zigbee-herdsman-converters to 15.0.109 (#17620)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-09 17:51:07 +00:00
Koen Kanters daedc54dd6 Update wrong_device.yaml 2023-05-09 19:30:18 +02:00
Koen Kanters df80a11663 Fix incorrect message being published when entity contains light or cover. https://github.com/Koenkk/zigbee2mqtt/issues/17594 2023-05-09 19:26:46 +02:00
github-actions[bot]andKoenkk a6bebf1e7a Update zigbee-herdsman-converters to 15.0.108 (#17603)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-08 19:11:34 +00:00
github-actions[bot]andKoenkk 52fdbbe057 Update zigbee-herdsman to 0.14.115 (#17602)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-08 20:27:28 +02:00
github-actions[bot]andKoenkk b2422589dc Update dependencies (#17581)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-08 20:21:24 +02:00
github-actions[bot]andKoenkk d602426951 Update zigbee-herdsman-converters to 15.0.106 (#17589)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-07 17:13:43 +00:00
Koen Kanters 64009d0dbb Fix Home Assistant State max length is 255 characters error for program sensor. https://github.com/Koenkk/zigbee2mqtt/issues/16460 2023-05-07 09:18:58 +02:00
github-actions[bot]andnurikk b8e46075df Update zigbee2mqtt-frontend to 0.6.129 (#17579)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-05-06 14:50:12 +00:00
github-actions[bot]andKoenkk 589d656594 Update zigbee-herdsman-converters to 15.0.105 (#17577)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-06 14:19:06 +00:00
github-actions[bot]andKoenkk 0872c670ad Update zigbee-herdsman to 0.14.114 (#17575)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-06 10:37:40 +00:00
github-actions[bot]andKoenkk 9b68684428 Update zigbee-herdsman-converters to 15.0.104 (#17573)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-05 18:29:10 +00:00
github-actions[bot]andKoenkk 626b8d2b08 Update zigbee-herdsman-converters to 15.0.103 (#17564)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-04 18:05:17 +00:00
github-actions[bot]andKoenkk 10d111e36a Update zigbee-herdsman-converters to 15.0.102 (#17555)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-03 18:29:59 +00:00
github-actions[bot]andKoenkk eb93c8aed7 Update zigbee-herdsman to 0.14.113 (#17554)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-03 18:18:56 +00:00
github-actions[bot]andKoenkk fe005e478a Update zigbee-herdsman-converters to 15.0.101 (#17543)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-02 17:56:22 +00:00
github-actions[bot]andKoenkk 8f88c4d26c Update zigbee-herdsman to 0.14.112 (#17523)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-05-01 17:14:11 +00:00
Koen Kanters 946887b841 Promote to dev 2023-05-01 18:41:46 +02:00
Koen Kanters b2dd21e164 1.30.4 2023-05-01 18:40:11 +02:00
Koen Kanters 01f4f1f940 Undev 2023-05-01 18:38:57 +02:00
Koen Kanters 563eb3a890 Merge branch 'dev' 2023-05-01 18:38:16 +02:00
github-actions[bot]andKoenkk ab4101dae8 Update zigbee-herdsman-converters to 15.0.100 (#17511)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-30 17:42:01 +00:00
9ab37735fe Update zigbee-herdsman-converters to 15.0.99 (#17503)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-04-30 16:30:36 +00:00
github-actions[bot]andKoenkk 8f275f414b Update zigbee-herdsman to 0.14.111 (#17504)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-30 07:32:09 +00:00
github-actions[bot]andKoenkk 55b17c95a4 Update dependencies (#17501)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-30 08:24:47 +02:00
github-actions[bot]andKoenkk 13c7348a97 Update zigbee-herdsman to 0.14.110 (#17486)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-28 17:58:44 +00:00
github-actions[bot]andKoenkk 62453a5d2a Update zigbee-herdsman-converters to 15.0.98 (#17476)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-27 17:38:14 +00:00
github-actions[bot]andKoenkk 9840433fc0 Update zigbee-herdsman-converters to 15.0.97 (#17470)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-27 07:27:05 +00:00
Aarni Koskela 8fe36d74ec Typo fixes (#17440)
* Fix "Succesfully"

* Fix herdsman typo

* Fix various other small typos
2023-04-27 09:14:04 +02:00
github-actions[bot]andKoenkk 8e85a1e081 Update zigbee-herdsman to 0.14.109 (#17469)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-27 07:12:42 +00:00
ce9a8ed86f Update zigbee-herdsman-converters to 15.0.96 (#17453)
* Update zigbee-herdsman-converters to 15.0.96

* Fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-04-24 19:34:18 +00:00
github-actions[bot]andKoenkk 49a1f56641 Update zigbee-herdsman-converters to 15.0.95 (#17428)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-23 07:50:40 +00:00
github-actions[bot]andKoenkk 76cf6fa444 Update dependencies (#17427)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-23 08:36:46 +02:00
Koen Kanters e1ecbd97d0 Wrong device issue improvements 2023-04-22 20:47:08 +02:00
Koen Kanters c389ab28cd Add wrong device issue 2023-04-22 20:44:23 +02:00
Koen Kanters 4c0c69b15f Support Node.js 20 (#17422) 2023-04-22 16:53:15 +02:00
github-actions[bot]andKoenkk 704bbb54d3 Update zigbee-herdsman-converters to 15.0.94 (#17407)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-20 19:29:39 +00:00
github-actions[bot]andKoenkk 17947aa809 Update zigbee-herdsman-converters to 15.0.93 (#17386)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-18 17:42:08 +00:00
github-actions[bot]andKoenkk 33811fec9f Update zigbee-herdsman-converters to 15.0.92 (#17378)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-17 16:35:22 +00:00
github-actions[bot]andKoenkk 76cd07a701 Update zigbee-herdsman-converters to 15.0.91 (#17367)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-16 19:25:16 +00:00
github-actions[bot]andKoenkk e2b18d8f02 Update zigbee-herdsman to 0.14.108 (#17357)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-16 07:53:49 +00:00
b3c886638a Update dependencies (#17354)
* Update dependencies

* Fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-04-16 08:56:31 +02:00
Sven Serlier f9121b2f0f Readme improvements (#17350)
* Update URLs

* Add more URLs
2023-04-15 19:06:56 +02:00
github-actions[bot]andKoenkk fb827f9dc0 Update zigbee-herdsman to 0.14.107 (#17351)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-15 17:06:40 +00:00
github-actions[bot]andKoenkk e5be5b0219 Update zigbee-herdsman-converters to 15.0.90 (#17343)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-15 08:04:45 +00:00
github-actions[bot]andKoenkk c360f5a7b1 Update zigbee-herdsman-converters to 15.0.89 (#17341)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-14 18:49:04 +00:00
Viktor Ryzhaiev 15f741b446 Add carbon_monoxide device_class to Home Assistant discovery (#17331) 2023-04-14 20:23:29 +02:00
github-actions[bot]andKoenkk 3b648c9e63 Update zigbee-herdsman to 0.14.106 (#17338)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-14 18:10:17 +00:00
github-actions[bot]andKoenkk 951360beba Update zigbee-herdsman-converters to 15.0.88 (#17324)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-13 17:20:22 +00:00
github-actions[bot]andKoenkk 71df01d613 Update zigbee-herdsman-converters to 15.0.87 (#17302)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-11 16:25:37 +00:00
github-actions[bot]andKoenkk a8f4daff30 Update zigbee-herdsman-converters to 15.0.86 (#17295)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-10 08:06:35 +00:00
github-actions[bot]andKoenkk d7dc083351 Update dependencies (#17286)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-09 09:06:03 +02:00
github-actions[bot]andKoenkk 45d55c9c71 Update zigbee-herdsman-converters to 15.0.85 (#17282)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-08 16:26:02 +00:00
085d5c9f8b Update zigbee-herdsman-converters to 15.0.84 (#17266)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-04-08 09:05:23 +00:00
github-actions[bot]andKoenkk 09a5650345 Update zigbee-herdsman to 0.14.105 (#17265)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-06 18:50:52 +00:00
github-actions[bot]andKoenkk 24050a3a10 Update zigbee-herdsman-converters to 15.0.83 (#17256)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-05 18:26:01 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> c6a2400f56 Bump peter-evans/create-pull-request from 4 to 5 (#17255)
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4 to 5.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v4...v5)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-05 19:58:23 +02:00
github-actions[bot]andKoenkk 9da7f53e78 Update zigbee-herdsman-converters to 15.0.82 (#17246)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-04 18:16:44 +00:00
github-actions[bot]andKoenkk f5a2c802ca Update zigbee-herdsman to 0.14.104 (#17245)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-04 18:13:41 +00:00
github-actions[bot]andKoenkk 372d991db9 Update zigbee-herdsman-converters to 15.0.81 (#17232)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-03 16:15:00 +00:00
github-actions[bot]andKoenkk bab0a3e902 Update zigbee-herdsman-converters to 15.0.80 (#17217)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-02 08:12:19 +00:00
github-actions[bot]andKoenkk b85aaf8e54 Update dependencies (#17215)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-02 09:24:23 +02:00
github-actions[bot]andKoenkk 64d744ea88 Update zigbee-herdsman-converters to 15.0.79 (#17203)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-01 07:31:16 +00:00
Koen Kanters 7748dd3321 Promote to dev 2023-04-01 09:06:17 +02:00
Koen Kanters 24c6b2e2c9 1.30.3 2023-04-01 09:05:40 +02:00
Koen Kanters 9589d12353 Undev 2023-04-01 09:05:26 +02:00
github-actions[bot]andKoenkk dcc13b7b53 Update zigbee-herdsman-converters to 15.0.78 (#17201)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-04-01 06:51:48 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 2d1733d0e7 Bump alpine from 3.17.2 to 3.17.3 in /docker (#17189)
Bumps alpine from 3.17.2 to 3.17.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-30 18:41:09 +02:00
github-actions[bot]andKoenkk 1368a78767 Update zigbee-herdsman-converters to 15.0.77 (#17174)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-29 07:05:47 +00:00
github-actions[bot]andKoenkk f29073e413 Update zigbee-herdsman to 0.14.103 (#17173)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-29 06:59:49 +00:00
github-actions[bot]andKoenkk 7005497cba Update zigbee-herdsman-converters to 15.0.76 (#17164)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-28 12:03:17 +00:00
github-actions[bot]andKoenkk 298c595deb Update zigbee-herdsman to 0.14.102 (#17163)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-28 11:52:39 +00:00
github-actions[bot]andKoenkk bdbe2b4a70 Update zigbee-herdsman to 0.14.101 (#17159)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-27 14:40:49 +00:00
Thomas KintscherandThomas Kintscher 653334b208 Expose voc_index sensor measurements as such in Home Assistant (#17144)
Co-authored-by: Thomas Kintscher <mail@thomaskintscher.de>
2023-03-26 09:50:22 +02:00
github-actions[bot]andKoenkk 24c6c0bf8e Update dependencies (#17146)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-26 09:03:01 +02:00
github-actions[bot]andKoenkk 3e252e4307 Update zigbee-herdsman-converters to 15.0.75 (#17127)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-23 16:26:30 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ae2de04251 Bump actions/stale from 7 to 8 (#17126)
Bumps [actions/stale](https://github.com/actions/stale) from 7 to 8.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-23 16:22:08 +00:00
oddlama 07d238d5b9 Support hosting the frontend on a Unix socket (#17123) 2023-03-23 17:08:23 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 407f0df6ad Bump peter-evans/enable-pull-request-automerge from 2 to 3 (#17125)
Bumps [peter-evans/enable-pull-request-automerge](https://github.com/peter-evans/enable-pull-request-automerge) from 2 to 3.
- [Release notes](https://github.com/peter-evans/enable-pull-request-automerge/releases)
- [Commits](https://github.com/peter-evans/enable-pull-request-automerge/compare/v2...v3)

---
updated-dependencies:
- dependency-name: peter-evans/enable-pull-request-automerge
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-23 17:06:11 +01:00
github-actions[bot]andKoenkk 2e593e37a6 Update zigbee-herdsman-converters to 15.0.74 (#17102)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-21 20:07:52 +00:00
github-actions[bot]andKoenkk 9f7fd479c4 Update zigbee-herdsman-converters to 15.0.73 (#17090)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-20 17:20:59 +00:00
github-actions[bot]andnurikk 0407a3b67c Update zigbee2mqtt-frontend to 0.6.127 (#17086)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-03-19 23:38:39 +00:00
github-actions[bot]andKoenkk 2c57bf81b0 Update zigbee-herdsman to 0.14.100 (#17078)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-19 08:13:42 +00:00
github-actions[bot]andKoenkk 960456401e Update dependencies (#17075)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-19 09:02:46 +01:00
github-actions[bot]andKoenkk d4774526c3 Update zigbee-herdsman-converters to 15.0.72 (#17073)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-18 16:13:01 +00:00
github-actions[bot]andKoenkk 2a365d39ac Update zigbee-herdsman-converters to 15.0.71 (#17055)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-16 16:46:28 +00:00
github-actions[bot]andKoenkk 347c023968 Update zigbee-herdsman-converters to 15.0.70 (#17052)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-15 16:38:15 +00:00
github-actions[bot]andKoenkk 4272d9a13e Update zigbee-herdsman-converters to 15.0.69 (#17028)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-13 17:16:42 +00:00
github-actions[bot]andKoenkk 54900c3680 Update zigbee-herdsman to 0.14.99 (#17026)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-13 16:44:47 +00:00
github-actions[bot]andKoenkk 461519cf39 Update zigbee-herdsman-converters to 15.0.68 (#17013)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-12 12:41:25 +00:00
github-actions[bot]andKoenkk 8edb176dc0 Update dependencies (#17007)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-12 13:00:09 +01:00
github-actions[bot]andKoenkk 61cdda96ff Update zigbee-herdsman-converters to 15.0.67 (#16994)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-11 10:10:41 +00:00
github-actions[bot]andKoenkk 43394b3376 Update zigbee-herdsman-converters to 15.0.66 (#16977)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-09 17:27:45 +00:00
github-actions[bot]andKoenkk ca7f9ec8ff Update zigbee-herdsman-converters to 15.0.65 (#16964)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-08 16:12:07 +00:00
github-actions[bot]andKoenkk 0857d087bd Update zigbee-herdsman-converters to 15.0.64 (#16954)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-07 19:19:45 +00:00
github-actions[bot]andKoenkk 818a9e3946 Update zigbee-herdsman to 0.14.98 (#16953)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-07 19:08:24 +00:00
github-actions[bot]andKoenkk 51460aacc8 Update zigbee-herdsman-converters to 15.0.63 (#16943)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-06 18:54:33 +00:00
github-actions[bot]andnurikk 354beb486d Update zigbee2mqtt-frontend to 0.6.126 (#16933)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-03-06 09:44:41 +00:00
github-actions[bot]andKoenkk 8261d4efc6 Update zigbee-herdsman-converters to 15.0.62 (#16921)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-05 08:59:13 +00:00
Koen Kanters bbb19371f3 Fix Home Assistant unit of measurement error for voc ppb sensors. https://github.com/Koenkk/zigbee2mqtt/issues/16057 2023-03-05 09:50:23 +01:00
github-actions[bot]andKoenkk 04ae93f00c Update dependencies (#16919)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-05 09:09:16 +01:00
github-actions[bot]andKoenkk 999c01086e Update zigbee-herdsman-converters to 15.0.61 (#16915)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-04 16:09:08 +00:00
baze-andKoen Kanters 0e67f8fa0a Fix old state send when long debounce time is used (#16828)
* Fixed caching problem where old messages were sent out if long debounce values is used for sensor.

* Fixed caching problem where old messages were sent out if long debounce values is used for sensor

* State cache updated during debounce IF cache is enabled in configuration.

* Fixed code styles

* Implemented test case for testing State cache is updated correctly during debouncing

* If-statement was obsolete as cache can be update right away.

---------

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-03-04 16:43:01 +01:00
github-actions[bot]andKoenkk f352d18854 Update zigbee-herdsman to 0.14.97 (#16914)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-04 15:17:35 +00:00
github-actions[bot]andKoenkk f865c976e3 Update zigbee-herdsman-converters to 15.0.60 (#16885)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-02 19:03:57 +00:00
github-actions[bot]andKoenkk aa90765db8 Update zigbee-herdsman-converters to 15.0.59 (#16862)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-01 16:18:51 +00:00
Koen Kanters 017fc03157 Promote to dev 2023-03-01 16:44:55 +01:00
Koen Kanters cdf62ea560 1.30.2 2023-03-01 16:43:20 +01:00
Koen Kanters 5dcd3f67ed Undev 2023-03-01 16:43:06 +01:00
github-actions[bot]andKoenkk b013a7d8ef Update zigbee-herdsman-converters to 15.0.58 (#16860)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-03-01 15:28:46 +00:00
github-actions[bot]andKoenkk 8e6e38b968 Update zigbee-herdsman to 0.14.96 (#16851)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-28 16:00:34 +00:00
github-actions[bot]andKoenkk 8f20640008 Update zigbee-herdsman-converters to 15.0.57 (#16850)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-28 15:51:18 +00:00
github-actions[bot]andnurikk 57707cd9b9 Update zigbee2mqtt-frontend to 0.6.125 (#16844)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-02-27 22:28:55 +00:00
github-actions[bot]andKoenkk 911683ad13 Update zigbee-herdsman-converters to 15.0.56 (#16841)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-27 19:42:13 +00:00
github-actions[bot]andKoenkk 99204682b8 Update dependencies (#16819)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-26 08:57:31 +01:00
github-actions[bot]andKoenkk fec7fca89e Update zigbee-herdsman-converters to 15.0.55 (#16814)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-25 10:17:03 +00:00
github-actions[bot]andKoenkk 6bea88eeb6 Update zigbee-herdsman to 0.14.95 (#16813)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-25 10:09:26 +00:00
github-actions[bot]andKoenkk 6afcb97c0d Update zigbee-herdsman-converters to 15.0.54 (#16798)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-23 17:09:09 +00:00
github-actions[bot]andKoenkk 73d60396bc Update zigbee-herdsman-converters to 15.0.53 (#16788)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-22 20:09:37 +00:00
Koen Kanters 942faf412f Revert "Capitalize entity name in Home Assistant (#16702)"
This reverts commit f5cceb1719.
2023-02-22 20:34:39 +01:00
github-actions[bot]andKoenkk b62f65f045 Update zigbee-herdsman-converters to 15.0.52 (#16771)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-21 16:26:31 +00:00
Artem Draft f5cceb1719 Capitalize entity name in Home Assistant (#16702) 2023-02-21 17:18:15 +01:00
github-actions[bot]andKoenkk 0b6040dd25 Update zigbee-herdsman-converters to 15.0.51 (#16765)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-20 19:32:31 +00:00
github-actions[bot]andKoenkk 45fda8aefd Update zigbee-herdsman to 0.14.94 (#16764)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-20 19:14:42 +00:00
Andreas Fritiofson 85f32c039f Add entity_category to indicator_mode and led_enable for Home Assistant discovery (#16744)
These names are used by some TuYa and IKEA devices.
2023-02-20 19:53:22 +01:00
github-actions[bot]andKoenkk 7fa2b5fcc3 Update zigbee-herdsman-converters to 15.0.50 (#16742)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-19 09:32:01 +00:00
github-actions[bot]andKoenkk 08a0ace11a Update dependencies (#16738)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-19 09:36:47 +01:00
github-actions[bot]andKoenkk 7605e1ec06 Update zigbee-herdsman-converters to 15.0.49 (#16722)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-18 08:53:16 +00:00
Koen Kanters e934b0d94e Support Hue effects for groups. https://github.com/Koenkk/zigbee2mqtt/issues/15997 2023-02-16 18:20:08 +01:00
github-actions[bot]andKoenkk 4aa8e17214 Update zigbee-herdsman-converters to 15.0.48 (#16694)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-15 19:36:12 +00:00
github-actions[bot]andKoenkk a9f5f7c620 Update zigbee-herdsman-converters to 15.0.47 (#16679)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-14 19:11:35 +00:00
github-actions[bot]andKoenkk 6e193ca442 Update zigbee-herdsman-converters to 15.0.46 (#16661)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-13 18:48:16 +00:00
Tami 2eadf30199 Fix error when device is added when device: [] in configuration.yaml (#16629)
* fix for TypeError: The "path" argument must be of type string in writeDevicesOrGroups

* added test case that produces the error when running on old implementation

Summary of all failing tests
 FAIL  test/settings.test.js
  ● Settings › Should add devices even when devices exist empty

    TypeError: The "path" argument must be of type string. Received undefined

      275 |
      276 | jest.mock('../../lib/util/data', () => ({
    > 277 |     joinPath: (file) => require('path').join(mockDir, file),
          |                                         ^
      278 |     getPath: () => mockDir,
      279 | }));
      280 |

      at Object.join [as joinPath] (test/stub/data.js:277:41)
      at joinPath (lib/util/settings.ts:245:38)
      at writeDevicesOrGroups (lib/util/settings.ts:250:5)
      at Object.write [as addDevice] (lib/util/settings.ts:555:5)
      at Object.addDevice (test/settings.test.js:128:18)
2023-02-13 19:41:49 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 600e743941 Bump alpine from 3.17.1 to 3.17.2 in /docker (#16659)
Bumps alpine from 3.17.1 to 3.17.2.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 19:23:38 +01:00
github-actions[bot]andKoenkk 932541649e Update zigbee-herdsman to 0.14.93 (#16635)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-12 08:44:39 +00:00
Artem Draft 0217593c77 Improve checks in HA covers (#16614) 2023-02-12 09:28:57 +01:00
github-actions[bot]andKoenkk 10e65b5f26 Update dependencies (#16632)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-12 09:17:14 +01:00
github-actions[bot]andKoenkk e9a38353fa Update zigbee-herdsman to 0.14.92 (#16616)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-10 20:42:59 +00:00
68caf0260d Update zigbee-herdsman-converters to 15.0.45 (#16604)
* Update zigbee-herdsman-converters to 15.0.45

* Fix tests

---------

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-02-09 18:32:04 +01:00
github-actions[bot]andKoenkk 7d887adb7f Update zigbee-herdsman to 0.14.91 (#16603)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-09 18:04:15 +01:00
github-actions[bot]andKoenkk ec57d899e5 Update zigbee-herdsman-converters to 15.0.44 (#16576)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-07 19:41:16 +00:00
github-actions[bot]andKoenkk 61b1732ecb Update zigbee-herdsman-converters to 15.0.43 (#16558)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-06 16:58:21 +00:00
Koen Kanters a35705cd38 Merge branch 'master' into dev 2023-02-06 17:49:55 +01:00
Koen Kanters eb878d3d8e 1.30.1 2023-02-06 17:42:06 +01:00
Robert Kaussow 3420cf508b disable buildx provenance in the ci build command (#16495) 2023-02-06 17:39:51 +01:00
Koen Kanters d5a3bf626f Update zigbee-herdsman-converters to 15.0.38-hotfix.0 2023-02-06 17:39:10 +01:00
github-actions[bot]andKoenkk 0e1220ff24 Update zigbee-herdsman-converters to 15.0.42 (#16542)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-05 14:54:53 +00:00
github-actions[bot]andKoenkk 1496b95067 Update dependencies (#16534)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-05 13:29:02 +01:00
github-actions[bot]andKoenkk bd0694e164 Update zigbee-herdsman to 0.14.90 (#16523)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-04 14:23:17 +00:00
github-actions[bot]andKoenkk d580741dfe Update zigbee-herdsman-converters to 15.0.41 (#16522)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-04 14:11:41 +00:00
Robert Kaussow a24586bec3 disable buildx provenance in the ci build command (#16495) 2023-02-04 14:12:24 +01:00
github-actions[bot]andKoenkk 1e7a76139d Update zigbee-herdsman-converters to 15.0.40 (#16487)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-02 16:57:11 +00:00
github-actions[bot]andKoenkk ea0a9990b9 Update zigbee-herdsman-converters to 15.0.39 (#16459)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-01 17:20:38 +00:00
Koen Kanters 97af5a64e7 Promote to dev 2023-02-01 17:17:11 +01:00
Koen Kanters 8f781db93e 1.30.0 2023-02-01 17:14:40 +01:00
Koen Kanters 1a6ba18ec2 Undev 2023-02-01 17:14:22 +01:00
Koen Kanters d91e363d76 Merge branch 'dev' 2023-02-01 17:13:53 +01:00
github-actions[bot]andKoenkk f7e45b8284 Update zigbee-herdsman-converters to 15.0.38 (#16452)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-02-01 14:58:34 +00:00
github-actions[bot]andKoenkk bbbaaf4d89 Update zigbee-herdsman-converters to 15.0.37 (#16443)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-31 17:17:49 +00:00
github-actions[bot]andKoenkk c9076f8ce6 Update zigbee-herdsman to 0.14.89 (#16442)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-31 18:11:43 +01:00
github-actions[bot]andKoenkk 82fd062668 Update zigbee-herdsman-converters to 15.0.36 (#16429)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-30 17:22:52 +00:00
github-actions[bot]andKoenkk 769a1afd96 Update zigbee-herdsman-converters to 15.0.35 (#16416)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-29 18:28:16 +00:00
Koen Kanters f943619387 Always respond to OTA request. https://github.com/Koenkk/zigbee2mqtt/issues/16371 2023-01-29 19:16:03 +01:00
github-actions[bot]andKoenkk 43e204b7d1 Update zigbee-herdsman-converters to 15.0.34 (#16409)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-29 11:55:41 +00:00
Koen Kanters a3f1399489 Log device OTA request response. https://github.com/Koenkk/zigbee2mqtt/issues/16371 2023-01-29 11:23:21 +01:00
github-actions[bot]andKoenkk 4179d879d2 Update dependencies (#16400)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-29 10:27:14 +01:00
github-actions[bot]andKoenkk 6ce2d2e73f Update zigbee-herdsman-converters to 15.0.33 (#16374)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-26 16:54:37 +00:00
github-actions[bot]andKoenkk 981542827c Update zigbee-herdsman-converters to 15.0.32 (#16355)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-25 18:24:35 +00:00
github-actions[bot]andKoenkk 2f0a2cee6e Update zigbee-herdsman-converters to 15.0.31 (#16335)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-24 16:30:10 +00:00
Koen Kanters 0bc685a8e3 Sanatize manufacturerName. https://github.com/home-assistant/core/issues/85691 2023-01-24 17:19:56 +01:00
Artem Draft 02a99703a8 Fix motor_state and moving in HA covers (#16324) 2023-01-24 17:00:24 +01:00
github-actions[bot]andKoenkk 7639ce44a7 Update zigbee-herdsman-converters to 15.0.30 (#16322)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-23 19:26:59 +00:00
Koen Kanters b89a99fe0c Fix another Failed to call 'Frontend' 'stop' . https://github.com/Koenkk/zigbee2mqtt/issues/16317 2023-01-23 20:21:03 +01:00
mtdcr 06820d2220 Sane defaults for remote syslog (#16300)
The most commonly used transport for remote syslog is port 514/udp.
It also is the only defined method for BSD syslog (RFC 3164). RFCs
5424+5425 specify an additional TLS transport via 6514/tcp, which
does not seem to be supported by zigbee2mqtt, as evidenced by the
lack of TLS-related configuration options in this area. RFC 6587
describes legacy uses of syslog over TCP, recommending against them.

Port 123, the previous default, was probably used by accident and
is reserved for NTP.

| $ grep -w -e 123 -e 514 -e 601 -e 6514 /etc/services
| ntp		123/udp				# Network Time Protocol
| shell		514/tcp		cmd syslog	# no passwords used
| syslog	514/udp
| syslog-tls	6514/tcp			# Syslog over TLS [RFC5425]
2023-01-23 19:31:10 +01:00
Roland Ramthun 140213950d Disable provenance information in Docker images (#16297)
* Disable provenance information in Docker images

The new default of buildx to include provenance information to OCI images causes a series of infrastructure issues with current Docker versions. 

Disable generation of the new provenance information until all necessary infrastructure software components and registries have been fixed to support it properly.

* Correct docker/setup-buildx-action version number
2023-01-23 19:26:43 +01:00
github-actions[bot]andKoenkk f4f2c498b7 Update zigbee-herdsman-converters to 15.0.29 (#16295)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-22 08:45:14 +00:00
github-actions[bot]andKoenkk 31807c6c6b Update zigbee-herdsman to 0.14.88 (#16294)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-22 08:08:45 +00:00
github-actions[bot]andKoenkk 8ccad8ee53 Update dependencies (#16293)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-22 09:03:03 +01:00
github-actions[bot]andKoenkk a930539dc3 Update zigbee-herdsman-converters to 15.0.28 (#16284)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-21 09:37:42 +00:00
github-actions[bot]andnurikk b33db9397d Update zigbee2mqtt-frontend to 0.6.124 (#16277)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-01-20 15:19:13 +00:00
github-actions[bot]andKoenkk de4b7fb022 Update zigbee-herdsman-converters to 15.0.27 (#16264)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-19 16:58:25 +00:00
github-actions[bot]andKoenkk 9e85419f9e Update zigbee-herdsman-converters to 15.0.26 (#16254)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-18 20:28:00 +00:00
github-actions[bot]andKoenkk 80c464c951 Update zigbee-herdsman-converters to 15.0.25 (#16230)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-17 16:29:30 +00:00
github-actions[bot]andKoenkk e56dff4972 Update zigbee-herdsman-converters to 15.0.24 (#16215)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-16 18:46:18 +00:00
Koen Kanters d8501f04eb Fix Failed to call 'Frontend' 'stop' (TypeError: Cannot read properties of null (reading 'clients') error. https://github.com/Koenkk/zigbee2mqtt/issues/16207 2023-01-16 19:19:51 +01:00
github-actions[bot]andKoenkk c927b4b935 Update zigbee-herdsman-converters to 15.0.23 (#16177)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-15 13:26:50 +00:00
github-actions[bot]andKoenkk fb9872a4ff Update dependencies (#16172)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-15 10:05:39 +01:00
39b0964739 Update zigbee-herdsman-converters to 15.0.22 (#16159)
* Update zigbee-herdsman-converters to 15.0.22

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-01-14 13:39:45 +00:00
Koen Kanters 2c509c0368 Promote to dev 2023-01-13 22:33:21 +01:00
Koen Kanters 49e1c68cac Merge branch 'master' into dev 2023-01-13 22:32:50 +01:00
Koen Kanters bb3e8f6d41 1.29.2 2023-01-13 22:28:52 +01:00
Koen Kanters 835a3288a0 Update zh to 0.14.83-hotfix.0 and zhc to 15.0.12-hotfix.1 2023-01-13 22:27:36 +01:00
Koen Kanters cddbb9a5e5 Fix f600066134 2023-01-13 16:59:20 +01:00
github-actions[bot]andnurikk 65366478e3 Update zigbee2mqtt-frontend to 0.6.123 (#16143)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-01-13 11:33:49 +00:00
1d8b19dce9 Update zigbee-herdsman-converters to 15.0.21 (#16123)
* Update zigbee-herdsman-converters to 15.0.21

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-01-12 17:34:49 +00:00
Koen Kanters f600066134 Fix 328b9fbd60. https://github.com/Koenkk/zigbee2mqtt/issues/15958 2023-01-12 17:20:07 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 75533c20b8 Bump alpine from 3.17.0 to 3.17.1 in /docker (#16081)
Bumps alpine from 3.17.0 to 3.17.1.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-12 09:42:42 +01:00
Koen Kanters 0605a5e0e3 Attempt to improve Log when MQTT client is unavailable stability 2023-01-12 09:41:30 +01:00
cf9640bd59 Update zigbee-herdsman-converters to 15.0.20 (#16106)
* Update zigbee-herdsman-converters to 15.0.20

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2023-01-12 08:37:17 +00:00
Koen Kanters 328b9fbd60 Remove state_class measurement when unit_of_measurement is not set. https://github.com/Koenkk/zigbee2mqtt/issues/15958 2023-01-11 18:23:13 +01:00
github-actions[bot]andnurikk bc6d1070c7 Update zigbee2mqtt-frontend to 0.6.122 (#16092)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2023-01-11 09:29:08 +00:00
github-actions[bot]andKoenkk bf339636b5 Update zigbee-herdsman to 0.14.87 (#16068)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-09 21:50:14 +00:00
github-actions[bot]andKoenkk d90dae5d9d Update zigbee-herdsman to 0.14.86 (#16066)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-09 21:00:50 +01:00
github-actions[bot]andKoenkk b34b0e866f Update zigbee-herdsman-converters to 15.0.19 (#16062)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-09 18:57:47 +00:00
Dan Klaffenbach 2288c0f1c2 Poll Busch-Jaeger devices for updates after binding-initiated changes (#16036)
The Busch-Jaeger devices don't support reporting and therefore their
state should be polled after being changed through a binding partner.
2023-01-09 19:18:13 +01:00
Miguel Cabral 9c4abb64c3 Expose cover moving state to Home Assistant (#16017) 2023-01-08 10:05:29 +01:00
github-actions[bot]andKoenkk 559f235e88 Update zigbee-herdsman-converters to 15.0.18 (#16023)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-08 09:01:56 +00:00
github-actions[bot]andKoenkk 30df0e25f9 Update zigbee-herdsman to 0.14.85 (#16020)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-08 08:44:31 +00:00
Koen Kanters e7735112e8 Fix Home Assistant Entity sensor.xxx (<class 'homeassistant.components.mqtt.sensor.MqttSensor'>) is using native unit of measurement '' which is not a valid unit for the device class ('illuminance') warning. https://github.com/Koenkk/zigbee2mqtt/issues/15958 2023-01-08 08:50:10 +01:00
github-actions[bot]andKoenkk b943feef29 Update dependencies (#16019)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-08 08:45:04 +01:00
Koen Kanters e92d3f4ede Promote to dev 2023-01-07 10:26:02 +01:00
Koen Kanters 044cd0b3a6 Merge branch 'master' into dev 2023-01-07 10:25:19 +01:00
github-actions[bot]andKoenkk 3351bc2f42 Update zigbee-herdsman to 0.14.84 (#15978)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-06 11:29:07 +01:00
github-actions[bot]andKoenkk 6a8d236b4d Update zigbee-herdsman-converters to 15.0.17 (#15977)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-06 10:26:52 +00:00
Koen Kanters 7d67ffc429 1.29.1 2023-01-06 11:07:47 +01:00
Koen Kanters f984734961 Update zigbee-herdsman-converters to v15.0.12-hotfix.0 2023-01-06 11:07:14 +01:00
Koen Kanters 217fbb284a Fix Home Assistant Template variable warning: 'dict object' has no attribute 'latest_version' when rendering '{{ value_json['update']['latest_version'] }}' error attempt 2. https://github.com/Koenkk/zigbee2mqtt/issues/15747 2023-01-06 10:41:43 +01:00
Koen Kanters 9fe48e2a88 Revert "Expose cover moving state to Home Assistant (#15555)"
This reverts commit 56f7f3e1bd.
2023-01-06 10:41:37 +01:00
Koen Kanters 1c7817ad77 Fix Home Assistant Template variable warning: 'dict object' has no attribute 'latest_version' when rendering '{{ value_json['update']['latest_version'] }}' error. https://github.com/Koenkk/zigbee2mqtt/issues/15747 2023-01-06 10:41:13 +01:00
github-actions[bot]andKoenkk cf801344f8 Update zigbee-herdsman-converters to 15.0.16 (#15947)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-04 19:00:11 +00:00
Koen Kanters 50bca161ce Fix Home Assistant Template variable warning: 'dict object' has no attribute 'latest_version' when rendering '{{ value_json['update']['latest_version'] }}' error attempt 2. https://github.com/Koenkk/zigbee2mqtt/issues/15747 2023-01-04 19:49:27 +01:00
github-actions[bot]andKoenkk 15ccf945c3 Update zigbee-herdsman-converters to 15.0.15 (#15906)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-03 10:27:14 +00:00
Koen Kanters d49f06f34d Revert "Expose cover moving state to Home Assistant (#15555)"
This reverts commit 56f7f3e1bd.
2023-01-03 10:59:20 +01:00
github-actions[bot]andKoenkk 826f03220d Update zigbee-herdsman-converters to 15.0.14 (#15876)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-02 09:12:10 +00:00
Koen Kanters cdb984f830 Fix Home Assistant Template variable warning: 'dict object' has no attribute 'latest_version' when rendering '{{ value_json['update']['latest_version'] }}' error. https://github.com/Koenkk/zigbee2mqtt/issues/15747 2023-01-02 09:18:36 +01:00
github-actions[bot]andKoenkk 4e40c8223f Update zigbee-herdsman-converters to 15.0.13 (#15852)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-01 10:27:09 +00:00
github-actions[bot]andKoenkk 02d86ab233 Update dependencies (#15848)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2023-01-01 11:13:54 +01:00
Koen Kanters a49079f560 Dev 2023-01-01 10:58:37 +01:00
Koen Kanters dddce571d3 1.29.0 2023-01-01 10:53:46 +01:00
Koen Kanters f1841377db Undev 2023-01-01 10:52:49 +01:00
Koen Kanters f3edfbf75b Update generateNewSupportedDevices.js 2023-01-01 10:52:02 +01:00
github-actions[bot]andnurikk d701d96bb2 Update zigbee2mqtt-frontend to 0.6.121 (#15845)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-12-31 19:11:30 +00:00
github-actions[bot]andKoenkk 3b9d6c5651 Update zigbee-herdsman-converters to 15.0.12 (#15837)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-31 09:36:55 +00:00
MattandKoen Kanters 19bd87de4a Keep cached device state until Zigbee2MQTT is stopped (#15770)
* Fix extension path to make debugginge easier in VScode

* Fix linting error

* Add setting "cache_state_persist_on_leave" (default false)

This setting does not remove a device from State if it leaves the network

* Merge from upstream kk/dev

* Re-define cache_state_persist_on_leave to be a timeout

Allows the config to specify how long the state should be held (and the device to re-join & maintain the state).

Remove all pending deletions if the system is stopped

* Add debug. Fix "time" test

* Disable esline warnings for long debug lines

* Simplify state maintenance for leave/join devices

* Restore default configuration.yaml

* Don't track device presence via events, but examine herdsman on system stop

* Update configuration.yaml

* Update state.ts

* Update state.ts

* Update controller.test.js

* Update eventBus.ts

* Update eventBus.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-12-31 10:15:11 +01:00
github-actions[bot]andKoenkk af27e910d8 Update zigbee-herdsman-converters to 15.0.11 (#15816)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-30 08:22:39 +00:00
github-actions[bot]andKoenkk d8f1f3ef06 Update zigbee-herdsman-converters to 15.0.10 (#15797)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-29 09:50:01 +00:00
Koen Kanters 5b2756fef3 Build linux/386 Docker image. https://github.com/Koenkk/zigbee2mqtt/issues/15796 2022-12-29 10:44:15 +01:00
github-actions[bot]andKoenkk 75db8cf3f1 Update zigbee-herdsman-converters to 15.0.9 (#15775)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-28 08:28:49 +00:00
github-actions[bot]andKoenkk b4660417f8 Update zigbee-herdsman-converters to 15.0.8 (#15764)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-27 08:28:19 +00:00
github-actions[bot]andKoenkk 75e677608b Update zigbee-herdsman-converters to 15.0.7 (#15757)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-26 11:43:44 +00:00
Matt 05cb1406bb Fix extension path to make debugging easier in VS Code (#15741)
* Fix extension path to make debugginge easier in VScode

* Fix linting error
2022-12-25 16:57:48 +01:00
github-actions[bot]andKoenkk 10c6d1e4d9 Update dependencies (#15746)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-25 16:40:03 +01:00
Koen Kanters 6d08a2f0f6 Use Node.js 18 in CI 2022-12-24 09:50:32 +01:00
Koen Kanters 8d8c46ecae Reduce Docker image size 2022-12-24 09:45:15 +01:00
Koen Kanters 1f642d86e8 Add disabled option (#15589)
* Add disabled option

* Updates

* Tests

* Add restart required
2022-12-23 23:56:29 +01:00
github-actions[bot]andKoenkk 5afda96cf4 Update zigbee-herdsman-converters to 15.0.6 (#15722)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-23 19:39:13 +00:00
github-actions[bot]andnurikk 2550ca5978 Update zigbee2mqtt-frontend to 0.6.120 (#15717)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-12-23 16:55:52 +00:00
github-actions[bot]andKoenkk 566fc625cd Update zigbee-herdsman-converters to 15.0.4 (#15703)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-22 17:24:59 +00:00
github-actions[bot]andKoenkk 7f9de55b6c Update zigbee-herdsman-converters to 15.0.3 (#15689)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-21 19:18:48 +00:00
github-actions[bot]andKoenkk ccb5b49c80 Update zigbee-herdsman to 0.14.83 (#15688)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-21 19:13:08 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> dea44579c3 Bump actions/stale from 6 to 7 (#15685)
Bumps [actions/stale](https://github.com/actions/stale) from 6 to 7.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-21 17:03:55 +01:00
github-actions[bot]andKoenkk 58445a2327 Update zigbee-herdsman to 0.14.82 (#15673)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-20 22:09:08 +00:00
github-actions[bot]andKoenkk 98cf8dbe5e Update zigbee-herdsman-converters to 15.0.2 (#15671)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-20 21:55:29 +00:00
github-actions[bot]andKoenkk 8fc83caac7 Update zigbee-herdsman-converters to 15.0.1 (#15651)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-19 20:07:35 +00:00
Miguel Cabral 56f7f3e1bd Expose cover moving state to Home Assistant (#15555) 2022-12-19 20:27:15 +01:00
Koen Kanters 01b46cf74e Use fileVersion for Home Assistant update sensor instead of softwareBuildID (#15630)
* Use fileVersion for Home Assistant update sensor instead of softwareBuildID. https://github.com/Koenkk/zigbee2mqtt/issues/15502

* Remove onlythis
2022-12-18 22:05:16 +01:00
github-actions[bot]andKoenkk 825c761c26 Update zigbee-herdsman-converters to 15.0.0 (#15631)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-18 21:04:48 +00:00
github-actions[bot]andKoenkk 443eb23a91 Update zigbee-herdsman-converters to 14.0.694 (#15624)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-18 13:01:34 +00:00
github-actions[bot]andKoenkk 9b78d85a46 Update dependencies (#15618)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-18 13:04:08 +01:00
6731c85981 Update zigbee-herdsman-converters to 14.0.693 (#15603)
* Update zigbee-herdsman-converters to 14.0.693

* fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-12-17 10:04:38 +00:00
github-actions[bot]andKoenkk da44667926 Update zigbee-herdsman-converters to 14.0.692 (#15573)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-15 20:02:58 +00:00
github-actions[bot]andKoenkk 3796084a27 Update zigbee-herdsman-converters to 14.0.691 (#15538)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-13 20:16:17 +00:00
Koen Kanters 4d32326a4f Fix failing configure blocking startup. https://github.com/Koenkk/zigbee2mqtt/issues/15299 2022-12-12 21:35:10 +01:00
github-actions[bot]andKoenkk 54d8002fd3 Update zigbee-herdsman-converters to 14.0.690 (#15517)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-12 20:31:55 +00:00
github-actions[bot]andKoenkk 21a30fc555 Update zigbee-herdsman-converters to 14.0.689 (#15490)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-11 09:44:07 +00:00
github-actions[bot]andKoenkk b90c0c4114 Update zigbee-herdsman to 0.14.81 (#15489)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-11 10:37:37 +01:00
github-actions[bot]andKoenkk e2deb23d77 Update dependencies (#15484)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-11 09:07:13 +01:00
github-actions[bot]andKoenkk b69d31d3ee Update zigbee-herdsman-converters to 14.0.688 (#15480)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-10 15:39:17 +00:00
github-actions[bot]andKoenkk 3481423810 Update zigbee-herdsman-converters to 14.0.687 (#15465)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-09 17:09:17 +00:00
github-actions[bot]andKoenkk d093200fec Update zigbee-herdsman to 0.14.80 (#15463)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-09 16:38:33 +00:00
eaf834a921 Update zigbee-herdsman to 0.14.79 (#15449)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-12-08 19:48:45 +01:00
github-actions[bot]andKoenkk 27377b0658 Update zigbee-herdsman-converters to 14.0.686 (#15448)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-08 18:40:40 +00:00
github-actions[bot]andKoenkk 2c53bc2c61 Update zigbee-herdsman-converters to 14.0.685 (#15430)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-07 19:15:23 +00:00
Gustav WestlingandKoen Kanters 83fae81724 docker: rebuild serialport from source (#15400)
* docker: rebuild serialport from source

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-12-07 17:54:24 +01:00
github-actions[bot]andKoenkk d075f0752e Update zigbee-herdsman-converters to 14.0.684 (#15399)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-06 17:21:51 +00:00
github-actions[bot]andKoenkk a29f90b441 Update zigbee-herdsman to 0.14.78 (#15398)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-06 17:11:48 +00:00
Koen Kanters 891392ff9a Revert "Fix Home Assistant installed_version error (#15369)" (#15396)
This reverts commit ba2d9aefe6.
2022-12-06 17:31:48 +01:00
Koen Kanters ba2d9aefe6 Fix Home Assistant installed_version error (#15369)
* Fix HA installed_version error

* add link
2022-12-05 16:52:11 +01:00
github-actions[bot]andKoenkk 586dda4d46 Update zigbee-herdsman-converters to 14.0.683 (#15356)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-04 20:09:14 +00:00
github-actions[bot]andKoenkk 1aa600ee59 Update zigbee-herdsman to 0.14.77 (#15355)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-04 19:56:20 +00:00
Pheel Tiandphil b0e352bfea Support HTTPS for frontend server (#15329)
* Adding 2 config params under 'frontend' : 'ssl_cert' and 'ssl_key' to contain file patch of certificate files to expose frontend in HTTPS.

* Taking all PR remarks in account.

Co-authored-by: phil <phil@8godsprod.com>
2022-12-04 19:33:04 +01:00
github-actions[bot]andKoenkk 959ca95219 Update dependencies (#15342)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-04 19:13:38 +01:00
github-actions[bot]andKoenkk 54bd9aa024 Update zigbee-herdsman-converters to 14.0.682 (#15320)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-02 16:55:00 +00:00
github-actions[bot]andKoenkk 0e4ea6a335 Update zigbee-herdsman-converters to 14.0.681 (#15287)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-01 19:18:59 +00:00
Koen Kanters ab1261385b Promote to dev 2022-12-01 19:59:17 +01:00
Koen Kanters 52e545f900 1.28.4 2022-12-01 19:58:42 +01:00
Koen Kanters 350abb354b Undev 2022-12-01 19:58:39 +01:00
Koen Kanters 87f253997c Update zhc to 14.0.681-hotfix.0 2022-12-01 19:56:37 +01:00
Koen Kanters 4e9b18fcbf Promote to dev 2022-12-01 17:38:11 +01:00
Koen Kanters e43c371d76 1.28.3 2022-12-01 17:35:02 +01:00
Koen Kanters a7e85a0bd9 Undev 2022-12-01 17:34:47 +01:00
Koen Kanters 7f6f6a69c7 Merge remote-tracking branch 'origin/master' into dev 2022-12-01 17:33:55 +01:00
github-actions[bot]andKoenkk 87667bdac7 Update zigbee-herdsman-converters to 14.0.680 (#15276)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-12-01 15:02:29 +00:00
github-actions[bot]andKoenkk bd8edd70bb Update zigbee-herdsman-converters to 14.0.679 (#15262)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-30 16:06:01 +00:00
github-actions[bot]andKoenkk 4a3e6b9561 Update zigbee-herdsman-converters to 14.0.678 (#15249)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-29 18:45:39 +00:00
Artem Draft f92134fc5f Disable by default update_available sensor in HA (#15237) 2022-11-29 19:18:33 +01:00
9dba2d7f11 Update zigbee-herdsman-converters to 14.0.677 (#15229)
* Update zigbee-herdsman-converters to 14.0.677

* Fix

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-28 18:49:34 +00:00
9289a26f11 Update dependencies (#15204)
* Update dependencies

* Fix diff

* fix

* update

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-27 14:52:47 +01:00
github-actions[bot]andKoenkk 17054627e9 Update zigbee-herdsman-converters to 14.0.676 (#15207)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-27 09:38:39 +00:00
github-actions[bot]andKoenkk 66c4ca072e Update zigbee-herdsman-converters to 14.0.675 (#15190)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-26 09:32:55 +00:00
github-actions[bot]andKoenkk 3b221d4fb0 Update zigbee-herdsman-converters to 14.0.674 (#15168)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-24 16:40:12 +00:00
github-actions[bot]andKoenkk 4464554f90 Update zigbee-herdsman to 0.14.76 (#15167)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-24 16:32:05 +00:00
b15cd433c4 Update zigbee-herdsman-converters to 14.0.673 (#15150)
* Update zigbee-herdsman-converters to 14.0.673

* Update homeassistant.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-23 17:56:32 +00:00
github-actions[bot]andKoenkk 4b5a03c6c5 Update zigbee-herdsman to 0.14.75 (#15149)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-23 16:10:46 +00:00
github-actions[bot]andKoenkk ca4badca4d Update zigbee-herdsman-converters to 14.0.672 (#15133)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-22 19:03:36 +00:00
DJTerentjevandAlex 1b3dd7540b Add polling when bounded for Trust and Gledopto (#15126)
* GitHub Workflows security hardening (#14799)

* build: harden update_frontend.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden update_zhc.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden ghcr_cleanup.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden update_zh.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* Add bound polling by manufacturerNames

Based on:
#7825

* Add bound polling by manufacturerNames

Based on:
#7825

Signed-off-by: Alex <aleksandrosansan@gmail.com>
Co-authored-by: Alex <aleksandrosansan@gmail.com>
2022-11-22 19:35:15 +01:00
Koen Kanters c7183ca080 Update external converter tester. 2022-11-22 19:16:25 +01:00
Koen Kanters 119531e9e2 Add external converter tester 2022-11-22 19:12:03 +01:00
85be7d28d5 Update zigbee-herdsman-converters to 14.0.671 (#15123)
* Update zigbee-herdsman-converters to 14.0.671

* Update homeassistant.ts

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-21 19:35:37 +00:00
github-actions[bot]andnurikk 6c147dae6c Update zigbee2mqtt-frontend to 0.6.119 (#15109)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-11-20 20:48:42 +00:00
github-actions[bot]andKoenkk 1fe138c34c Update zigbee-herdsman-converters to 14.0.670 (#15107)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-20 18:26:44 +00:00
github-actions[bot]andKoenkk 1258aee464 Update zigbee-herdsman to 0.14.74 (#15105)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-20 16:35:01 +00:00
github-actions[bot]andnurikk fbb0ed0e67 Update zigbee2mqtt-frontend to 0.6.118 (#15083)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-11-19 11:16:56 +00:00
github-actions[bot]andKoenkk 8510e99010 Update zigbee-herdsman-converters to 14.0.669 (#15053)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-17 17:07:37 +00:00
Koen Kanters 342955666a Fix 'dict object' has no attribute 'installed_version'. https://github.com/Koenkk/zigbee2mqtt/discussions/15039 2022-11-17 17:52:59 +01:00
github-actions[bot]andKoenkk 50cb421f64 Update zigbee-herdsman-converters to 14.0.668 (#15007)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-15 19:38:26 +00:00
github-actions[bot]andnurikk 16398b7810 Update zigbee2mqtt-frontend to 0.6.117 (#14995)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-11-15 11:36:57 +00:00
github-actions[bot]andKoenkk f3b5aee173 Update zigbee-herdsman-converters to 14.0.667 (#14983)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-14 20:16:38 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> e8f85b35c1 Bump actions/dependency-review-action from 2 to 3 (#14978)
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 2 to 3.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 18:13:49 +01:00
github-actions[bot]andKoenkk dd8f13aa8d Update zigbee-herdsman to 0.14.73 (#14979)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-14 17:07:35 +00:00
dreed47 ced2ba7344 small clarification to the description for adding a user-defined device icon (#14960)
* small clarification to the description for adding a user-defined device icon

* small wording change
2022-11-14 17:49:18 +01:00
Jakub Jirutka a2f8534823 Allow to specify full file name in value reference '!' (#14955)
* Extract parsing of value reference '!' in settings into a function

* Allow to specify full file name in value reference '!'

This `network_key: '!secret network_key'` is really confusing because
it looks like a YAML tag named 'secret' and a value "network_key".
When we write `network_key: '!secret.yaml network_key'` instead, it's
a little clearer what's going on. Also, it's more consistent with file
references in 'devices' and 'groups'.
2022-11-13 15:17:59 +01:00
github-actions[bot]andKoenkk d05ef70901 Update zigbee-herdsman to 0.14.72 (#14958)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-13 09:26:45 +00:00
Jakub JirutkaandKoen Kanters 4bc0c3ed6b Use path.resolve instead of path.join in data.joinPath (#14953)
This allows specifying a path outside of the data directory using an
absolute path (e.g. /path/to/devices.yaml) or a path relative to the data
directory (e.g. devices.yaml, foo/devices.yaml, ../../devices.yaml, ...).
This change is backward compatible because file names and nested paths are
just a special case of a relative path.

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-13 09:24:47 +01:00
Koen Kanters 489d1de756 Fix Cannot set properties of undefined (setting 'installed_version'). https://github.com/Koenkk/zigbee2mqtt/issues/14917 2022-11-13 09:21:27 +01:00
github-actions[bot]andKoenkk 499b993410 Update zigbee-herdsman to 0.14.71 (#14946)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-12 15:20:46 +00:00
github-actions[bot]andKoenkk 9f0b16291a Update zigbee-herdsman-converters to 14.0.666 (#14930)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-11 16:16:51 +00:00
github-actions[bot]andKoenkk 98a6a2dfe8 Update zigbee-herdsman-converters to 14.0.665 (#14916)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-10 17:05:54 +00:00
Koen Kanters fb14ba20ca Update Docker image to use node:18-alpine3.16 (#14915) 2022-11-10 17:48:17 +01:00
Koen Kanters b68b984de6 Log Zigbee2MQTT started! on startup. https://github.com/Koenkk/zigbee2mqtt/issues/14283 2022-11-10 17:45:48 +01:00
Koen Kanters 1d36dfd932 Support Home Assistant MQTT update #14748 (#14905) 2022-11-09 21:01:30 +01:00
github-actions[bot]andKoenkk 672da64913 Update zigbee-herdsman-converters to 14.0.664 (#14900)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-09 18:53:08 +00:00
github-actions[bot]andKoenkk cb29e164f8 Update zigbee-herdsman-converters to 14.0.663 (#14889)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-08 18:20:43 +00:00
Vincenzo Mantova 1e6a457190 more Home Assistant icons (#14865)
* add missing icons and classes for BRT-100-TRV (and possibly others)

* use high/low thermometer icons for max/min temperatures
2022-11-08 16:24:19 +01:00
github-actions[bot]andKoenkk cd22dafc89 Update zigbee-herdsman-converters to 14.0.662 (#14860)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-07 17:34:17 +00:00
github-actions[bot]andKoenkk 83d8a0e6a2 Update zigbee-herdsman to 0.14.70 (#14858)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-07 17:06:27 +00:00
Vincenzo Mantova e0b765ba88 Revert "Respect climate system_mode ACCESS_SET bit in Home Assistant (#14715)" (#14842)
This reverts commit 58c800181a.
2022-11-07 17:38:30 +01:00
5e2df18b75 Update zigbee-herdsman-converters to 14.0.661 (#14839)
* Update zigbee-herdsman-converters to 14.0.661

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-06 14:42:08 +00:00
github-actions[bot]andKoenkk 9b48334e0e Update zigbee-herdsman to 0.14.69 (#14838)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-06 12:51:48 +00:00
github-actions[bot]andKoenkk c8ae15e92d Update dependencies (#14834)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-06 13:37:56 +01:00
John DoeandAinur Timerbaev f88ac154a2 Mark node v19 as supported (#14837)
* Mark node19 as supported

* Fix condition

* Fix tests

Co-authored-by: Ainur Timerbaev <ainur.timerbaev@superawesome.com>
2022-11-06 12:28:59 +00:00
Alex e66fe8534e GitHub Workflows security hardening (#14799)
* build: harden update_frontend.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden update_zhc.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden ghcr_cleanup.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden update_zh.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

Signed-off-by: Alex <aleksandrosansan@gmail.com>
2022-11-05 14:21:55 +01:00
Jakub Jirutka c2e95bdb6a Remove core-js polyfills (#14788)
According to engines.node in package.json, the minimal supported version
of Node.js is 14.

* `Object.fromEntries()` is supported by Node.js since 12.0.0
* `Array.prototype.flat()` is supported by Node.js since 11.0.0

These polyfills were added in #9085, but the minimum supported Node.js
version has since been raised to 14.
2022-11-05 14:17:53 +01:00
github-actions[bot]andnurikk 7c5ef8a3d6 Update zigbee2mqtt-frontend to 0.6.115 (#14816)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-11-05 09:59:34 +00:00
Koen Kanters 4a2190f969 Add back fsevents 2022-11-04 19:35:14 +01:00
github-actions[bot]andKoenkk a3ed236524 Update dependencies (#14810)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-04 17:08:56 +01:00
Koen Kanters f4d8e6f4c5 Merge branch 'master' into dev 2022-11-04 17:05:54 +01:00
Koen Kanters 360a777a4e 1.28.2 2022-11-04 16:53:33 +01:00
Koen Kanters 5ed8b36cf2 Bump zigbee-herdsman-converters to 14.0.657-hotfix.0 2022-11-04 16:52:53 +01:00
github-actions[bot]andKoenkk 9540b6c182 Update zigbee-herdsman-converters to 14.0.660 (#14792)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-03 18:43:32 +00:00
Koen Kanters 31f002294e Update README.md 2022-11-02 22:00:25 +01:00
ecfc7e8906 Update zigbee-herdsman-converters to 14.0.659 (#14780)
* Update zigbee-herdsman-converters to 14.0.659

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-11-02 20:56:54 +00:00
Koen Kanters 60bf855e74 Fix starting via cli.js. https://github.com/Koenkk/zigbee2mqtt/pull/14396 2022-11-02 20:01:06 +01:00
Koen Kanters c3f6e793fa Promote to dev 2022-11-01 19:59:25 +01:00
Koen Kanters 48117fddfa 1.28.1 2022-11-01 19:58:47 +01:00
Koen Kanters 7e70a5984f Undev 2022-11-01 19:58:44 +01:00
github-actions[bot]andKoenkk 4589c9f691 Update zigbee-herdsman-converters to 14.0.657 (#14753)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-01 18:51:21 +00:00
github-actions[bot]andKoenkk d81c15b5af Update zigbee-herdsman to 0.14.68 (#14754)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-01 16:44:28 +00:00
github-actions[bot]andKoenkk 043ae738d2 Update zigbee-herdsman to 0.14.67 (#14752)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-11-01 16:07:35 +00:00
github-actions[bot]andKoenkk 68184d669e Update zigbee-herdsman-converters to 14.0.655 (#14734)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-31 18:20:01 +00:00
github-actions[bot]andKoenkk fb3ee70c7a Update zigbee-herdsman-converters to 14.0.654 (#14727)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-30 19:07:00 +00:00
github-actions[bot]andKoenkk c5697e6c2b Update dependencies (#14718)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-30 19:23:11 +01:00
Vincenzo Mantova 58c800181a Respect climate system_mode ACCESS_SET bit in Home Assistant (#14715) 2022-10-30 19:16:32 +01:00
github-actions[bot]andKoenkk fd023268c5 Update zigbee-herdsman-converters to 14.0.652 (#14708)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-29 15:50:52 +00:00
github-actions[bot]andKoenkk 9dc93c7d27 Update zigbee-herdsman-converters to 14.0.651 (#14700)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-29 08:21:29 +00:00
Koen Kanters c943992e49 Fix 60de5b7676 2022-10-27 21:49:25 +02:00
github-actions[bot]andKoenkk dd9e92f81f Update zigbee-herdsman-converters to 14.0.650 (#14677)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-27 21:46:16 +02:00
Koen Kanters 60de5b7676 Respond with NO_IMAGE_AVAILABLE when device requests OTA. https://github.com/Koenkk/zigbee2mqtt/issues/13396 2022-10-27 20:39:44 +02:00
github-actions[bot]andKoenkk 6c0430b6e2 Update zigbee-herdsman-converters to 14.0.649 (#14660)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-26 16:57:24 +00:00
github-actions[bot]andKoenkk ddc4345f01 Update zigbee-herdsman-converters to 14.0.648 (#14633)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-24 17:49:52 +00:00
Koen Kanters 41053aa024 Set NODE_ENV to PRODUTION in Docker container. https://github.com/Koenkk/zigbee2mqtt/discussions/14625 2022-10-24 19:30:40 +02:00
github-actions[bot]andKoenkk 08ceae235e Update dependencies (#14602)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-23 09:09:56 +02:00
github-actions[bot]andKoenkk 599380dd63 Update zigbee-herdsman-converters to 14.0.647 (#14592)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-22 15:58:08 +00:00
github-actions[bot]andKoenkk a426ee1041 Update zigbee-herdsman-converters to 14.0.646 (#14576)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-21 14:44:53 +00:00
github-actions[bot]andKoenkk 939fdf0496 Update zigbee-herdsman-converters to 14.0.645 (#14553)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-19 15:59:22 +00:00
github-actions[bot]andKoenkk 3cffc2fdd8 Update zigbee-herdsman to 0.14.66 (#14549)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-19 15:26:35 +00:00
github-actions[bot]andKoenkk 22d2170d41 Update zigbee-herdsman-converters to 14.0.644 (#14540)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-18 18:16:04 +00:00
Vladyslav Pavlov 50a9de4e2b Expose step size of local_temperature_calibration Home Assistant sensor (#14502) 2022-10-18 17:59:32 +02:00
github-actions[bot]andKoenkk 2c12cbaf18 Update zigbee-herdsman to 0.14.65 (#14538)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-18 15:50:13 +00:00
github-actions[bot]andKoenkk ef6826f263 Update dependencies (#14503)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-18 17:38:26 +02:00
github-actions[bot]andKoenkk ceeaabafbc Update zigbee-herdsman-converters to 14.0.643 (#14458)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-12 19:47:13 +00:00
github-actions[bot]andKoenkk c49f5b157d Update zigbee-herdsman-converters to 14.0.642 (#14444)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-11 18:52:33 +00:00
github-actions[bot]andKoenkk 0a71e39253 Update zigbee-herdsman-converters to 14.0.641 (#14426)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-10 15:20:46 +00:00
github-actions[bot]andKoenkk 52a0f68c87 Update zigbee-herdsman-converters to 14.0.640 (#14416)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-09 18:19:11 +00:00
github-actions[bot]andKoenkk 457fc9da7c Update dependencies (#14411)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-09 09:01:32 +02:00
github-actions[bot]andKoenkk 5b39884c13 Update zigbee-herdsman-converters to 14.0.639 (#14403)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-08 12:18:16 +00:00
Matt 4d7b1a6c03 Allow Zigbee2MQTT to be installed as a module (#14396)
* Fix mnodule resolution

Allows the correct module path to be found if installed as a package

* Correct signature to avoid TS error

* Allow module to be included in another module

Only create hash ot auto-start if it is the main module, otherwise export the `start` function
2022-10-08 10:48:15 +02:00
Koen Kanters 50b5c67dde Support effects for Home Assistant light groups. #13438 2022-10-08 10:22:26 +02:00
Ben Windsor 005ada0237 Make temperature sensor selection for thermostats appear as a config item in HA (#14376) 2022-10-07 16:58:06 +02:00
github-actions[bot]andKoenkk e9b1080734 Update zigbee-herdsman-converters to 14.0.638 (#14374)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-06 16:12:23 +00:00
Ben Windsor 56cc1432e9 Mark min_temperature_limit as a config variable for HA (#14358) 2022-10-06 17:31:48 +02:00
github-actions[bot]andKoenkk e3dcc7b0a6 Update zigbee-herdsman-converters to 14.0.637 (#14353)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-05 19:08:45 +00:00
github-actions[bot]andKoenkk 37aea8df8f Update zigbee-herdsman to 0.14.64 (#14348)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-05 14:30:54 +00:00
github-actions[bot]andKoenkk f8d64b67ad Update zigbee-herdsman-converters to 14.0.636 (#14331)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-04 17:30:49 +00:00
github-actions[bot]andKoenkk 77fc3a9308 Update dependencies (#14279)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-04 19:26:54 +02:00
Ben Windsor db3730ea44 Expose value_step to home assistant if it has been set on a numeric type (#14313) 2022-10-04 18:02:35 +02:00
github-actions[bot]andnurikk 98ceaa04bb Update zigbee2mqtt-frontend to 0.6.114 (#14290)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-10-02 16:51:48 +00:00
github-actions[bot]andnurikk e3e4a0a440 Update zigbee2mqtt-frontend to 0.6.113 (#14271)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-10-01 09:41:07 +00:00
github-actions[bot]andKoenkk 52150b7257 Update zigbee-herdsman to 0.14.63 (#14270)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-01 08:53:48 +00:00
Koen Kanters 5727fe3a49 Dev 2022-10-01 09:40:35 +02:00
Koen Kanters 03ba647dc6 1.28.0 2022-10-01 09:39:09 +02:00
Koen Kanters be1e9b4421 Undev 2022-10-01 09:38:55 +02:00
github-actions[bot]andKoenkk 57ce1e98a7 Update zigbee-herdsman-converters to 14.0.635 (#14268)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-10-01 07:33:47 +00:00
github-actions[bot]andKoenkk 3d2d4fd298 Update zigbee-herdsman-converters to 14.0.633 (#14262)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-30 18:58:14 +00:00
github-actions[bot]andKoenkk 2258ed1dfa Update zigbee-herdsman to 0.14.62 (#14259)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-30 18:02:25 +00:00
github-actions[bot]andKoenkk 2d750f8b9a Update zigbee-herdsman-converters to 14.0.632 (#14254)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-29 20:31:02 +00:00
b54e29917e Update zigbee-herdsman to 0.14.61 (#14238)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-09-28 18:28:27 +00:00
Markus WegmannandKoen Kanters 3b60a8e02a Fix cover state publishing of multi-endpoint devices (#14200)
* Fix cover state publishing of multi-endpoint devices

* WIP testing

* WIP test for multiEndpoint cover device

* WIP zigfred plus test

* WIP zigfred plus test

* Remove zigfred plus meta testing flag

* Working zigfred plus integration into bridge test

* Working integration of zigfred plus in tests

* WIP zigfred plus testing

* Add working test for multi-cover devices. Working cover state for multi-cover + multi-light devices.

* Fix republishing of cover state

* Fix cover position and tilt readout with postfix topic

* Fix homeassistant.test.js for zigfred plus cover

* Fix cover value template to support multi-cover devices

* Update homeassistant.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-09-28 20:21:30 +02:00
github-actions[bot]andKoenkk a95d47fef9 Update zigbee-herdsman-converters to 14.0.631 (#14232)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-28 15:14:56 +00:00
github-actions[bot]andKoenkk d385d6c1af Update zigbee-herdsman to 0.14.60 (#14231)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-28 15:12:36 +00:00
github-actions[bot]andnurikk 3453585fd0 Update zigbee2mqtt-frontend to 0.6.112 (#14216)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-09-27 15:55:09 +00:00
github-actions[bot]andKoenkk 7b72b85cf7 Update zigbee-herdsman-converters to 14.0.630 (#14186)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-25 08:15:30 +00:00
github-actions[bot]andKoenkk 47378c46bd Update dependencies (#14180)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-25 09:16:35 +02:00
github-actions[bot]andKoenkk 647d45c4fa Update zigbee-herdsman-converters to 14.0.629 (#14171)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-23 20:03:53 +00:00
github-actions[bot]andKoenkk 6775423b86 Update zigbee-herdsman to 0.14.59 (#14167)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-23 18:13:43 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 3413d472ab Bump actions/stale from 5 to 6 (#14160)
Bumps [actions/stale](https://github.com/actions/stale) from 5 to 6.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-23 19:49:49 +02:00
github-actions[bot]andKoenkk d654e085ae Update zigbee-herdsman-converters to 14.0.628 (#14143)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-22 18:24:44 +00:00
github-actions[bot]andKoenkk 802803479e Update zigbee-herdsman to 0.14.58 (#14142)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-22 18:00:13 +00:00
github-actions[bot]andKoenkk 639babd9ab Update zigbee-herdsman-converters to 14.0.627 (#14127)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-21 18:05:46 +00:00
Koen Kanters 49f7a5ca1d Improve Home Assistant history view for sensors without unit. #14103 2022-09-21 17:11:03 +02:00
github-actions[bot]andKoenkk 615c70f3bb Update zigbee-herdsman to 0.14.57 (#14102)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-20 14:59:08 +00:00
github-actions[bot]andKoenkk 9b4a03c0e8 Update zigbee-herdsman-converters to 14.0.626 (#14083)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-19 16:17:25 +00:00
github-actions[bot]andKoenkk 0ccfb5aded Update zigbee-herdsman to 0.14.56 (#14082)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-19 18:01:46 +02:00
NoneangelandKoen Kanters 1966456814 Add HVAC swing mode to Home Assistant discovery (#13784)
* hvac swing mode

* test: add GW003-AS-IN-TE-FC to tested devices

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-09-19 17:56:58 +02:00
github-actions[bot]andKoenkk 925714022f Update dependencies (#14052)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-19 17:39:10 +02:00
github-actions[bot]andKoenkk 1e24734a6c Update zigbee-herdsman-converters to 14.0.625 (#14022)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-16 07:50:35 +00:00
github-actions[bot]andKoenkk c4fc5335d5 Update zigbee-herdsman to 0.14.55 (#14017)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-15 08:44:52 +00:00
github-actions[bot]andKoenkk 0133afaef0 Update zigbee-herdsman-converters to 14.0.624 (#14016)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-15 08:15:30 +00:00
github-actions[bot]andKoenkk 4d0fd3275b Update zigbee-herdsman-converters to 14.0.623 (#14004)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-14 07:41:56 +00:00
5f992cae76 Update zigbee-herdsman-converters to 14.0.622 (#13994)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-09-13 08:04:17 +00:00
Koen Kanters 5a24e62b51 Fix #ba1e3a06b62d9b53f456065f18807410333da3fd 2022-09-13 10:00:22 +02:00
Koen Kanters ba1e3a06b6 Fix cover value_template properties for multi endpoint devices. #13944 2022-09-13 09:16:24 +02:00
github-actions[bot]andKoenkk 809f5d3ed1 Update zigbee-herdsman-converters to 14.0.621 (#13977)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-12 09:25:13 +00:00
Koen Kanters 125ca61812 Log MQTT disconnect reason. #13965 2022-09-12 09:34:20 +02:00
Koen Kanters d38b8ff5f1 Fix cover state in Home Assistant for multi channel cover controllers. #13944 2022-09-12 09:30:07 +02:00
github-actions[bot]andKoenkk 3f7e9941e2 Update zigbee-herdsman-converters to 14.0.619 (#13961)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-11 08:13:59 +00:00
github-actions[bot]andKoenkk 8ba0fe9367 Update dependencies (#13955)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-11 09:39:20 +02:00
github-actions[bot]andKoenkk cbf75d6339 Update zigbee-herdsman-converters to 14.0.618 (#13949)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-10 07:51:44 +00:00
github-actions[bot]andKoenkk 0ea528f750 Update zigbee-herdsman-converters to 14.0.617 (#13936)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-09 07:51:25 +00:00
github-actions[bot]andKoenkk d12b6e0ca9 Update zigbee-herdsman to 0.14.54 (#13935)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-09 07:20:30 +00:00
github-actions[bot]andKoenkk 2b1d1ff6ef Update zigbee-herdsman-converters to 14.0.616 (#13915)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-08 08:11:04 +00:00
github-actions[bot]andKoenkk fc7de95d1d Update zigbee-herdsman-converters to 14.0.614 (#13897)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-07 08:16:05 +00:00
Koen Kanters 2bca5deb66 Fix setting devices/groups to file via environment variables not working. #7807 2022-09-07 10:07:16 +02:00
github-actions[bot]andKoenkk 8be8c4df56 Update zigbee-herdsman-converters to 14.0.613 (#13883)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-06 08:56:30 +00:00
Koen KantersandJohn Doe 9519ffdac7 Add install code support (#13780)
* Add install code support

* Update bridge.ts

Co-authored-by: John Doe <nurikk@users.noreply.github.com>
2022-09-06 09:30:03 +02:00
github-actions[bot]andKoenkk 0b645a4e6a Update zigbee-herdsman-converters to 14.0.611 (#13868)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-05 08:02:00 +00:00
github-actions[bot]andKoenkk 67a94621ab Update dependencies (#13842)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-05 09:10:10 +02:00
github-actions[bot]andnurikk 24d83b05f7 Update zigbee2mqtt-frontend to 0.6.111 (#13841)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-09-03 21:26:02 +00:00
Koen Kanters 178f72c304 Promote to dev 2022-09-01 11:27:14 +02:00
Koen Kanters 7dc48fb6d6 1.27.2 2022-09-01 11:24:20 +02:00
Koen Kanters 5017f556fa Undev 2022-09-01 11:24:17 +02:00
github-actions[bot]andKoenkk 437eeb350c Update zigbee-herdsman to 0.14.53 (#13793)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-01 11:23:29 +02:00
github-actions[bot]andKoenkk cfd792dc70 Update zigbee-herdsman to 0.14.52 (#13792)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-09-01 09:11:55 +00:00
Koen Kanters 2a4722bd38 Promote to dev 2022-09-01 08:42:29 +02:00
Koen Kanters d381f2daa4 1.27.1 2022-09-01 08:41:47 +02:00
Koen Kanters b05b4adf57 Undev 2022-09-01 08:40:53 +02:00
Koen Kanters 96d72103f2 Merge branch 'dev' 2022-09-01 08:37:54 +02:00
github-actions[bot]andKoenkk 97ffa9610b Update zigbee-herdsman-converters to 14.0.610 (#13782)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-31 16:46:59 +00:00
github-actions[bot]andKoenkk 09d6c8601c Update zigbee-herdsman to 0.14.51 (#13781)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-31 16:04:14 +00:00
github-actions[bot]andKoenkk fc409a6884 Update zigbee-herdsman-converters to 14.0.609 (#13769)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-30 15:38:45 +00:00
github-actions[bot]andnurikk fa63ede4b6 Update zigbee2mqtt-frontend to 0.6.110 (#13757)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-08-29 19:21:24 +00:00
github-actions[bot]andKoenkk fd24c8186e Update zigbee-herdsman to 0.14.50 (#13753)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-29 18:06:26 +00:00
github-actions[bot]andKoenkk 0816d07b93 Update zigbee-herdsman-converters to 14.0.608 (#13752)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-29 16:39:36 +00:00
github-actions[bot]andnurikk c1b9345613 Update zigbee2mqtt-frontend to 0.6.109 (#13748)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-08-29 10:30:15 +00:00
github-actions[bot]andKoenkk 7f198d18ac Update zigbee-herdsman-converters to 14.0.607 (#13739)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-28 17:49:58 +00:00
github-actions[bot]andKoenkk 802bccd1f3 Update zigbee-herdsman to 0.14.49 (#13736)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-28 15:26:35 +00:00
github-actions[bot]andKoenkk 77bd76d1ca Update zigbee-herdsman-converters to 14.0.606 (#13710)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-27 08:14:22 +00:00
github-actions[bot]andKoenkk 8dd8b2848c Update zigbee-herdsman-converters to 14.0.605 (#13703)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-26 19:23:43 +00:00
github-actions[bot]andKoenkk c5d54a845a Update zigbee-herdsman-converters to 14.0.604 (#13687)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-25 16:04:17 +00:00
github-actions[bot]andKoenkk f1a19151fc Update zigbee-herdsman-converters to 14.0.603 (#13670)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-24 17:08:37 +00:00
963c2d86d3 Update zigbee-herdsman-converters to 14.0.602 (#13654)
* Update zigbee-herdsman-converters to 14.0.602

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-08-23 19:53:49 +00:00
9e6b4083b2 Update zigbee-herdsman-converters to 14.0.601 (#13646)
* Update zigbee-herdsman-converters to 14.0.601

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-08-22 18:06:45 +00:00
github-actions[bot]andKoenkk f29c4a24c2 Update zigbee-herdsman-converters to 14.0.600 (#13634)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-21 18:23:36 +00:00
github-actions[bot]andKoenkk a75e1c2b2b Update dependencies (#13630)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-21 09:30:25 +02:00
github-actions[bot]andKoenkk 62499483ce Update zigbee-herdsman-converters to 14.0.599 (#13618)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-20 07:39:24 +00:00
github-actions[bot]andKoenkk 304bb7b9d1 Update zigbee-herdsman-converters to 14.0.598 (#13611)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-19 19:06:19 +00:00
github-actions[bot]andKoenkk 15a069e3c7 Update zigbee-herdsman to 0.14.48 (#13610)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-19 19:01:11 +00:00
Koen Kanters e0a9323d6e Update dont-stale label 2022-08-19 20:57:44 +02:00
github-actions[bot]andKoenkk a0182c2e39 Update zigbee-herdsman-converters to 14.0.597 (#13596)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-18 17:23:05 +00:00
github-actions[bot]andKoenkk 327f816c0e Update zigbee-herdsman-converters to 14.0.596 (#13586)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-17 18:29:55 +00:00
github-actions[bot]andnurikk 040d2a1b36 Update zigbee2mqtt-frontend to 0.6.108 (#13573)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-08-16 20:51:02 +00:00
github-actions[bot]andKoenkk 497a48b8b0 Update zigbee-herdsman-converters to 14.0.595 (#13569)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-16 18:59:33 +00:00
github-actions[bot]andKoenkk 36a4754430 Update zigbee-herdsman-converters to 14.0.594 (#13542)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-14 16:29:56 +00:00
Koen Kanters 60b9f6f6b2 Home Assistant discovery: add enums with only SET (e.g. selftest). https://github.com/Koenkk/zigbee2mqtt/issues/13532 2022-08-14 18:22:35 +02:00
github-actions[bot]andKoenkk 2bdc7b7aca Update dependencies (#13535)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-14 09:58:14 +02:00
github-actions[bot]andKoenkk fea5d44a57 Update zigbee-herdsman-converters to 14.0.593 (#13517)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-12 14:59:07 +00:00
Koen Kanters 281e3870d3 Fix tests 2022-08-11 20:32:01 +02:00
Koen Kanters c9b2a7f6d4 Revert "Publish device and bridge availability when Home Assistant comes online. https://github.com/Koenkk/zigbee2mqtt/issues/13382"
This reverts commit 619d5232db.
2022-08-11 20:23:40 +02:00
Koen Kanters 6314b86d9b Better fix for #13382 2022-08-11 20:23:19 +02:00
Koen Kanters 619d5232db Publish device and bridge availability when Home Assistant comes online. https://github.com/Koenkk/zigbee2mqtt/issues/13382 2022-08-11 19:50:46 +02:00
Koen Kanters da4a3b9a77 Fix exception when using group remove_all. https://github.com/Koenkk/zigbee2mqtt/issues/13484 2022-08-10 22:38:04 +02:00
github-actions[bot]andKoenkk 62284dbd1a Update zigbee-herdsman-converters to 14.0.592 (#13489)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-10 17:41:21 +00:00
wysiwyng addb09275a Add category and icon for flip_indicator_light Home Assistant discovery (#13477) 2022-08-10 16:57:31 +02:00
github-actions[bot]andKoenkk 9c45a5fdf0 Update zigbee-herdsman-converters to 14.0.591 (#13469)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-09 15:06:24 +00:00
Koen Kanters 0aa29a0fab Home Assistant discovery: always expose cover state. https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/issues/359 2022-08-09 17:01:22 +02:00
github-actions[bot]andKoenkk 5f778a7570 Update zigbee-herdsman-converters to 14.0.590 (#13458)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-08 15:54:36 +00:00
github-actions[bot]andKoenkk e8f6def246 Update zigbee-herdsman-converters to 14.0.589 (#13447)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-07 16:27:47 +00:00
github-actions[bot]andKoenkk 99485fa324 Update dependencies (#13441)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-07 09:20:22 +02:00
github-actions[bot]andKoenkk 483ff4aa8a Update zigbee-herdsman-converters to 14.0.588 (#13424)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-06 08:02:28 +00:00
github-actions[bot]andKoenkk b6c0afc129 Update zigbee-herdsman-converters to 14.0.587 (#13402)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-04 19:55:35 +00:00
github-actions[bot]andKoenkk 7def5ea9bf Update zigbee-herdsman to 0.14.47 (#13394)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-03 16:06:19 +00:00
github-actions[bot]andKoenkk 4e590ece19 Update zigbee-herdsman-converters to 14.0.586 (#13376)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-02 17:42:22 +00:00
c2faa3815a Update zigbee-herdsman-converters to 14.0.585 (#13362)
* Update zigbee-herdsman-converters to 14.0.585

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-08-01 18:12:28 +00:00
Koen Kanters 52f8753a09 Promote to dev 2022-08-01 17:44:02 +02:00
Koen Kanters a9b8808237 1.27.0 2022-08-01 17:43:26 +02:00
Koen Kanters 26b323e1f6 Undev 2022-08-01 17:43:20 +02:00
Koen Kanters 5990bb384a Merge branch 'dev' 2022-08-01 17:42:35 +02:00
github-actions[bot]andKoenkk be70b83be5 Update zigbee-herdsman-converters to 14.0.583 (#13355)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-08-01 15:08:54 +00:00
github-actions[bot]andKoenkk 7f28c557cd Update dependencies (#13340)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-31 09:55:29 +02:00
github-actions[bot]andKoenkk b1f9f5f3b3 Update zigbee-herdsman-converters to 14.0.582 (#13332)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-30 08:52:22 +00:00
github-actions[bot]andKoenkk f5740021a1 Update zigbee-herdsman-converters to 14.0.581 (#13327)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-29 15:16:24 +00:00
github-actions[bot]andKoenkk 2996cfaf07 Update zigbee-herdsman-converters to 14.0.580 (#13321)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-28 16:33:03 +00:00
github-actions[bot]andKoenkk eda087af99 Update zigbee-herdsman-converters to 14.0.579 (#13303)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-26 18:10:02 +00:00
Koen Kanters 343ef7fd9f Only republish retained messages when none are received. #9629 2022-07-25 19:37:33 +02:00
Koen Kanters 316daee49d Republish retained messages when reconnected to MQTT server. #9629 2022-07-24 22:17:29 +02:00
github-actions[bot]andKoenkk 68aae1a450 Update zigbee-herdsman-converters to 14.0.578 (#13272)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-24 15:23:53 +00:00
github-actions[bot]andKoenkk d92b2f2ea9 Update dependencies (#13266)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-24 16:59:01 +02:00
github-actions[bot]andKoenkk e132a22f20 Update zigbee-herdsman-converters to 14.0.577 (#13260)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-23 15:36:49 +00:00
github-actions[bot]andKoenkk ebcf49b504 Update zigbee-herdsman-converters to 14.0.576 (#13254)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-23 10:30:57 +00:00
github-actions[bot]andKoenkk 6a2de3cd3b Update zigbee-herdsman-converters to 14.0.575 (#13237)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-21 20:58:00 +00:00
github-actions[bot]andKoenkk 8d8da9f286 Update zigbee-herdsman-converters to 14.0.574 (#13226)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-20 18:16:35 +00:00
Andrew Lamchenko 759c2f3f00 Add new clusters for bind (#13214)
* Add new clasters for bind

Add new clasters for bind

* Add new clasters for bind

Add new clasters for bind
2022-07-20 19:41:46 +02:00
github-actions[bot]andKoenkk b140e4bfe6 Update zigbee-herdsman-converters to 14.0.573 (#13213)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-19 18:18:04 +00:00
github-actions[bot]andKoenkk 4ef9ea749d Update zigbee-herdsman-converters to 14.0.571 (#13187)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-17 20:56:28 +00:00
github-actions[bot]andKoenkk 11f3f5b170 Update zigbee-herdsman to 0.14.46 (#13185)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-17 20:30:52 +00:00
github-actions[bot]andKoenkk b6f88aad80 Update dependencies (#13173)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-17 22:14:33 +02:00
Koen Kanters d07b65a03d Fix coverage 2022-07-17 22:14:02 +02:00
Koen Kanters aabc010191 Log error stack on fromZigbee converter error. https://github.com/Koenkk/zigbee2mqtt/issues/13138 2022-07-17 22:03:24 +02:00
github-actions[bot]andnurikk cf8e7b10db Update zigbee2mqtt-frontend to 0.6.107 (#13175)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-07-17 03:15:43 +00:00
github-actions[bot]andKoenkk 63777464cc Update zigbee-herdsman-converters to 14.0.570 (#13162)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-15 15:33:36 +00:00
Koen Kanters 26fc4609f0 Enable publish to ghcr.io 2022-07-15 12:50:43 +02:00
github-actions[bot]andKoenkk 1d8d6fe070 Update zigbee-herdsman-converters to 14.0.569 (#13150)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-14 15:31:24 +00:00
Koen Kanters ca2186a9c5 Finally fix for https://github.com/Koenkk/zigbee2mqtt/issues/13080 2022-07-13 22:04:27 +02:00
github-actions[bot]andKoenkk 7d8b506c49 Update zigbee-herdsman-converters to 14.0.568 (#13134)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-13 17:39:24 +00:00
Koen Kanters 994de20f49 Another attempt to fix https://github.com/Koenkk/zigbee2mqtt/issues/13080 2022-07-13 18:05:45 +02:00
github-actions[bot]andKoenkk f553601ff1 Update zigbee-herdsman to 0.14.45 (#13132)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-13 15:40:54 +00:00
Koen Kanters 3478715926 Update ci.yml 2022-07-12 22:15:26 +02:00
Koen Kanters ed351ee712 TEMP: disable ghcr.io Docker build since ghcr.io is unstable 2022-07-12 22:09:43 +02:00
github-actions[bot]andKoenkk affa15cbae Update zigbee-herdsman to 0.14.44 (#13121)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-12 19:58:07 +00:00
Koen Kanters c6d504a5df Set device_class to temperature for local_temperature_calibration. https://github.com/Koenkk/zigbee2mqtt/issues/13080 2022-07-12 21:45:20 +02:00
Koen Kanters 420b34c909 Fix group and device states changing when cached states are published. https://github.com/Koenkk/zigbee2mqtt/issues/13028 2022-07-12 17:01:29 +02:00
github-actions[bot]andnurikk 4347034ba1 Update zigbee2mqtt-frontend to 0.6.106 (#13110)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-07-12 03:01:48 +00:00
github-actions[bot]andKoenkk ec8e7ed946 Update zigbee-herdsman-converters to 14.0.567 (#13104)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-11 15:57:15 +00:00
Koen Kanters 440fc74368 Fix Home Assistant discovery error: expected NumberDeviceClass or one of 'temperature' for dictionary value @ data['device_class']. https://github.com/Koenkk/zigbee2mqtt/issues/13080 2022-07-11 17:44:08 +02:00
Jorge Schrauwen a0255d0f2c Always treat filtered_* as full matches (#13083)
* Revert "update tests to use regex ^$ anchors"

This reverts commit 3d9bc552e9.

* utils: filterProperties should ensure full match
2022-07-11 17:24:34 +02:00
github-actions[bot]andKoenkk 14216b7454 Update zigbee-herdsman-converters to 14.0.566 (#13093)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-10 08:11:17 +00:00
github-actions[bot]andKoenkk 0da033ce95 Update zigbee-herdsman to 0.14.43 (#13092)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-10 07:57:07 +00:00
3bd3196a40 Update dependencies (#13089)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-07-10 09:23:51 +02:00
github-actions[bot]andnurikk 47e05c32ec Update zigbee2mqtt-frontend to 0.6.105 (#13090)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-07-10 01:55:15 +00:00
github-actions[bot]andKoenkk bcd19509fb Update zigbee-herdsman-converters to 14.0.565 (#13085)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-09 18:32:35 +00:00
github-actions[bot]andKoenkk 05a9920638 Update zigbee-herdsman to 0.14.42 (#13084)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-09 18:05:19 +00:00
Koen Kanters 8af3ad5541 Fix crash when ZIGBEE2MQTT_CONFIG_ADVANCED_NETWORK_KEY environment variable is set to GENERATE. https://github.com/Koenkk/zigbee2mqtt/issues/12999 2022-07-08 16:58:23 +02:00
Koen Kanters 6ef9e4f479 Fix matrix test jobs unstable (#13068)
* Update ci.yml

* Update ci.yml
2022-07-07 15:21:37 +02:00
183dad97e7 Update zigbee-herdsman to 0.14.41 (#13063)
* Update zigbee-herdsman to 0.14.41

* Update package-lock.json

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-07-07 07:44:34 +00:00
github-actions[bot]andKoenkk 3bbdf17fed Update zigbee-herdsman-converters to 14.0.564 (#13062)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-06 15:50:54 +00:00
Jorge Schrauwen db021e6711 Allow regexes for filtered_attributes, filtered_cache and filtered_optimistic options (#13047)
* Ensure filtered_attributes and filtered_optimistic are also regex

Bring filtered_attributes and filtered_optimistic in line with the newer filtered_cache.
All three of them are now regex matches instead of absolute matches.

* update tests to use regex ^$ anchors

* utils: add filterProperties
2022-07-06 17:07:22 +02:00
github-actions[bot]andKoenkk 4a58dbf84c Update zigbee-herdsman-converters to 14.0.563 (#13049)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-05 15:20:46 +00:00
github-actions[bot]andKoenkk ee227d85c7 Update zigbee-herdsman-converters to 14.0.562 (#13035)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-04 15:20:19 +00:00
github-actions[bot]andKoenkk d8c0ef8a9c Update dependencies (#13023)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-04 17:05:01 +02:00
github-actions[bot]andKoenkk 53ae00c46f Update zigbee-herdsman-converters to 14.0.561 (#13022)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-02 18:53:10 +00:00
Jorge SchrauwenandKoen Kanters dedbf336af Add filtered_cache option (#12988)
* want a way to prevent attribute from being cached

* Update filtered_cache description to be more clear

* Fix emitStateChange was returning wrong payload in to parameter

* Directly get filtered_cache from entity and forgo parameter to State.set()

* Add tests to cover filtered_cache

* Update state.ts

* Update controller.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-07-02 20:33:04 +02:00
Sam bc4ffc00b6 add search before issue create requirement (#13021) 2022-07-02 20:28:30 +02:00
5662e6c29e Update zigbee-herdsman-converters to 14.0.560 (#13016)
* Update zigbee-herdsman-converters to 14.0.560

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-07-01 21:35:16 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 4cc838accf Bump actions/dependency-review-action from 1 to 2 (#13009)
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 1 to 2.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-01 23:10:32 +02:00
github-actions[bot]andnurikk 3b58ac79dc Update zigbee2mqtt-frontend to 0.6.104 (#13008)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-07-01 15:20:07 +00:00
bab764e2be Binding to msRelativeHumidity (#12877)
* Binding to new clusters

Binding to new clusters. This is necessary for new EFEKTA devices.

* Update bind.ts

* Fix tests

Co-authored-by: nurikk <ainur@yojee.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-07-01 17:02:34 +02:00
Koen Kanters 81892ef70d Promote to dev 2022-07-01 16:42:33 +02:00
Koen Kanters cd23aeaa46 1.26.0 2022-07-01 16:41:38 +02:00
Koen Kanters 5d5b731053 Undev 2022-07-01 16:41:00 +02:00
Koen Kanters c973632efd Merge branch 'dev' 2022-07-01 16:40:18 +02:00
github-actions[bot]andKoenkk e0b63f2baa Update zigbee-herdsman-converters to 14.0.559 (#13004)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-07-01 14:39:37 +00:00
github-actions[bot]andKoenkk 3d406c3c0d Update zigbee-herdsman-converters to 14.0.558 (#12984)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-29 16:06:12 +00:00
github-actions[bot]andKoenkk d4811791fc Update zigbee-herdsman to 0.14.40 (#12983)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-29 16:01:43 +00:00
github-actions[bot]andKoenkk 3b7ef63300 Update zigbee-herdsman-converters to 14.0.557 (#12975)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-28 15:15:39 +00:00
github-actions[bot]andKoenkk 8adb2f1247 Update zigbee-herdsman-converters to 14.0.556 (#12967)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-27 17:18:22 +00:00
Vladimir Vitkov 326c2aaa90 Allow to specify MQTT server in secrets (#12904)
* add server, pan_id, ext_pan_id to secrets

* fix tests

* clean secrets before every test run

* add interpolation of mqtt.server, advanced.pan_id, advanced.ext_pan_id and split mqtt.user, mqtt.pass requirement

* remove pan_id and ext_pan_id from secrets processing
2022-06-27 18:42:05 +02:00
e291687870 Update zigbee-herdsman-converters to 14.0.555 (#12951)
* Update zigbee-herdsman-converters to 14.0.555

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-06-26 17:01:17 +02:00
Koen Kanters 80f8fb4d98 Node 17 is EOL 2022-06-26 16:56:01 +02:00
RoboMagus 402081e39d Fix EnvVar parsing of settings scheme with 'oneOf'. (#12948) 2022-06-26 16:16:44 +02:00
Koen Kanters 05309db92b Fix crash when poll of bounded device fails. https://github.com/Koenkk/zigbee2mqtt/issues/12918 2022-06-26 16:14:21 +02:00
github-actions[bot]andKoenkk d3fa977ebf Update dependencies (#12942)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-26 09:46:15 +02:00
github-actions[bot]andKoenkk 92f7bc8eb5 Update zigbee-herdsman to 0.14.39 (#12926)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-24 14:19:32 +00:00
github-actions[bot]andKoenkk 80b6f1dfa3 Update zigbee-herdsman-converters to 14.0.554 (#12906)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-22 15:20:07 +00:00
github-actions[bot]andKoenkk 1eaa73bb52 Update zigbee-herdsman-converters to 14.0.553 (#12895)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-21 14:39:48 +00:00
github-actions[bot]andKoenkk 0fc831cd82 Update zigbee-herdsman-converters to 14.0.552 (#12886)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-20 16:20:23 +00:00
github-actions[bot]andKoenkk 59c18af1f7 Update dependencies (#12874)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-20 17:47:45 +02:00
github-actions[bot]andnurikk 0fd47c0ad1 Update zigbee2mqtt-frontend to 0.6.103 (#12885)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-06-20 15:32:50 +00:00
github-actions[bot]andnurikk 6b643f0e67 Update zigbee2mqtt-frontend to 0.6.102 (#12884)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-06-20 14:55:48 +00:00
github-actions[bot]andKoenkk 3c9fab143c Update zigbee-herdsman-converters to 14.0.551 (#12871)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-18 17:50:50 +00:00
Koen Kanters f2e953cf18 Add group off_state option (#12868) 2022-06-18 15:47:06 +02:00
github-actions[bot]andKoenkk ecb18a6c41 Update zigbee-herdsman-converters to 14.0.550 (#12864)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-18 09:24:55 +00:00
github-actions[bot]andKoenkk d405c43202 Update zigbee-herdsman-converters to 14.0.549 (#12862)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-18 08:30:31 +00:00
github-actions[bot]andKoenkk 24e7a368cb Update zigbee-herdsman to 0.14.38 (#12861)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-18 08:22:20 +00:00
github-actions[bot]andKoenkk 8848e1e6ce Update zigbee-herdsman-converters to 14.0.548 (#12856)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-17 15:08:56 +00:00
John Doeandnurikk 820c20af80 Fix windows tests (#12840)
Co-authored-by: nurikk <ainur@yojee.com>
2022-06-16 14:00:09 +08:00
github-actions[bot]andnurikk 4b8b951c28 Update zigbee2mqtt-frontend to 0.6.101 (#12839)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-06-16 05:37:34 +00:00
github-actions[bot]andnurikk 8964421350 Update zigbee2mqtt-frontend to 0.6.100 (#12838)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-06-16 05:13:27 +00:00
github-actions[bot]andKoenkk 0895f29a83 Update zigbee-herdsman-converters to 14.0.547 (#12833)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-15 16:00:32 +00:00
Koen Kanters f213729dcb Remove Home Assistant away_mode_* discovery. https://github.com/Koenkk/zigbee2mqtt/issues/11738 2022-06-15 17:56:13 +02:00
rikroeandKoen Kanters 6df20010dd Change HA hold_mode to preset_mode (#12565)
* Update homeassistant.ts

* Update homeassistant.test.js

* Update homeassistant.ts

* Update homeassistant.ts

* Updates

* Updates

* Updates

* Updates

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-06-15 17:40:44 +02:00
github-actions[bot]andKoenkk a5204cdeb1 Update zigbee-herdsman to 0.14.37 (#12832)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-15 15:14:36 +00:00
Koen Kanters dd129830d3 Create herdsman backup before backup. https://github.com/Koenkk/zigbee2mqtt/pull/12797 2022-06-15 17:05:20 +02:00
github-actions[bot]andKoenkk a8233e0521 Update zigbee-herdsman to 0.14.36 (#12831)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-15 17:04:20 +02:00
Koen Kanters 9b2a92106e Disable ghcr_cleanup 2022-06-15 17:03:16 +02:00
github-actions[bot]andKoenkk 8fe6ab4866 Update zigbee-herdsman-converters to 14.0.546 (#12826)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-14 18:36:31 +00:00
Koen Kanters a08ff9bf6d Prepare for zhc 14.0.546 2022-06-14 20:31:25 +02:00
Koen Kanters 83b490a968 Add zigbee2mqtt/bridge/request/backup (#12797)
* Add backup call

* Updates
2022-06-14 20:14:01 +02:00
github-actions[bot]andnurikk 3498c6e260 Update zigbee2mqtt-frontend to 0.6.99 (#12812)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-06-13 14:28:42 +00:00
github-actions[bot]andKoenkk 5c93aaf6db Update zigbee-herdsman-converters to 14.0.545 (#12804)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-12 19:51:52 +00:00
github-actions[bot]andKoenkk e860978564 Update zigbee-herdsman-converters to 14.0.544 (#12796)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-12 07:17:00 +00:00
github-actions[bot]andKoenkk 2d7a6e9f42 Update dependencies (#12795)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-12 08:48:41 +02:00
github-actions[bot]andKoenkk 1390bc1d04 Update zigbee-herdsman-converters to 14.0.543 (#12783)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-11 08:12:40 +00:00
github-actions[bot]andKoenkk a9349ac49d Update zigbee-herdsman to 0.14.35 (#12782)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-11 08:07:05 +00:00
github-actions[bot]andKoenkk 5bed214aef Update zigbee-herdsman-converters to 14.0.542 (#12781)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-11 07:53:34 +00:00
github-actions[bot]andKoenkk 4f181b0107 Update zigbee-herdsman-converters to 14.0.541 (#12767)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-09 19:25:49 +00:00
Koen Kanters 8e2f0f613f Send cached group state on startup and when Home Assistant comes online. https://github.com/Koenkk/zigbee2mqtt/issues/12693 2022-06-09 20:52:39 +02:00
github-actions[bot]andKoenkk 2bb4f91d1c Update zigbee-herdsman-converters to 14.0.540 (#12756)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-08 18:29:55 +00:00
Koen Kanters 389ff844c4 Revert "Revert "Revert "Temp: disable ghcr.io since it makes build fail"""
This reverts commit 975eb7d6ae.
2022-06-08 16:40:20 +02:00
github-actions[bot]andKoenkk cb0542eaad Update zigbee-herdsman-converters to 14.0.539 (#12746)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-07 16:17:18 +00:00
Koen Kanters 300b2973e1 Update ci.yml 2022-06-06 13:32:44 +02:00
Koen Kanters 5c44582b69 Update zigbee2mqtt/hassio-zigbee2mqtt trigger 2022-06-06 12:58:37 +02:00
github-actions[bot]andKoenkk 2f2a66db2e Update zigbee-herdsman-converters to 14.0.538 (#12728)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-05 20:07:53 +00:00
github-actions[bot]andKoenkk b075d6bbda Update dependencies (#12727)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-05 22:02:11 +02:00
Koen Kanters a252914ecd Update update_deps.yml 2022-06-05 21:48:26 +02:00
github-actions[bot]andKoenkk 87edd1e6f1 Update zigbee-herdsman-converters to 14.0.537 (#12712)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-04 12:25:18 +00:00
github-actions[bot]andKoenkk ba69e1788f Update zigbee-herdsman-converters to 14.0.536 (#12709)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-04 08:42:26 +00:00
Naveen 05538ec28b chore: Enable codeql action (#12708)
This action runs GitHub's industry-leading semantic code analysis engine,
CodeQL, against a repository's source code to find security vulnerabilities.

https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning-with-codeql

https://github.com/ossf/scorecard/blob/main/docs/checks.md#sast
Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com>
2022-06-04 10:28:44 +02:00
NaveenandKoen Kanters 2676c3f641 chore(deps): Included dependency review (#12695)
* chore(deps): Included dependency review

> Dependency Review GitHub Action in your repository to enforce dependency
> reviews on your pull requests.
> The action scans for vulnerable versions of dependencies introduced by package version
> changes in pull requests,
> and warns you about the associated security vulnerabilities.
> This gives you better visibility of what's changing in a pull request,
> and helps prevent vulnerabilities being added to your repository.

https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com>

* Update depsreview.yaml

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-06-03 16:41:06 +02:00
github-actions[bot]andKoenkk e525919160 Update zigbee-herdsman-converters to 14.0.535 (#12692)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-02 16:13:26 +00:00
John Doeandnurikk d064a73131 Rework ci and use package-lock.json instead of npm-shrinkwrap.json (#12631)
* Update ci

* Use package-lock

* Use package-lock.json

* Use cache for ci

* Enable node18 windows

* Revert "Enable node18 windows"

This reverts commit e427551acdd64c3a256b48a5b8e86b3c4c986405.

* Remove redundant cache

* Don't do shrinkwrap

* Remove shrinkwrap

* Remove redundant step

* Cache node-gyp

* Debug

* Add key

* Update ci.yml

* Add cache detection

* Fix

* Add deps

* Fix2

* Update caches

* Fix ci

* Update patsh

* Update paths

* Update paths

* Fix max cache path

* Change cache key

* Remove spaces

* Split caches

* Fix linux cache

* Fix linux cache

* Merge caches

* Ignore errs

* Find only dirs

* Run find after ci

* Fix mac cache

* Fix caches

* Remove env run

Co-authored-by: nurikk <ainur@yojee.com>
2022-06-02 14:38:07 +00:00
Koen Kanters 64ab3b0492 Revert "Downgrade docker/setup-qemu-action to v1"
This reverts commit 35b9e01230.
2022-06-02 16:27:18 +02:00
Koen Kanters e1c9d68c68 Revert "Check if ghcr.io build works again"
This reverts commit 1596714ccb.
2022-06-02 16:27:11 +02:00
Koen Kanters 35b9e01230 Downgrade docker/setup-qemu-action to v1 2022-06-02 16:13:40 +02:00
Koen Kanters 1596714ccb Check if ghcr.io build works again 2022-06-02 16:02:51 +02:00
Koen Kanters e852851273 Update ghcr_cleanup.yml 2022-06-02 08:30:55 +02:00
github-actions[bot]andKoenkk 24e9c5bc9f Update zigbee-herdsman-converters to 14.0.534 (#12676)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-01 17:22:40 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> dc4f4ad047 Bump actions/github-script from 3 to 6 (#12674)
Bumps [actions/github-script](https://github.com/actions/github-script) from 3 to 6.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v3...v6)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-01 19:16:21 +02:00
neilnaveenandKoen Kanters cc42ab7584 chore: Set permissions for GitHub actions (#12626)
Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much.

- Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions

https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs

[Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)

Signed-off-by: neilnaveen <42328488+neilnaveen@users.noreply.github.com>

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-06-01 19:15:06 +02:00
Koen Kanters 03fdb0cb88 Fix Home Assistant rename creating duplicate entities. #12610 2022-06-01 18:57:02 +02:00
Koen Kanters f7c6518506 Promote to dev 2022-06-01 17:38:46 +02:00
Koen Kanters 3c5854fa9f 1.25.2 2022-06-01 17:38:09 +02:00
Koen Kanters 900175af47 Undev 2022-06-01 17:37:39 +02:00
Koen Kanters 9b9e2289d3 Merge remote-tracking branch 'origin/master' into dev 2022-06-01 17:36:50 +02:00
github-actions[bot]andKoenkk ea10936641 Update zigbee-herdsman-converters to 14.0.533 (#12672)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-01 15:14:02 +00:00
github-actions[bot]andKoenkk 6b56b0bcf8 Update zigbee-herdsman-converters to 14.0.532 (#12671)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-06-01 15:03:10 +00:00
Koen Kanters 975eb7d6ae Revert "Revert "Temp: disable ghcr.io since it makes build fail""
This reverts commit 4e28df88ae.
2022-06-01 16:57:47 +02:00
Koen Kanters 4de04c19c0 Update ghcr_cleanup.yml 2022-06-01 15:12:32 +02:00
Koen Kanters 1db12612e6 Add GHCR cleanup (#12669)
* Create ghcr_cleanup.yml

* Update ghcr_cleanup.yml

* Update ghcr_cleanup.yml

* Update ghcr_cleanup.yml

* Update ghcr_cleanup.yml
2022-06-01 14:18:41 +02:00
github-actions[bot]andKoenkk ec010df79a Update zigbee-herdsman-converters to 14.0.531 (#12659)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-31 15:17:42 +00:00
github-actions[bot]andKoenkk 88b65625de Update zigbee-herdsman to 0.14.34 (#12658)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-31 14:58:08 +00:00
Koen Kanters 4e28df88ae Revert "Temp: disable ghcr.io since it makes build fail"
This reverts commit a1db076c02.
2022-05-31 08:28:36 +02:00
github-actions[bot]andKoenkk 44815435e7 Update zigbee-herdsman-converters to 14.0.530 (#12645)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-30 16:11:37 +00:00
Koen Kanters fe011ba7b3 Disable node 18 testing for now (fails quite often) 2022-05-29 10:21:23 +02:00
Koen Kanters 68035a1256 Fix restart not working (#12629) 2022-05-29 08:15:47 +00:00
github-actions[bot]andKoenkk cc535f11c6 Update zigbee-herdsman-converters to 14.0.529 (#12628)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-29 07:23:01 +00:00
github-actions[bot]andKoenkk 7001b2fc79 Update dependencies (#12627)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-29 06:46:27 +00:00
Koen Kanters 05975109a4 Lock connect-gzip-static https://github.com/Koenkk/zigbee2mqtt/pull/12624/files#r884205347 2022-05-29 08:43:02 +02:00
github-actions[bot]andKoenkk 502443aae8 Update zigbee-herdsman-converters to 14.0.528 (#12615)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-27 19:15:31 +00:00
Koen Kanters 43a82ad835 Delete ghcr_delete_untagged.yml 2022-05-27 16:29:50 +02:00
Koen Kanters a1db076c02 Temp: disable ghcr.io since it makes build fail 2022-05-27 16:23:34 +02:00
Koen Kanters bfc70c3bb8 Update ghcr_delete_untagged.yml 2022-05-27 15:09:48 +02:00
Koen Kanters b268b1ed75 Update ghcr_delete_untagged.yml 2022-05-27 12:08:55 +02:00
Koen Kanters 64769b3e9f Update ghcr_delete_untagged.yml 2022-05-27 12:05:51 +02:00
Koen Kanters 66e804d71e Create ghcr_delete_untagged.yml 2022-05-27 12:01:21 +02:00
github-actions[bot]andKoenkk 1c30a4f4bc Update zigbee-herdsman to 0.14.33 (#12612)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-27 09:51:49 +00:00
Koen Kanters be55e3ee80 Revert "Temp disable ghcr.io push (seems to make build fail)"
This reverts commit c1372852e9.
2022-05-27 11:47:43 +02:00
github-actions[bot]andnurikk 1aa7971ca1 Update zigbee2mqtt-frontend to 0.6.97 (#12605)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-26 11:25:29 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 6e2ab644a0 Bump peter-evans/create-pull-request from 3 to 4 (#12602)
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 3 to 4.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-26 09:54:13 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 4fa6c33622 Bump peter-evans/enable-pull-request-automerge from 1 to 2 (#12600)
Bumps [peter-evans/enable-pull-request-automerge](https://github.com/peter-evans/enable-pull-request-automerge) from 1 to 2.
- [Release notes](https://github.com/peter-evans/enable-pull-request-automerge/releases)
- [Commits](https://github.com/peter-evans/enable-pull-request-automerge/compare/v1...v2)

---
updated-dependencies:
- dependency-name: peter-evans/enable-pull-request-automerge
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-26 09:53:39 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 3fd405e570 Bump actions/stale from 3 to 5 (#12601)
Bumps [actions/stale](https://github.com/actions/stale) from 3 to 5.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v3...v5)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-26 09:53:15 +02:00
Koen Kanters c1372852e9 Temp disable ghcr.io push (seems to make build fail) 2022-05-26 09:50:39 +02:00
Koen Kanters 95eedc9ec1 Add dependabot.yml 2022-05-26 09:48:43 +02:00
Koen Kanters d7b926d47f Update ci.yml dependencies 2022-05-26 09:43:11 +02:00
github-actions[bot]andKoenkk 67039a1a94 Update zigbee-herdsman-converters to 14.0.527 (#12599)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-26 07:27:42 +00:00
github-actions[bot]andKoenkk f79fb16e41 Update zigbee-herdsman-converters to 14.0.526 (#12595)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-25 16:58:18 +00:00
Koen Kanters d910c05e6e Improve tests 2022-05-25 11:38:37 +02:00
github-actions[bot]andnurikk 4858e06060 Update zigbee2mqtt-frontend to 0.6.96 (#12592)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-25 09:31:15 +00:00
f71db6816a Update zigbee-herdsman-converters to 14.0.525 (#12585)
* Update zigbee-herdsman-converters to 14.0.525

* Fix tests

* Ignore

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-24 18:27:17 +00:00
github-actions[bot]andnurikk c6b129c68d Update zigbee2mqtt-frontend to 0.6.95 (#12572)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-23 04:59:27 +00:00
e5dbe01329 Update zigbee-herdsman-converters to 14.0.522 (#12568)
* Update zigbee-herdsman-converters to 14.0.522

* Fix

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-22 20:32:15 +00:00
Koen Kanters c00768b7c7 Move ci before tests 2022-05-21 15:08:07 +02:00
Koen Kanters ad070c99ef Add official support for node 18 and drop for node 10, 12, 15 (#12553) 2022-05-21 08:29:22 +00:00
aec082c0cf Update zigbee-herdsman-converters to 14.0.521 (#12552)
* Update zigbee-herdsman-converters to 14.0.521

* Fixes

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-21 08:20:37 +00:00
github-actions[bot]andKoenkk cc84452f23 Update zigbee-herdsman to 0.14.32 (#12551)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-21 07:45:02 +00:00
John Doeandnurikk 84bac2b8d8 Add compatibility tests (#12527)
* Add tests gh action

* Fix zigbee_ota_override_index_location

* Fix Shouldnt crash when it cannot save state test

* Add node17

* Update tests.yml

* Drop old versions

* Move to ci.yml

* Update controller.test.js

* Fix linebraks on windows

* Ignore windows and node 17

* Fail on error

* Add comment

* Mark node 18 as supported

Co-authored-by: nurikk <ainur@yojee.com>
2022-05-21 08:37:39 +02:00
github-actions[bot]andKoenkk 29a9d227de Update zigbee-herdsman-converters to 14.0.520 (#12546)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-20 14:58:14 +00:00
github-actions[bot]andnurikk 39ae0c775a Update zigbee2mqtt-frontend to 0.6.94 (#12540)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-20 02:44:04 +00:00
github-actions[bot]andKoenkk f1eaf2d7aa Update zigbee-herdsman-converters to 14.0.519 (#12530)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-18 15:35:44 +00:00
Koen Kanters c6840a9a43 Mark node 17 as supported 2022-05-18 14:56:17 +02:00
John Doeandnurikk 3a1c64a88e Downgrade connect-gzip-static to 2.1.1 (#12525)
Co-authored-by: nurikk <ainur@yojee.com>
2022-05-18 17:30:04 +08:00
github-actions[bot]andnurikk d4a0c93c91 Update zigbee2mqtt-frontend to 0.6.86 (#12524)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-18 08:14:56 +00:00
github-actions[bot]andKoenkk 5ae8347317 Update zigbee-herdsman-converters to 14.0.518 (#12518)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-17 15:06:53 +00:00
github-actions[bot]andKoenkk afbfa4631f Update zigbee-herdsman to 0.14.31 (#12504)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-16 16:05:24 +00:00
github-actions[bot]andKoenkk 096f906ac7 Update zigbee-herdsman-converters to 14.0.517 (#12503)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-16 14:44:14 +00:00
github-actions[bot]andnurikk b844f607ee Update zigbee2mqtt-frontend to 0.6.85 (#12502)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-16 13:59:21 +00:00
github-actions[bot]andKoenkk 6002bc475b Update dependencies (#12479)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-16 15:19:07 +02:00
github-actions[bot]andKoenkk 24cfdf4594 Update zigbee-herdsman to 0.14.30 (#12466)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-13 13:15:51 +00:00
github-actions[bot]andKoenkk bc5fd1a52f Update zigbee-herdsman to 0.14.29 (#12464)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-13 08:30:16 +00:00
Koen Kanters fd344a3017 Revert "Additional logging for https://github.com/Koenkk/zigbee2mqtt/issues/12432"
This reverts commit 920b4924b0.
2022-05-13 10:05:49 +02:00
github-actions[bot]andKoenkk f9bd184543 Update zigbee-herdsman-converters to 14.0.516 (#12460)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-12 17:53:53 +00:00
github-actions[bot]andKoenkk f2c1e85b4b Update zigbee-herdsman-converters to 14.0.515 (#12447)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-11 18:21:27 +00:00
Koen Kanters 920b4924b0 Additional logging for https://github.com/Koenkk/zigbee2mqtt/issues/12432 2022-05-11 17:22:48 +02:00
github-actions[bot]andKoenkk 99e67b1495 Update zigbee-herdsman-converters to 14.0.514 (#12435)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-10 18:03:45 +00:00
github-actions[bot]andKoenkk e65344c9fa Update zigbee-herdsman-converters to 14.0.513 (#12429)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-09 18:15:01 +00:00
147fe22f08 Update dependencies (#12416)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-08 10:01:25 +02:00
Koen Kanters 7f1f1497c6 Always return a device state 2022-05-08 09:58:30 +02:00
Koen Kanters 6278c86d02 Pass device options in global on event. https://github.com/Koenkk/zigbee2mqtt/commit/723dd8358f3cee0b90d624f27989a8bb587e25b0#comments 2022-05-07 14:40:25 +02:00
6f09d45a7b Update zigbee-herdsman-converters to 14.0.512 (#12413)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-07 12:39:32 +00:00
Koen Kanters 49a730f77d Update tests for https://github.com/Koenkk/zigbee2mqtt/pull/12413 2022-05-07 14:37:29 +02:00
github-actions[bot]andKoenkk e5a74894d2 Update zigbee-herdsman-converters to 14.0.511 (#12409)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-07 08:43:02 +00:00
Jorge SchrauwenandKoen Kanters 723dd8358f Pass device state to zhc onEvent (#12407)
* onEvent: want device state as argument

* onEvent: test should check deviceOptions and deviceState returns

* Update onEvent.ts

* Update onEvent.ts

* Fix

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-07 08:36:03 +00:00
github-actions[bot]andKoenkk 47a22cce2a Update zigbee-herdsman-converters to 14.0.510 (#12403)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-06 15:24:31 +00:00
github-actions[bot]andKoenkk b3791684fd Update zigbee-herdsman-converters to 14.0.509 (#12392)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-05 16:43:18 +00:00
github-actions[bot]andKoenkk ebd3255fc6 Update zigbee-herdsman to 0.14.28 (#12390)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-05 16:17:04 +00:00
github-actions[bot]andKoenkk 9b594a4cba Update zigbee-herdsman-converters to 14.0.508 (#12380)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-04 19:08:08 +00:00
Koen Kanters d0530b8214 Don't allow friendly names to include control character. #12379 2022-05-04 21:00:29 +02:00
5c7e968028 Update zigbee-herdsman-converters to 14.0.507 (#12368)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-05-03 17:42:17 +00:00
Koen Kanters 40ef638e0e Fix null not allowed for Home Assistant device options. #12340 2022-05-03 19:39:30 +02:00
github-actions[bot]andKoenkk b9499618d3 Update zigbee-herdsman-converters to 14.0.506 (#12354)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-02 17:35:37 +00:00
Alex Kay 6618872839 Add new config and diagnostic entities to HA (#12353) 2022-05-02 19:23:40 +02:00
Alex Kay b977dd1140 Add battery2 for HA (#12332) 2022-05-02 14:20:45 +00:00
github-actions[bot]andnurikk 71d5c7b4a2 Update zigbee2mqtt-frontend to 0.6.84 (#12351)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-05-02 12:31:28 +00:00
github-actions[bot]andKoenkk dd8a83e592 Update zigbee-herdsman-converters to 14.0.505 (#12338)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-01 18:45:05 +00:00
Koen Kanters 664182def2 Promote to dev 2022-05-01 20:16:18 +02:00
Koen Kanters 3f6a13786e 1.25.1 2022-05-01 20:14:19 +02:00
Koen Kanters a800197262 Undev 2022-05-01 20:14:12 +02:00
github-actions[bot]andKoenkk 0c145d81cf Update zigbee-herdsman-converters to 14.0.504 (#12336)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-05-01 17:53:38 +00:00
github-actions[bot]andKoenkk 7d7f8aabfe Update zigbee-herdsman-converters to 14.0.503 (#12321)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-30 07:50:44 +00:00
github-actions[bot]andKoenkk 95c2fcfb00 Update zigbee-herdsman-converters to 14.0.502 (#12317)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-29 20:45:59 +00:00
github-actions[bot]andKoenkk 2a6a6c43ce Update zigbee-herdsman-converters to 14.0.501 (#12309)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-28 16:26:57 +00:00
github-actions[bot]andKoenkk 47ed86d735 Update zigbee-herdsman-converters to 14.0.500 (#12294)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-27 07:34:32 +00:00
github-actions[bot]andKoenkk 50990d1f7a Update zigbee-herdsman-converters to 14.0.499 (#12288)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-26 18:05:33 +00:00
Koen Kanters f7b484f24f Log stack trace of "Failed to execute LQI" error. https://github.com/Koenkk/zigbee2mqtt/issues/11968 2022-04-26 20:02:18 +02:00
github-actions[bot]andKoenkk f6ad3c9926 Update zigbee-herdsman-converters to 14.0.498 (#12280)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-25 18:31:28 +00:00
11b415634c Update zigbee-herdsman to 0.14.27 (#12267)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-04-24 18:40:24 +00:00
github-actions[bot]andKoenkk d980d38747 Update zigbee-herdsman-converters to 14.0.497 (#12266)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-24 18:32:09 +00:00
github-actions[bot]andKoenkk 808671dd59 Update dependencies (#12256)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-24 13:55:36 +02:00
Koen Kanters cf22dd60a0 Always respond to OTA request (#12247)
* Always respond to OTA request

* Improve

* Rename
2022-04-23 10:12:29 +02:00
github-actions[bot]andKoenkk 3b820bae9f Update zigbee-herdsman-converters to 14.0.496 (#12249)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-22 18:35:06 +00:00
github-actions[bot]andKoenkk 60a987c004 Update zigbee-herdsman-converters to 14.0.495 (#12240)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-21 15:46:27 +00:00
github-actions[bot]andKoenkk d90be2dc66 Update zigbee-herdsman-converters to 14.0.494 (#12233)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-20 17:09:34 +00:00
Koen Kanters e305ecf571 Improve #ec2bf1a95d6c45c093f68df832bc6bcbdd372a5a 2022-04-20 17:59:16 +02:00
Koen Kanters ec2bf1a95d Fix out of memory error when starting on system with low RAM. #12034 2022-04-20 16:59:30 +02:00
github-actions[bot]andKoenkk 7d5c44a5bd Update zigbee-herdsman-converters to 14.0.493 (#12213)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-19 07:09:28 +00:00
github-actions[bot]andKoenkk 8c4312db72 Update zigbee-herdsman-converters to 14.0.492 (#12210)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-18 17:32:40 +00:00
github-actions[bot]andKoenkk 037a72e0f3 Update zigbee-herdsman-converters to 14.0.491 (#12200)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-17 18:18:25 +00:00
github-actions[bot]andKoenkk d657ea48cf Update dependencies (#12195)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-17 11:47:00 +02:00
github-actions[bot]andKoenkk b4e0c3afcf Update zigbee-herdsman-converters to 14.0.490 (#12193)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-16 07:32:45 +00:00
John Doeandnurikk 27bc646cf6 Add home assistant name to settings schema (#12191)
Co-authored-by: nurikk <ainur@yojee.com>
2022-04-16 10:27:41 +08:00
github-actions[bot]andKoenkk 23ef22e9ba Update zigbee-herdsman-converters to 14.0.489 (#12190)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-15 22:09:50 +00:00
github-actions[bot]andKoenkk 84c8da2532 Update zigbee-herdsman-converters to 14.0.488 (#12186)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-15 15:05:35 +00:00
github-actions[bot]andnurikk e6ec66c844 Update zigbee2mqtt-frontend to 0.6.83 (#12185)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-04-15 14:16:14 +00:00
github-actions[bot]andnurikk d1c26f9aa0 Update zigbee2mqtt-frontend to 0.6.82 (#12181)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-04-15 12:44:03 +00:00
github-actions[bot]andnurikk a7704b9038 Update zigbee2mqtt-frontend to 0.6.81 (#12179)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-04-15 09:36:36 +00:00
github-actions[bot]andKoenkk eabd662757 Update zigbee-herdsman-converters to 14.0.487 (#12172)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-14 15:38:56 +00:00
github-actions[bot]andKoenkk 764895b9d2 Update zigbee-herdsman-converters to 14.0.486 (#12164)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-13 17:48:12 +00:00
Míguel Ángel Mulero MartínezandKoen Kanters 8f5b26a2fb Mark calibration, calibration_time and motor_reversal as config sensors (#12146)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-04-13 19:37:41 +02:00
github-actions[bot]andKoenkk 533cd36ffd Update zigbee-herdsman to 0.14.26 (#12159)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-12 19:26:50 +02:00
github-actions[bot]andKoenkk 3a77ebf52d Update zigbee-herdsman-converters to 14.0.485 (#12156)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-12 15:11:50 +00:00
github-actions[bot]andKoenkk 0e3bef7e42 Update zigbee-herdsman to 0.14.25 (#12155)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-12 15:00:48 +00:00
github-actions[bot]andKoenkk dda63bd65a Update zigbee-herdsman-converters to 14.0.484 (#12145)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-11 15:59:24 +00:00
github-actions[bot]andKoenkk 2aa1b4ead3 Update zigbee-herdsman-converters to 14.0.483 (#12133)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-10 08:12:57 +00:00
github-actions[bot]andKoenkk 422b7e0168 Update dependencies (#12128)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-10 09:48:40 +02:00
github-actions[bot]andKoenkk 8053eceb84 Update zigbee-herdsman-converters to 14.0.482 (#12124)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-09 16:14:15 +00:00
github-actions[bot]andKoenkk d10d3c9b56 Update zigbee-herdsman-converters to 14.0.481 (#12118)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-08 14:54:54 +00:00
github-actions[bot]andKoenkk 6ff45b1006 Update zigbee-herdsman-converters to 14.0.480 (#12109)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-07 20:39:48 +00:00
github-actions[bot]andKoenkk c901e66e7a Update zigbee-herdsman-converters to 14.0.479 (#12103)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-07 16:01:10 +00:00
github-actions[bot]andKoenkk 6ee7f56df3 Update zigbee-herdsman-converters to 14.0.478 (#12094)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-06 15:38:55 +00:00
github-actions[bot]andKoenkk d7073409d4 Update zigbee-herdsman to 0.14.24 (#12092)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-06 15:27:58 +00:00
github-actions[bot]andKoenkk e46ddb8c79 Update zigbee-herdsman-converters to 14.0.477 (#12091)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-06 15:12:18 +00:00
github-actions[bot]andKoenkk f91d0f6bfe Update zigbee-herdsman-converters to 14.0.476 (#12084)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-05 18:21:15 +00:00
github-actions[bot]andKoenkk 7e61252d11 Update zigbee-herdsman-converters to 14.0.475 (#12069)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-04 18:26:35 +00:00
github-actions[bot]andKoenkk 67c5481965 Update zigbee-herdsman-converters to 14.0.474 (#12068)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-04 18:22:54 +00:00
github-actions[bot]andKoenkk e251fc0803 Update zigbee-herdsman-converters to 14.0.473 (#12060)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-03 19:27:11 +00:00
Koen Kanters 5d4268515c Fix garage door status incorrect in Home Assistant. https://github.com/Koenkk/zigbee2mqtt/issues/12038 2022-04-03 21:09:26 +02:00
github-actions[bot]andKoenkk 91d80f1bb0 Update zigbee-herdsman-converters to 14.0.472 (#12056)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-03 12:14:53 +00:00
github-actions[bot]andKoenkk c9fbc6d52e Update zigbee-herdsman to 0.14.23 (#12055)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-03 12:08:18 +00:00
github-actions[bot]andKoenkk b84ad454e5 Update zigbee-herdsman-converters to 14.0.471 (#12049)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-03 07:31:13 +00:00
github-actions[bot]andKoenkk 51ae801cb8 Update dependencies (#12047)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-03 08:49:18 +02:00
Koen Kanters cabef43421 Revert "Switch to package-lock.json"
This reverts commit 0163b7281a.
2022-04-03 08:49:03 +02:00
Koen Kanters 8fd8df75be Reduce Docker image size again. 2022-04-02 21:50:12 +02:00
Koen Kanters 51f8c1c487 Fix Docker build 2022-04-02 21:13:22 +02:00
Koen Kanters aeb9927c20 Reduce Docker image build time 2022-04-02 21:09:02 +02:00
Koen Kanters 0163b7281a Switch to package-lock.json 2022-04-02 20:57:44 +02:00
Koen Kanters 0471eb5501 Switch to package-lock.json 2022-04-02 20:51:32 +02:00
2679219d87 Update zigbee-herdsman to 0.14.22 (#12046)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-04-02 18:47:51 +00:00
Koen Kanters d83eb72c4b Add registry url 2022-04-02 20:44:16 +02:00
Koen Kanters 414ea10b14 Update actions 2022-04-02 20:41:18 +02:00
github-actions[bot]andKoenkk d6e29538b1 Update zigbee-herdsman-converters to 14.0.470 (#12045)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-02 18:38:36 +00:00
Koen Kanters eb9b764cc5 Anoter attempt to fix shrinkwrap 2022-04-02 20:25:02 +02:00
Koen Kanters db642832f8 Update shrinkwrap 2022-04-02 19:59:40 +02:00
github-actions[bot]andKoenkk a56e5e0f36 Update zigbee-herdsman to 0.14.21 (#12043)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-04-02 17:58:11 +00:00
Koen Kanters 1b0fbf556b Fix invalid Home Assistant device class for garage_door_contact. #12038 2022-04-02 19:31:32 +02:00
Artem Draft 3e7eddf3ce Improve handle motor_state in HA (#12028) 2022-04-02 19:17:36 +02:00
Koen Kanters ad24c4f677 Promote to dev 2022-04-01 08:28:18 +02:00
Koen Kanters 6f1460e47b 1.25.0 2022-04-01 08:26:35 +02:00
Koen Kanters 91239291ec Undev 2022-04-01 08:26:33 +02:00
Koen Kanters beccc18ba7 Merge branch 'master' into dev 2022-03-31 22:02:47 +02:00
github-actions[bot]andKoenkk 2901df37fb Update zigbee-herdsman-converters to 14.0.467 (#12008)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-31 19:28:24 +00:00
github-actions[bot]andnurikk 1c1ca6faea Update zigbee2mqtt-frontend to 0.6.80 (#12001)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-03-31 07:49:42 +00:00
github-actions[bot]andKoenkk 85308daf5f Update zigbee-herdsman-converters to 14.0.466 (#11991)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-30 15:31:23 +00:00
github-actions[bot]andKoenkk 4631f6fc22 Update zigbee-herdsman-converters to 14.0.465 (#11984)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-29 19:05:17 +00:00
github-actions[bot]andKoenkk 95c698758d Update zigbee-herdsman-converters to 14.0.464 (#11974)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-28 18:32:35 +00:00
github-actions[bot]andKoenkk 95c48309a0 Update dependencies (#11962)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-27 09:55:27 +02:00
github-actions[bot]andKoenkk 2e42f50d6a Update zigbee-herdsman-converters to 14.0.463 (#11961)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-26 22:05:47 +00:00
github-actions[bot]andKoenkk 62a7b5115c Update zigbee-herdsman-converters to 14.0.462 (#11959)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-26 14:01:19 +00:00
github-actions[bot]andKoenkk b805dadceb Update zigbee-herdsman-converters to 14.0.461 (#11947)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-24 18:18:15 +00:00
Artem Draft f95c0bb048 Handle cover motor_state in HA (#11926)
* Handle cover motor_state in HA

* lint
2022-03-23 17:19:06 +01:00
github-actions[bot]andKoenkk 0202399ff6 Update zigbee-herdsman-converters to 14.0.460 (#11927)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-22 18:44:49 +00:00
github-actions[bot]andKoenkk e4d4f04a05 Update zigbee-herdsman-converters to 14.0.459 (#11920)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-21 16:39:48 +00:00
github-actions[bot]andKoenkk efe768d24a Update zigbee-herdsman-converters to 14.0.458 (#11912)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-20 15:51:12 +00:00
github-actions[bot]andKoenkk 0a868b451f Update dependencies (#11906)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-20 16:12:41 +01:00
Koen Kanters a73caa3e66 Update issue template 2022-03-19 16:44:09 +01:00
Koen Kanters 02bc325fc2 Fix configure failing when rejoining device. #10973 2022-03-19 16:41:22 +01:00
github-actions[bot]andKoenkk 847e7f8652 Update zigbee-herdsman-converters to 14.0.457 (#11901)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-19 14:22:43 +00:00
github-actions[bot]andKoenkk 0cd02c7495 Update zigbee-herdsman-converters to 14.0.456 (#11898)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-18 16:11:22 +00:00
github-actions[bot]andKoenkk cae83c90b9 Update zigbee-herdsman-converters to 14.0.455 (#11888)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-17 18:33:40 +00:00
Koen Kanters 2524e030fa Fix device reconnect resulting in brightness 1 when device is off. #11864 2022-03-17 19:21:35 +01:00
github-actions[bot]andKoenkk 652d4018dd Update zigbee-herdsman-converters to 14.0.454 (#11877)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-16 19:28:58 +00:00
github-actions[bot]andKoenkk 5b730575e4 Update zigbee-herdsman-converters to 14.0.452 (#11857)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-15 16:00:14 +00:00
github-actions[bot]andKoenkk 83f8250358 Update zigbee-herdsman-converters to 14.0.451 (#11845)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-14 17:12:06 +00:00
Koen Kanters 8bf06901c2 Availability for groups (#11626)
* Availability for groups. https://github.com/Koenkk/zigbee2mqtt/issues/9176

* Updates

* Fix
2022-03-14 15:51:02 +01:00
github-actions[bot]andKoenkk 4a0cd427de Update zigbee-herdsman-converters to 14.0.450 (#11839)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-13 18:20:54 +00:00
github-actions[bot]andKoenkk 23aacc4c00 Update dependencies (#11824)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-13 18:51:28 +01:00
github-actions[bot]andnurikk e7aef4c208 Update zigbee2mqtt-frontend to 0.6.79 (#11833)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-03-13 13:27:05 +00:00
github-actions[bot]andKoenkk 3cf3366070 Update zigbee-herdsman-converters to 14.0.449 (#11814)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-12 09:21:24 +00:00
Artem Draft 8f1787ed4a Expose cover running state to Home Assistant (#11789)
* handle cover running state in HA

* add running if the expose

* find running in definitionExposes
2022-03-12 10:14:25 +01:00
Koen Kanters b515c3213f Node 16 (#11804)
* Node 16

* More Node 16
2022-03-11 20:39:25 +01:00
github-actions[bot]andKoenkk 1aea3194bb Update zigbee-herdsman-converters to 14.0.448 (#11801)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-11 16:18:36 +00:00
github-actions[bot]andKoenkk 8f98a2f6d0 Update zigbee-herdsman-converters to 14.0.447 (#11787)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-10 17:27:39 +00:00
github-actions[bot]andKoenkk 52d151e70f Update zigbee-herdsman-converters to 14.0.446 (#11764)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-08 18:34:43 +00:00
github-actions[bot]andKoenkk 42f229b19e Update zigbee-herdsman-converters to 14.0.445 (#11753)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-07 17:52:33 +00:00
Koen Kanters e5d6bd1d68 Don't cache no_occupancy_since. https://github.com/Koenkk/zigbee2mqtt/issues/11183 2022-03-07 18:38:36 +01:00
github-actions[bot]andKoenkk c49f546256 Update zigbee-herdsman-converters to 14.0.444 (#11737)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-06 20:41:29 +00:00
github-actions[bot]andKoenkk 141f9f6d04 Update dependencies (#11726)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-06 20:13:20 +01:00
github-actions[bot]andnurikk a73a5b2cd4 Update zigbee2mqtt-frontend to 0.6.78 (#11733)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-03-06 08:39:44 +00:00
github-actions[bot]andKoenkk f7c6207d4f Update zigbee-herdsman-converters to 14.0.443 (#11716)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-05 15:36:48 +00:00
github-actions[bot]andKoenkk 9592147972 Update zigbee-herdsman-converters to 14.0.442 (#11696)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-03 17:24:06 +00:00
github-actions[bot]andnurikk a1cc8049b1 Update zigbee2mqtt-frontend to 0.6.77 (#11691)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-03-03 14:57:17 +00:00
st4ro 625236721f new device class GARAGE for garage door opener (#11680) 2022-03-02 21:31:15 +01:00
Andrew Berry 364a6dd2aa Only colorize output if logging to a tty (#11645) 2022-03-02 20:07:22 +01:00
github-actions[bot]andKoenkk 3535b2c6c2 Update zigbee-herdsman-converters to 14.0.439 (#11662)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-01 18:44:56 +00:00
Koen Kanters 91d597e53d Dev 2022-03-01 17:03:45 +01:00
Koen Kanters 7a2ddf24d3 1.24.0 2022-03-01 17:02:51 +01:00
Koen Kanters d123ea3e61 Undev 2022-03-01 17:02:10 +01:00
github-actions[bot]andKoenkk eda6e7ca37 Update zigbee-herdsman-converters to 14.0.438 (#11660)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-03-01 16:01:10 +00:00
Koen Kanters b50e40c9ca Update generateNewSupportedDevices.js 2022-03-01 16:50:26 +01:00
github-actions[bot]andnurikk 1eb3287029 Update zigbee2mqtt-frontend to 0.6.76 (#11656)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-03-01 03:45:41 +00:00
github-actions[bot]andKoenkk bc8cd8df94 Update zigbee-herdsman-converters to 14.0.437 (#11655)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-28 17:07:31 +00:00
github-actions[bot]andKoenkk 8751eca171 Update zigbee-herdsman-converters to 14.0.436 (#11634)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-27 12:57:56 +00:00
github-actions[bot]andKoenkk 107b2726b2 Update dependencies (#11630)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-27 13:38:54 +01:00
github-actions[bot]andKoenkk 987205c004 Update zigbee-herdsman-converters to 14.0.435 (#11624)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-26 11:55:57 +00:00
github-actions[bot]andKoenkk 4f7ee6898a Update zigbee-herdsman-converters to 14.0.434 (#11620)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-25 19:12:14 +00:00
github-actions[bot]andKoenkk 67ffcebe69 Update zigbee-herdsman-converters to 14.0.433 (#11614)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-25 16:16:56 +00:00
github-actions[bot]andKoenkk afe94a7cba Update zigbee-herdsman-converters to 14.0.432 (#11596)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-24 16:10:04 +00:00
a5db6ef0c4 Update zigbee-herdsman-converters to 14.0.431 (#11585)
* Update zigbee-herdsman-converters to 14.0.431

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-23 18:59:33 +00:00
github-actions[bot]andKoenkk 5dc369c5a4 Update zigbee-herdsman to 0.14.20 (#11584)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-23 18:23:39 +00:00
github-actions[bot]andKoenkk 65bd5423e8 Update zigbee-herdsman to 0.14.19 (#11583)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-23 18:17:16 +00:00
github-actions[bot]andKoenkk 9c33c90650 Update zigbee-herdsman-converters to 14.0.430 (#11569)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-22 15:54:08 +00:00
github-actions[bot]andKoenkk caafc64fbf Update zigbee-herdsman-converters to 14.0.429 (#11551)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-21 20:56:31 +00:00
github-actions[bot]andKoenkk 9e35f22ac4 Update zigbee-herdsman-converters to 14.0.427 (#11550)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-21 16:51:07 +00:00
github-actions[bot]andnurikk 23b7898a43 Update zigbee2mqtt-frontend to 0.6.75 (#11549)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-02-21 16:45:42 +00:00
github-actions[bot]andKoenkk 0fdbb9153d Update zigbee-herdsman to 0.14.18 (#11546)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-21 16:31:22 +00:00
github-actions[bot]andnurikk a345181812 Update zigbee2mqtt-frontend to 0.6.74 (#11534)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-02-21 01:16:43 +00:00
github-actions[bot]andKoenkk 7f4f48309e Update zigbee-herdsman to 0.14.17 (#11513)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-20 14:28:17 +00:00
github-actions[bot]andKoenkk f1eb605bef Update zigbee-herdsman-converters to 14.0.426 (#11512)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-20 14:01:14 +00:00
TobiasandKoen Kanters 9cfc38223e Add device and groups descriptions (#11493)
* Add device and groups descriptions

* Improvements

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-20 14:45:53 +01:00
github-actions[bot]andKoenkk abdb2b20c2 Update dependencies (#11499)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-20 14:22:20 +01:00
github-actions[bot]andnurikk 6d521147fa Update zigbee2mqtt-frontend to 0.6.73 (#11506)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-02-20 12:02:22 +00:00
github-actions[bot]andnurikk df97c79b78 Update zigbee2mqtt-frontend to 0.6.72 (#11504)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-02-20 05:43:33 +00:00
github-actions[bot]andKoenkk f6f507cda0 Update zigbee-herdsman-converters to 14.0.425 (#11486)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-19 09:04:10 +00:00
github-actions[bot]andKoenkk ba1843ff74 Update zigbee-herdsman-converters to 14.0.424 (#11478)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-18 15:33:45 +00:00
github-actions[bot]andKoenkk aace02ccda Update zigbee-herdsman-converters to 14.0.423 (#11457)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-16 20:51:36 +00:00
Koen Kanters 7ec6a2b483 Allow to specify options device/configure_reporting. https://github.com/Koenkk/zigbee2mqtt/issues/11442 2022-02-16 21:32:59 +01:00
84043702c1 Update zigbee-herdsman-converters to 14.0.422 (#11441)
* Update zigbee-herdsman-converters to 14.0.422

* fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-15 19:12:49 +00:00
github-actions[bot]andKoenkk 825308df20 Update zigbee-herdsman to 0.14.16 (#11440)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-15 19:03:43 +00:00
github-actions[bot]andKoenkk e0694a444e Update zigbee-herdsman to 0.14.15 (#11438)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-15 18:48:02 +00:00
github-actions[bot]andKoenkk f284a5d2d5 Update zigbee-herdsman-converters to 14.0.421 (#11402)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-13 14:46:03 +00:00
github-actions[bot]andKoenkk 5849a90030 Update dependencies (#11396)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-13 15:03:23 +01:00
github-actions[bot]andKoenkk b518e3e200 Update zigbee-herdsman-converters to 14.0.420 (#11389)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-12 16:09:56 +00:00
github-actions[bot]andKoenkk bccd7b390c Update zigbee-herdsman-converters to 14.0.419 (#11380)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-12 09:52:42 +00:00
4933b9080e Update zigbee-herdsman-converters to 14.0.418 (#11366)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-11 18:25:00 +00:00
github-actions[bot]andKoenkk cd9fd2d5c2 Update zigbee-herdsman to 0.14.14 (#11365)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-11 18:00:39 +00:00
Koen Kanters 9602574cd2 Add winston-transport dependency. https://github.com/Koenkk/zigbee2mqtt/issues/11356 2022-02-11 18:52:00 +01:00
github-actions[bot]andKoenkk 711e2d9cfc Update zigbee-herdsman-converters to 14.0.417 (#11346)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-10 18:46:56 +00:00
github-actions[bot]andKoenkk d8ecc6f26e Update zigbee-herdsman-converters to 14.0.416 (#11331)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-09 18:26:33 +00:00
github-actions[bot]andKoenkk 7fe803a28c Update zigbee-herdsman-converters to 14.0.415 (#11310)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-08 19:03:03 +00:00
6394d0f42e Update zigbee-herdsman-converters to 14.0.414 (#11284)
* Update zigbee-herdsman-converters to 14.0.414

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-07 17:11:04 +00:00
github-actions[bot]andKoenkk 52607d03cf Update zigbee-herdsman to 0.14.13 (#11275)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-07 09:13:59 +00:00
github-actions[bot]andKoenkk 5dd8873fcd Update zigbee-herdsman-converters to 14.0.413 (#11266)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-06 19:52:50 +00:00
github-actions[bot]andKoenkk 02e18b9d5b Update zigbee-herdsman-converters to 14.0.412 (#11258)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-06 13:26:16 +00:00
github-actions[bot]andKoenkk 42bb73e263 Update dependencies (#11254)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-06 14:11:24 +01:00
Ryan Kim(True-World) 39bf36b0b5 delete device class of alram(enum) (#11236) 2022-02-06 13:50:55 +01:00
github-actions[bot]andKoenkk b5e8566f58 Update zigbee-herdsman-converters to 14.0.411 (#11233)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-05 09:39:34 +00:00
Ryan Kim(True-World)andKoen Kanters 21567ab810 Add more Home Assistant device classes (#11225)
* add some device class

device class.

* fix lint

* Update homeassistant.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-05 09:20:35 +00:00
ValentinandKoen Kanters f9c4b4e926 HA Discover when user change option (#11210)
* HA Discover when user change option

* Fix unit tests

* Update homeassistant.ts

* Update homeassistant.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-02-05 10:12:13 +01:00
github-actions[bot]andKoenkk 8357da270d Update zigbee-herdsman to 0.14.12 (#11228)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-04 17:31:55 +00:00
github-actions[bot]andKoenkk 4def85b3ca Update zigbee-herdsman-converters to 14.0.410 (#11227)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-04 17:24:23 +00:00
Koen Kanters 0e11ae07d9 Recompute device definition when device changes modelID. https://github.com/Koenkk/zigbee-herdsman-converters/issues/3016 2022-02-04 18:02:47 +01:00
github-actions[bot]andKoenkk 9fb1eb40d3 Update zigbee-herdsman-converters to 14.0.409 (#11209)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-03 16:17:09 +00:00
github-actions[bot]andKoenkk ddcb8e12d5 Update zigbee-herdsman-converters to 14.0.408 (#11196)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-02 19:01:18 +00:00
github-actions[bot]andKoenkk 3470681ea7 Update zigbee-herdsman-converters to 14.0.407 (#11195)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-02 18:52:28 +00:00
Koen Kanters 41ece365aa Allow to configure availablility payloads to be a JSON object. #10802 2022-02-02 19:28:44 +01:00
Koen Kanters 73f02bfee3 Fix crash when availability is enabled per device. #11184 2022-02-02 17:39:45 +01:00
github-actions[bot]andKoenkk fae8e96229 Update zigbee-herdsman to 0.14.11 (#11185)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-02 10:40:49 +00:00
Koen Kanters 7f9b198722 Promote to dev 2022-02-01 19:13:28 +01:00
Koen Kanters 6ea61bae2c 1.23.0 2022-02-01 19:12:56 +01:00
Koen Kanters 5c915e5fd7 Undev 2022-02-01 19:12:11 +01:00
Koen Kanters b1f50701b2 Merge branch 'dev' 2022-02-01 19:11:47 +01:00
github-actions[bot]andKoenkk 273fc61099 Update zigbee-herdsman-converters to 14.0.406 (#11168)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-02-01 16:08:31 +00:00
github-actions[bot]andKoenkk 59ef38f076 Update zigbee-herdsman-converters to 14.0.405 (#11151)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-31 16:59:43 +00:00
Steven RoebertandKoen Kanters 9171ef35da Allowing to use HA device name override as base for entities (#11107)
* When overriding the home assistant name, use that name as the device name and as a base for each entity name

* Update homeassistant.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-31 17:46:42 +01:00
Koen Kanters 912360c1f0 Fix availability passive device timeout config. https://github.com/Koenkk/zigbee2mqtt/pull/10437 2022-01-31 17:28:08 +01:00
github-actions[bot]andKoenkk 04290274b8 Update zigbee-herdsman to 0.14.10 (#11150)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-31 15:13:10 +00:00
github-actions[bot]andKoenkk 9fc413dea9 Update zigbee-herdsman to 0.14.9 (#11147)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-31 10:26:31 +00:00
github-actions[bot]andnurikk 7863f600c8 Update zigbee2mqtt-frontend to 0.6.71 (#11130)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-01-30 17:19:43 +00:00
github-actions[bot]andnurikk 0bdbf7194b Update zigbee2mqtt-frontend to 0.6.70 (#11122)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-01-30 15:07:02 +00:00
github-actions[bot]andKoenkk 81131c32a8 Update zigbee-herdsman-converters to 14.0.404 (#11120)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-30 13:27:41 +00:00
github-actions[bot]andKoenkk 26ae01a0e4 Update dependencies (#11108)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-30 14:12:07 +01:00
Ilya Kirov 93921c6be9 Fix endpoint match (again) (#11083)
https://github.com/Koenkk/zigbee2mqtt/pull/10898
https://github.com/Koenkk/zigbee2mqtt/issues/11068
2022-01-29 09:58:23 +01:00
github-actions[bot]andKoenkk 2721cc1bbf Update zigbee-herdsman-converters to 14.0.403 (#11078)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-28 16:32:45 +00:00
github-actions[bot]andKoenkk 9120ccf403 Update zigbee-herdsman to 0.14.8 (#11077)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-28 16:26:37 +00:00
Ilya Kirov@RubenKelevra <cyrond@gmail.com>Koen Kanters
b92131cad6 Revert "Fix endpoint match" (#11072)
* GitHub issue templates: : Remove leading "[Problem]" in the title and the requirements to fill out all fields (#10779)

* remove leading "[Problem] " in the title

We already set a tag for this

* remove the need to enter all field in a bug report

there are certain cases where this isn't needed and filling them out with blank texts just to remove the text with an edit after filing feels dumb.

* Revert "Fix endpoint match (#10898)"

This reverts commit 5b918d9e3474c313878ff4275b551f79f39c85e2.

Co-authored-by: @RubenKelevra <cyrond@gmail.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-28 15:45:05 +00:00
github-actions[bot]andKoenkk 0b06483ce0 Update zigbee-herdsman-converters to 14.0.402 (#11063)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-27 19:00:39 +00:00
github-actions[bot]andKoenkk 6a4fba82df Update zigbee-herdsman-converters to 14.0.401 (#11060)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-27 16:09:43 +00:00
github-actions[bot]andKoenkk 1a2943d45e Update zigbee-herdsman-converters to 14.0.400 (#11030)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-26 16:52:47 +00:00
Joshua SpenceandKoen Kanters 1a70b80282 Flush logger before exiting process (#10905)
* Wait for async logs

* Fix tests

* Better solution

Based on https://stackoverflow.com/a/59260151

* Fix lint/test coverage

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-26 15:57:51 +00:00
github-actions[bot]andKoenkk c4c02d2e2d Update zigbee-herdsman-converters to 14.0.399 (#11011)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-25 16:06:24 +00:00
github-actions[bot]andKoenkk 5b9b7e4804 Update zigbee-herdsman to 0.14.7 (#11003)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-25 11:33:24 +00:00
github-actions[bot]andKoenkk 8e8c3d7b49 Update zigbee-herdsman-converters to 14.0.398 (#10996)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-24 15:59:58 +00:00
github-actions[bot]andKoenkk f0f7662f9e Update zigbee-herdsman-converters to 14.0.397 (#10987)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-23 20:17:22 +00:00
github-actions[bot]andKoenkk 5ef7b673d8 Update zigbee-herdsman to 0.14.6 (#10985)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-23 20:05:07 +00:00
github-actions[bot]andnurikk b6d26e351c Update zigbee2mqtt-frontend to 0.6.69 (#10976)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-01-23 16:56:05 +00:00
github-actions[bot]andKoenkk a10306b247 Update zigbee-herdsman-converters to 14.0.396 (#10970)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-23 13:36:08 +00:00
github-actions[bot]andKoenkk e7e23a1092 Update dependencies (#10961)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-23 13:25:38 +01:00
github-actions[bot]andKoenkk d5de1c6248 Update zigbee-herdsman to 0.14.5 (#10950)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-22 14:12:23 +00:00
github-actions[bot]andKoenkk 14dd4800f1 Update zigbee-herdsman-converters to 14.0.395 (#10949)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-22 13:56:37 +00:00
Koen Kanters 3451c71a21 Updates for https://github.com/Koenkk/zigbee-herdsman-converters/pull/3708 2022-01-22 10:54:01 +01:00
Koen Kanters 8e72b3bf64 Add preferredColorMode option. https://github.com/Koenkk/zigbee-herdsman-converters/pull/3708 2022-01-22 08:48:37 +01:00
github-actions[bot]andKoenkk 3ba185815f Update zigbee-herdsman-converters to 14.0.394 (#10941)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-21 19:39:06 +00:00
Koen Kanters 64f83d74b7 Clear old availability topic when device is renamed. #5244 2022-01-21 20:21:18 +01:00
github-actions[bot]andKoenkk ef2f28019b Update zigbee-herdsman to 0.14.4 (#10939)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-21 19:11:48 +00:00
github-actions[bot]andKoenkk e446c81677 Update zigbee-herdsman-converters to 14.0.393 (#10917)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-20 19:09:12 +00:00
Ilya Kirov d87347923b Fix endpoint match (#10898)
https://github.com/Koenkk/zigbee2mqtt/discussions/9504

For this case topic is 'state_top_left', 'state_bottom_left' and etc..,
Old pattern it is match as: [state_top_left, state_top, left]
New pattern it is match as: [state_top_left, state, top_left]
2022-01-19 22:15:23 +01:00
github-actions[bot]andKoenkk a867b719dc Update zigbee-herdsman-converters to 14.0.392 (#10895)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-19 17:00:46 +00:00
github-actions[bot]andKoenkk da3817bd40 Update zigbee-herdsman to 0.14.3 (#10893)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-19 16:36:11 +00:00
github-actions[bot]andKoenkk 7f98caca22 Update zigbee-herdsman to 0.14.2 (#10887)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-19 07:39:24 +00:00
github-actions[bot]andKoenkk 107ac3659f Update zigbee-herdsman-converters to 14.0.391 (#10876)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-18 16:25:25 +00:00
github-actions[bot]andKoenkk 48dfd581c1 Update zigbee-herdsman-converters to 14.0.390 (#10859)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-17 17:07:52 +00:00
github-actions[bot]andKoenkk 8e53d745cd Update zigbee-herdsman-converters to 14.0.389 (#10840)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-16 21:50:06 +00:00
github-actions[bot]andKoenkk 6877c591b8 Update zigbee-herdsman to 0.14.1 (#10839)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-16 21:44:33 +00:00
Koen Kanters d0ceaba6f2 Fix OTA (#10833)
* dump

* updates

* Updates
2022-01-16 18:25:53 +01:00
0d60777565 Update zigbee-herdsman-converters to 14.0.388 (#10838)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-16 18:16:10 +01:00
github-actions[bot]andKoenkk 074c70be54 Update zigbee-herdsman to 0.14.0 (#10837)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-16 18:15:06 +01:00
Koen Kanters b6a7ade6f2 Publish bridge/state online when Home Assistant comes online. https://github.com/Koenkk/zigbee2mqtt/issues/9629 2022-01-16 14:56:58 +01:00
github-actions[bot]andKoenkk d6ee1a6450 Update zigbee-herdsman-converters to 14.0.387 (#10827)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-16 08:59:30 +00:00
github-actions[bot]andKoenkk 3617ba2b1d Update dependencies (#10826)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-16 09:11:18 +01:00
github-actions[bot]andKoenkk ec8e7f57fa Update zigbee-herdsman-converters to 14.0.386 (#10821)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-15 19:14:46 +00:00
github-actions[bot]andKoenkk 87d33febcf Update zigbee-herdsman-converters to 14.0.385 (#10803)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-15 10:20:46 +00:00
Valentin 43e7ca7ad6 Expose optional user settings to configure() (#10791) 2022-01-14 16:53:22 +01:00
github-actions[bot]andKoenkk 4fd98c2aca Update zigbee-herdsman-converters to 14.0.384 (#10790)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-14 15:35:44 +00:00
@RubenKelevra 1a0a9a6eab GitHub issue templates: : Remove leading "[Problem]" in the title and the requirements to fill out all fields (#10779)
* remove leading "[Problem] " in the title

We already set a tag for this

* remove the need to enter all field in a bug report

there are certain cases where this isn't needed and filling them out with blank texts just to remove the text with an edit after filing feels dumb.
2022-01-14 15:59:10 +01:00
github-actions[bot]andKoenkk 57852fcddf Update zigbee-herdsman-converters to 14.0.383 (#10769)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-13 18:48:27 +00:00
c1b0a13e10 Update zigbee-herdsman to 0.13.194 (#10739)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-12 18:20:42 +00:00
github-actions[bot]andKoenkk 3835b792f0 Update zigbee-herdsman-converters to 14.0.382 (#10738)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-12 18:15:43 +00:00
github-actions[bot]andKoenkk 00124215a8 Update dependencies (#10723)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-11 18:32:11 +00:00
github-actions[bot]andKoenkk cac384c3fb Update zigbee-herdsman to 0.13.193 (#10699)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-10 18:33:00 +00:00
github-actions[bot]andKoenkk 0b3727d296 Update zigbee-herdsman-converters to 14.0.380 (#10696)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-10 17:59:01 +00:00
Koen Kanters 30177b0db4 Restructure settings (#10437)
* -

* deep copy schema

* -

* -

* -

* -

* -

* -

* -

* -

* -

* -

* -

* -
2022-01-09 22:28:44 +01:00
Koen Kanters ee6b035108 Support homeassistant_rename for groups. https://github.com/Koenkk/zigbee2mqtt/discussions/10672 2022-01-09 20:39:15 +01:00
Oleksandr MasliuchenkoandKoen Kanters 6ac8a6237e Add support for local OTA firmware images (#10676)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-09 20:38:58 +01:00
github-actions[bot]andKoenkk 44ee2f5f2b Update zigbee-herdsman-converters to 14.0.379 (#10684)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-09 19:29:16 +00:00
github-actions[bot]andKoenkk 9d6009ec99 Update zigbee-herdsman-converters to 14.0.378 (#10669)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-09 09:46:42 +00:00
github-actions[bot]andKoenkk cd60eb5069 Update zigbee-herdsman to 0.13.192 (#10668)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-09 08:48:46 +00:00
github-actions[bot]andKoenkk a10687ecaa Update dependencies (#10667)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-09 09:26:41 +01:00
github-actions[bot]andKoenkk 89693df2e1 Update zigbee-herdsman to 0.13.191 (#10659)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-08 16:30:44 +00:00
Koen Kanters e783117a3a Xiaomi retransmitted messages handling has been moved to zigbee-herdsman. https://github.com/Koenkk/zigbee2mqtt/issues/10656 2022-01-08 17:25:20 +01:00
github-actions[bot]andKoenkk e6b041436a Update zigbee-herdsman-converters to 14.0.376 (#10654)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-08 14:38:40 +00:00
github-actions[bot]andKoenkk 3d4d7dc910 Update zigbee-herdsman-converters to 14.0.375 (#10650)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-07 22:21:24 +00:00
github-actions[bot]andKoenkk 811ef1dcb5 Update zigbee-herdsman-converters to 14.0.374 (#10646)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-07 16:31:15 +00:00
github-actions[bot]andKoenkk 208a552c02 Update zigbee-herdsman-converters to 14.0.373 (#10628)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-06 20:57:04 +00:00
github-actions[bot]andKoenkk 74cf20b172 Update zigbee-herdsman-converters to 14.0.372 (#10622)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-06 17:34:01 +00:00
Koen Kanters dbcd768e1d Log out of memory error when initial build fails. #10555 2022-01-06 17:59:10 +01:00
github-actions[bot]andKoenkk 43ded111fb Update zigbee-herdsman-converters to 14.0.371 (#10600)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-05 18:56:05 +00:00
Oleksandr MasliuchenkoandKoen Kanters 16842a3e72 Add posibility to have local OTA index (#10141)
* Add a configuration option to override OTA index file

* Cleanup

* Code review corrections

* Move zigbee_ota_override_index_location to ota section of the configuration file

* Suport both local and remote (HTTP) OTA override index files

* Updates

* updates

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-04 20:29:17 +01:00
Koen Kanters e88ceeec2e Merge remote-tracking branch 'origin/master' into dev 2022-01-04 20:23:20 +01:00
github-actions[bot]andKoenkk f51a7883fe Update zigbee-herdsman-converters to 14.0.370 (#10570)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-04 19:17:53 +00:00
github-actions[bot]andnurikk 4f887a1a3b Update zigbee2mqtt-frontend to 0.6.68 (#10539)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2022-01-03 15:38:54 +00:00
github-actions[bot]andKoenkk 23bdc18608 Update zigbee-herdsman-converters to 14.0.369 (#10523)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-02 21:42:02 +00:00
github-actions[bot]andKoenkk 101e0192bd Update zigbee-herdsman to 0.13.190 (#10522)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-02 21:30:24 +00:00
github-actions[bot]andKoenkk 24d9065d26 Update zigbee-herdsman-converters to 14.0.368 (#10521)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-02 21:07:03 +00:00
05d545945d Update zigbee-herdsman-converters to 14.0.367 (#10502)
* Update zigbee-herdsman-converters to 14.0.367

* Update publish.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-02 12:54:30 +00:00
github-actions[bot]andKoenkk 089ff8f370 Update zigbee-herdsman to 0.13.189 (#10503)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-02 10:39:13 +00:00
Koen Kanters 301ba14b00 Update new_device_support.yaml 2022-01-02 10:44:47 +01:00
ValentinandKoen Kanters 9d120d225d Automatically expose entitity as energy when Wh/kWh exists (#10133)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2022-01-02 09:39:34 +00:00
github-actions[bot]andKoenkk 38b07fb8ca Update dependencies (#10495)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-02 10:33:26 +01:00
Rotzbua e8caddaf63 Fix typo: suppress (#10490)
* Fix typo: suppress

* Fix typo: discovered
2022-01-02 07:11:39 +00:00
Koen Kanters 15f1df8fa4 Promote to dev 2022-01-01 10:47:30 +01:00
Koen Kanters 414c51f5b2 1.22.2 2022-01-01 10:46:42 +01:00
Koen Kanters 0c42067006 Undev 2022-01-01 10:45:46 +01:00
Koen Kanters 5741904e75 Merge branch 'master' into dev 2022-01-01 10:44:52 +01:00
github-actions[bot]andKoenkk c60fdfd39b Update zigbee-herdsman-converters to 14.0.366 (#10472)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2022-01-01 09:37:27 +00:00
Koen Kanters a7682498ef Fix set message with endpoint in payload where the endpoint name ends with a number not working. #10423 2021-12-31 14:05:15 +01:00
github-actions[bot]andnurikk c6a3b90c2f Update zigbee2mqtt-frontend to 0.6.67 (#10466)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-31 12:17:44 +00:00
github-actions[bot]andKoenkk ebd35052c0 Update zigbee-herdsman-converters to 14.0.365 (#10463)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-31 11:02:13 +00:00
github-actions[bot]andnurikk 2849f30417 Update zigbee2mqtt-frontend to 0.6.66 (#10458)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-31 06:04:35 +00:00
Koen Kanters e8526b7b58 Better test for #10355 2021-12-30 17:32:02 +01:00
github-actions[bot]andKoenkk 3166d37096 Update zigbee-herdsman-converters to 14.0.364 (#10446)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-30 14:43:59 +00:00
github-actions[bot]andKoenkk 2d2c01981e Update zigbee-herdsman-converters to 14.0.363 (#10441)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-30 10:37:06 +00:00
58b702e8ef Update zigbee-herdsman to 0.13.188 (#10440)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-30 10:11:08 +00:00
github-actions[bot]andKoenkk 6efa20fa1d Update zigbee-herdsman-converters to 14.0.362 (#10439)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-30 10:06:22 +00:00
github-actions[bot]andKoenkk bf72347468 Update zigbee-herdsman-converters to 14.0.361 (#10433)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-29 18:14:08 +00:00
Ryan Kim(True-World) 73a6ad4cf8 add HA expose, binary sensor card (#10406)
* add binary sensor card

* fix lint
2021-12-29 16:21:59 +01:00
Koen Kanters 1e75dd5628 Test case for #10355 2021-12-27 20:29:16 +01:00
bc92bd73e6 Update zigbee-herdsman to 0.13.187 (#10394)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-27 19:08:38 +00:00
github-actions[bot]andKoenkk 8756367666 Update zigbee-herdsman-converters to 14.0.360 (#10393)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-27 19:03:17 +00:00
Alex CherkayevandOleksandr Cherkayev 79e5f0844a Add 4417 to bind poll (#10379)
Co-authored-by: Oleksandr Cherkayev <ocherkayev@luxoft.com>
2021-12-27 18:11:21 +01:00
github-actions[bot]andKoenkk b0585172f4 Update zigbee-herdsman-converters to 14.0.359 (#10369)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-26 10:28:37 +00:00
Koen Kanters 89996835ed Update new device support template 2021-12-26 11:21:52 +01:00
Koen Kanters 4f2a1e55e5 Update new device support template 2021-12-26 11:18:56 +01:00
Koen Kanters d488563f2a Update new device support template 2021-12-26 11:18:10 +01:00
Koen Kanters 4310171abc Update new device support template 2021-12-26 11:16:14 +01:00
Koen Kanters 36d7b4b022 Update new device support template 2021-12-26 11:15:11 +01:00
Koen Kanters 50a6ed14d4 Allow read/write to unsupported devices. 2021-12-26 10:54:39 +01:00
github-actions[bot]andKoenkk ee623c2484 Update dependencies (#10362)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-26 10:10:22 +01:00
github-actions[bot]andKoenkk 2e6588719b Update zigbee-herdsman-converters to 14.0.358 (#10356)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-25 15:00:19 +00:00
github-actions[bot]andnurikk fb35b52ca6 Update zigbee2mqtt-frontend to 0.6.65 (#10349)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-25 04:43:38 +00:00
github-actions[bot]andKoenkk 3306b63299 Update zigbee-herdsman-converters to 14.0.357 (#10345)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-24 19:58:58 +00:00
Koen Kanters 7a4ecadb6a Change coordinator ieee addr place. 2021-12-24 17:56:18 +01:00
Koen Kanters 511f3b09af Expose coordinator_ieeeaddr on bridge/info 2021-12-24 17:52:30 +01:00
github-actions[bot]andnurikk 828982d36c Update zigbee2mqtt-frontend to 0.6.64 (#10344)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-24 15:37:18 +00:00
github-actions[bot]andKoenkk 61bd95f8b8 Update zigbee-herdsman to 0.13.186 (#10338)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-23 20:27:48 +00:00
ValentinandKoen Kanters 74cff6a983 Call onEvent when device options change (#10322)
* Notify when options change

* publish device info after options change

* Refactor

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-23 21:18:27 +01:00
Koen Kanters fdf7d10a41 Update problem report template 2021-12-23 21:12:06 +01:00
Koen Kanters 1145e4b81b Update 2021-12-23 21:08:31 +01:00
Koen Kanters 93f01d545e Fix issue templates 2021-12-23 21:04:38 +01:00
Koen Kanters 30e7385cac Update issue templates 2021-12-23 21:02:15 +01:00
Koen Kanters 513314963c Update issue template 2021-12-23 20:31:14 +01:00
Koen Kanters 3c0cd8ebfa Fix issue template syntax 2021-12-23 20:27:00 +01:00
Koen Kanters 5bedc044d6 Update issue templates 2021-12-23 20:24:06 +01:00
2a8a98f9a3 Update zigbee-herdsman-converters to 14.0.356 (#10329)
* Update zigbee-herdsman-converters to 14.0.356

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-23 19:00:19 +00:00
github-actions[bot]andKoenkk 03f24a63d5 Update zigbee-herdsman to 0.13.185 (#10330)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-23 18:46:45 +00:00
53003b3d0d Update zigbee-herdsman-converters to 14.0.355 (#10317)
* Update zigbee-herdsman-converters to 14.0.355

* Fix tests

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-22 20:34:24 +00:00
ValentinandKoen Kanters cd5dd39971 Dynamically expose attributes (#10132)
* Dynamically expose attributes

* Rollback options in configure step

Use event instead, as proposed in https://github.com/Koenkk/zigbee2mqtt/pull/10132/files#r771801648

* Simplify code

* Switch to already existing event

* Fix all unit tests

* Remove redundant code

* Perfect rollback

* Fix typescript types

* Updates

* Updates

* Updates

* updates

* Improve

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-22 19:31:41 +00:00
github-actions[bot]andKoenkk 41b150af82 Update zigbee-herdsman-converters to 14.0.354 (#10314)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-22 19:12:34 +00:00
github-actions[bot]andnurikk 3ba1f8cad0 Update zigbee2mqtt-frontend to 0.6.63 (#10311)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-22 14:58:41 +00:00
Koen Kanters f9aa525048 Refactor Home Assistant extension mapping, prepares for #10132 2021-12-21 22:02:05 +01:00
github-actions[bot]andKoenkk 8b4be3d6ad Update zigbee-herdsman-converters to 14.0.353 (#10301)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-21 20:28:49 +00:00
github-actions[bot]andKoenkk 0efe869fcb Update zigbee-herdsman-converters to 14.0.352 (#10277)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-20 20:13:36 +00:00
github-actions[bot]andKoenkk 18cfbae9ca Update zigbee-herdsman-converters to 14.0.351 (#10272)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-20 17:49:39 +00:00
7625d261a5 Update zigbee-herdsman to 0.13.184 (#10247)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-19 17:14:25 +00:00
Koen Kanters 6d8eea2142 Fix tests 2021-12-19 18:12:16 +01:00
Koen Kanters 2a9d22e2b3 Software/datacode is now updated by zigbee-herdsman. #10131 2021-12-19 18:00:27 +01:00
github-actions[bot]andKoenkk 656446c828 Update zigbee-herdsman-converters to 14.0.350 (#10239)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-19 10:15:31 +00:00
github-actions[bot]andnurikk f1ffc1d265 Update zigbee2mqtt-frontend to 0.6.62 (#10237)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-19 09:36:53 +00:00
github-actions[bot]andKoenkk 2d1df8f0cb Update dependencies (#10234)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-19 10:28:09 +01:00
github-actions[bot]andKoenkk 253e985388 Update zigbee-herdsman-converters to 14.0.349 (#10220)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-18 09:08:56 +00:00
Koen Kanters 1dd1163288 Fix list not overridable in Home Assistant discovery payload. #10120 2021-12-17 21:37:19 +01:00
github-actions[bot]andKoenkk bb5627d33b Update zigbee-herdsman-converters to 14.0.348 (#10211)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-17 20:28:39 +00:00
github-actions[bot]andKoenkk 38f42bb3c8 Update zigbee-herdsman-converters to 14.0.347 (#10205)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-16 18:34:01 +00:00
github-actions[bot]andKoenkk 5f37145a02 Update zigbee-herdsman-converters to 14.0.346 (#10194)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-15 18:55:43 +00:00
Koen Kanters a56061b36d Attempt to fix crash due to availability state read. #10177 2021-12-15 19:48:32 +01:00
github-actions[bot]andKoenkk b890b1bcb7 Update zigbee-herdsman to 0.13.183 (#10193)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-15 18:33:09 +00:00
Koen Kanters aa84a140e1 Fix null race condition exception. #10108 2021-12-15 19:13:14 +01:00
github-actions[bot]andKoenkk d875b297ad Update zigbee-herdsman to 0.13.182 (#10182)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-14 21:18:08 +00:00
Koen Kanters 1c6ca6519c Delete branch-switcher.yml 2021-12-14 22:14:43 +01:00
github-actions[bot]andKoenkk 900c9f302e Update zigbee-herdsman-converters to 14.0.345 (#10183)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-14 21:13:20 +00:00
Koen Kanters ea04021438 Cleanup availability experimental log. #9907 2021-12-14 20:38:44 +01:00
Koen Kanters 5a624ae188 Fix error for Home Assistant last_seen sensor when epoch is used. #8287 2021-12-14 20:27:49 +01:00
Dmitriy Fishman 42569d6c39 Fix a typo in CONTRIBUTING.md (#10159) 2021-12-14 16:49:23 +01:00
github-actions[bot]andKoenkk 46e06dbbee Update dependencies (#10147)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-14 11:30:45 +01:00
github-actions[bot]andKoenkk a282221e40 Update zigbee-herdsman to 0.13.181 (#10164)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-13 14:30:32 +00:00
github-actions[bot]andnurikk bb22216d09 Update zigbee2mqtt-frontend to 0.6.61 (#10134)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-11 02:54:47 +00:00
github-actions[bot]andnurikk 28cb8b08fb Update zigbee2mqtt-frontend to 0.6.60 (#10122)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-10 04:36:26 +00:00
594a463f8b Update zigbee-herdsman-converters to 14.0.344 (#10116)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-09 18:56:19 +00:00
Pavel Sokolov 9c1a15465d Tuya zcl refactor (#10112)
* Rename Tuya command setData->dataRequest
https://github.com/Koenkk/zigbee-herdsman/issues/466

* Fix Tuya datapoint commands invalid format (status,transid -> seq). Tuya has `uint16` type for the sequence(transaction) number.
https://github.com/Koenkk/zigbee-herdsman/issues/466

* Tuya zcl refactoring: fix zigbe2mqtt tests
https://github.com/Koenkk/zigbee-herdsman/issues/466
2021-12-09 19:54:06 +01:00
Koen Kanters 22836f224d Fix filtered attributes being published as null. #10099 2021-12-09 19:52:21 +01:00
github-actions[bot]andKoenkk aafd937f8a Update zigbee-herdsman to 0.13.180 (#10115)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-09 18:39:54 +00:00
github-actions[bot]andKoenkk d0195d0ff9 Update zigbee-herdsman-converters to 14.0.343 (#10092)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-08 17:14:53 +00:00
Koen Kanters 7592c627c2 Fix typo in settings.schema.json. https://github.com/Koenkk/zigbee2mqtt/pull/9803 2021-12-08 17:46:17 +01:00
github-actions[bot]andnurikk 98a57b4540 Update zigbee2mqtt-frontend to 0.6.59 (#10082)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-08 01:50:06 +00:00
github-actions[bot]andKoenkk 70b9d29ddf Update zigbee-herdsman-converters to 14.0.342 (#10079)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-07 21:11:32 +00:00
Koen Kanters ac16d7ce69 Reconfigure device after OTA update. #7716 #7150 2021-12-07 21:58:11 +01:00
Koen Kanters d4f560d198 Validate QOS value. https://github.com/Koenkk/zigbee2mqtt/issues/9962 2021-12-07 18:52:54 +01:00
github-actions[bot]andKoenkk 4136b1e539 Update zigbee-herdsman to 0.13.179 (#10072)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-07 17:30:28 +00:00
github-actions[bot]andKoenkk b4af8329e7 Update zigbee-herdsman-converters to 14.0.341 (#10049)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-06 20:46:06 +00:00
github-actions[bot]andKoenkk ac0aca59a3 Update zigbee-herdsman-converters to 14.0.340 (#10046)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-06 19:40:28 +00:00
github-actions[bot]andnurikk bc8274b9fd Update zigbee2mqtt-frontend to 0.6.58 (#10035)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-06 03:48:12 +00:00
github-actions[bot]andKoenkk e5321d3f20 Update zigbee-herdsman-converters to 14.0.339 (#10021)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-05 14:49:20 +00:00
github-actions[bot]andnurikk 7a81a04b2f Update zigbee2mqtt-frontend to 0.6.57 (#10023)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-05 14:44:58 +00:00
github-actions[bot]andKoenkk 3b3d886121 Update zigbee-herdsman to 0.13.178 (#10022)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-05 14:30:05 +00:00
TilmanK 48b790cbf3 Adds link to web interface to the readme (#10015) 2021-12-05 15:05:26 +01:00
9c93103fb7 Update dependencies (#10011)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-05 15:01:53 +01:00
github-actions[bot]andnurikk 33b35c1e61 Update zigbee2mqtt-frontend to 0.6.56 (#10017)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-05 10:36:58 +00:00
github-actions[bot]andKoenkk 073c7aedf7 Update zigbee-herdsman-converters to 14.0.337 (#10000)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-04 15:20:48 +00:00
github-actions[bot]andKoenkk e789514777 Update zigbee-herdsman to 0.13.177 (#9999)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-04 14:31:30 +00:00
github-actions[bot]andnurikk fd762fcf10 Update zigbee2mqtt-frontend to 0.6.55 (#9998)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-04 13:26:16 +00:00
github-actions[bot]andnurikk 45b49bac0a Update zigbee2mqtt-frontend to 0.6.54 (#9997)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-04 12:30:48 +00:00
github-actions[bot]andnurikk 055fba259a Update zigbee2mqtt-frontend to 0.6.53 (#9996)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-04 09:49:59 +00:00
github-actions[bot]andnurikk b206dc910f Update zigbee2mqtt-frontend to 0.6.52 (#9995)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-04 09:40:34 +00:00
github-actions[bot]andnurikk 70db18f3ab Update zigbee2mqtt-frontend to 0.6.51 (#9992)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-04 03:33:58 +00:00
Koen Kanters cb2ef51df8 Fix last seen not always updated. #7423 2021-12-03 19:21:52 +01:00
Koen Kanters 68e5b39172 Mock update.state for Home Asisstant sensor. https://github.com/Koenkk/zigbee2mqtt/issues/9939 2021-12-03 19:08:00 +01:00
github-actions[bot]andnurikk b17ea2e4d9 Update zigbee2mqtt-frontend to 0.6.50 (#9982)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-03 16:17:11 +00:00
github-actions[bot]andnurikk 41f9361922 Update zigbee2mqtt-frontend to 0.6.49 (#9975)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-03 11:45:25 +00:00
github-actions[bot]andnurikk dae66fd3fc Update zigbee2mqtt-frontend to 0.6.48 (#9955)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-02 13:28:03 +00:00
github-actions[bot]andnurikk d6ea54b8df Update zigbee2mqtt-frontend to 0.6.47 (#9953)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-02 12:25:07 +00:00
Koen Kanters c47b9c7c9b Promote to dev 2021-12-01 17:21:30 +01:00
Koen Kanters c2b5229f76 1.22.1 2021-12-01 17:20:47 +01:00
Koen Kanters 0c605688af Undev 2021-12-01 17:20:43 +01:00
Koen Kanters 6876e19008 Merge branch 'dev' 2021-12-01 17:19:37 +01:00
github-actions[bot]andKoenkk 437b1dfb3e Update zigbee-herdsman-converters to 14.0.336 (#9930)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-12-01 16:15:02 +00:00
github-actions[bot]andnurikk fda1f23829 Update zigbee2mqtt-frontend to 0.6.46 (#9928)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-01 12:02:13 +00:00
ed9d09a629 Replace serve-static with connect-gzip-static (#9921)
* Replace serve-static with connect-gzip-static in order to serve .gz files

* Make linter happy

Co-authored-by: nurikk <ainur@yojee.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-12-01 07:20:53 +00:00
github-actions[bot]andnurikk d298412a1d Update zigbee2mqtt-frontend to 0.6.45 (#9922)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-12-01 02:20:56 +00:00
Koen Kanters e7447cf1e3 Another attempt to fix https://github.com/Koenkk/zigbee2mqtt/issues/9822 2021-11-30 20:20:46 +01:00
c90171d2cc Update zigbee-herdsman to 0.13.176 (#9916)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-30 18:26:53 +00:00
github-actions[bot]andKoenkk d2cf0dd8aa Update zigbee-herdsman-converters to 14.0.335 (#9915)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-30 18:22:06 +00:00
Hai-Nam Nguyen d415f57e30 Fix link to Zigbee cluster library (#9901) 2021-11-30 17:02:56 +00:00
github-actions[bot]andnurikk 56998f72f5 Update zigbee2mqtt-frontend to 0.6.44 (#9909)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-30 14:36:40 +00:00
github-actions[bot]andnurikk 97bd090ad6 Update zigbee2mqtt-frontend to 0.6.43 (#9908)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-30 14:10:51 +00:00
amadeo-alexandKoen Kanters df182be21f Fix log commit hash newline (#9897)
* Added trim operation before commitHash is returned

* Update utils.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-30 12:24:36 +08:00
290a0312d4 Update zigbee-herdsman to 0.13.175 (#9894)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-29 17:46:28 +00:00
github-actions[bot]andKoenkk 4d432658e9 Update zigbee-herdsman-converters to 14.0.334 (#9893)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-29 17:20:10 +00:00
Koen Kanters c2d9ffa7ad Fix "Possible EventEmitter memory leak detected. 1001 drain listeners added to [Socket]" warning. #9822 2021-11-29 17:49:54 +01:00
github-actions[bot]andnurikk 82f5ddb748 Update zigbee2mqtt-frontend to 0.6.42 (#9882)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-29 01:29:37 +00:00
github-actions[bot]andKoenkk 1069ec2a1a Update zigbee-herdsman-converters to 14.0.333 (#9879)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-28 19:14:34 +00:00
Koen Kanters cd4ac0c174 Ignore messages from coordinator. https://github.com/Koenkk/zigbee2mqtt/issues/9218 2021-11-28 20:08:09 +01:00
134b80ccf6 Update dependencies (#9870)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-28 17:34:57 +00:00
github-actions[bot]andnurikk b07450d413 Update zigbee2mqtt-frontend to 0.6.41 (#9875)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-28 15:19:05 +00:00
Koen Kanters 65f7fc0532 Fix lint errors of 0a7a477281 2021-11-27 09:36:03 +01:00
Koen Kanters 0a7a477281 Send only 1 MQTT message when last_seen is enabled and Zigbee message is received. https://github.com/Koenkk/zigbee2mqtt/issues/9519 2021-11-27 09:31:31 +01:00
github-actions[bot]andKoenkk a170f304c7 Update zigbee-herdsman to 0.13.174 (#9862)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-27 08:30:42 +00:00
github-actions[bot]andKoenkk 35ed5154c8 Update zigbee-herdsman-converters to 14.0.332 (#9861)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-27 07:42:00 +00:00
Koen Kanters 641853e6d5 Revert "Increase max event listeners. https://github.com/Koenkk/zigbee2mqtt/issues/9822"
This reverts commit 51321affcf.
2021-11-27 08:38:33 +01:00
github-actions[bot]andKoenkk 2af9f21961 Update zigbee-herdsman-converters to 14.0.331 (#9859)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-26 21:19:41 +00:00
Koen Kanters 51321affcf Increase max event listeners. https://github.com/Koenkk/zigbee2mqtt/issues/9822 2021-11-25 21:49:50 +01:00
github-actions[bot]andKoenkk 5fca6fbd09 Update zigbee-herdsman-converters to 14.0.330 (#9842)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-25 15:55:42 +00:00
github-actions[bot]andnurikk 070065a248 Update zigbee2mqtt-frontend to 0.6.40 (#9841)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-25 14:01:40 +00:00
github-actions[bot]andKoenkk 9a8f204683 Update zigbee-herdsman-converters to 14.0.329 (#9831)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-24 20:47:44 +00:00
github-actions[bot]andKoenkk 167c05681e Update zigbee-herdsman to 0.13.173 (#9817)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-23 19:40:54 +00:00
github-actions[bot]andKoenkk 01d7bd25be Update zigbee-herdsman-converters to 14.0.328 (#9816)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-23 19:20:32 +00:00
tteckster 372ec315b5 Update settings.schema.json (#9803)
* Update settings.schema.json

* Update settings.schema.json
2021-11-23 18:00:44 +00:00
Dmitriy Fishman df0543d4b7 Update README.md (#9801) 2021-11-23 18:00:16 +00:00
github-actions[bot]andKoenkk a9e3fb3358 Update zigbee-herdsman-converters to 14.0.327 (#9799)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-22 21:34:30 +00:00
github-actions[bot]andKoenkk 678e19fd7e Update zigbee-herdsman-converters to 14.0.326 (#9795)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-22 19:05:41 +00:00
github-actions[bot]andnurikk 9128838534 Update zigbee2mqtt-frontend to 0.6.39 (#9789)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-22 14:03:18 +00:00
github-actions[bot]andnurikk 35876616ef Update zigbee2mqtt-frontend to 0.6.37 (#9786)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-22 07:10:51 +00:00
github-actions[bot]andKoenkk 0bc3129b7a Update zigbee-herdsman-converters to 14.0.325 (#9781)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-21 21:30:33 +00:00
Koen Kanters 5e3b18a053 Log failed to ping as warning instead of error. https://github.com/Koenkk/zigbee2mqtt/issues/9700 2021-11-21 22:11:10 +01:00
github-actions[bot]andnurikk ad3ff7fa40 Update zigbee2mqtt-frontend to 0.6.36 (#9772)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-21 04:15:04 +00:00
github-actions[bot]andnurikk 008d6f9aa0 Update zigbee2mqtt-frontend to 0.6.35 (#9771)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-21 04:03:44 +00:00
github-actions[bot]andKoenkk 854353fb71 Update dependencies (#9770)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-21 01:15:28 +01:00
github-actions[bot]andnurikk e35ba0f83c Update zigbee2mqtt-frontend to 0.6.34 (#9764)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-20 16:58:33 +00:00
github-actions[bot]andKoenkk a154e18326 Update zigbee-herdsman-converters to 14.0.324 (#9761)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-20 13:12:15 +00:00
Filip SandborgandKoen Kanters c793cc83ad Expose pi_heating_demand to Home Assistant (#9759)
* homeassistant: expose pi_heating_demand on climate

This allows homeassistant to access the actual percentage actuation currently used on thermostats.

* Update homeassistant.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-20 13:59:04 +01:00
Koen Kanters a51626e357 Add sleep before enable-pull-request-automerge 2021-11-19 19:51:14 +01:00
github-actions[bot]andKoenkk 0f3315063f Update zigbee-herdsman-converters to 14.0.323 (#9751)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-19 18:47:34 +00:00
Koen Kanters 1065916a01 Enable auto merge for update_frontend 2021-11-19 09:36:17 +01:00
github-actions[bot]andKoenkk a980b4dff5 Update zigbee-herdsman to 0.13.172 (#9731)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-18 20:08:18 +00:00
Koen Kanters 825c7465ae Merge branch 'master' into dev 2021-11-18 20:59:53 +01:00
Koen Kanters 97521478c6 Enable auto merge for update_zhc/zh 2021-11-18 20:57:29 +01:00
Koen Kanters 6279c83e65 Merge branch 'master' into dev 2021-11-18 20:14:37 +01:00
Koen Kanters 91479fc0ec Enable auto merge for update_zhc/zh 2021-11-18 20:14:26 +01:00
github-actions[bot]andKoenkk 9dbe6f0a6c Update zigbee-herdsman-converters to 14.0.322 (#9725)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-18 19:10:01 +00:00
Koen Kanters 5d415aa299 Support multiple endpoints for Home Assistant tilt cover. https://github.com/Koenkk/zigbee-herdsman-converters/issues/3376 2021-11-18 19:43:38 +01:00
github-actions[bot]andKoenkk 6a75e0d4ee Update zigbee-herdsman-converters to 14.0.321 (#9720)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-17 22:08:15 +01:00
github-actions[bot]andKoenkk 13e9616c92 Update zigbee-herdsman-converters to 14.0.320 (#9716)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-17 19:56:28 +01:00
Koen Kanters cc03be46df Fix properties missing when debounce is used under some conditions #9658 (#9682)
* Add logging

* Kill bugs

* Updates
2021-11-17 17:59:00 +00:00
github-actions[bot]andKoenkk 64154e0cb2 Update zigbee-herdsman-converters to 14.0.319 (#9696)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-16 19:42:18 +01:00
github-actions[bot]andnurikk b2eaa3141e Update zigbee2mqtt-frontend to 0.6.33 (#9663)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-15 16:36:31 +08:00
github-actions[bot]andKoenkk d192bbd28f Update zigbee-herdsman-converters to 14.0.318 (#9654)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-14 16:20:45 +00:00
Koen Kanters 9582808b09 Prepare for https://github.com/Koenkk/zigbee2mqtt/pull/9654 2021-11-14 17:18:01 +01:00
github-actions[bot]andKoenkk 623f999ec8 Update zigbee-herdsman to 0.13.170 (#9655)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-14 16:43:51 +01:00
Koen Kanters 3141a14fec Attempt to fix race condition in availability stop. https://github.com/Koenkk/zigbee2mqtt/issues/9644 2021-11-14 16:18:54 +01:00
Koen Kanters 7e2a2bdd34 Remove led control (#9404) 2021-11-14 15:04:23 +00:00
github-actions[bot]andKoenkk 2f503bf39a Update dependencies (#9647)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-14 16:02:25 +01:00
Ernst 945b72b990 a few simple language fixes (README.md) (#9642) 2021-11-13 16:09:46 +00:00
github-actions[bot]andKoenkk 3bfc7f31cf Update zigbee-herdsman-converters to 14.0.317 (#9632)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-13 10:13:28 +01:00
github-actions[bot]andnurikk 1f60edff99 Update zigbee2mqtt-frontend to 0.6.32 (#9628)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-13 13:31:39 +08:00
github-actions[bot]andKoenkk 3249ab00ab Update zigbee-herdsman-converters to 14.0.316 (#9624)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-12 18:38:26 +01:00
github-actions[bot]andKoenkk 8c8f907fd3 Update zigbee-herdsman to 0.13.169 (#9606)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-11 21:15:38 +01:00
Koen Kanters 170ef40982 Fix startup blocked by onEvent handlers 2021-11-11 21:00:16 +01:00
github-actions[bot]andKoenkk e547062702 Update zigbee-herdsman-converters to 14.0.315 (#9605)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-11 20:47:54 +01:00
Artem DraftandKoen Kanters 6ca8d35183 Expose local_temperature_calibration to Home Assistant (#9595)
* expose local_temperature_calibration in HA as numeric

* fix eslint

* added min/max logic

* remove magic values

* Update homeassistant.ts

* Update types.d.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-10 20:17:56 +00:00
Koen Kanters 420bae4259 Fix Home Assistant command topics for multi endpoint climate devices. https://github.com/Koenkk/zigbee-herdsman-converters/pull/3217 2021-11-10 21:07:47 +01:00
github-actions[bot]andKoenkk 97dacd7623 Update zigbee-herdsman-converters to 14.0.314 (#9596)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-10 20:45:28 +01:00
Kenny LevinsenandKoen Kanters 8ef82fe23f receive: Add genPollCtrl to ignored clusters (#9580)
zigbee-herdsman may bind genPollCtrl for poll control integration, but
that does not mean that there will be a converter available further up
the stack.

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-10 18:44:07 +00:00
github-actions[bot]andKoenkk cd3df10a54 Update zigbee-herdsman-converters to 14.0.313 (#9563)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-08 19:03:42 +00:00
github-actions[bot]andKoenkk d5ccd9221c Update zigbee-herdsman to 0.13.168 (#9562)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-08 18:49:16 +00:00
github-actions[bot]andKoenkk fc9abfe53b Update zigbee-herdsman-converters to 14.0.311 (#9552)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-07 20:58:55 +01:00
01ea46b280 Update zigbee-herdsman-converters to 14.0.310 (#9549)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-07 18:40:12 +00:00
github-actions[bot]andKoenkk ab629d52ea Update zigbee-herdsman to 0.13.167 (#9548)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-07 19:37:44 +01:00
Adam BelebczukandKoen Kanters 9e216011d4 Fix Home Assistant discovery message for running_state fan_only (#9547)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-07 17:38:51 +00:00
Koen Kanters 91d90bdcf1 Merge remote-tracking branch 'origin/master' into dev 2021-11-07 18:37:01 +01:00
github-actions[bot]andKoenkk 6ba743cbed Update dependencies (#9538)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-07 12:22:36 +01:00
2399ec040f Update zigbee-herdsman-converters to 14.0.309 (#9526)
* Update zigbee-herdsman-converters to 14.0.309

* Update receive.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-05 19:41:23 +00:00
Koen Kanters f151e1d371 Fix 89af770d96 for real now 2021-11-05 20:39:12 +01:00
Koen Kanters 55802ef648 Fix 89af770d96 2021-11-05 20:31:09 +01:00
Koen Kanters 89af770d96 Fix external extensions not started. https://github.com/Koenkk/zigbee2mqtt/issues/9520 2021-11-05 20:24:09 +01:00
Koen Kanters 0efd0cfe17 Fix min/max value for Home Assistant number entity. https://github.com/Koenkk/zigbee2mqtt/issues/9012 2021-11-05 19:30:14 +01:00
Franck Nijhof c852434dde Cleanup unused legacyApi variable (#9512) 2021-11-05 19:20:42 +01:00
Franck Nijhof 57e93a48ff Fix HA discovery device firmware version (#9511) 2021-11-05 19:19:55 +01:00
Pavel Sokolov 181944d2ff Fix invalid frontend.host default value in schema (#9508) 2021-11-05 19:08:34 +01:00
Franck NijhofandKoen Kanters a09aa4243e Improve expose of update sensors to HA (#9306)
* Improve expose of update sensors to HA

* Update homeassistant.ts

* Update homeassistant.ts

* Update homeassistant.test.js

* Update homeassistant.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-04 21:11:58 +01:00
932ee433c4 Update zigbee-herdsman-converters to 14.0.308 (#9500)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-04 20:53:06 +01:00
Koen Kanters 20b6fd42d3 Stop pinging device (availability feature) when it is removed. https://github.com/Koenkk/zigbee2mqtt/issues/9490 2021-11-04 20:52:10 +01:00
github-actions[bot]andKoenkk 178da2db1d Update zigbee-herdsman to 0.13.166 (#9501)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-04 20:47:50 +01:00
github-actions[bot]andnurikk e504da33d4 Update zigbee2mqtt-frontend to 0.6.31 (#9498)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-05 00:12:30 +08:00
github-actions[bot]andKoenkk fa1775d8b4 Update zigbee-herdsman-converters to 14.0.307 (#9488)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-03 21:05:21 +01:00
Franck NijhofandKoen Kanters 2612de3c34 Correct device class and entity category for last seen HA sensor (#9305)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-03 20:36:01 +01:00
Franck NijhofandKoen Kanters 416f4fa548 Mark indicator led HA switch as entity type config (#9309)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-03 20:31:31 +01:00
Franck Nijhof ee57b0ce0b Add support for unit of measurement to HA number entities (#9312) 2021-11-03 20:24:55 +01:00
Franck Nijhof 9729a72d33 Add Home Assistant entity_category support (#9293) 2021-11-03 20:23:46 +01:00
github-actions[bot]andKoenkk 23719df7ac Update zigbee-herdsman-converters to 14.0.306 (#9485)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-03 20:10:35 +01:00
github-actions[bot]andKoenkk ef6bf0a8f9 Update zigbee-herdsman-converters to 14.0.305 (#9466)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-02 18:29:04 +01:00
ciB89 b3e9afaf3e fix link (#9462)
fix one link not working (still directing to old site)
2021-11-02 17:50:25 +01:00
github-actions[bot]andKoenkk 5709898c94 Update zigbee-herdsman-converters to 14.0.304 (#9448)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-01 20:53:15 +01:00
Koen Kanters 68b5be0ce7 Properly handle update available check failing for IKEA device. https://github.com/Koenkk/zigbee-herdsman-converters/issues/3253 2021-11-01 19:09:34 +01:00
Koen Kanters 62bf76c11f Fix site links 2021-11-01 18:12:27 +01:00
Koen Kanters 243d333526 Merge branch 'dev' of github.com:Koenkk/zigbee2mqtt into dev 2021-11-01 18:12:15 +01:00
09383877b0 Update dependencies (#9444)
* Update dependencies

* Fix lint

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-01 18:10:54 +01:00
Koen Kanters 359af6f9ff Merge remote-tracking branch 'origin/master' into dev 2021-11-01 18:10:00 +01:00
Koen Kanters cf68507ec3 Update site links 2021-11-01 18:09:42 +01:00
github-actions[bot]andKoenkk 78a3e4a371 Update zigbee-herdsman to 0.13.165 (#9446)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-01 18:08:41 +01:00
Alexey KotenkoandKoen Kanters 11753a7078 Update new_device_support.md (#9436)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-11-01 17:59:35 +01:00
Koen Kanters 512b785427 Promote to dev 2021-11-01 17:32:01 +01:00
Koen Kanters 0a1fccf6b3 1.22.0 2021-11-01 17:30:27 +01:00
Koen Kanters 9e4b65b188 Undev 2021-11-01 17:30:23 +01:00
github-actions[bot]andKoenkk 39c0b522d9 Update zigbee-herdsman-converters to 14.0.303 (#9443)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-11-01 17:28:04 +01:00
github-actions[bot]andnurikk 109c62bb4d Update zigbee2mqtt-frontend to 0.6.30 (#9438)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-11-01 19:42:05 +08:00
github-actions[bot]andnurikk a2e3f60de3 Update zigbee2mqtt-frontend to 0.6.28 (#9425)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-31 22:45:37 +08:00
github-actions[bot]andKoenkk bbf05b5c95 Update zigbee-herdsman-converters to 14.0.302 (#9418)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-30 22:55:00 +02:00
github-actions[bot]andnurikk a5413b9254 Update zigbee2mqtt-frontend to 0.6.26 (#9417)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-31 01:23:54 +08:00
github-actions[bot]andKoenkk d6890b5fe4 Update zigbee-herdsman-converters to 14.0.301 (#9407)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-30 10:24:04 +02:00
github-actions[bot]andKoenkk b1c1637547 Update zigbee-herdsman-converters to 14.0.298 (#9401)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-29 17:14:45 +02:00
Koen Kanters ed8ca293a3 Log stack in debug when MQTT request fails. https://github.com/Koenkk/zigbee2mqtt/issues/9367 2021-10-29 17:10:18 +02:00
github-actions[bot]andKoenkk abd4b23024 Update zigbee-herdsman-converters to 14.0.297 (#9387)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-28 17:50:38 +02:00
github-actions[bot]andKoenkk 7a198ce4a3 Update zigbee-herdsman to 0.13.164 (#9385)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-28 17:32:35 +02:00
github-actions[bot]andKoenkk e0c3ea28c0 Update zigbee-herdsman-converters to 14.0.296 (#9370)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-27 21:26:28 +02:00
Koen Kanters d137d1975b Fix value_min/max not correct for Home Assistant number when 0. https://github.com/Koenkk/zigbee-herdsman-converters/issues/3229 2021-10-27 20:52:54 +02:00
github-actions[bot]andKoenkk e7bc8b9a9a Update zigbee-herdsman-converters to 14.0.295 (#9351)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-26 21:07:57 +02:00
github-actions[bot]andKoenkk 72ffe4d118 Update zigbee-herdsman-converters to 14.0.294 (#9348)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-26 20:43:40 +02:00
github-actions[bot]andKoenkk e81d197979 Update zigbee-herdsman to 0.13.163 (#9342)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-26 17:03:57 +02:00
github-actions[bot]andnurikk 1dc36f4cc1 Update zigbee2mqtt-frontend to 0.6.25 (#9340)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-26 19:43:23 +08:00
github-actions[bot]andnurikk 252994968d Update zigbee2mqtt-frontend to 0.6.24 (#9321)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-26 10:05:20 +08:00
7fed9e7334 Update zigbee-herdsman-converters to 14.0.293 (#9330)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-10-25 18:08:32 +02:00
Koen Kanters bef5bff637 Revert "Add Home Assistant entity_category support (#9293)" (#9328)
This reverts commit 16c3f912b1.
2021-10-25 17:58:42 +02:00
Koen Kanters 498a5b3f32 Revert "Add support for unit of measurement to HA number entities (#9312)" (#9329)
This reverts commit b08ce534c8.
2021-10-25 17:54:18 +02:00
Franck Nijhof b08ce534c8 Add support for unit of measurement to HA number entities (#9312) 2021-10-25 17:12:01 +02:00
56812e7844 Update zigbee-herdsman-converters to 14.0.292 (#9303)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-10-24 15:57:04 +02:00
github-actions[bot]andKoenkk d19c60be07 Update zigbee-herdsman to 0.13.162 (#9302)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-24 15:43:11 +02:00
Dirk van DonkelaarandKoen Kanters 387378e935 Fix Home Assistant discovery for select having numbers as options (#9268)
* Updated select entities to parse values as string

To prevent 'invalid option for select' error

* Update homeassistant.ts

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-10-24 15:22:09 +02:00
Franck Nijhof 16c3f912b1 Add Home Assistant entity_category support (#9293) 2021-10-24 15:11:56 +02:00
github-actions[bot]andKoenkk 3f0a2fed9d Update zigbee-herdsman-converters to 14.0.291 (#9292)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-23 14:15:47 +02:00
github-actions[bot]andnurikk c8e3c9b5a2 Update zigbee2mqtt-frontend to 0.6.22 (#9290)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-23 17:12:47 +08:00
Koen Kanters b665106d44 Expose converter options (#9110)
* Expose converter options

* Updates
2021-10-23 10:27:16 +02:00
github-actions[bot]andKoenkk 88314f1c6a Update zigbee-herdsman-converters to 14.0.290 (#9289)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-23 10:24:40 +02:00
github-actions[bot]andnurikk 8c12551ac8 Update zigbee2mqtt-frontend to 0.6.21 (#9288)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-23 12:40:46 +08:00
github-actions[bot]andKoenkk 011d02d0e6 Update zigbee-herdsman-converters to 14.0.289 (#9279)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-22 19:47:12 +02:00
github-actions[bot]andKoenkk 8ac3989ada Update zigbee-herdsman-converters to 14.0.288 (#9263)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-21 18:18:42 +02:00
github-actions[bot]andKoenkk caa22c559e Update zigbee-herdsman to 0.13.161 (#9261)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-21 18:02:52 +02:00
github-actions[bot]andKoenkk 7469e29877 Update zigbee-herdsman-converters to 14.0.287 (#9255)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-20 19:28:39 +02:00
github-actions[bot]andKoenkk c647e87641 Update zigbee-herdsman-converters to 14.0.286 (#9238)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-19 20:01:18 +02:00
github-actions[bot]andKoenkk de825014c0 Update zigbee-herdsman-converters to 14.0.285 (#9230)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-19 17:24:45 +02:00
Koen Kanters ca7bb0cd4d Attempt to fix Home Assistant error when running_state is unknown. https://github.com/Koenkk/zigbee2mqtt/issues/9219 2021-10-19 16:56:31 +02:00
github-actions[bot]andKoenkk 158341a9ff Update zigbee-herdsman to 0.13.160 (#9226)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-19 16:43:17 +02:00
Koen Kanters eaad39a199 Expose device and group configuration_url to Home Assistant. (#9214) 2021-10-18 18:16:00 +02:00
github-actions[bot]andKoenkk ca255d3aa3 Update zigbee-herdsman-converters to 14.0.283 (#9213)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-18 17:49:13 +02:00
Koen Kanters 97d15b8d15 Home Assistant fix discovery for covers only supporting tilt. https://github.com/Koenkk/zigbee-herdsman-converters/issues/3122 2021-10-18 17:34:40 +02:00
Koen Kanters 549ccf036e Fix start being called twice for external extensions. https://github.com/Koenkk/zigbee2mqtt/issues/9165 2021-10-17 18:19:13 +02:00
github-actions[bot]andKoenkk 8ae4909836 Update zigbee-herdsman-converters to 14.0.282 (#9193)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-17 13:53:54 +02:00
github-actions[bot]andKoenkk bfb2427a6c Update zigbee-herdsman-converters to 14.0.281 (#9168)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-16 10:08:03 +02:00
github-actions[bot]andKoenkk 3571937060 Update zigbee-herdsman-converters to 14.0.280 (#9163)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-15 17:31:12 +02:00
Koen Kanters f7c0b46bef Catch exception when removing device via pass/blocklist. https://github.com/Koenkk/zigbee2mqtt/issues/9116 2021-10-14 22:18:37 +02:00
github-actions[bot]andKoenkk ad5cda4d40 Update zigbee-herdsman to 0.13.159 (#9156)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-14 22:12:08 +02:00
github-actions[bot]andKoenkk d18455b596 Update zigbee-herdsman-converters to 14.0.279 (#9153)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-14 20:31:51 +02:00
github-actions[bot]andKoenkk 0ae7bd0a2d Update zigbee-herdsman-converters to 14.0.278 (#9143)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-13 22:09:01 +02:00
Koen Kanters 8fac172ced Fix crash when event listener throws exception. https://github.com/Koenkk/zigbee2mqtt/commit/749381bf2f6fdb8788d5f5f7857ae75e5f73303a 2021-10-13 21:57:04 +02:00
github-actions[bot]andKoenkk cff4ea726e Update zigbee-herdsman-converters to 14.0.277 (#9141)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-13 19:09:31 +02:00
Koen Kanters 749381bf2f Fix crash when converter throws exception. https://github.com/Koenkk/zigbee2mqtt/issues/9133 2021-10-13 19:05:14 +02:00
Koen Kanters 6b380526ae Fix no configure on device interview. https://github.com/Koenkk/zigbee2mqtt/issues/8971 2021-10-13 18:32:19 +02:00
github-actions[bot]andKoenkk e8dd29e183 Update zigbee-herdsman to 0.13.158 (#9140)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-13 17:32:46 +02:00
github-actions[bot]andKoenkk b58e123594 Update zigbee-herdsman-converters to 14.0.276 (#9135)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-12 19:51:49 +02:00
github-actions[bot]andnurikk 899383d79e Update zigbee2mqtt-frontend to 0.6.20 (#9129)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-12 18:45:58 +08:00
github-actions[bot]andKoenkk de7b120ed2 Update zigbee-herdsman-converters to 14.0.275 (#9123)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-11 17:31:29 +02:00
Koen Kanters 4608de5d57 Allow publishing to device by endpoint ID. https://github.com/nurikk/zigbee2mqtt-frontend/issues/926 2021-10-11 17:30:48 +02:00
github-actions[bot]andnurikk a362e6c99d Update zigbee2mqtt-frontend to 0.6.19 (#9122)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-11 23:27:54 +08:00
github-actions[bot]andnurikk ed8a863c30 Update zigbee2mqtt-frontend to 0.6.18 (#9112)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-11 10:10:57 +08:00
github-actions[bot]andKoenkk 7086bc3e9d Update zigbee-herdsman-converters to 14.0.274 (#9111)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-10 21:08:18 +02:00
github-actions[bot]andKoenkk 2144e9b622 Update zigbee-herdsman-converters to 14.0.273 (#9109)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-10 20:55:14 +02:00
github-actions[bot]andnurikk ff5411a328 Update zigbee2mqtt-frontend to 0.6.17 (#9100)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-10 15:26:15 +08:00
github-actions[bot]andKoenkk 47297983c2 Update zigbee-herdsman-converters to 14.0.272 (#9094)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-09 20:42:49 +02:00
Koen Kanters a774b43d63 Fix Home Assistant template variable warnings (#9088)
* Fix more template warnings. https://github.com/Koenkk/zigbee2mqtt/issues/8769

* Update

* Updates
2021-10-09 19:41:00 +02:00
Koen Kanters 7f8632437d Add polyfills. https://github.com/Koenkk/zigbee2mqtt/issues/9085 2021-10-09 17:18:31 +02:00
Koen Kanters 6977235200 Revert "Fix group publish on Node 10 (doesn't support Object.fromEntries). https://github.com/Koenkk/zigbee2mqtt/issues/9085"
This reverts commit 4e520bb042.
2021-10-09 17:01:26 +02:00
Koen Kanters 4e520bb042 Fix group publish on Node 10 (doesn't support Object.fromEntries). https://github.com/Koenkk/zigbee2mqtt/issues/9085 2021-10-09 15:50:03 +02:00
45f096ec0a Update zigbee-herdsman to 0.13.157 (#9087)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-10-09 10:45:18 +02:00
github-actions[bot]andKoenkk 0ea74e18b2 Update zigbee-herdsman-converters to 14.0.271 (#9086)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-09 10:44:37 +02:00
Koen Kanters ab5d368a4e Small Home Assistant cleanup 2021-10-09 10:42:52 +02:00
Koen Kanters ebd20e30dc Home Assistant: discover last_seen sensor when enabled. https://github.com/Koenkk/zigbee2mqtt/issues/8287 2021-10-09 10:19:07 +02:00
github-actions[bot]andKoenkk c2d4335e45 Update zigbee-herdsman to 0.13.156 (#9080)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-08 17:10:12 +02:00
38cbfa4e91 Update zigbee-herdsman to 0.13.155 (#9079)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-10-08 16:51:21 +02:00
github-actions[bot]andKoenkk f7fd0ce825 Update zigbee-herdsman-converters to 14.0.270 (#9078)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-08 16:47:57 +02:00
github-actions[bot]andnurikk ea550a8fcf Update zigbee2mqtt-frontend to 0.6.16 (#9076)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-08 21:14:09 +08:00
github-actions[bot]andnurikk 9907e59fa7 Update zigbee2mqtt-frontend to 0.6.15 (#9070)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-08 19:47:31 +08:00
Koen Kanters 3b0a906a97 Expose scenes (#9056)
* Expose scenes

* Republish devices and groups when changed.

* Send scene name if set.
2021-10-08 19:02:24 +08:00
github-actions[bot]andKoenkk c88f643407 Update zigbee-herdsman-converters to 14.0.269 (#9074)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-08 12:35:17 +02:00
github-actions[bot]andKoenkk 89d2b0088d Update zigbee-herdsman-converters to 14.0.268 (#9062)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-07 22:11:45 +02:00
github-actions[bot]andKoenkk d03c5e2372 Update zigbee-herdsman to 0.13.154 (#9060)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-07 21:07:43 +02:00
github-actions[bot]andKoenkk 90d20f936e Update zigbee-herdsman-converters to 14.0.267 (#9059)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-07 20:37:26 +02:00
Koen Kanters 6f9371e4b0 Fix incorrect state when last_seen and debounce is enabled. https://github.com/Koenkk/zigbee2mqtt/issues/8958 https://github.com/Koenkk/zigbee2mqtt/issues/9010 2021-10-07 20:36:42 +02:00
github-actions[bot]andKoenkk 4082763f59 Update zigbee-herdsman to 0.13.153 (#9055)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-07 18:19:07 +02:00
Koen Kanters 42497f3176 Fix some todos 2021-10-06 21:27:23 +02:00
github-actions[bot]andKoenkk 7ea29eadf4 Update zigbee-herdsman-converters to 14.0.266 (#9041)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-06 20:58:55 +02:00
github-actions[bot]andKoenkk db8d0ecf20 Update zigbee-herdsman-converters to 14.0.265 (#9026)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-05 22:20:17 +02:00
github-actions[bot]andKoenkk bd216d7a24 Update zigbee-herdsman to 0.13.152 (#9022)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-05 18:44:27 +02:00
Koen Kanters 23b87755cf Stop Zigbee2MQTT with error when initial MQTT connect fails. https://github.com/Koenkk/zigbee2mqtt/issues/8956 2021-10-04 22:08:06 +02:00
Koen Kanters 7415e8416d Update availability config title. https://github.com/Koenkk/zigbee2mqtt/issues/6281 2021-10-04 21:24:31 +02:00
Koen Kanters 8e2c79f85d Fix external converters not loaded. https://github.com/Koenkk/zigbee2mqtt/issues/8959 2021-10-04 21:22:44 +02:00
Koen Kanters ab3a9da630 Revert "Improve MQTT error handling. https://github.com/Koenkk/zigbee2mqtt/issues/8956"
This reverts commit 45a4978ca8.
2021-10-04 20:51:09 +02:00
github-actions[bot]andKoenkk 7ccf781b65 Update zigbee-herdsman-converters to 14.0.264 (#9003)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-04 17:58:41 +02:00
Koen Kanters 30badb62e7 Update availabiltiy config schema. https://github.com/Koenkk/zigbee2mqtt/issues/6281 2021-10-04 17:48:05 +02:00
github-actions[bot]andKoenkk a0512a489d Update zigbee-herdsman-converters to 14.0.263 (#8989)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-03 22:23:48 +02:00
github-actions[bot]andKoenkk edb145a8c3 Update zigbee-herdsman to 0.13.151 (#8972)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-03 21:46:31 +02:00
Koen Kanters 45a4978ca8 Improve MQTT error handling. https://github.com/Koenkk/zigbee2mqtt/issues/8956 2021-10-03 12:29:54 +02:00
github-actions[bot]andKoenkk fb96551beb Update dependencies (#8965)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-03 12:09:35 +02:00
github-actions[bot]andKoenkk 2fb59f8efa Update zigbee-herdsman-converters to 14.0.262 (#8951)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-02 11:04:22 +02:00
Koen Kanters c28731957a Fix last seen not published when changed. https://github.com/Koenkk/zigbee2mqtt/issues/7423 2021-10-02 10:49:47 +02:00
Koen Kanters 0282011255 Replace old availability implementation with new one (#8904)
* Update

* Updates

* More refactoringzzz

* Bindoo

* Loadz of typescripting

* Logga

* Updates

* Updates

* Updates

* Updates

* cleanup

* updates

* Fix coverage

* Fixes

* Updates

* Updates

* Replace old availability implementation with new one.
2021-10-02 10:25:43 +02:00
Koen Kanters 045ee573a0 Final TypeScript refactor (#8859)
* Update

* Updates

* More refactoringzzz

* Bindoo

* Loadz of typescripting

* Logga

* Updates

* Updates

* Updates

* Updates

* cleanup

* updates

* Fix coverage

* Fixes

* Updates

* Updates
2021-10-02 10:09:38 +02:00
Koen Kanters 839e280159 Dev 2021-10-01 17:54:04 +02:00
Koen Kanters 44922120a6 1.21.2 2021-10-01 17:53:20 +02:00
Koen Kanters c7b9c06c89 Undev 2021-10-01 17:53:17 +02:00
github-actions[bot]andKoenkk 258326a88c Update zigbee-herdsman-converters to 14.0.261 (#8939)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-01 17:52:34 +02:00
Koen Kanters 4ec828d68e Merge branch 'dev' 2021-10-01 17:43:57 +02:00
github-actions[bot]andKoenkk d9735f5981 Update zigbee-herdsman-converters to 14.0.260 (#8938)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-10-01 17:42:53 +02:00
github-actions[bot]andnurikk fa8011983d Update zigbee2mqtt-frontend to 0.6.12 (#8929)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-10-01 08:55:08 +08:00
github-actions[bot]andnurikk 7f98771e99 Update zigbee2mqtt-frontend to 0.6.11 (#8876)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-30 19:17:44 +08:00
github-actions[bot]andKoenkk 7d6d71dcbe Update zigbee-herdsman-converters to 14.0.259 (#8918)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-29 22:16:11 +02:00
Koen Kanters 8d9f14e30b Fix device configuring with endpoint ID not working. https://github.com/nurikk/zigbee2mqtt-frontend/issues/874 2021-09-29 22:00:01 +02:00
github-actions[bot]andKoenkk 06d30d1036 Update zigbee-herdsman-converters to 14.0.258 (#8903)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-28 20:43:12 +02:00
github-actions[bot]andKoenkk f517b85a75 Update zigbee-herdsman-converters to 14.0.257 (#8896)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-27 20:40:14 +02:00
738b241a31 Update zigbee-herdsman to 0.13.149 (#8889)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-09-26 19:08:19 +02:00
github-actions[bot]andKoenkk 2605d48557 Update zigbee-herdsman-converters to 14.0.256 (#8888)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-26 19:05:41 +02:00
github-actions[bot]andKoenkk 918d8e2f88 Update dependencies (#8884)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-26 17:18:04 +02:00
github-actions[bot]andKoenkk 0dfadb3a10 Update zigbee-herdsman-converters to 14.0.255 (#8880)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-25 19:15:34 +02:00
github-actions[bot]andKoenkk 27a7bdb14a Update zigbee-herdsman-converters to 14.0.254 (#8869)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-24 18:41:45 +02:00
github-actions[bot]andKoenkk 5829663b95 Update zigbee-herdsman-converters to 14.0.253 (#8856)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-23 20:30:04 +02:00
Koen Kanters a8eec889f5 Remove debug log. https://github.com/Koenkk/zigbee2mqtt/issues/8836 2021-09-22 20:02:41 +02:00
Koen Kanters 6888394600 Refactor frontend to TypeScript. 2021-09-22 20:01:46 +02:00
github-actions[bot]andKoenkk 57b4d678d5 Update zigbee-herdsman-converters to 14.0.252 (#8847)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-22 19:40:10 +02:00
Koen Kanters 59dd6e6bff Fix error when device does not exists. https://github.com/Koenkk/zigbee2mqtt/issues/8836 2021-09-22 19:06:28 +02:00
Koen Kanters 89dea86b3a Refactor HomeAssistant extension to TypeScript 2021-09-22 18:04:57 +02:00
github-actions[bot]andKoenkk 74ee5581fe Update zigbee-herdsman-converters to 14.0.251 (#8837)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-21 22:18:41 +02:00
Koen Kanters aaad76e323 Add debug logging for https://github.com/Koenkk/zigbee2mqtt/issues/8836 2021-09-21 22:01:31 +02:00
Koen Kanters 7557c10095 More TypeScript refactoring 2021-09-21 16:58:20 +02:00
github-actions[bot]andKoenkk 58957a30e4 Update zigbee-herdsman to 0.13.148 (#8825)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-20 22:06:59 +02:00
github-actions[bot]andKoenkk 32ddcc5e61 Update zigbee-herdsman-converters to 14.0.250 (#8824)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-20 21:55:35 +02:00
Koen Kanters 6369fe1528 Fix Home Assistant discovery for covers only supporting tilt. https://github.com/Koenkk/zigbee-herdsman-converters/pull/2663 2021-09-20 21:52:26 +02:00
github-actions[bot]andKoenkk 187dde436c Update zigbee-herdsman to 0.13.147 (#8823)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-20 21:33:42 +02:00
github-actions[bot]andnurikk 80b35ba728 Update zigbee2mqtt-frontend to 0.6.8 (#8822)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-21 00:46:38 +08:00
github-actions[bot]andKoenkk 41b1d53723 Update dependencies (#8812)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-20 12:11:07 +02:00
github-actions[bot]andKoenkk 9f12ef7370 Update zigbee-herdsman to 0.13.146 (#8809)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-19 21:54:46 +02:00
Koen Kanters 7f4a9c2a9b Refactor onEvent extension to TypeScript 2021-09-19 11:37:08 +02:00
Koen Kanters 48de2fa647 Refactor configure extension to TypeScript. 2021-09-19 11:08:16 +02:00
Koen Kanters 27b36b316c Update CI node version to 14 2021-09-18 18:26:17 +02:00
Koen Kanters ca3c6ce32f More TypeScript refactoring (#8797)
* ts

* Updates
2021-09-18 18:23:28 +02:00
github-actions[bot]andKoenkk 0d3998f369 Update zigbee-herdsman-converters to 14.0.249 (#8796)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-18 16:20:06 +02:00
github-actions[bot]andnurikk b929dcbeb8 Update zigbee2mqtt-frontend to 0.6.7 (#8792)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-18 12:31:21 +08:00
github-actions[bot]andKoenkk b558bbdc85 Update zigbee-herdsman to 0.13.145 (#8762)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-16 00:38:35 +02:00
github-actions[bot]andKoenkk bb5be4df25 Update zigbee-herdsman-converters to 14.0.248 (#8756)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-15 14:58:56 +02:00
github-actions[bot]andKoenkk eca5492a8e Update zigbee-herdsman-converters to 14.0.247 (#8752)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-15 01:44:01 +02:00
ac44a50d3d Update zigbee-herdsman-converters to 14.0.246 (#8737)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-09-13 02:10:39 +02:00
github-actions[bot]andKoenkk 32b127d280 Update zigbee-herdsman to 0.13.144 (#8736)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-13 02:02:21 +02:00
github-actions[bot]andKoenkk 8c0827afe3 Update zigbee-herdsman-converters to 14.0.245 (#8728)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-12 13:30:54 +02:00
github-actions[bot]andKoenkk 7a97c67f74 Update dependencies (#8724)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-12 13:10:42 +02:00
github-actions[bot]andnurikk bb1cbf3de7 Update zigbee2mqtt-frontend to 0.6.6 (#8727)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-12 18:29:08 +08:00
github-actions[bot]andKoenkk 75d2fe393d Update zigbee-herdsman to 0.13.143 (#8723)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-11 19:18:29 -04:00
Koen Kanters fb081316e2 More TypeScript refactoring (#8721)
* Update

* u

* Updates

* Updates

* updates

* Updates

* Update
2021-09-11 14:51:29 +02:00
github-actions[bot]andKoenkk feff729eb6 Update zigbee-herdsman-converters to 14.0.244 (#8720)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-11 14:36:06 +02:00
Koen Kanters 69e3deb7ac Add multi endpoint support for Home Assistant cover. https://github.com/Koenkk/zigbee2mqtt/issues/8712 2021-09-11 13:53:00 +02:00
github-actions[bot]andKoenkk c1eb56aa30 Update zigbee-herdsman-converters to 14.0.243 (#8715)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-11 02:00:02 +02:00
Pavel Sokolov cadcdc3525 Fix zStackEraseAllNvMem.js (#8692)
* Fix zStackEraseAllNvMem.js

* lint fix
2021-09-09 00:46:10 +08:00
github-actions[bot]andKoenkk d140d2b4b2 Update zigbee-herdsman-converters to 14.0.242 (#8679)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-07 19:36:36 +02:00
frooglandKoen Kanters 22bba95a70 ead bulb state, brightness and colour on scene recall command (#8585)
* Poll brightness/state after recalling scene

When a ZigBee Scene Controller is recalling a scene through a direct binding
we need to poll for changed state and brightness.

* Also poll for color changes on scene recalling

* Force copy of settings.schema.json

* Update bind.js

* Update zigbeeHerdsman.js

* Update bind.test.js

* Update bind.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-09-07 19:17:23 +02:00
Koen Kanters 291383fe2f Fix tests failing on Node 16 2021-09-06 18:41:53 +02:00
github-actions[bot]andKoenkk 7e5814aaad Update zigbee-herdsman-converters to 14.0.241 (#8669)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-06 18:20:52 +02:00
github-actions[bot]andKoenkk 22a607da7b Update zigbee-herdsman to 0.13.142 (#8668)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-06 17:40:08 +02:00
Robert AlexaandKoen Kanters d07333c70d Home Assistant discover number selection entities for numeric values supporting set (#8640)
* Add support for numeric that allows SET access as number entities

* Remove redundant comment

* gitignore intellij idea folder

* Expose both entities to avoid breaking changes

* Improve comment

* Update homeassistant.js

* Update homeassistant.test.js

* Update homeassistant.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-09-06 17:38:34 +02:00
github-actions[bot]andnurikk 3c87803c79 Update zigbee2mqtt-frontend to 0.6.4 (#8664)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-06 20:09:38 +08:00
github-actions[bot]andKoenkk 02a508270f Update zigbee-herdsman to 0.13.141 (#8652)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-05 13:49:44 +02:00
Koen Kanters 4a51e0c0c9 Force copy of settings.schema.json 2021-09-05 13:36:28 +02:00
github-actions[bot]andKoenkk edf14b80d2 Update dependencies (#8646)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-05 13:35:43 +02:00
Koen Kanters 3708b314d1 Force copy of settings.schema.json 2021-09-05 13:32:45 +02:00
github-actions[bot]andnurikk 7da50f9248 Update zigbee2mqtt-frontend to 0.6.2 (#8641)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-04 22:46:55 +08:00
github-actions[bot]andnurikk e59f347d68 Update zigbee2mqtt-frontend to 0.6.1 (#8639)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-09-04 17:05:39 +08:00
github-actions[bot]andKoenkk b112184b65 Update zigbee-herdsman-converters to 14.0.240 (#8634)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-03 22:02:21 +02:00
Koen Kanters 1a514b824f Home Assistant remove deprecated last_reset_topic and change state_class to total_increasing for energy. https://github.com/Koenkk/zigbee2mqtt/issues/8604 2021-09-03 21:40:59 +02:00
github-actions[bot]andKoenkk a2653037e9 Update zigbee-herdsman to 0.13.140 (#8633)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-03 21:27:59 +02:00
Koen Kanters cf019195af Fix tests failing 2021-09-03 16:35:58 +02:00
github-actions[bot]andKoenkk b8c245b9f3 Update zigbee-herdsman to 0.13.139 (#8627)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-03 16:31:06 +02:00
Koen Kanters 31327f7e1b Fix "Cannot read property 'version' of undefined". https://github.com/Koenkk/zigbee2mqtt/pull/8567 2021-09-02 20:18:13 +02:00
github-actions[bot]andKoenkk e050a763f7 Update zigbee-herdsman-converters to 14.0.239 (#8613)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-02 17:56:47 +02:00
Koen Kanters 4125ae0888 TypeScript refactoring (#8567)
* Updates

* Updates

* Updates

* Rename

* Updates

* updates

* Updates

* Updates
2021-09-01 20:39:17 +02:00
Koen Kanters c299d9b632 Promote to dev 2021-09-01 18:10:44 +02:00
Koen Kanters eb5750d968 1.21.1 2021-09-01 18:10:02 +02:00
Koen Kanters d8432b502e Undev 2021-09-01 18:05:33 +02:00
github-actions[bot]andKoenkk 15685cacf8 Update zigbee-herdsman-converters to 14.0.238 (#8598)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-09-01 17:15:29 +02:00
github-actions[bot]andKoenkk d92bdf1c57 Update zigbee-herdsman to 0.13.138 (#8590)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-31 20:14:24 +02:00
github-actions[bot]andKoenkk 4f7264e565 Update zigbee-herdsman-converters to 14.0.237 (#8588)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-31 20:09:33 +02:00
github-actions[bot]andKoenkk 05b19117cf Update zigbee-herdsman-converters to 14.0.236 (#8576)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-30 20:03:32 +02:00
github-actions[bot]andnurikk 991b937451 Update zigbee2mqtt-frontend to 0.6.0 (#8572)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-30 20:36:37 +08:00
github-actions[bot]andKoenkk 9d60f9b64f Update zigbee-herdsman-converters to 14.0.235 (#8568)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-29 19:20:33 +02:00
github-actions[bot]andKoenkk 9e3afbf48a Update dependencies (#8555)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-29 18:56:17 +02:00
Koen Kanters 17b2315d89 Enable Home Assistant availability_mode all only when new availability feature is enabled. #6281 2021-08-28 16:20:02 +02:00
github-actions[bot]andKoenkk 7122137639 Update zigbee-herdsman to 0.13.136 (#8548)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-28 15:43:19 +02:00
Koen Kanters a9e4745075 More availability fixes. #6281 2021-08-28 14:42:04 +02:00
Koen Kanters fd7351ff61 Small availability fixes. #6281 2021-08-28 14:06:47 +02:00
Koen Kanters 22430631d2 Honour legacy availability options and retrieve state when device reconnects #6281 (#8545)
* Availability

* Updates
2021-08-28 10:08:09 +02:00
github-actions[bot]andKoenkk 7b8c5944a0 Update zigbee-herdsman-converters to 14.0.234 (#8543)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-27 20:09:38 +02:00
github-actions[bot]andKoenkk 09198d5ad5 Update zigbee-herdsman to 0.13.135 (#8541)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-27 19:49:22 +02:00
github-actions[bot]andKoenkk 352ebceadd Update zigbee-herdsman-converters to 14.0.233 (#8534)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-26 20:17:53 +02:00
Koen Kanters 3774a78134 Migrate utils to typescript. 2021-08-25 20:11:55 +02:00
Koen Kanters 5b6b4c1736 Availability stop pining when device leaves. #6281 2021-08-25 19:14:48 +02:00
github-actions[bot]andKoenkk 8bb296f3f7 Update zigbee-herdsman-converters to 14.0.232 (#8521)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-25 19:02:43 +02:00
github-actions[bot]andKoenkk 6741e43e32 Update zigbee-herdsman to 0.13.134 (#8520)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-25 18:55:07 +02:00
Koen Kanters d78bf2a3d2 Fix devices missing from UI after repair. https://github.com/nurikk/z2m-frontend/issues/746 2021-08-24 20:25:31 +02:00
github-actions[bot]andKoenkk 13e757429d Update zigbee-herdsman-converters to 14.0.231 (#8506)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-24 20:22:08 +02:00
f21516a2f2 Update zigbee-herdsman-converters to 14.0.230 (#8495)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-23 20:59:35 +02:00
github-actions[bot]andKoenkk ccc91b499a Update zigbee-herdsman to 0.13.133 (#8494)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-23 20:55:05 +02:00
Koen Kanters 1234c5a3e0 Don't use node_modules for binaries. https://github.com/Koenkk/zigbee2mqtt/issues/8410 2021-08-23 20:52:25 +02:00
Koen Kanters 9129f95c39 Add availability_mode for Home Assistant and publish availability only when its enabled for that device. #6281 2021-08-23 19:24:10 +02:00
github-actions[bot]andKoenkk b18373b669 Update zigbee-herdsman-converters to 14.0.229 (#8493)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-23 17:15:30 +02:00
Koen Kanters 5e2e8f3eb3 Don't discover entity specific availability topic for groups. #6281 2021-08-23 17:04:43 +02:00
Koen Kanters d7ae59886e Revert "Add availability_mode all for Home Assistant discovery. #6281"
This reverts commit d07f1dab31.
2021-08-23 08:19:51 +02:00
github-actions[bot]andnurikk 8f75dd8652 Update zigbee2mqtt-frontend to 0.5.27 (#8485)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-23 13:29:20 +08:00
Koen Kanters d07f1dab31 Add availability_mode all for Home Assistant discovery. #6281 2021-08-22 22:41:27 +02:00
Koen Kanters 9e8dcb2784 Allow to disable/enable availability for device and allow to configure timeout. #6281 2021-08-22 22:30:32 +02:00
github-actions[bot]andKoenkk 59f6455f13 Update zigbee-herdsman-converters to 14.0.228 (#8482)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-22 21:19:43 +02:00
github-actions[bot]andKoenkk 69d51c95db Update dependencies (#8473)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-22 18:27:27 +02:00
github-actions[bot]andKoenkk dffc58aa6b Update zigbee-herdsman-converters to 14.0.227 (#8466)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-21 14:51:11 +02:00
Jorge Schrauwen c7bf3324dc Don't publish of msg is empty after filtering (#8448) 2021-08-21 14:00:42 +02:00
github-actions[bot]andnurikk cb47efe3fe Update zigbee2mqtt-frontend to 0.5.26 (#8459)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-21 16:04:47 +08:00
Koen Kanters 94cfad445b Debug log when device requests OTA. https://github.com/Koenkk/zigbee2mqtt/issues/4561 2021-08-19 20:36:31 +02:00
github-actions[bot]andKoenkk eebc92f931 Update zigbee-herdsman-converters to 14.0.226 (#8439)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-19 19:56:40 +02:00
Koen Kanters f9451ffe22 Ping 2 times when device is unavailable where second attempt has recovery enabled. #6281 2021-08-18 21:22:06 +02:00
github-actions[bot]andKoenkk 288c0b795c Update zigbee-herdsman to 0.13.132 (#8419)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-18 21:17:01 +02:00
github-actions[bot]andKoenkk c134d4e975 Update zigbee-herdsman-converters to 14.0.225 (#8418)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-18 18:09:52 +02:00
github-actions[bot]andKoenkk fb390544af Update zigbee-herdsman-converters to 14.0.224 (#8407)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-17 19:41:20 +02:00
Franck NijhofandKoen Kanters c93b9300da Add Home Assistant device classes for air quality sensors (#8399)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-17 17:02:38 +02:00
Koen Kanters 486333d342 Fix typo. https://github.com/Koenkk/zigbee2mqtt/commit/773de25657f52b24a33c49c5565f6881ff611f7d 2021-08-17 16:45:20 +02:00
Koen Kanters 773de25657 Attempt 3 pings before marking device as unavailable and 1 when device is already unavailable. #6281 2021-08-16 21:16:52 +02:00
github-actions[bot]andKoenkk 726462caed Update zigbee-herdsman-converters to 14.0.223 (#8395)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-16 17:52:52 +02:00
Koen Kanters fe24391de8 Fix availability sleep duration. #6281 2021-08-15 22:15:38 +02:00
Koen Kanters 05deca6261 Reduce availability verbosity. #6281 2021-08-15 21:42:24 +02:00
Koen Kanters 755e8d3866 Ping twice before marking device as unavailable and wait 2 seconds between pings. #6281 2021-08-15 21:31:28 +02:00
ffc48131de Update zigbee-herdsman-converters to 14.0.222 (#8389)
* Update zigbee-herdsman-converters to 14.0.222

* Update package.json

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-15 21:02:16 +02:00
github-actions[bot]andKoenkk 0d5d5a696a Update zigbee-herdsman to 0.13.131 (#8388)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-15 20:55:07 +02:00
z-x-fandKoen Kanters a8545d08b6 Add usb to endpoint names (#8370)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-15 20:27:43 +02:00
github-actions[bot]andKoenkk e5f20f342d Update dependencies (#8375)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-15 20:11:19 +02:00
Koen Kanters c18a698e6b Availability refactor part 1 (#8243)
* Initial

* Updates

* update

* Updates

* Updates

* Updates
2021-08-14 16:04:03 +02:00
github-actions[bot]andKoenkk f74047d090 Update zigbee-herdsman to 0.13.130 (#8366)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-14 12:48:14 +02:00
Koen Kanters 17dc22fdb0 Move source map install to index.js 2021-08-14 09:59:31 +02:00
github-actions[bot]andKoenkk 5a2f262fe5 Update zigbee-herdsman-converters to 14.0.221 (#8362)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-13 19:27:22 +02:00
github-actions[bot]andKoenkk 61e133b894 Update zigbee-herdsman to 0.13.129 (#8361)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-13 19:16:54 +02:00
github-actions[bot]andnurikk fc2e8304f5 Update zigbee2mqtt-frontend to 0.5.25 (#8347)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-13 15:48:52 +08:00
github-actions[bot]andKoenkk a3f22833cd Update zigbee-herdsman-converters to 14.0.220 (#8346)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-12 17:30:34 +02:00
Koen Kanters a41c00faea Fix Home Assistant discovery for Hive SLR2(b). https://github.com/Koenkk/zigbee2mqtt/issues/7903 2021-08-12 16:55:47 +02:00
github-actions[bot]andKoenkk 632f9f579c Update zigbee-herdsman-converters to 14.0.219 (#8332)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-11 17:15:09 +02:00
github-actions[bot]andKoenkk 6dcae7b83e Update zigbee-herdsman-converters to 14.0.218 (#8324)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-10 22:39:55 +02:00
Koen Kanters 5c8fa5cb48 Log error stack on OTA update exception. https://github.com/Koenkk/zigbee2mqtt/issues/8297 2021-08-10 20:39:56 +02:00
github-actions[bot]andKoenkk 500642d42c Update zigbee-herdsman to 0.13.128 (#8323)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-10 19:21:50 +02:00
bee7474b8f Update dependencies (#8298)
* Update dependencies

* Update frontend.js

* Update frontend.js

* Update frontend.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-10 19:12:13 +02:00
github-actions[bot]andKoenkk 911c3d285e Update zigbee-herdsman-converters to 14.0.217 (#8309)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-09 17:39:52 +02:00
github-actions[bot]andnurikk 86743179a2 Update zigbee2mqtt-frontend to 0.5.23 (#8306)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-09 13:57:13 +08:00
108694276e Update zigbee-herdsman to 0.13.127 (#8305)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-08 21:48:08 +02:00
3d27a63b5a Update zigbee-herdsman-converters to 14.0.216 (#8289)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-08 21:45:09 +02:00
github-actions[bot]andnurikk 950498898c Update zigbee2mqtt-frontend to 0.5.22 (#8299)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-08 11:08:37 +08:00
Koen Kanters fab62e10fe Fix removing device from blocklist in frontend not working. https://github.com/Koenkk/zigbee2mqtt/issues/8266 2021-08-07 13:00:22 +02:00
github-actions[bot]andnurikk 08fa79d6d8 Update zigbee2mqtt-frontend to 0.5.21 (#8286)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-07 15:22:25 +08:00
github-actions[bot]andKoenkk 1b2398f13f Update zigbee-herdsman-converters to 14.0.215 (#8279)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-06 18:20:55 +02:00
github-actions[bot]andKoenkk 0685ade693 Update zigbee-herdsman to 0.13.126 (#8278)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-06 16:56:44 +02:00
github-actions[bot]andKoenkk 10615e29f3 Update zigbee-herdsman-converters to 14.0.214 (#8264)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-05 20:37:43 +02:00
a380df4f21 Update zigbee-herdsman-converters to 14.0.213 (#8247)
* Update zigbee-herdsman-converters to 14.0.213

* Update publish.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-08-03 21:04:52 +02:00
github-actions[bot]andKoenkk 86d92a9591 Update zigbee-herdsman to 0.13.125 (#8246)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-03 20:48:55 +02:00
github-actions[bot]andKoenkk 33ee9f7bd7 Update zigbee-herdsman-converters to 14.0.212 (#8245)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-03 20:26:31 +02:00
github-actions[bot]andnurikk 056e07a411 Update zigbee2mqtt-frontend to 0.5.19 (#8229)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-08-03 10:36:14 +08:00
Koen Kanters 62d763614a Fix build failing when starting from outside Zigbee2MQTT directory. https://github.com/Koenkk/zigbee2mqtt/issues/8222 2021-08-02 18:18:44 +02:00
github-actions[bot]andKoenkk 7db4e1b8d0 Update zigbee-herdsman-converters to 14.0.211 (#8225)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-02 18:15:29 +02:00
Jorge Schrauwen db61a623d5 Allow non systemctl systems to use update.sh (#8206)
With this change update.sh works on systems that do not use systemctl.
I can update z2m on my illumos machine by running `svcadm disable zigbee2mqtt; ./update.sh ; svcadm enable zigbee2mqtt`
2021-08-02 09:38:08 +02:00
github-actions[bot]andKoenkk c813eca843 Update dependencies (#8199)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-01 20:54:44 +02:00
Koen Kanters ceb63071c8 Promote to dev 2021-08-01 20:39:47 +02:00
Koen Kanters 70891eec39 1.21.0 2021-08-01 20:39:11 +02:00
Koen Kanters e637eca3ea Undev 2021-08-01 20:38:00 +02:00
github-actions[bot]andKoenkk 30f80c08d2 Update zigbee-herdsman-converters to 14.0.210 (#8204)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-01 20:29:03 +02:00
github-actions[bot]andKoenkk 745951f38d Update zigbee-herdsman-converters to 14.0.209 (#8202)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-08-01 19:27:13 +02:00
github-actions[bot]andKoenkk 30ff15b7dc Update zigbee-herdsman-converters to 14.0.208 (#8193)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-31 16:56:29 +02:00
Franck Nijhof be2689ee04 Add support for Home Assistant energy statistics (#8187)
* Add support for Home Assistant energy statistics

* Correct timestamp

* darn quotes
2021-07-31 16:30:42 +02:00
github-actions[bot]andnurikk cee9eb1e26 Update zigbee2mqtt-frontend to 0.5.18 (#8182)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-30 23:51:53 +08:00
github-actions[bot]andKoenkk 1e5e3bef97 Update zigbee-herdsman-converters to 14.0.207 (#8181)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-30 16:18:16 +02:00
github-actions[bot]andKoenkk 2457b7ee27 Update zigbee-herdsman-converters to 14.0.206 (#8177)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-29 20:22:46 +02:00
github-actions[bot]andKoenkk 6068cd8541 Update zigbee-herdsman to 0.13.124 (#8176)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-29 20:11:18 +02:00
github-actions[bot]andnurikk ffea1ed97d Update zigbee2mqtt-frontend to 0.5.16 (#8173)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-29 22:27:30 +08:00
github-actions[bot]andKoenkk 05a535cf30 Update zigbee-herdsman to 0.13.123 (#8166)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-28 20:37:14 +02:00
github-actions[bot]andKoenkk b1ee119575 Update zigbee-herdsman to 0.13.122 (#8164)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-28 19:42:51 +02:00
github-actions[bot]andKoenkk cd033c8995 Update zigbee-herdsman-converters to 14.0.205 (#8158)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-27 20:10:04 +02:00
Koen Kanters bf29fa8164 Always write hash on build. https://github.com/Koenkk/zigbee2mqtt/issues/8145 2021-07-27 19:47:39 +02:00
Koen Kanters 26ade49513 Fix ".flat is not a function" error. https://github.com/Koenkk/zigbee2mqtt/issues/8137 2021-07-27 18:39:39 +02:00
github-actions[bot]andKoenkk f9b8217996 Update zigbee-herdsman to 0.13.121 (#8157)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-27 18:28:38 +02:00
github-actions[bot]andKoenkk 35c2ffc0e5 Update zigbee-herdsman-converters to 14.0.204 (#8129)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-25 18:34:07 +02:00
github-actions[bot]andKoenkk 3653edeac3 Update dependencies (#8124)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-25 17:23:10 +02:00
Koen Kanters 6e84c149fe Fix typos 2021-07-24 16:13:11 +02:00
Koen Kanters 236b751bd1 Fix some cacheable not being cached. https://github.com/Koenkk/zigbee-herdsman-converters/pull/2814 2021-07-24 15:12:43 +02:00
github-actions[bot]andKoenkk b09f20e62e Update zigbee-herdsman-converters to 14.0.203 (#8119)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-24 10:36:30 +02:00
github-actions[bot]andKoenkk f74f5fd638 Update zigbee-herdsman to 0.13.120 (#8116)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-23 14:59:39 +02:00
github-actions[bot]andKoenkk 7279bc0e3c Update zigbee-herdsman-converters to 14.0.202 (#8109)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-22 19:26:06 +02:00
github-actions[bot]andnurikk 0e498c6d49 Update zigbee2mqtt-frontend to 0.5.14 (#8071)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-22 21:46:30 +08:00
Koen Kanters f571938efc Migrate settings.js to TypeScript. 2021-07-21 22:14:33 +02:00
Koen Kanters 402a9f6d95 Mark source-map-support as production dependency 2021-07-21 20:19:01 +02:00
github-actions[bot]andKoenkk aae288b3fe Update zigbee-herdsman-converters to 14.0.201 (#8100)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-21 19:36:02 +02:00
Koen Kanters 7b65dc631b Enable TypeScript (#8074)
* Enable Typescript

* Fix tests

* Fix tests again

* Automatically (re)build

* Updates

* Updates

* Update shrinkwrap

* Enable sourcemaps
2021-07-21 19:35:14 +02:00
Koen Kanters 321b34721f Clear outdated Home Assistant discovery when topic does not match. https://github.com/Koenkk/zigbee2mqtt/issues/8079 2021-07-20 18:14:56 +02:00
github-actions[bot]andKoenkk eaaa83dbe5 Update zigbee-herdsman-converters to 14.0.200 (#8089)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-20 18:12:58 +02:00
Franck Nijhof 7675dd1bcb Handle enabled by default for enum types / select|sensor entities (#8087)
* Disable power_on_behavior select entities by default

* Populate a bunch more

* Restore text type action lookup, it is used for DIY devices

* Remove stale comment
2021-07-20 16:53:49 +02:00
github-actions[bot]andKoenkk 46e2a772fe Update zigbee-herdsman-converters to 14.0.199 (#8077)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-19 20:33:07 +02:00
github-actions[bot]andKoenkk 6242da009c Update dependencies (#8064)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-19 10:07:12 +02:00
github-actions[bot]andnurikk bf97e668b0 Update zigbee2mqtt-frontend to 0.4.43 (#8065)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-18 13:38:05 +08:00
github-actions[bot]andKoenkk c6fdb253c6 Update zigbee-herdsman-converters to 14.0.198 (#8063)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-17 20:49:42 +02:00
Koen Kanters 51f4348e41 Fix adding endpoint to groups without endpoint name failing. #8027 2021-07-17 20:26:46 +02:00
github-actions[bot]andKoenkk b172c49bf3 Update zigbee-herdsman-converters to 14.0.197 (#8058)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-16 19:51:52 +02:00
Koen Kanters f8927a94ec Home Assistant groups use color temperature range supported by all bulbs. https://github.com/Koenkk/zigbee2mqtt/issues/8032 2021-07-16 19:09:29 +02:00
github-actions[bot]andKoenkk 07ff52a56f Update zigbee-herdsman-converters to 14.0.196 (#8055)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-15 20:17:12 +02:00
Koen Kanters a1c0bf2a85 Log stack on group add failure. #8027 2021-07-15 19:52:18 +02:00
github-actions[bot]andnurikk 0fd25cddb2 Update zigbee2mqtt-frontend to 0.4.40 (#8052)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-16 00:40:30 +08:00
github-actions[bot]andKoenkk f8742344c9 Update zigbee-herdsman to 0.13.119 (#8046)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-15 10:44:59 +02:00
github-actions[bot]andKoenkk be246fa841 Update zigbee-herdsman-converters to 14.0.195 (#8045)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-14 20:36:25 +02:00
Koen Kanters 515599ad13 Discover color temperature range for Home Assistant groups. https://github.com/Koenkk/zigbee2mqtt/issues/8032 2021-07-14 19:47:02 +02:00
Koen Kanters a2bf9c5d01 Log stack on group add failure. https://github.com/Koenkk/zigbee2mqtt/issues/8027 2021-07-14 19:13:06 +02:00
github-actions[bot]andnurikk 0974cbe08d Update zigbee2mqtt-frontend to 0.4.39 (#8029)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-14 11:57:53 +08:00
github-actions[bot]andKoenkk 465d47c163 Update zigbee-herdsman-converters to 14.0.194 (#8034)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-13 19:46:47 +02:00
Ilya Kirov c4936da726 Expose manufacturer in frontend (#8030) 2021-07-13 19:22:44 +02:00
github-actions[bot]andnurikk 0a2a8dd563 Update zigbee2mqtt-frontend to 0.4.37 (#8028)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-13 13:41:49 +08:00
github-actions[bot]andKoenkk 3e005170b4 Update zigbee-herdsman-converters to 14.0.193 (#8025)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-12 19:33:58 +02:00
github-actions[bot]andnurikk 685c707d90 Update zigbee2mqtt-frontend to 0.4.34 (#8017)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-12 12:00:56 +08:00
github-actions[bot]andKoenkk 589af545af Update dependencies (#8012)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-11 20:49:25 +02:00
Yip Rui FungandKoen Kanters 9edbe5a2a8 Discover enum exposes as select entities in Home Assistant (#7980)
* Read/write exposed enums are now discovered as MQTT Select entities in home assistant 2021.7.

* Read/Write enums are now exposed as a Select in addition to the existing sensor, for compatibility.

Also, the sensor will be disabled by default for new entities, shouldn't effect existing installations.

* Add support for returning multiple config from a single call to exposeToConfig.

* Update homeassistant.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-07-09 19:37:32 +02:00
github-actions[bot]andKoenkk 60a1cf3727 Update zigbee-herdsman-converters to 14.0.192 (#7995)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-09 16:40:05 +02:00
github-actions[bot]andKoenkk 4e9863aa76 Update zigbee-herdsman-converters to 14.0.191 (#7979)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-08 17:02:05 +02:00
Koen Kanters 679d231743 Use unique identifier for Home Assistant group. https://github.com/Koenkk/zigbee2mqtt/issues/7918 2021-07-07 21:07:40 +02:00
Koen Kanters 8c929cf94b Fix Home Assistant discovery clearing all group discoveries. https://github.com/Koenkk/zigbee2mqtt/issues/7918 2021-07-06 20:14:39 +02:00
github-actions[bot]andKoenkk 486ae903a3 Update zigbee-herdsman-converters to 14.0.190 (#7972)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-06 20:12:05 +02:00
github-actions[bot]andKoenkk fbf9a58fff Update zigbee-herdsman-converters to 14.0.189 (#7958)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-05 22:53:18 +02:00
d67649e458 Update dependencies (#7956)
* Update dependencies

* Update dependencies

* updates

* update

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-07-05 22:12:50 +02:00
github-actions[bot]andKoenkk 08c5758aee Update dependencies (#7955)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-05 21:32:22 +02:00
github-actions[bot]andKoenkk c85987459a Update zigbee-herdsman to 0.13.118 (#7954)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-05 21:08:37 +02:00
Koen Kanters 47882ab933 Update update_deps 2021-07-05 21:04:40 +02:00
Koen Kanters a76c13c461 Make tests compatible with Jest 27 2021-07-05 20:46:53 +02:00
Colin McCambridgeandKoen Kanters 67391615d9 Update to new Home Assistant MQTT Fan discovery (#7359)
* Update to new Home Assistant MQTT Fan discovery

- Support 3 generic speeds plus presets.

* Customize Home Assistant discovery for 99432

* Revert "Update homeassistant.js"

This reverts commit 87b0a93c7a43244a58741c72cb8dabc58e1dc87e.

* Fix

* fix

* u

* Update homeassistant.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-07-04 20:30:33 +02:00
Koen Kanters 53ae10e17b Remove console.log 2021-07-04 20:26:29 +02:00
github-actions[bot]andnurikk 223ba7fdee Update zigbee2mqtt-frontend to 0.4.33 (#7940)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-05 00:30:25 +08:00
github-actions[bot]andnurikk 6e1d6b5051 Update zigbee2mqtt-frontend to 0.4.31 (#7910)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-07-04 16:24:03 +08:00
Koen Kanters 96657e1a7d Update last_seen for all received Zigbee messages (not only handled ones). https://github.com/Koenkk/zigbee2mqtt/issues/7423 2021-07-03 17:40:22 +02:00
github-actions[bot]andKoenkk 82767a2a18 Update zigbee-herdsman-converters to 14.0.188 (#7929)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-03 15:39:31 +02:00
github-actions[bot]andKoenkk f8a978d1d8 Update zigbee-herdsman-converters to 14.0.187 (#7924)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-02 21:16:29 +02:00
Koen Kanters fe1aa084fb Only use converters of group members. https://github.com/Koenkk/zigbee2mqtt/issues/7922 2021-07-02 21:01:58 +02:00
Koen Kanters cd1a4573b1 Fix Home Assistant group discovery collision between different Zigbee2MQTT instances. https://github.com/Koenkk/zigbee2mqtt/issues/7918 2021-07-02 20:21:18 +02:00
github-actions[bot]andKoenkk 0df8663c8b Update zigbee-herdsman-converters to 14.0.186 (#7917)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-01 20:20:17 +02:00
Koen Kanters 1985e24517 Postfix all properties with endpoint name. https://github.com/Koenkk/zigbee-herdsman-converters/pull/2735 2021-07-01 19:59:52 +02:00
Koen Kanters 234e39eaea Add -dev 2021-07-01 18:16:42 +02:00
Koen Kanters 41b67fdd07 1.20.0 2021-07-01 18:16:02 +02:00
Koen Kanters 112a731812 Undev 2021-07-01 18:15:53 +02:00
github-actions[bot]andKoenkk be36316355 Update zigbee-herdsman-converters to 14.0.185 (#7916)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-07-01 17:52:41 +02:00
github-actions[bot]andKoenkk 2afd9ab68b Update zigbee-herdsman-converters to 14.0.184 (#7909)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-30 17:42:57 +02:00
github-actions[bot]andKoenkk 4cfa22501c Update zigbee-herdsman-converters to 14.0.183 (#7896)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-29 08:59:36 +02:00
github-actions[bot]andKoenkk 519a6e91f4 Update zigbee-herdsman-converters to 14.0.182 (#7885)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-26 17:50:27 +02:00
Koen Kanters 1587dc7b84 Add additional debug logging for OTA updates. https://github.com/Koenkk/zigbee2mqtt/issues/3997 2021-06-26 17:21:48 +02:00
github-actions[bot]andnurikk 523b315ab1 Update zigbee2mqtt-frontend to 0.4.29 (#7884)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-26 22:43:10 +08:00
github-actions[bot]andnurikk 1c6730ea5f Update zigbee2mqtt-frontend to 0.4.28 (#7877)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-26 00:21:54 +08:00
github-actions[bot]andnurikk a4eb3a7a0b Update zigbee2mqtt-frontend to 0.4.27 (#7876)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-25 20:31:31 +08:00
github-actions[bot]andnurikk 6898f9c54a Update zigbee2mqtt-frontend to 0.4.25 (#7872)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-25 08:36:17 +08:00
github-actions[bot]andnurikk dadda2de96 Update zigbee2mqtt-frontend to 0.4.24 (#7866)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-25 00:30:11 +08:00
Koen Kanters c27c300324 Combine published state of /set command into one message. https://github.com/Koenkk/zigbee2mqtt/issues/7854 2021-06-23 16:33:34 +02:00
06a30f7ae9 Update zigbee-herdsman-converters to 14.0.181 (#7857)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-06-22 23:05:47 +02:00
github-actions[bot]andKoenkk 74c2b1c252 Update zigbee-herdsman to 0.13.117 (#7856)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-22 23:03:30 +02:00
Koen Kanters 7b7f511dc7 Fix non supported color_mode and color properties being published for group members. https://github.com/Koenkk/zigbee2mqtt/issues/7220 https://github.com/Koenkk/zigbee2mqtt/issues/7736 2021-06-22 22:45:12 +02:00
Koen Kanters 0c45812c69 Fix frontend not working when MQTT broker is offline. https://github.com/nurikk/z2m-frontend/issues/589 2021-06-22 17:03:06 +02:00
github-actions[bot]andnurikk ac855963cb Update zigbee2mqtt-frontend to 0.4.22 (#7845)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-21 23:56:30 +08:00
github-actions[bot]andKoenkk 02e4abbff2 Update zigbee-herdsman-converters to 14.0.180 (#7840)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-20 20:54:43 +02:00
github-actions[bot]andnurikk 76a0cd507f Update zigbee2mqtt-frontend to 0.4.21 (#7830)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-20 01:17:32 +08:00
Koen Kanters 91c16812df Home Assistant: enable expose binary as switch for boolean values. https://github.com/Koenkk/zigbee2mqtt/issues/7797 2021-06-18 14:45:56 +02:00
github-actions[bot]andKoenkk 922f5024ff Update zigbee-herdsman-converters to 14.0.179 (#7817)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-18 13:20:31 +02:00
Koen Kanters 8dc7ad8dcc Home Assistant group discovery #2410 (#7672)
* Initial

* done
2021-06-16 22:48:48 +02:00
github-actions[bot]andKoenkk c8fdfc77f2 Update zigbee-herdsman-converters to 14.0.178 (#7808)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-16 21:44:24 +02:00
Koen Kanters ce311c93b1 Home Assistant: disable expose binary as switch for boolean values. https://github.com/Koenkk/zigbee2mqtt/issues/7797 2021-06-16 17:20:11 +02:00
github-actions[bot]andKoenkk 04c4c77d1e Update zigbee-herdsman-converters to 14.0.177 (#7801)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-15 18:18:44 +02:00
github-actions[bot]andKoenkk 1c8fd479d0 Update zigbee-herdsman to 0.13.116 (#7799)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-15 18:12:19 +02:00
github-actions[bot]andKoenkk 497ca1800b Update zigbee-herdsman-converters to 14.0.176 (#7789)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-14 19:15:38 +02:00
Koen Kanters 7f995e964d Fix "Cannot read property 'group' of null" exception on "request/group/members/remove_all". https://github.com/Koenkk/zigbee2mqtt/issues/7785 2021-06-14 19:12:24 +02:00
github-actions[bot]andKoenkk 3b3dae51b5 Update zigbee-herdsman-converters to 14.0.175 (#7767)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-12 19:51:51 +02:00
github-actions[bot]andKoenkk c314e8d267 Update zigbee-herdsman to 0.13.115 (#7766)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-12 19:37:56 +02:00
Robert AlexaandKoen Kanters 8dab33dee9 Home Assistant: expose binary with SET access as switch (#7760)
* Add support for binary attributes with SET access - discover as switch in HA

* Code linting

* Update npm-shrinkwrap.json

* Update homeassistant.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-06-12 19:05:13 +02:00
github-actions[bot]andKoenkk 217ce2212a Update zigbee-herdsman-converters to 14.0.174 (#7758)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-11 19:21:04 +02:00
github-actions[bot]andKoenkk 4ccee02fe3 Update zigbee-herdsman-converters to 14.0.173 (#7748)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-10 19:38:57 +02:00
github-actions[bot]andKoenkk ee7bdf4ae2 Update zigbee-herdsman-converters to 14.0.172 (#7735)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-08 16:23:08 +02:00
Koen Kanters fa8593c898 Log and publish friendly_name on deviceLeave. https://github.com/Koenkk/zigbee2mqtt/issues/7725 2021-06-08 15:58:10 +02:00
Franck Nijhof 000884b080 Deprecate Home Assistant entity attributes (#7683)
* Deprecate Home Assistant entity attributes

* Adjust test to match latest dev

* Set default only for new installations

* Fix tests
2021-06-08 15:33:14 +02:00
github-actions[bot]andKoenkk 9eb1fe61e7 Update zigbee-herdsman-converters to 14.0.171 (#7724)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-07 15:54:32 +02:00
github-actions[bot]andKoenkk 741b936680 Update zigbee-herdsman to 0.13.114 (#7723)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-07 15:49:32 +02:00
github-actions[bot]andKoenkk 61b57aceae Update zigbee-herdsman to 0.13.113 (#7719)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-07 10:09:34 +02:00
Koen Kanters 7b13b2d213 Improve 0401a13d5d 2021-06-07 09:54:33 +02:00
Koen Kanters 0401a13d5d Disable legacy options on new network start. 2021-06-07 09:46:10 +02:00
github-actions[bot]andnurikk 95d39a3ff6 Update zigbee2mqtt-frontend to 0.4.19 (#7711)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-06 17:26:29 +08:00
github-actions[bot]andKoenkk 34e286c261 Update zigbee-herdsman to 0.13.112 (#7705)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-05 19:35:46 +02:00
github-actions[bot]andKoenkk 0b19d01e6d Update zigbee-herdsman-converters to 14.0.170 (#7702)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-04 22:16:48 +02:00
Franck Nijhof 5e7387fa9c Disable less common Home Assistant entities by default (#7684)
* Disable less common Home Assistant entities by default

* Disable illuminance by default

* Please eslint
2021-06-04 21:33:45 +02:00
Franck Nijhof 51fd598e32 Add Home Assistant sensor state_class support (#7677) 2021-06-04 11:41:42 +02:00
Koen Kanters 269dac2bf8 Promote to dev 2021-06-04 11:33:25 +02:00
Koen Kanters 9781c4352f Merge branch 'master' into dev 2021-06-04 11:32:57 +02:00
Koen Kanters 9bd46932c3 1.19.1 2021-06-04 11:29:42 +02:00
Koen Kanters ac5ebae639 Fix Docker container not starting on Raspberry Pi. https://github.com/Koenkk/zigbee2mqtt/issues/7662 2021-06-04 11:29:28 +02:00
github-actions[bot]andnurikk a608c3984b Update zigbee2mqtt-frontend to 0.4.18 (#7689)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-06-03 22:54:47 +08:00
github-actions[bot]andKoenkk c5081559cf Update zigbee-herdsman-converters to 14.0.169 (#7670)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-02 20:36:13 +02:00
Koen Kanters 0ea5f14ab7 Fix Docker container not starting on Raspberry Pi. https://github.com/Koenkk/zigbee2mqtt/issues/7662 2021-06-02 19:42:20 +02:00
Koen Kanters 9f02eb3359 Promote to dev 2021-06-01 17:55:58 +02:00
Koen Kanters 89cb4f9536 1.19.0 2021-06-01 17:55:07 +02:00
Koen Kanters fbf34f51ec Undev 2021-06-01 17:54:54 +02:00
github-actions[bot]andKoenkk 337c1fdef3 Update zigbee-herdsman-converters to 14.0.168 (#7661)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-06-01 15:26:08 +02:00
github-actions[bot]andKoenkk e0b9e3e738 Update zigbee-herdsman-converters to 14.0.167 (#7652)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-31 19:14:03 +02:00
Koen Kanters 34bc82ddd6 Fix tests 2021-05-31 19:01:12 +02:00
Koen Kanters cae4e1ff7c Display network address in router as hex. https://github.com/Koenkk/zigbee2mqtt/discussions/7603 2021-05-31 18:57:27 +02:00
Jorge Schrauwen e1bc0b53a2 Update title/description for filtered_attributes and filtired_optimistic (#7643)
* Update title/description for filtered_attributes and filtired_optimistic

The way the frontend displays it is a bit confusing, this should hopefully clear that up.

* Lint
2021-05-30 17:27:23 +02:00
github-actions[bot]andKoenkk ae4a332946 Update zigbee-herdsman-converters to 14.0.166 (#7640)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-30 14:05:37 +02:00
Jorge Schrauwen 15a7bab5f3 #7571 Add filtered_optimistic device option (#7633)
* Add filtered_optimistic device option

* Add test to cover filtered_optimistic
2021-05-30 13:03:55 +02:00
github-actions[bot]andKoenkk c6e2e875d5 Update zigbee-herdsman-converters to 14.0.165 (#7632)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-29 15:44:00 +02:00
github-actions[bot]andKoenkk 2e739cdc07 Update zigbee-herdsman to 0.13.111 (#7631)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-29 15:20:49 +02:00
Koen Kanters bd64be2b5d Show network address as hex in graphviz and plantuml network map. #7603 2021-05-29 15:19:26 +02:00
Koen Kanters fff76e6013 Republish devices when network address changes. https://github.com/Koenkk/zigbee2mqtt/discussions/7603 2021-05-29 15:06:14 +02:00
github-actions[bot]andnurikk 3d00338bc8 Update zigbee2mqtt-frontend to 0.4.16 (#7629)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-29 13:57:50 +08:00
github-actions[bot]andKoenkk 7d7ef3c7eb Update zigbee-herdsman-converters to 14.0.164 (#7626)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-28 22:03:07 +02:00
Koen Kanters 9941be1d1a Honour optimisitic false for groups (#7615)
* Honour optimisitic false for groups. https://github.com/Koenkk/zigbee2mqtt/issues/7571

* Remove default optimistic true for groups. https://github.com/Koenkk/zigbee2mqtt/issues/7571

* Updates
2021-05-28 20:23:00 +02:00
github-actions[bot]andKoenkk 7185741881 Update zigbee-herdsman-converters to 14.0.163 (#7616)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-27 18:07:18 +02:00
github-actions[bot]andKoenkk a996f5ca34 Update zigbee-herdsman-converters to 14.0.162 (#7610)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-26 18:45:49 +02:00
github-actions[bot]andKoenkk f41789e8ba Update zigbee-herdsman-converters to 14.0.161 (#7600)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-25 19:44:12 +02:00
github-actions[bot]andKoenkk fc22702bc1 Update zigbee-herdsman to 0.13.110 (#7598)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-25 19:28:43 +02:00
github-actions[bot]andKoenkk 2e8a9d9050 Update zigbee-herdsman-converters to 14.0.160 (#7597)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-25 18:53:07 +02:00
github-actions[bot]andKoenkk 6e3822caa2 Update zigbee-herdsman to 0.13.109 (#7594)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-25 18:10:19 +02:00
Koen Kanters 085983d4cd Bump to alpine 3.13 2021-05-24 21:27:49 +02:00
Koen Kanters 4af5314cd5 Merge remote-tracking branch 'origin/master' into dev 2021-05-24 21:25:39 +02:00
github-actions[bot]andKoenkk 3ef1f6a726 Update zigbee-herdsman-converters to 14.0.159 (#7586)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-24 21:23:37 +02:00
github-actions[bot]andKoenkk 85d397b1a5 Update zigbee-herdsman-converters to 14.0.158 (#7585)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-24 20:46:18 +02:00
github-actions[bot]andKoenkk 2faa252f88 Update zigbee-herdsman to 0.13.108 (#7584)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-24 20:32:05 +02:00
github-actions[bot]andKoenkk 5195f5f248 Update zigbee-herdsman-converters to 14.0.157 (#7570)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-23 15:52:57 +02:00
Jorge SchrauwenandKoen Kanters 597a5a4925 Add skip_disable_reporting to unbind group/remove (#7455)
* Allow skipping disable of reporting during unbind

* Allow skipping disable of reporting during remove from group

* Add tests

* Update bind.js

* Update groups.js

* Update bind.test.js

* Update bind.test.js

* Update bind.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-23 15:37:34 +02:00
github-actions[bot]andKoenkk ab84000040 Update dependencies (#7568)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-23 15:13:30 +02:00
github-actions[bot]andKoenkk ab466d3073 Update zigbee-herdsman-converters to 14.0.156 (#7563)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-22 19:42:37 +02:00
github-actions[bot]andKoenkk 792883c3db Update zigbee-herdsman-converters to 14.0.155 (#7560)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-22 14:36:26 +02:00
github-actions[bot]andKoenkk 6ca931207d Update zigbee-herdsman to 0.13.107 (#7559)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-22 14:13:37 +02:00
github-actions[bot]andKoenkk 70f5838c85 Update zigbee-herdsman-converters to 14.0.153 (#7551)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-21 20:02:28 +02:00
github-actions[bot]andKoenkk 49942df205 Update zigbee-herdsman to 0.13.106 (#7550)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-21 19:24:36 +02:00
github-actions[bot]andnurikk 888cc7eeee Update zigbee2mqtt-frontend to 0.4.15 (#7544)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-21 15:00:53 +08:00
github-actions[bot]andKoenkk 8344622815 Update zigbee-herdsman-converters to 14.0.152 (#7541)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-20 19:36:54 +02:00
github-actions[bot]andKoenkk dd9caff60f Update zigbee-herdsman to 0.13.105 (#7540)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-20 19:25:11 +02:00
github-actions[bot]andKoenkk 55916d7cd8 Update zigbee-herdsman-converters to 14.0.151 (#7531)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-19 20:16:07 +02:00
github-actions[bot]andKoenkk 7671a983bf Update zigbee-herdsman to 0.13.104 (#7530)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-19 20:10:32 +02:00
github-actions[bot]andKoenkk 891e7029fc Update zigbee-herdsman to 0.13.103 (#7529)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-19 19:59:07 +02:00
github-actions[bot]andKoenkk 7bdf52d824 Update zigbee-herdsman-converters to 14.0.150 (#7518)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-18 20:08:46 +02:00
github-actions[bot]andKoenkk c171e02cc9 Update zigbee-herdsman to 0.13.102 (#7517)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-18 18:30:28 +02:00
github-actions[bot]andKoenkk 45aa352578 Update zigbee-herdsman to 0.13.101 (#7515)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-18 17:14:43 +02:00
github-actions[bot]andnurikk 92cef6726a Update zigbee2mqtt-frontend to 0.4.14 (#7514)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-18 22:38:46 +08:00
github-actions[bot]andKoenkk 0d91b9474c Update zigbee-herdsman-converters to 14.0.149 (#7506)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-17 20:32:24 +02:00
github-actions[bot]andKoenkk c50547e465 Update zigbee-herdsman to 0.13.100 (#7504)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-17 20:16:00 +02:00
github-actions[bot]andnurikk 74bf357757 Update zigbee2mqtt-frontend to 0.4.13 (#7496)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-17 09:15:47 +08:00
Koen Kanters 669489fe97 Delete codeql-analysis.yml 2021-05-16 20:47:38 +02:00
9d0dd59c6c Update zigbee-herdsman-converters to 14.0.148 (#7492)
* Update zigbee-herdsman-converters to 14.0.148

* Update bridge.test.js

* Update group.test.js

* Update homeassistant.test.js

* Update networkMap.test.js

* Update publish.test.js

* Update homeassistant.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-16 20:47:09 +02:00
github-actions[bot]andKoenkk 638233263d Update zigbee-herdsman to 0.13.99 (#7493)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-16 19:33:56 +02:00
russdanandKoen Kanters 5aa1d21ed4 Fix controlling heat endpoint with occupied_heating_setpoint_heat not working (#7481)
* Update publish.js

Fix for issue #7470 .  Tests:

error 2021-05-14 11:37:13: key: occupied_heating_setpoint_heat
error 2021-05-14 11:37:13: endpointNameMatch 'heat' (heat)
error 2021-05-14 11:37:13: Before replace 'occupied_heating_setpoint_heat' (occupied_heating_setpoint_heat)
error 2021-05-14 11:37:13: After replace 'occupied_heating_setpoint' (occupied_heating_setpoint)
error 2021-05-14 11:37:26: key: occupied_heating_setpoint_water
error 2021-05-14 11:37:26: endpointNameMatch 'water' (water)
error 2021-05-14 11:37:26: Before replace 'occupied_heating_setpoint_water' (occupied_heating_setpoint_water)
error 2021-05-14 11:37:26: After replace 'occupied_heating_setpoint' (occupied_heating_setpoint)

* Update publish.js

* Update publish.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-16 16:08:36 +02:00
github-actions[bot]andKoenkk f20429664f Update dependencies (#7490)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-16 16:00:52 +02:00
github-actions[bot]andKoenkk 3557779efc Update zigbee-herdsman-converters to 14.0.146 (#7480)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-15 15:35:13 +02:00
github-actions[bot]andKoenkk fe8d20f86e Update zigbee-herdsman to 0.13.98 (#7479)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-15 15:27:36 +02:00
github-actions[bot]andKoenkk 39b68aa07d Update zigbee-herdsman to 0.13.97 (#7457)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-13 20:17:20 +02:00
Jorge Schrauwen 55ce381d28 homeassistant: copy hue/saturation to h/s (#7453) 2021-05-13 14:57:18 +02:00
github-actions[bot]andKoenkk 05b9252a4b Update zigbee-herdsman-converters to 14.0.145 (#7448)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-12 19:07:21 +02:00
github-actions[bot]andnurikk 766c632c30 Update zigbee2mqtt-frontend to 0.4.10 (#7447)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-12 23:17:19 +08:00
333db4ca77 Update zigbee-herdsman-converters to 14.0.144 (#7436)
* Update zigbee-herdsman-converters to 14.0.144

* Update homeassistant.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-12 08:33:43 +02:00
github-actions[bot]andnurikk f799550095 Update zigbee2mqtt-frontend to 0.4.9 (#7427)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-11 09:39:48 +08:00
John Doe fb7be8684f Fix json schema default values and examples (#7426) 2021-05-11 09:25:55 +08:00
github-actions[bot]andKoenkk 82f69beb38 Update zigbee-herdsman-converters to 14.0.143 (#7425)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-10 21:21:26 +02:00
github-actions[bot]andKoenkk d8dc4e79fe Update dependencies (#7401)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-10 17:52:07 +02:00
github-actions[bot]andnurikk 8f07addade Update zigbee2mqtt-frontend to 0.4.8 (#7420)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-10 22:48:42 +08:00
github-actions[bot]andnurikk 4666ee7261 Update zigbee2mqtt-frontend to 0.4.6 (#7406)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-10 00:04:06 +08:00
github-actions[bot]andnurikk a6736c4cd5 Update zigbee2mqtt-frontend to 0.4.5 (#7402)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-09 12:12:21 +08:00
github-actions[bot]andnurikk 7447b61841 Update zigbee2mqtt-frontend to 0.4.4 (#7398)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-09 01:05:51 +08:00
Koen Kanters 723121d671 Fix tests 2021-05-08 15:52:14 +02:00
github-actions[bot]andKoenkk fe8098c8b2 Update zigbee-herdsman to 0.13.96 (#7394)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-08 15:32:39 +02:00
Koen Kanters e6b317b762 Pass disableLED option to herdsman 2021-05-08 15:30:57 +02:00
github-actions[bot]andKoenkk 56397e2027 Update zigbee-herdsman-converters to 14.0.142 (#7382)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-07 19:20:03 +02:00
Koen Kanters 6bbe738f91 Fix controlling of different endpoint names in one message not working when endpoints have same ID. https://github.com/Koenkk/zigbee-herdsman-converters/pull/2545 2021-05-07 19:03:44 +02:00
github-actions[bot]andKoenkk a893cac951 Update zigbee-herdsman-converters to 14.0.141 (#7369)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-06 21:52:42 +02:00
github-actions[bot]andKoenkk c27249b676 Update zigbee-herdsman to 0.13.95 (#7366)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-06 21:13:21 +02:00
github-actions[bot]andnurikk 1ec33bdd8a Update zigbee2mqtt-frontend to 0.4.3 (#7358)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-06 08:46:26 +08:00
github-actions[bot]andKoenkk d74865b5f1 Update zigbee-herdsman-converters to 14.0.140 (#7356)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-05 20:43:33 +02:00
github-actions[bot]andKoenkk 548589cb70 Update zigbee-herdsman to 0.13.94 (#7355)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-05 20:05:19 +02:00
Koen Kanters febcb2b1c7 Set default for adapter to auto in schema. https://github.com/nurikk/z2m-frontend/issues/449 2021-05-05 19:50:59 +02:00
beacbd3496 Update zigbee-herdsman-converters to 14.0.139 (#7339)
* Update zigbee-herdsman-converters to 14.0.139

* Update configure.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-04 22:43:04 +02:00
Koen Kanters a77e857868 Fix color_mode missing for lights with multiple endpoints. #7220 2021-05-04 22:29:23 +02:00
github-actions[bot]andKoenkk 6c6956f1c1 Update zigbee-herdsman-converters to 14.0.138 (#7338)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-04 21:16:44 +02:00
Koen Kanters 504917bfa6 Fix device not removed from group in configuration.yaml upon device removal. https://github.com/Koenkk/zigbee2mqtt/issues/7326 2021-05-04 21:06:00 +02:00
Koen Kanters 37f773a5ee Add auto adapter type. 2021-05-04 20:04:21 +02:00
github-actions[bot]andKoenkk aace96a96c Update zigbee-herdsman to 0.13.93 (#7336)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-04 20:02:58 +02:00
github-actions[bot]andnurikk b2a64ea066 Update zigbee2mqtt-frontend to 0.4.2 (#7331)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-04 23:38:22 +08:00
github-actions[bot]andKoenkk baeac6fa68 Update zigbee-herdsman-converters to 14.0.137 (#7312)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-03 20:59:11 +02:00
Koen Kanters a35faa9554 Allow null values for serial.adapter. https://github.com/nurikk/z2m-frontend/issues/449 2021-05-03 20:44:33 +02:00
Koen Kanters 700e9c0c3a Improve network scan stability. https://github.com/Koenkk/zigbee2mqtt/issues/7163 2021-05-03 20:04:54 +02:00
svasilievandKoen Kanters 2dc409bf38 Include nodejs version 16 to supported engines (#7297)
Updating Arch, brought nodejs version 16, that made zigbee2mqtt not working. Adding 16 to supported engines, fixes it.

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-03 19:26:13 +02:00
github-actions[bot]andKoenkk 7fa04cf183 Update zigbee-herdsman-converters to 14.0.136 (#7296)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-02 20:21:11 +02:00
b76e63d222 Update zigbee-herdsman-converters to 14.0.135 (#7295)
* Update zigbee-herdsman-converters to 14.0.135

* Update group.test.js

* Update publish.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-02 20:13:34 +02:00
github-actions[bot]andnurikk 3393ac1035 Update zigbee2mqtt-frontend to 0.4.1 (#7291)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-02 23:24:13 +08:00
github-actions[bot]andKoenkk 2886d90dde Update dependencies (#7287)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-02 13:20:41 +02:00
github-actions[bot]andKoenkk e3deb03331 Update zigbee-herdsman-converters to 14.0.134 (#7279)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-01 19:21:49 +02:00
github-actions[bot]andKoenkk e64b7d2e86 Update zigbee-herdsman-converters to 14.0.133 (#7278)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-01 17:39:32 +02:00
Koen Kanters 2fe085d409 Home Assistant: don't publish mocked values anymore replaced by unknown state in #7032 2021-05-01 17:01:59 +02:00
a1983e2a32 Update zigbee-herdsman-converters to 14.0.132 (#7277)
* Update zigbee-herdsman-converters to 14.0.132

* Update configure.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-01 16:16:12 +02:00
Koen Kanters 4f495a0ed7 Promote to dev 2021-05-01 14:52:40 +02:00
Koen Kanters f2e39af12c 1.18.3 2021-05-01 14:52:07 +02:00
Koen Kanters 111d4d70bd Undev 2021-05-01 14:52:01 +02:00
github-actions[bot]andKoenkk fae2e4851c Update zigbee-herdsman-converters to 14.0.131 (#7276)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-05-01 14:15:31 +02:00
43ff2daebe Update zigbee-herdsman-converters to 14.0.129 (#7275)
* Update zigbee-herdsman-converters to 14.0.129

* Update homeassistant.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-05-01 13:56:44 +02:00
github-actions[bot]andnurikk 19373d815f Update zigbee2mqtt-frontend to 0.4.0 (#7271)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-05-01 11:35:36 +08:00
Koen Kanters e9a5ec1a58 Revert "Home Assistant: remove attributes from discovered entities. https://github.com/Koenkk/zigbee2mqtt/discussions/7249"
This reverts commit 54ab0a3f98.
2021-04-30 16:41:18 +02:00
Koen Kanters ec97931ee4 Home Assistant: don't counter action: null payload. 2021-04-30 16:41:00 +02:00
github-actions[bot]andnurikk 20c0712aba Update zigbee2mqtt-frontend to 0.3.121 (#7247)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-04-30 09:15:36 +08:00
github-actions[bot]andKoenkk 2e5e5beb83 Update zigbee-herdsman-converters to 14.0.128 (#7251)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-29 20:03:24 +02:00
Koen Kanters 54ab0a3f98 Home Assistant: remove attributes from discovered entities. https://github.com/Koenkk/zigbee2mqtt/discussions/7249 2021-04-29 19:43:54 +02:00
Koen Kanters d61d6e28f2 Only attempt to configure end device when message is received from it. (#7242) 2021-04-29 18:18:51 +02:00
ssierglandKoen Kanters 1d8b37eee0 Properly handle SIGTERM and other kernel events (#7230)
* Properly handle SIGTERM and other kernel events

see

https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals

* Update Dockerfile

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-29 18:13:41 +02:00
github-actions[bot]andKoenkk 2b488ccff4 Update zigbee-herdsman-converters to 14.0.127 (#7241)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-28 20:06:27 +02:00
cedbd1fd4c Update zigbee-herdsman-converters to 14.0.126 (#7240)
* Update zigbee-herdsman-converters to 14.0.126

* Update bind.js

* Update networkMap.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-28 19:48:08 +02:00
Koen Kanters f27e5efe0f Fix Home Assistant "KeyError: 'color_mode'" for brightness only lights. https://github.com/Koenkk/zigbee2mqtt/issues/7220 2021-04-28 19:10:39 +02:00
github-actions[bot]andKoenkk 7eeaeafbd0 Update zigbee-herdsman-converters to 14.0.125 (#7221)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-27 16:27:58 +02:00
github-actions[bot]andKoenkk e4d868652a Update zigbee-herdsman-converters to 14.0.124 (#7216)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-26 21:42:48 +02:00
71d77ac27c Update zigbee-herdsman-converters to 14.0.121 (#7213)
* Update zigbee-herdsman-converters to 14.0.121

* Update bridge.test.js

* Update bridge.test.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-26 16:34:08 +02:00
github-actions[bot]andKoenkk 1f80a05477 Update zigbee-herdsman to 0.13.92 (#7211)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-26 11:35:25 +02:00
github-actions[bot]andKoenkk a02c8d242a Update zigbee-herdsman-converters to 14.0.120 (#7205)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-25 19:26:15 +02:00
daxy01andKoen Kanters edc18e3376 Add log_symlink_current option (#7166)
* Update logger.js

Adding a symlink from "log/<timestamp>" to "log/current" to be able to always view the last logfile using "log/current/log.txt".

* Update logger.js

* Update logger.js

Create directory first to prevent startup failure

* Update logger.js

Fixing check on startup

* Update settings.js

* Update logger.js

* Update settings.schema.json

* Update bridge.test.js

* Update logger.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-25 19:21:38 +02:00
github-actions[bot]andKoenkk 1f797e5e3a Update zigbee-herdsman-converters to 14.0.119 (#7204)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-25 18:55:26 +02:00
Koen Kanters aee4e96619 Attempt to fix https://github.com/Koenkk/zigbee2mqtt/issues/7198 2021-04-25 15:27:40 +02:00
Koen Kanters 7631c191c5 Home Assistant discovery: add color_mode for lights (#7057)
* Home Assistant add color_mode.

* Fix tests

* Fix coverage
2021-04-25 14:56:59 +02:00
github-actions[bot]andKoenkk 8802354ca9 Update dependencies (#7199)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-25 14:30:39 +02:00
github-actions[bot]andKoenkk 627b94e5ab Update zigbee-herdsman-converters to 14.0.118 (#7192)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-24 18:56:42 +02:00
github-actions[bot]andnurikk 8ed842603c Update zigbee2mqtt-frontend to 0.3.120 (#7190)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-04-24 21:58:41 +08:00
github-actions[bot]andKoenkk 6904020f7d Update zigbee-herdsman-converters to 14.0.117 (#7182)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-23 20:44:47 +02:00
d3fd3bcacc Update zigbee-herdsman-converters to 14.0.116 (#7169)
* Fix state of members from group incorrect when toZigbee converter reads a member state. #7038

* Update zigbee-herdsman-converters to 14.0.116

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-22 20:34:13 +02:00
Koen Kanters 366c5fcb4d Fix state of members from group incorrect when toZigbee converter reads a member state. #7038 2021-04-22 20:28:54 +02:00
Koen Kanters 2c44f4ede9 Test case for #7106 2021-04-22 19:20:03 +02:00
Koen Kanters 3f0ef8e08f Improve utils.getObjectProperty() 2021-04-22 19:19:17 +02:00
github-actions[bot]andKoenkk 01af249e95 Update zigbee-herdsman-converters to 14.0.115 (#7162)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-21 19:56:15 +02:00
github-actions[bot]andKoenkk a1e6439a5c Update zigbee-herdsman-converters to 14.0.114 (#7148)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-20 18:42:49 +02:00
github-actions[bot]andKoenkk ba305ad18b Update zigbee-herdsman-converters to 14.0.113 (#7134)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-19 20:17:37 +02:00
pklokke 95dd6c485c Support binding of server clusters towards clients (#7127)
This allows binding of devices such as sleepy temperature sensors to heating actuators
2021-04-19 20:16:31 +02:00
github-actions[bot]andKoenkk dbfdbcba4a Update zigbee-herdsman to 0.13.91 (#7122)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-18 20:43:42 +02:00
github-actions[bot]andKoenkk 14cc33cd44 Update zigbee-herdsman-converters to 14.0.112 (#7121)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-18 20:32:21 +02:00
xyzroeandKoen Kanters 9a53b954f8 Add wifi endpoint name (#7103)
* Update utils.js

added endpointNames wifi, ds, bme
wifi for future devices
ds and bme are using in DIYRuZ_Flower

* Update utils.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-18 20:25:18 +02:00
github-actions[bot]andKoenkk 615026984c Update dependencies (#7110)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-18 19:40:27 +02:00
github-actions[bot]andKoenkk bd660dee82 Update zigbee-herdsman-converters to 14.0.111 (#7105)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-17 16:13:09 +02:00
HeddaandKoen Kanters 75dc72550f Add 57600 as another common baud rate speed example (#7094)
* Add 57600 as another common board date example

Add 57600 as another common board date example to avoid confusions like in https://github.com/Koenkk/zigbee-herdsman/issues/319

* Spelling and grammar

Spelling and grammar

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-17 14:45:48 +02:00
github-actions[bot]andKoenkk c7443191ff Update zigbee-herdsman-converters to 14.0.110 (#7089)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-15 17:27:08 +02:00
Koen Kanters dff4af94f5 Home Assistant: fix device_automation not published when homeassistant is in device options. https://github.com/Koenkk/zigbee2mqtt/issues/7074 2021-04-14 20:22:26 +02:00
github-actions[bot]andKoenkk a1fc606d99 Update zigbee-herdsman to 0.13.90 (#7076)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-14 16:48:24 +02:00
github-actions[bot]andKoenkk 89ceaac3d1 Update zigbee-herdsman-converters to 14.0.109 (#7072)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-13 21:05:43 +02:00
Koen Kanters 8df8ef629e Fix state of group not changing when state of specific endpoint is changed. https://github.com/Koenkk/zigbee2mqtt/issues/6905 2021-04-13 20:20:44 +02:00
Koen Kanters 07262bd62f Fix device option set to null instead of removed when sending null. https://github.com/nurikk/z2m-frontend/issues/430 2021-04-12 19:49:21 +02:00
Koen Kanters 5963f3b7f4 Home Assistant: set unknown values to null (#7032) 2021-04-12 16:59:41 +02:00
github-actions[bot]andKoenkk 7e861aa3bb Update zigbee-herdsman-converters to 14.0.108 (#7047)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-11 17:54:23 +02:00
github-actions[bot]andKoenkk a4da036266 Update dependencies (#7040)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-11 13:04:15 +02:00
Koen Kanters 487ab0648d Improve logging 2021-04-10 18:51:13 +02:00
github-actions[bot]andKoenkk e91a23b3ed Update zigbee-herdsman-converters to 14.0.107 (#7022)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-09 22:33:05 +02:00
ptvoandptvoinfo d5d16d1616 Update schema with the Icon device property. (#7018)
* Device-specific icon

* Updated tests.

* Updated test

* Updated tests

* Updated tests.

* Updated tests

* Update schema with the Icon device property.

* Fix

Co-authored-by: ptvoinfo <xagga@ya.ru>
2021-04-09 20:52:41 +08:00
ptvoandptvoinfo e81ac11466 Allow to redefine device icon (#7013)
* Device-specific icon

* Updated tests.

* Updated test

* Updated tests

* Updated tests.

* Updated tests

Co-authored-by: ptvoinfo <xagga@ya.ru>
2021-04-09 19:35:44 +08:00
github-actions[bot]andKoenkk 93c0a8a7ba Update zigbee-herdsman-converters to 14.0.106 (#7003)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-08 21:00:02 +02:00
John Doe 42a4596be6 Add device icon from converter definition (#7001) 2021-04-08 22:57:55 +08:00
github-actions[bot]andnurikk 53772e5536 Update zigbee2mqtt-frontend to 0.3.119 (#6998)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-04-08 21:57:42 +08:00
github-actions[bot]andKoenkk 2446e173b6 Update zigbee-herdsman-converters to 14.0.105 (#6990)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-07 19:28:18 +02:00
Koen Kanters 30efb3e824 Fix "Cannot read property 'ID' of undefined". https://github.com/Koenkk/zigbee2mqtt/issues/6981 2021-04-07 18:39:54 +02:00
ab0ae8ce91 Update zigbee-herdsman-converters to 14.0.104 (#6975)
* Update zigbee-herdsman-converters to 14.0.104

* Update bridge.test.js

* Update otaUpdate.test.js

* Update zigbeeHerdsman.js

Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2021-04-06 22:24:30 +02:00
github-actions[bot]andKoenkk 172689976e Update zigbee-herdsman-converters to 14.0.103 (#6968)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-05 21:06:24 +02:00
Koen Kanters bf47282ea7 Fix optimistic group state property not postfixed with endpoint name when necessary. https://github.com/Koenkk/zigbee2mqtt/issues/6905 2021-04-04 21:00:24 +02:00
github-actions[bot]andnurikk ec8348854b Update zigbee2mqtt-frontend to 0.3.118 (#6952)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-04-04 17:24:22 +08:00
github-actions[bot]andKoenkk 348c562f97 Update zigbee-herdsman to 0.13.89 (#6953)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-04 10:45:20 +02:00
github-actions[bot]andKoenkk 92bd2166e3 Update dependencies (#6948)
Co-authored-by: Koenkk <Koenkk@users.noreply.github.com>
2021-04-04 10:35:29 +02:00
github-actions[bot]andnurikk d6a1d2deb5 Update zigbee2mqtt-frontend to 0.3.115 (#6938)
Co-authored-by: nurikk <nurikk@users.noreply.github.com>
2021-04-03 15:54:29 +08:00
Koen Kanters f98d71ba6e Promote to dev 2021-04-01 09:08:03 +02:00
143 changed files with 30256 additions and 36701 deletions
+2 -1
View File
@@ -1,5 +1,5 @@
.eslintignore
.eslintrc.json
.eslintrc.js
.git
.github
.gitignore
@@ -13,4 +13,5 @@ images
node_modules
scripts
test
coverage
update.sh
+46
View File
@@ -0,0 +1,46 @@
module.exports = {
'env': {
'jest/globals': true,
'es6': true,
'node': true,
},
'extends': ['eslint:recommended', 'google', 'plugin:jest/recommended', 'plugin:jest/style'],
'parserOptions': {
'ecmaVersion': 2018,
'sourceType': 'module',
},
'rules': {
'require-jsdoc': 'off',
'indent': ['error', 4],
'max-len': ['error', {'code': 120}],
'no-prototype-builtins': 'off',
'linebreak-style': ['error', (process.platform === 'win32' ? 'windows' : 'unix')], // https://stackoverflow.com/q/39114446/2771889
},
'plugins': [
'jest',
],
'overrides': [{
files: ['*.ts'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['plugin:@typescript-eslint/recommended'],
parserOptions: {
project: './tsconfig.json',
},
rules: {
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/semi': ['error'],
'array-bracket-spacing': ['error', 'never'],
'indent': ['error', 4],
'max-len': ['error', {'code': 120}],
'no-return-await': 'error',
'object-curly-spacing': ['error', 'never'],
},
}],
};
-21
View File
@@ -1,21 +0,0 @@
{
"env": {
"jest/globals": true,
"es6": true,
"node": true
},
"extends": ["eslint:recommended", "google", "plugin:jest/recommended", "plugin:jest/style"],
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"require-jsdoc": "off",
"indent": ["error", 4],
"max-len": ["error", { "code": 120 }],
"no-prototype-builtins": "off"
},
"plugins": [
"jest"
]
}
-46
View File
@@ -1,46 +0,0 @@
<!--
Before submitting an issue make sure you've searched for a similar issue and read the documentation: https://www.zigbee2mqtt.io/.
Rules (don't ignore these, your issue will be closed without further notice):
- English only
- Make sure you are on the latest Zigbee2MQTT version
- Provide a clear description of the problem
- DON'T copy logs directly here, post a link to https://hastebin.com/ or https://pastebin.com/.
- Make sure you are running the latest firmware https://github.com/koenkk/z-stack-firmware.
Did you read the FAQ?
- https://www.zigbee2mqtt.io/information/FAQ.html
Zigbee2MQTT fails to start?
- https://www.zigbee2mqtt.io/information/FAQ.html#help-zigbee2mqtt-fails-to-start
Having issues when using a CC2531?
- Make sure the CC2531 is connected through a USB extension cable
- Try the source routing firmware: https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_Home_1.2/bin/source_routing
- With larger networks (30/40+) devices, your CC2531 might not be powerful enough. This will cause weird issues, in this case it's advised to use a more powerful adapter: https://www.zigbee2mqtt.io/information/supported_adapters.html#texas-instruments-cc26x2r1
Unsupported device?
- https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html
Device does not pair or interview fails?
- https://www.zigbee2mqtt.io/information/FAQ.html#why-does-my-device-not-or-fail-to-pair
Bug report?
- If applicable, provide steps how to reproduce the problem.
- Provide the herdsman debug logging: https://www.zigbee2mqtt.io/information/debug.html#zigbee-herdsman-debug-logging
-->
<!--Start your bug report below this line-->
# Bug Report
## What happened
## What did you expect to happen
## How to reproduce it (minimal and precise)
## Debug Info
Zigbee2MQTT version:
Adapter hardware: CC2531, CC2530, CC26X2R1 or CC1352P-2
Adapter firmware version:
+4 -1
View File
@@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: "IMPORTANT: Check development branch changelog first!!"
url: https://gist.github.com/Koenkk/bfd4c3d1725a2cccacc11d6ba51008ba
about: "Before submitting an issue, check if the issue hasn't already been solved in the development branch. Click 'Open' to see the release notes of the development branch. In case it is, you can read here how to switch to the development branch: https://www.zigbee2mqtt.io/advanced/more/switch-to-dev-branch.html"
- name: Questions/discussion
url: https://github.com/Koenkk/zigbee2mqtt/discussions/new
about: Ask questions, discuss about devices or show things you made
@@ -10,7 +13,7 @@ contact_links:
url: https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/issues
about: Issues related to the Home Assistant addon.
- name: FAQ
url: https://www.zigbee2mqtt.io/information/FAQ.html
url: https://www.zigbee2mqtt.io/guide/faq
about: Frequently asked questions.
- name: Support Chat
url: https://discord.gg/NyseBeK
-20
View File
@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request
assignees: ''
---
## Is your feature request related to a problem? Please describe
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
## Describe the solution you'd like
A clear and concise description of what you want to happen.
## Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
## Additional context
Add any other context or screenshots about the feature request here.
@@ -0,0 +1,38 @@
name: Feature request
description: Suggest an idea for this project
title: "[Feature request]: "
labels: [feature request]
body:
- type: markdown
attributes:
value: |
**IMPORTANT:** Before submitting:
- Is your feature request related to the fronted? Then click [here](https://github.com/nurikk/zigbee2mqtt-frontend/issues/new?assignees=&labels=&template=feature_request.md&title=)
- type: textarea
id: textarea1
attributes:
label: Is your feature request related to a problem? Please describe
placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: textarea2
attributes:
label: Describe the solution you'd like
placeholder: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: textarea3
attributes:
label: Describe alternatives you've considered
placeholder: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: textarea
id: textarea4
attributes:
label: Additional context
placeholder: Add any other context or screenshots about the feature request here.
validations:
required: true
@@ -1,21 +0,0 @@
---
name: New device support request
about: Request support for a new device
title: ''
labels: new device support
assignees: ''
---
<!--
VERY IMPORTANT: Before submitting a request, first (try to) follow: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html
Dumping just the info about this device without actually attemping adding support yourself will likely lead into this issue being ignored.
Clearly indicate what you tried and where you got stuck.
-->
## Information about the device + link
..
## data/database.db entry of the device
..
@@ -0,0 +1,55 @@
name: New device support request
description: Request support for a new device
title: "[New device support]: "
labels: [new device support]
body:
- type: markdown
attributes:
value: |
**IMPORTANT:** Before submitting:
- Make sure this device is not already supported in the [dev branch](https://www.zigbee2mqtt.io/advanced/more/switch-to-dev-branch.html)
- Make sure there is no existing issue or PR for this device already, search for your device here: https://github.com/Koenkk/zigbee2mqtt/issues
- Follow this [guide](https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html)
- If you are using the Home Assistant addon and are still on 1.18.1, check the first point of [this](https://github.com/Koenkk/zigbee2mqtt/releases/tag/1.19.0)
- type: input
id: link
attributes:
label: Link
description: Link of this device (product page)
placeholder: https://www.linktomydevice.org
validations:
required: true
- type: input
id: database
attributes:
label: Database entry
description: Entry of this device in `data/database.db` after pairing it
placeholder: '{"id":53,"type":"Router","ieeeAddr":"0x10458d00024284f69","nwkAddr":10148,"manufId":4151,"manufName":"LUMI","powerSource":"DC Source","modelId":"lumi.relay.c2acn01","epList":[1,2],"endpoints":{"1":{"profId":260,"epId":1,"devId":257,"inClusterList":[0,3,4,5,1,2,10,6,16,2820,12],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"modelId":"lumi.relay.c2acn01","appVersion":1,"manufacturerName":"LUMI","powerSource":4,"zclVersion":0,"stackVersion":2,"hwVersion":18,"dateCode":"8-6-2020"}},"genAnalogInput":{"attributes":{"presentValue":129.04425048828125}},"genOnOff":{"attributes":{"61440":117440715,"onOff":1}}},"binds":[],"configuredReportings":[],"meta":{}},"2":{"profId":260,"epId":2,"devId":257,"inClusterList":[6,16,4,5],"outClusterList":[],"clusters":{"genOnOff":{"attributes":{"61440":237478966,"onOff":0}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":1,"stackVersion":2,"hwVersion":18,"dateCode":"8-6-2020","zclVersion":0,"interviewCompleted":true,"meta":{},"lastSeen":1640285631405}'
validations:
required: true
- type: textarea
id: notes
attributes:
label: Comments
placeholder: I tried to follow the supporting new device page but got stuck at...
validations:
required: true
- type: textarea
attributes:
label: External converter
description: In case you tried to create an external converter, put it below
render: shell
- type: markdown
attributes:
value: |
# Lights
In case this device is a light, fill in the fields below:
- type: input
attributes:
label: Supported color modes
placeholder: color temperature, color (rgb)
- type: input
attributes:
label: Color temperature range
description: In case this light supports color temperature, provide the color temperature range. [How to do this](https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html#_3-1-retrieving-color-temperature-range-only-required-for-lights-which-support-color-temperature).
placeholder: '{"colorTempPhysicalMin":153,"colorTempPhysicalMax":454}'
-54
View File
@@ -1,54 +0,0 @@
---
name: Problem report
about: Create a report to help us improve
title: ''
labels: problem
assignees: ''
---
<!--
Before submitting an issue make sure you've searched for a similar issue and read the documentation: https://www.zigbee2mqtt.io/.
Rules (don't ignore these, your issue will be closed without further notice):
- English only
- Make sure you are on the latest Zigbee2MQTT version
- Provide a clear description of the problem
- DON'T copy logs directly here, post a link to https://hastebin.com/ or https://pastebin.com/.
- Make sure you are running the latest firmware https://github.com/koenkk/z-stack-firmware.
Did you read the FAQ?
- https://www.zigbee2mqtt.io/information/FAQ.html
Zigbee2MQTT fails to start?
- https://www.zigbee2mqtt.io/information/FAQ.html#help-zigbee2mqtt-fails-to-start
Having issues when using a CC2531?
- Make sure the CC2531 is connected through a USB extension cable
- Try the source routing firmware: https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_Home_1.2/bin/source_routing
- With larger networks (30/40+) devices, your CC2531 might not be powerful enough. This will cause weird issues, in this case it's advised to use a more powerful adapter: https://www.zigbee2mqtt.io/information/supported_adapters.html#texas-instruments-cc26x2r1
Unsupported device?
- https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html
Device does not pair or interview fails?
- https://www.zigbee2mqtt.io/information/FAQ.html#why-does-my-device-not-or-fail-to-pair
Bug report?
- If applicable, provide steps how to reproduce the problem.
- Provide the herdsman debug logging: https://www.zigbee2mqtt.io/information/debug.html#zigbee-herdsman-debug-logging
-->
<!--Start your bug report below this line-->
## What happened
## What did you expect to happen
## How to reproduce it (minimal and precise)
## Debug info
Zigbee2MQTT version:
Adapter hardware: CC2531, CC2530, CC26X2R1, CC1352P-2, Conbee II
Adapter firmware version:
@@ -0,0 +1,67 @@
name: Problem report
description: Create a report to help us improve
labels: [problem]
body:
- type: markdown
attributes:
value: |
**IMPORTANT:** Before submitting:
- You read the [FAQ](https://www.zigbee2mqtt.io/guide/faq/)
- Zigbee2MQTT fails to start? Read [this](https://www.zigbee2mqtt.io/guide/installation/20_zigbee2mqtt-fails-to-start.html)
- Make sure the bug also occurs in the [dev branch](https://www.zigbee2mqtt.io/advanced/more/switch-to-dev-branch.html)
- Make sure you are using the [latest firmware](https://www.zigbee2mqtt.io/guide/adapters/#recommended) on your adapter
- The issue has not been [reported already](https://github.com/Koenkk/zigbee2mqtt/issues)
- Is your issue related to the fronted? Then click [here](https://github.com/nurikk/zigbee2mqtt-frontend/issues/new?assignees=&labels=bug%2Ctriage&template=bug_report.yaml&title=%5BBug%5D%3A+)
- If you are using the Home Assistant addon and are still on 1.18.1, check the first point of [this](https://github.com/Koenkk/zigbee2mqtt/releases/tag/1.19.0)
- type: textarea
id: what_happend
attributes:
label: What happened?
validations:
required: true
- type: textarea
id: expect_to_happen
attributes:
label: What did you expect to happen?
placeholder: I expected that ...
validations:
required: false
- type: textarea
id: reproduce
attributes:
label: How to reproduce it (minimal and precise)
placeholder: First do this, than this..
validations:
required: false
- type: input
id: z2m_version
attributes:
label: Zigbee2MQTT version
description: Can be found in the frontend -> settings -> about -> Zigbee2MQTT version. Are you running Zigbee2MQTT 1.18.1? Then read [this](https://github.com/Koenkk/zigbee2mqtt/releases/tag/1.19.0).
placeholder: '1.22.1'
validations:
required: true
- type: input
id: adapter_fwversion
attributes:
label: Adapter firmware version
description: Can be found in the frontend -> settings -> about -> coordinator revision
placeholder: '20211210'
validations:
required: true
- type: input
id: adapter
attributes:
label: Adapter
description: The adapter you are using
placeholder: Electrolama zig-a-zig-ah! (zzh!), Slaesh's CC2652RB stick, ...
validations:
required: true
- type: textarea
id: log
attributes:
label: Debug log
description: After enabling [debug logging](https://www.zigbee2mqtt.io/guide/usage/debug.html) the log can be found under `data/log`. Attach the file below
placeholder: Click here and drag the file into it or click on "Attach files by.." below
validations:
required: false
+64
View File
@@ -0,0 +1,64 @@
name: Wrong device picture/vendor/model/description
description: Use if device is detected as supported and is fully functional but has a wrong picture, vendor, model or description
title: "[Wrong device]: "
labels: [wrong device]
body:
- type: markdown
attributes:
value: |
Only use this if the device is detected as **supported** and is **fully functional** but has a wrong picture, vendor, model or description.
- type: input
id: link
attributes:
label: Link
description: Link of this device (product page)
placeholder: https://www.linktomydevice.org
validations:
required: true
- type: input
id: model
attributes:
label: Model
description: Expected model, model that is printed on the device, for TuYa device this is NOT something like TS0601 or _TZE200_cf1sl3tj
placeholder: RTCGQ01LM
validations:
required: true
- type: input
id: description
attributes:
label: Description
description: Expected description
placeholder: Motion sensor
validations:
required: true
- type: input
id: vendor
attributes:
label: Vendor
description: Expected vendor
placeholder: Xiaomi
validations:
required: true
- type: input
id: picture
attributes:
label: Picture (link)
description: Expected picture
placeholder: https://www.linktomydevice.org/RTCGQ01LM.jpg
validations:
required: true
- type: input
id: database
attributes:
label: Database entry
description: Entry of this device in `data/database.db` after pairing it
placeholder: '{"id":53,"type":"Router","ieeeAddr":"0x10458d00024284f69","nwkAddr":10148,"manufId":4151,"manufName":"LUMI","powerSource":"DC Source","modelId":"lumi.relay.c2acn01","epList":[1,2],"endpoints":{"1":{"profId":260,"epId":1,"devId":257,"inClusterList":[0,3,4,5,1,2,10,6,16,2820,12],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"modelId":"lumi.relay.c2acn01","appVersion":1,"manufacturerName":"LUMI","powerSource":4,"zclVersion":0,"stackVersion":2,"hwVersion":18,"dateCode":"8-6-2020"}},"genAnalogInput":{"attributes":{"presentValue":129.04425048828125}},"genOnOff":{"attributes":{"61440":117440715,"onOff":1}}},"binds":[],"configuredReportings":[],"meta":{}},"2":{"profId":260,"epId":2,"devId":257,"inClusterList":[6,16,4,5],"outClusterList":[],"clusters":{"genOnOff":{"attributes":{"61440":237478966,"onOff":0}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":1,"stackVersion":2,"hwVersion":18,"dateCode":"8-6-2020","zclVersion":0,"interviewCompleted":true,"meta":{},"lastSeen":1640285631405}'
validations:
required: true
- type: textarea
id: notes
attributes:
label: Notes
placeholder: Some additional notes...
validations:
required: false
-1
View File
@@ -1 +0,0 @@
preferredBranch: dev
+13
View File
@@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
target-branch: dev
- package-ecosystem: "docker"
directory: "/docker"
schedule:
interval: "daily"
target-branch: dev
+47 -27
View File
@@ -1,29 +1,25 @@
name: CI
name: ci
on: [push, pull_request]
on: [pull_request, push]
permissions:
contents: write
pull-requests: write
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2-beta
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: 12
node-version: 20
registry-url: https://registry.npmjs.org/
- name: Get NodeJS Version
id: nodeversion
run: |
echo "::set-output name=version::$(node --version)"
- name: Restore node_modules cache
id: cache-node-modules
uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.os }}-${{ steps.nodeversion.outputs.version }}-${{ hashFiles('npm-shrinkwrap.json') }}
cache: npm
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
- name: Build
run: npm run build
- name: Test
run: npm run test-with-coverage
- name: Lint
@@ -33,16 +29,16 @@ jobs:
run: echo ${{ secrets.DOCKER_KEY }} | docker login -u koenkk --password-stdin
- name: Docker login ghcr.io
if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push'
run: echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u koenkk --password-stdin
run: echo ${{ secrets.GH_TOKEN }} | docker login ghcr.io -u koenkk --password-stdin
- name: Docker setup - QEMU
if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push'
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Docker setup - Buildx
if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push'
id: buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
with:
version: latest
- name: Docker build dev
@@ -50,8 +46,9 @@ jobs:
run: |
docker buildx build \
--build-arg COMMIT=$(git rev-parse --short HEAD) \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7 \
--platform linux/arm64/v8,linux/386,linux/amd64,linux/arm/v6,linux/arm/v7 \
-f docker/Dockerfile \
--provenance=false \
--push \
-t koenkk/zigbee2mqtt:latest-dev -t ghcr.io/koenkk/zigbee2mqtt:latest-dev \
.
@@ -61,8 +58,9 @@ jobs:
TAG="$(git describe --tags)"
docker buildx build \
--build-arg COMMIT=$(git rev-parse --short HEAD) \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7 \
--platform linux/arm64/v8,linux/386,linux/amd64,linux/arm/v6,linux/arm/v7 \
-f docker/Dockerfile \
--provenance=false \
--push \
-t koenkk/zigbee2mqtt:latest -t "koenkk/zigbee2mqtt:$TAG" -t ghcr.io/koenkk/zigbee2mqtt:latest -t "ghcr.io/koenkk/zigbee2mqtt:$TAG" \
.
@@ -74,9 +72,31 @@ jobs:
- name: Trigger zigbee2mqtt/hassio-zigbee2mqtt build
if: github.ref == 'refs/heads/dev' && github.event_name == 'push'
run: |
curl -s \
--request POST \
--header "Content-Type: application/json" \
--data '{"definition": {"id": 9}}' \
-u ${{ secrets.HASSIO_TRIGGER_SECRET }} \
"https://dev.azure.com/zigbee2mqtt/Zigbee2mqtt%20Add-on/_apis/build/builds?api-version=5.1"
curl \
-X POST \
-H "Authorization: token ${{ secrets.GH_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/zigbee2mqtt/hassio-zigbee2mqtt/actions/workflows/ci.yml/dispatches \
-d '{"ref":"master","inputs":{}}'
tests:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [16, 18, 20]
runs-on: ${{ matrix.os }}
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
registry-url: https://registry.npmjs.org/
cache: 'npm'
- name: Install dependencies
# --ignore-scripts prevents the serialport build which often fails on Windows
run: npm ci --ignore-scripts
- name: Build
run: npm run build
- name: Test
run: npm run test-with-coverage
-67
View File
@@ -1,67 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master, dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '28 12 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+23
View File
@@ -0,0 +1,23 @@
name: codeql
on:
push:
branches:
- dev
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
+14
View File
@@ -0,0 +1,14 @@
name: deps-review
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout repository'
uses: actions/checkout@v4
- name: 'Dependency review'
uses: actions/dependency-review-action@v3
+34
View File
@@ -0,0 +1,34 @@
on:
workflow_dispatch:
name: ghcr-cleanup
permissions: {}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Delete untagged images
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
const response = await github.request("GET /${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions",
{ per_page: ${{ env.PER_PAGE }}
});
for(version of response.data) {
if (version.metadata.container.tags.length == 0) {
try {
console.log("delete " + version.id)
const deleteResponse = await github.request("DELETE /${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions/" + version.id, { });
console.log("status " + deleteResponse.status)
} catch (e) {
console.log("failed")
}
}
}
env:
OWNER: user
PACKAGE_NAME: zigbee2mqtt
PER_PAGE: 2000
+19
View File
@@ -0,0 +1,19 @@
name: merge-master-to-dev
on:
push:
branches:
- master
jobs:
merge_master_to_dev:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: devmasx/merge-branch@master
with:
type: now
head_to_merge: master
target_branch: dev
message: "chore: merge master to dev"
github_token: ${{ secrets.GH_TOKEN }}
+115
View File
@@ -0,0 +1,115 @@
on:
push:
branches:
- dev
permissions:
contents: write
pull-requests: write
name: release-please
jobs:
release-please:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
version: "${{steps.release.outputs.major}}.${{steps.release.outputs.minor}}.${{steps.release.outputs.patch}}"
steps:
- uses: actions/setup-node@v3
with:
node-version: 20
- uses: google-github-actions/release-please-action@v3
id: release
with:
release-type: node
package-name: release-please-action
default-branch: dev
token: ${{secrets.GH_TOKEN}}
include-v-in-tag: false
skip-github-release: true
# Checkout repos
- uses: actions/checkout@v4
with:
repository: koenkk/zigbee2mqtt
path: ./z2m
- uses: actions/checkout@v4
with:
repository: koenkk/zigbee2mqtt
path: ./z2m-master
ref: master
- name: Restore cache commit-user-lookup.json
uses: actions/cache/restore@v3
with:
path: z2m/scripts/commit-user-lookup.json
key: commit-user-lookup-dummy
restore-keys: |
commit-user-lookup-
- name: Generate changelog
run: |
MASTER_Z2M_VERSION=$(cat z2m-master/package.json | jq -r '.version')
MASTER_ZHC_VERSION=$(cat z2m-master/package.json | jq -r '.dependencies."zigbee-herdsman-converters"')
MASTER_ZH_VERSION=$(cat z2m-master/package.json | jq -r '.dependencies."zigbee-herdsman"')
wget -q -O - https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/release-please--branches--dev--components--release-please-action/CHANGELOG.md > z2m/CHANGELOG.md || true
cd z2m
npm ci
node scripts/generateChangelog.js $MASTER_Z2M_VERSION $MASTER_ZHC_VERSION $MASTER_ZH_VERSION >> ../changelog.md
env:
GH_TOKEN: ${{secrets.GH_TOKEN}}
- name: Update changelog in release PR
run: |
gh gist edit bfd4c3d1725a2cccacc11d6ba51008ba -a changelog.md
env:
GH_TOKEN: ${{secrets.GH_TOKEN}}
- name: Upload changelog
uses: actions/upload-artifact@v3
with:
name: changelog
path: changelog.md
- name: Save cache commit-user-lookup.json
uses: actions/cache/save@v3
if: always()
with:
path: z2m/scripts/commit-user-lookup.json
key: commit-user-lookup-${{ hashFiles('z2m/scripts/commit-user-lookup.json') }}
create_release:
runs-on: ubuntu-latest
needs: [release-please]
if: ${{ needs.release-please.outputs.release_created }}
steps:
- uses: actions/checkout@v4
with:
ref: dev
token: ${{secrets.GH_TOKEN}}
- name: Download changelog
uses: actions/download-artifact@v3
with:
name: changelog
path: ../changelog
- uses: ncipollo/release-action@v1
name: Create release
with:
bodyFile: ../changelog/changelog.md
draft: true
name: ${{ needs.release-please.outputs.version }}
tag: ${{ needs.release-please.outputs.version }}
- name: Merge dev -> master
uses: devmasx/merge-branch@master
with:
type: now
from_branch: dev
target_branch: master
github_token: ${{secrets.GH_TOKEN}}
- name: Promote to dev
run: |
jq '.version = "${{ needs.release-please.outputs.version }}-dev"' package.json > package.json.tmp
jq '.version = "${{ needs.release-please.outputs.version }}-dev"' package-lock.json > package-lock.json.tmp
mv package.json.tmp package.json
mv package-lock.json.tmp package-lock.json
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "chore: promote to dev"
+4 -3
View File
@@ -1,4 +1,5 @@
name: "Close stale issues/pull requests"
name: stale
on:
schedule:
- cron: "0 0 * * *"
@@ -8,12 +9,12 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days'
stale-pr-message: 'This pull request is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days'
days-before-stale: 30
days-before-close: 7
exempt-issue-labels: dont-stale
operations-per-run: 500
exempt-issue-labels: 'breaking change'
+38
View File
@@ -0,0 +1,38 @@
on:
repository_dispatch:
types: update_dep
name: update-dep
permissions: {}
jobs:
update_dep:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: dev
token: ${{ secrets.GH_TOKEN }}
- uses: actions/setup-node@v3
with:
node-version: 20
cache: npm
- run: npm install ${{ github.event.client_payload.package }}@${{ github.event.client_payload.version }} --save-exact
- uses: peter-evans/create-pull-request@v5
id: cpr
with:
commit-message: "fix(ignore): update ${{ github.event.client_payload.package }} to ${{ github.event.client_payload.version }}"
branch: "deps/${{ github.event.client_payload.package }}"
title: Update ${{ github.event.client_payload.package }} to ${{ github.event.client_payload.version }}
token: ${{ secrets.GH_TOKEN }}
- run: sleep 5 # Otherwise pull request may not exist yet causing automerge to fail
- uses: peter-evans/enable-pull-request-automerge@v3
if: steps.cpr.outputs.pull-request-operation == 'created'
with:
token: ${{ secrets.GH_TOKEN }}
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
merge-method: squash
+18 -9
View File
@@ -4,22 +4,31 @@ on:
schedule:
- cron: "0 0 * * 0"
permissions:
contents: read
jobs:
update_deps:
permissions:
contents: write # for peter-evans/create-pull-request to create branch
pull-requests: write # for peter-evans/create-pull-request to create a PR
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
ref: dev
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- uses: actions/setup-node@v2-beta
token: ${{ secrets.GH_TOKEN }}
- uses: actions/setup-node@v3
with:
node-version: 12
node-version: 20
cache: npm
# connect-gzip-static only supports node 16
# @types/ws 8.5.5 is broken
- run: npx npm-check-updates -u -x connect-gzip-static -x @types/ws
- run: npm install
- run: npm ls --depth 0 --prod --parseable | tail -n +2 | grep -v "zigbee" | xargs -I '{}' basename "{}" | xargs -I '{}' npm install '{}'@latest
- run: rm -rf node_modules npm-shrinkwrap.json && npm install && npm shrinkwrap --dev
- uses: peter-evans/create-pull-request@v3
- uses: peter-evans/create-pull-request@v5
with:
commit-message: Update dependencies
branch: "update_deps"
commit-message: "fix(ignore): update dependencies"
branch: "deps/all"
title: Update dependencies
token: ${{ secrets.GH_TOKEN }}
-22
View File
@@ -1,22 +0,0 @@
name: Update zigbee-frontend
on:
repository_dispatch:
types: update_frontend
jobs:
update_frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- uses: actions/setup-node@v2-beta
with:
node-version: 12
- run: npm install zigbee2mqtt-frontend@${{ github.event.client_payload.version }} --save-exact
- uses: peter-evans/create-pull-request@v3
with:
commit-message: Update zigbee2mqtt-frontend to ${{ github.event.client_payload.version }}
branch: "update_frontend"
title: Update zigbee-frontend to ${{ github.event.client_payload.version }}
-22
View File
@@ -1,22 +0,0 @@
name: Update zigbee-herdsman
on:
repository_dispatch:
types: update_zh
jobs:
update_zh:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- uses: actions/setup-node@v2-beta
with:
node-version: 12
- run: npm install zigbee-herdsman@${{ github.event.client_payload.version }} --save-exact
- uses: peter-evans/create-pull-request@v3
with:
commit-message: Update zigbee-herdsman to ${{ github.event.client_payload.version }}
branch: "update_zh"
title: Update zigbee-herdsman to ${{ github.event.client_payload.version }}
-22
View File
@@ -1,22 +0,0 @@
name: Update zigbee-herdsman-converters
on:
repository_dispatch:
types: update_zhc
jobs:
update_zhc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- uses: actions/setup-node@v2-beta
with:
node-version: 12
- run: npm install zigbee-herdsman-converters@${{ github.event.client_payload.version }} --save-exact
- uses: peter-evans/create-pull-request@v3
with:
commit-message: Update zigbee-herdsman-converters to ${{ github.event.client_payload.version }}
branch: "update_zhc"
title: Update zigbee-herdsman-converters to ${{ github.event.client_payload.version }}
+11 -1
View File
@@ -11,6 +11,9 @@ pids
*.seed
*.pid.lock
# Compiled source
dist/*
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
@@ -72,5 +75,12 @@ data/extension
# MacOS indexing file
.DS_Store
# IDE specific folders
.idea
# Ignore config
data/*.yaml
data/*.yaml
!data/configuration.example.yaml
# commit-user-lookup.json
scripts/commit-user-lookup.json
+3
View File
@@ -7,6 +7,7 @@ coverage
.jenkins.yml
.codeclimate.yml
.github
babel.config.js
#linters
.jscsrc
@@ -14,11 +15,13 @@ coverage
.eslintrc*
.dockerignore
.eslintignore
.gitignore
#editor settings
.vscode
#src
lib
docs
docker
images
+4
View File
@@ -0,0 +1,4 @@
{
".": "1.33.1",
"bootstrap-sha": "7ee207fc0e05f32c9636c0298b48eea1b91ed9e1"
}
+195
View File
@@ -0,0 +1,195 @@
# Changelog
## [1.33.1](https://github.com/Koenkk/zigbee2mqtt/compare/1.33.0...1.33.1) (2023-10-03)
### Bug Fixes
* Correct typos ([#19143](https://github.com/Koenkk/zigbee2mqtt/issues/19143)) ([83e3313](https://github.com/Koenkk/zigbee2mqtt/commit/83e331323c19c70f25617fa6baf75e933cd9baf7))
* Fix `configuration.example.yaml` missing from container ([#18836](https://github.com/Koenkk/zigbee2mqtt/issues/18836)) ([0543ad4](https://github.com/Koenkk/zigbee2mqtt/commit/0543ad4b19f2a8e79a12f2b84b94d005acb60396))
* **ignore:** update dependencies ([#18995](https://github.com/Koenkk/zigbee2mqtt/issues/18995)) ([5477163](https://github.com/Koenkk/zigbee2mqtt/commit/5477163727d0ed3399614fbb5c12201b2c098127))
* **ignore:** update dependencies ([#19061](https://github.com/Koenkk/zigbee2mqtt/issues/19061)) ([d99da63](https://github.com/Koenkk/zigbee2mqtt/commit/d99da63b8968c1cb8ae9788317e493f4343dd1a1))
* **ignore:** update dependencies ([#19127](https://github.com/Koenkk/zigbee2mqtt/issues/19127)) ([1c7bb8f](https://github.com/Koenkk/zigbee2mqtt/commit/1c7bb8fc241d7c3232d2088d6a603318d9cf6c01))
* **ignore:** update zigbee-herdsman to 0.18.6 ([#18838](https://github.com/Koenkk/zigbee2mqtt/issues/18838)) ([6654c7f](https://github.com/Koenkk/zigbee2mqtt/commit/6654c7f1a34694590fc575270f80faca32472cca))
* **ignore:** update zigbee-herdsman to 0.18.7 ([#18865](https://github.com/Koenkk/zigbee2mqtt/issues/18865)) ([914b4c6](https://github.com/Koenkk/zigbee2mqtt/commit/914b4c67575b77534af98e9ae76749e331e81ffa))
* **ignore:** update zigbee-herdsman to 0.19.0 ([#18998](https://github.com/Koenkk/zigbee2mqtt/issues/18998)) ([84f9950](https://github.com/Koenkk/zigbee2mqtt/commit/84f99505561501690f8cf15cd9c98bda580d13df))
* **ignore:** update zigbee-herdsman-converters to 15.69.0 ([#18835](https://github.com/Koenkk/zigbee2mqtt/issues/18835)) ([3285850](https://github.com/Koenkk/zigbee2mqtt/commit/3285850efa2080c9bfc71373387d4cf5296bbc5b))
* **ignore:** update zigbee-herdsman-converters to 15.70.0 ([#18866](https://github.com/Koenkk/zigbee2mqtt/issues/18866)) ([91a9e32](https://github.com/Koenkk/zigbee2mqtt/commit/91a9e32a8369fc5c9b919670e4d7564ace3b9371))
* **ignore:** update zigbee-herdsman-converters to 15.71.0 ([#18887](https://github.com/Koenkk/zigbee2mqtt/issues/18887)) ([f509410](https://github.com/Koenkk/zigbee2mqtt/commit/f5094101898d33fc691311a45ec32f6ac85c18cb))
* **ignore:** update zigbee-herdsman-converters to 15.72.0 ([#18901](https://github.com/Koenkk/zigbee2mqtt/issues/18901)) ([ea8de2b](https://github.com/Koenkk/zigbee2mqtt/commit/ea8de2ba1e60abeda455092ee79219ea2d11adcc))
* **ignore:** update zigbee-herdsman-converters to 15.73.0 ([#18917](https://github.com/Koenkk/zigbee2mqtt/issues/18917)) ([d6ed0f4](https://github.com/Koenkk/zigbee2mqtt/commit/d6ed0f45da8a4e2aa0629b89f1a3361f495245e7))
* **ignore:** update zigbee-herdsman-converters to 15.74.0 ([#18949](https://github.com/Koenkk/zigbee2mqtt/issues/18949)) ([6de7662](https://github.com/Koenkk/zigbee2mqtt/commit/6de7662ca80667cbba669ea3a6ccc7bd3e83362b))
* **ignore:** update zigbee-herdsman-converters to 15.75.0 ([#18972](https://github.com/Koenkk/zigbee2mqtt/issues/18972)) ([cc95c85](https://github.com/Koenkk/zigbee2mqtt/commit/cc95c859692b4316f3313ad49f99ad7f8e2b29d3))
* **ignore:** update zigbee-herdsman-converters to 15.76.0 ([#18978](https://github.com/Koenkk/zigbee2mqtt/issues/18978)) ([4040840](https://github.com/Koenkk/zigbee2mqtt/commit/4040840d8e9dc222324be917a281cf29c3bf0da6))
* **ignore:** update zigbee-herdsman-converters to 15.77.0 ([#18984](https://github.com/Koenkk/zigbee2mqtt/issues/18984)) ([0a69bb5](https://github.com/Koenkk/zigbee2mqtt/commit/0a69bb54c8eb7b4bc459a72d15b408e0c6f3d3de))
* **ignore:** update zigbee-herdsman-converters to 15.78.0 ([#18999](https://github.com/Koenkk/zigbee2mqtt/issues/18999)) ([eac9240](https://github.com/Koenkk/zigbee2mqtt/commit/eac9240e0600e91e9fcd71f45e861cb4d90acdef))
* **ignore:** update zigbee-herdsman-converters to 15.80.0 ([#19023](https://github.com/Koenkk/zigbee2mqtt/issues/19023)) ([af209b6](https://github.com/Koenkk/zigbee2mqtt/commit/af209b6f53ebca7032169c689617da169c7b56d4))
* **ignore:** update zigbee-herdsman-converters to 15.81.1 ([#19041](https://github.com/Koenkk/zigbee2mqtt/issues/19041)) ([9a7aeaf](https://github.com/Koenkk/zigbee2mqtt/commit/9a7aeaf62b1d17fe3935ac731029e93ccd7b32d5))
* **ignore:** update zigbee-herdsman-converters to 15.82.0 ([#19067](https://github.com/Koenkk/zigbee2mqtt/issues/19067)) ([1190a34](https://github.com/Koenkk/zigbee2mqtt/commit/1190a342e90194184e76de80fd4264f87a65de94))
* **ignore:** update zigbee-herdsman-converters to 15.83.0 ([#19088](https://github.com/Koenkk/zigbee2mqtt/issues/19088)) ([a7bb3fc](https://github.com/Koenkk/zigbee2mqtt/commit/a7bb3fc9e882d0ffabaea61357db41818bdbbaa3))
* **ignore:** update zigbee-herdsman-converters to 15.84.0 ([#19096](https://github.com/Koenkk/zigbee2mqtt/issues/19096)) ([7ccb4bc](https://github.com/Koenkk/zigbee2mqtt/commit/7ccb4bcafe9837a59285e8cebac4dfda1095ca62))
* **ignore:** update zigbee-herdsman-converters to 15.85.0 ([#19102](https://github.com/Koenkk/zigbee2mqtt/issues/19102)) ([90763fd](https://github.com/Koenkk/zigbee2mqtt/commit/90763fd83f2904be174ab86f74623de1029babca))
* **ignore:** update zigbee-herdsman-converters to 15.86.0 ([#19149](https://github.com/Koenkk/zigbee2mqtt/issues/19149)) ([45ce494](https://github.com/Koenkk/zigbee2mqtt/commit/45ce4949518c7755fba2ac0ded36c54c254c66e1))
* **ignore:** update zigbee-herdsman-converters to 15.86.1 ([#19150](https://github.com/Koenkk/zigbee2mqtt/issues/19150)) ([b990ed9](https://github.com/Koenkk/zigbee2mqtt/commit/b990ed9a60351c5d2782c34b38234cdcddff0f3a))
* **ignore:** update zigbee2mqtt-frontend to 0.6.136 ([#19040](https://github.com/Koenkk/zigbee2mqtt/issues/19040)) ([9b66ab1](https://github.com/Koenkk/zigbee2mqtt/commit/9b66ab1367638c7291c8b4a997c215354915a642))
## [1.33.0](https://github.com/Koenkk/zigbee2mqtt/compare/1.32.2...1.33.0) (2023-09-01)
### Features
* Add Home Assistant origin to discovery ([#18741](https://github.com/Koenkk/zigbee2mqtt/issues/18741)) ([704ecf3](https://github.com/Koenkk/zigbee2mqtt/commit/704ecf366e51ff777e96379acbb89d9c3c416d6d))
* Drop Node.js 14 support ([#18555](https://github.com/Koenkk/zigbee2mqtt/issues/18555)) ([1f52fae](https://github.com/Koenkk/zigbee2mqtt/commit/1f52faee398e720ad64e61b559e04be81b58b979))
* Let Home Assistant generate entity name when device_class is present ([#18208](https://github.com/Koenkk/zigbee2mqtt/issues/18208)) ([df93e4c](https://github.com/Koenkk/zigbee2mqtt/commit/df93e4c8f9490e503e5896e082fc2578f98c2e0e))
* Support coordinator check ([#18599](https://github.com/Koenkk/zigbee2mqtt/issues/18599)) ([3af130a](https://github.com/Koenkk/zigbee2mqtt/commit/3af130a2c056aab74d793a963aceead348f56058))
* Support generating extended_pan_id ([#18596](https://github.com/Koenkk/zigbee2mqtt/issues/18596)) ([aa021d9](https://github.com/Koenkk/zigbee2mqtt/commit/aa021d988db31ef206a9bfa6b5312d631bb3de79))
* Support scene renaming ([#18667](https://github.com/Koenkk/zigbee2mqtt/issues/18667)) ([4b3a2c9](https://github.com/Koenkk/zigbee2mqtt/commit/4b3a2c9f5a74ec25fd82d219a7fc31cddb7c7def))
* Use labels in Home Assistant entity naming ([#18678](https://github.com/Koenkk/zigbee2mqtt/issues/18678)) ([e33e335](https://github.com/Koenkk/zigbee2mqtt/commit/e33e335c0ca92670eee4be672ec53282cc2b79d3))
### Bug Fixes
* Add secure default config ([#18357](https://github.com/Koenkk/zigbee2mqtt/issues/18357)) ([68ec507](https://github.com/Koenkk/zigbee2mqtt/commit/68ec507e30bead5e9263c0fdc4c47e18c257d82f))
* Fix Home Assistant `MQTT device name is equal to entity name in your config ([#18491](https://github.com/Koenkk/zigbee2mqtt/issues/18491)) ([f619610](https://github.com/Koenkk/zigbee2mqtt/commit/f6196107a75f9257366505a3ad5ef7b29ff5bc1c))
* Fix Home Assistant `TypeError: object of type 'NoneType' has no len()` error. https://github.com/Koenkk/zigbee2mqtt/issues/17861 ([ed22ece](https://github.com/Koenkk/zigbee2mqtt/commit/ed22ecedbfd51fc2f5572930aacd37e5b48e04cf))
* Generate pan_id for new installations ([#18530](https://github.com/Koenkk/zigbee2mqtt/issues/18530)) ([cf313c5](https://github.com/Koenkk/zigbee2mqtt/commit/cf313c503b7b070e24739a1f5139e5833405eebc))
* **ignore:** chore: Update dependencies ([#18459](https://github.com/Koenkk/zigbee2mqtt/issues/18459)) ([b55cc0a](https://github.com/Koenkk/zigbee2mqtt/commit/b55cc0a037ccb2c16ac2147ae7e1fb2e4d596806))
* **ignore:** Revert "chore: Update dependencies ([#18459](https://github.com/Koenkk/zigbee2mqtt/issues/18459))" ([b09b8ec](https://github.com/Koenkk/zigbee2mqtt/commit/b09b8ec3d6b30b0bc34c36819e39298ec5a94c63))
* **ignore:** update dependencies ([#18598](https://github.com/Koenkk/zigbee2mqtt/issues/18598)) ([0d00a14](https://github.com/Koenkk/zigbee2mqtt/commit/0d00a144f5c40bf1fce30f9ee65335a6d0076972))
* **ignore:** update dependencies ([#18755](https://github.com/Koenkk/zigbee2mqtt/issues/18755)) ([bc17e64](https://github.com/Koenkk/zigbee2mqtt/commit/bc17e6406bdd4104ba7f1b4c7663a18f82fee35b))
* **ignore:** update zigbee-herdsman to 0.17.3 ([#18556](https://github.com/Koenkk/zigbee2mqtt/issues/18556)) ([a892a1b](https://github.com/Koenkk/zigbee2mqtt/commit/a892a1b898f8cf4fc02c1ec7d9159d426c5ea547))
* **ignore:** update zigbee-herdsman to 0.18.0 ([#18600](https://github.com/Koenkk/zigbee2mqtt/issues/18600)) ([cc0536c](https://github.com/Koenkk/zigbee2mqtt/commit/cc0536c5ab1d5f04b75bf9cd21c4f9579c60dc31))
* **ignore:** update zigbee-herdsman to 0.18.1 ([#18627](https://github.com/Koenkk/zigbee2mqtt/issues/18627)) ([3736b59](https://github.com/Koenkk/zigbee2mqtt/commit/3736b5901b9f497b74a2efa57adb105802ddc153))
* **ignore:** update zigbee-herdsman to 0.18.2 ([#18648](https://github.com/Koenkk/zigbee2mqtt/issues/18648)) ([db812cd](https://github.com/Koenkk/zigbee2mqtt/commit/db812cd72918eb0438129639c9d7a8af86f8fc37))
* **ignore:** update zigbee-herdsman to 0.18.3 ([#18714](https://github.com/Koenkk/zigbee2mqtt/issues/18714)) ([6a1b6a1](https://github.com/Koenkk/zigbee2mqtt/commit/6a1b6a14038290fc9d13008b09da002fd55f540f))
* **ignore:** update zigbee-herdsman to 0.18.4 ([#18727](https://github.com/Koenkk/zigbee2mqtt/issues/18727)) ([1439f4c](https://github.com/Koenkk/zigbee2mqtt/commit/1439f4c6ace962f8b14ec43a8b418ca12a4db27f))
* **ignore:** update zigbee-herdsman to 0.18.5 ([#18816](https://github.com/Koenkk/zigbee2mqtt/issues/18816)) ([68169f0](https://github.com/Koenkk/zigbee2mqtt/commit/68169f0e50290c8c2fa5fba052b4446c9a46d2f1))
* **ignore:** update zigbee-herdsman-converters to 15.51.0 ([#18501](https://github.com/Koenkk/zigbee2mqtt/issues/18501)) ([2d917a7](https://github.com/Koenkk/zigbee2mqtt/commit/2d917a7d0db1fc4d89ba163d63e2d2932d0655fe))
* **ignore:** update zigbee-herdsman-converters to 15.52.0 ([#18514](https://github.com/Koenkk/zigbee2mqtt/issues/18514)) ([0718ca1](https://github.com/Koenkk/zigbee2mqtt/commit/0718ca162dcf6ab41f192e4dd8ecc83b38e25410))
* **ignore:** update zigbee-herdsman-converters to 15.53.0 ([#18524](https://github.com/Koenkk/zigbee2mqtt/issues/18524)) ([f08cd81](https://github.com/Koenkk/zigbee2mqtt/commit/f08cd81ac0ad4436883acf39947e7254002ef9fe))
* **ignore:** update zigbee-herdsman-converters to 15.54.0 ([#18527](https://github.com/Koenkk/zigbee2mqtt/issues/18527)) ([abba8b3](https://github.com/Koenkk/zigbee2mqtt/commit/abba8b3ba8c31c2b9057f74e455824045082a4ec))
* **ignore:** update zigbee-herdsman-converters to 15.54.1 ([#18537](https://github.com/Koenkk/zigbee2mqtt/issues/18537)) ([b5e9ed4](https://github.com/Koenkk/zigbee2mqtt/commit/b5e9ed436cd3a8e5b8183fe44685d2f41422b2fd))
* **ignore:** update zigbee-herdsman-converters to 15.55.0 ([#18547](https://github.com/Koenkk/zigbee2mqtt/issues/18547)) ([6050428](https://github.com/Koenkk/zigbee2mqtt/commit/60504285663e346c2078819c6445905fb2aaff1c))
* **ignore:** update zigbee-herdsman-converters to 15.55.1 ([#18557](https://github.com/Koenkk/zigbee2mqtt/issues/18557)) ([7f05f31](https://github.com/Koenkk/zigbee2mqtt/commit/7f05f31c72cfd394cbe0d8e20de5c9f5d245db85))
* **ignore:** update zigbee-herdsman-converters to 15.55.2 ([#18566](https://github.com/Koenkk/zigbee2mqtt/issues/18566)) ([8675b1c](https://github.com/Koenkk/zigbee2mqtt/commit/8675b1c9ed405d7abe42f6725c0627968c533f4b))
* **ignore:** update zigbee-herdsman-converters to 15.55.3 ([#18578](https://github.com/Koenkk/zigbee2mqtt/issues/18578)) ([b1796e3](https://github.com/Koenkk/zigbee2mqtt/commit/b1796e3e1a1d58c79dda39a8041ce67ceea133a4))
* **ignore:** update zigbee-herdsman-converters to 15.57.0 ([#18616](https://github.com/Koenkk/zigbee2mqtt/issues/18616)) ([145bc05](https://github.com/Koenkk/zigbee2mqtt/commit/145bc05dc30d952e919035a7b741f91ee98a8997))
* **ignore:** update zigbee-herdsman-converters to 15.58.1 ([#18658](https://github.com/Koenkk/zigbee2mqtt/issues/18658)) ([dcbf4e5](https://github.com/Koenkk/zigbee2mqtt/commit/dcbf4e5b0e75d0e50688434079588fe179406520))
* **ignore:** update zigbee-herdsman-converters to 15.59.0 ([#18661](https://github.com/Koenkk/zigbee2mqtt/issues/18661)) ([7185d9e](https://github.com/Koenkk/zigbee2mqtt/commit/7185d9e5013888f8276e74849c7463560c46f369))
* **ignore:** update zigbee-herdsman-converters to 15.60.0 ([#18672](https://github.com/Koenkk/zigbee2mqtt/issues/18672)) ([71c4211](https://github.com/Koenkk/zigbee2mqtt/commit/71c4211d13df29aefb217a030c5e114c7a666112))
* **ignore:** update zigbee-herdsman-converters to 15.62.0 ([#18742](https://github.com/Koenkk/zigbee2mqtt/issues/18742)) ([514d9f3](https://github.com/Koenkk/zigbee2mqtt/commit/514d9f38b2a7a46fe766dd422f540350bbbe0f5e))
* **ignore:** update zigbee-herdsman-converters to 15.63.0 ([#18758](https://github.com/Koenkk/zigbee2mqtt/issues/18758)) ([b193d89](https://github.com/Koenkk/zigbee2mqtt/commit/b193d8904299a0c5673da3b9185200ef6a3ed368))
* **ignore:** update zigbee-herdsman-converters to 15.64.0 ([#18784](https://github.com/Koenkk/zigbee2mqtt/issues/18784)) ([5084b12](https://github.com/Koenkk/zigbee2mqtt/commit/5084b1293e2ea857b363837eabf7ca0087f2607c))
* **ignore:** update zigbee-herdsman-converters to 15.66.1 ([#18790](https://github.com/Koenkk/zigbee2mqtt/issues/18790)) ([0ec68a4](https://github.com/Koenkk/zigbee2mqtt/commit/0ec68a4b71208fe42ea011e0084c8af0b187a261))
* **ignore:** update zigbee-herdsman-converters to 15.67.0 ([#18815](https://github.com/Koenkk/zigbee2mqtt/issues/18815)) ([97f6a84](https://github.com/Koenkk/zigbee2mqtt/commit/97f6a840e47612e98f20ba355dae7fb3dfd0868c))
* **ignore:** update zigbee-herdsman-converters to 15.67.1 ([#18817](https://github.com/Koenkk/zigbee2mqtt/issues/18817)) ([e78aa35](https://github.com/Koenkk/zigbee2mqtt/commit/e78aa3589b4c468716917f9f734f03801f86c3cd))
* **ignore:** update zigbee2mqtt-frontend to 0.6.134 ([#18761](https://github.com/Koenkk/zigbee2mqtt/issues/18761)) ([4949a54](https://github.com/Koenkk/zigbee2mqtt/commit/4949a54d664083f6152bafa78c5468f9a2c50f2b))
* **ignore:** update zigbee2mqtt-frontend to 0.6.135 ([#18814](https://github.com/Koenkk/zigbee2mqtt/issues/18814)) ([9a6445a](https://github.com/Koenkk/zigbee2mqtt/commit/9a6445a8a024c8b415caa9cd08e48df12a46e83b))
* Use QOS1 for rarely sent discovery and availability messages ([#18756](https://github.com/Koenkk/zigbee2mqtt/issues/18756)) ([d1e50ce](https://github.com/Koenkk/zigbee2mqtt/commit/d1e50ce534b906f426b28f2aaf8b0a51a97de264))
## [1.32.2](https://github.com/Koenkk/zigbee2mqtt/compare/1.32.1...1.32.2) (2023-08-01)
### Bug Fixes
* Fix `'dict object' has no attribute 'ir_code_to_send'` error. https://github.com/Koenkk/zigbee2mqtt/issues/18180 ([dec9191](https://github.com/Koenkk/zigbee2mqtt/commit/dec91919bc50aed1f1d3fd9525abd2db49242e7f))
* Fix insecure Zigbee network encryption key generation ([#18372](https://github.com/Koenkk/zigbee2mqtt/issues/18372)) ([df8e168](https://github.com/Koenkk/zigbee2mqtt/commit/df8e1687b2db3f49ba8c3d97a4c92b7892a54f1e))
* Fix not all cluster unbound/bound when specified. https://github.com/Koenkk/zigbee2mqtt/issues/10740 ([0bdf663](https://github.com/Koenkk/zigbee2mqtt/commit/0bdf663ca126d0569b62871e1b787992472faea4))
* Fix socket error crashing Zigbee2MQTT ([#18388](https://github.com/Koenkk/zigbee2mqtt/issues/18388)) ([f64cd7e](https://github.com/Koenkk/zigbee2mqtt/commit/f64cd7e8f38f0c1fc1bbd85b5b5caf560565c024))
* **ignore:** Add ep `l` till 24 ([#18422](https://github.com/Koenkk/zigbee2mqtt/issues/18422)) ([4bd281c](https://github.com/Koenkk/zigbee2mqtt/commit/4bd281ce6cbd43f38b2a3131cd38b25885a22b3a))
* **ignore:** Add th1-th10 endpoints for Ubisys H10 ([#18405](https://github.com/Koenkk/zigbee2mqtt/issues/18405)) ([91f22f1](https://github.com/Koenkk/zigbee2mqtt/commit/91f22f1230241f5fb3b27b2ee84d944a1c3c5107))
* **ignore:** Attempt 2 to fix cache saving ([ea412cf](https://github.com/Koenkk/zigbee2mqtt/commit/ea412cfe82a0462930ec8dddf00b9a363c484b73))
* **ignore:** Attempt 3 to fix commit-user-lookup ([590564c](https://github.com/Koenkk/zigbee2mqtt/commit/590564c15888f73826f20eca91e2c253c7d000e7))
* **ignore:** Attempt to fix cache not saving ([fa02bb5](https://github.com/Koenkk/zigbee2mqtt/commit/fa02bb5b74216db78b23db144c915d00c7dc48c1))
* **ignore:** fix commit-user-lookup cache ([758b814](https://github.com/Koenkk/zigbee2mqtt/commit/758b8144a19ca04eac5faae5b7e16c090e9fda77))
* **ignore:** Fix failing test ([ba0cc61](https://github.com/Koenkk/zigbee2mqtt/commit/ba0cc6196550b3b6873f3733690daef9002c5863))
* **ignore:** update dependencies ([#18260](https://github.com/Koenkk/zigbee2mqtt/issues/18260)) ([ee1a5f0](https://github.com/Koenkk/zigbee2mqtt/commit/ee1a5f04008beaac54fb68e20c31c1664563a4f2))
* **ignore:** update dependencies ([#18403](https://github.com/Koenkk/zigbee2mqtt/issues/18403)) ([8e94662](https://github.com/Koenkk/zigbee2mqtt/commit/8e946623a9db6282a53b55d5d5f3e4b000d080ee))
* **ignore:** update zigbee-herdsman to 0.17.2 ([#18291](https://github.com/Koenkk/zigbee2mqtt/issues/18291)) ([073989c](https://github.com/Koenkk/zigbee2mqtt/commit/073989c7a434c3fd73abaee95fa4ada9394d695d))
* **ignore:** update zigbee-herdsman-converters to 15.38.0 ([#18262](https://github.com/Koenkk/zigbee2mqtt/issues/18262)) ([813dd49](https://github.com/Koenkk/zigbee2mqtt/commit/813dd49a41e7d3f41b6c79db708bb08d29cd7f0c))
* **ignore:** update zigbee-herdsman-converters to 15.39.0 ([#18282](https://github.com/Koenkk/zigbee2mqtt/issues/18282)) ([3c855d2](https://github.com/Koenkk/zigbee2mqtt/commit/3c855d20424761d43ace9b5ed55460eedce092f0))
* **ignore:** update zigbee-herdsman-converters to 15.39.1 ([#18292](https://github.com/Koenkk/zigbee2mqtt/issues/18292)) ([a3c8e1c](https://github.com/Koenkk/zigbee2mqtt/commit/a3c8e1c3c98bd97ef52c29929dc9bb5f9598d0fd))
* **ignore:** update zigbee-herdsman-converters to 15.40.0 ([#18314](https://github.com/Koenkk/zigbee2mqtt/issues/18314)) ([af0521b](https://github.com/Koenkk/zigbee2mqtt/commit/af0521b54ca9195e62d68ccd9fcb49d0d0c226e4))
* **ignore:** update zigbee-herdsman-converters to 15.41.0 ([#18328](https://github.com/Koenkk/zigbee2mqtt/issues/18328)) ([330a913](https://github.com/Koenkk/zigbee2mqtt/commit/330a913e76b556295f57290743670a40e48139ca))
* **ignore:** update zigbee-herdsman-converters to 15.42.0 ([#18343](https://github.com/Koenkk/zigbee2mqtt/issues/18343)) ([313865b](https://github.com/Koenkk/zigbee2mqtt/commit/313865b0a38754df52ef2f28132053a47379cc43))
* **ignore:** update zigbee-herdsman-converters to 15.43.0 ([#18356](https://github.com/Koenkk/zigbee2mqtt/issues/18356)) ([7a22cee](https://github.com/Koenkk/zigbee2mqtt/commit/7a22cee639bf9115c6782302900b89f4978468d9))
* **ignore:** update zigbee-herdsman-converters to 15.44.0 ([#18365](https://github.com/Koenkk/zigbee2mqtt/issues/18365)) ([3408e3c](https://github.com/Koenkk/zigbee2mqtt/commit/3408e3c05a102d32818260c0368a47c9726aa40d))
* **ignore:** update zigbee-herdsman-converters to 15.45.0 ([#18404](https://github.com/Koenkk/zigbee2mqtt/issues/18404)) ([57d031d](https://github.com/Koenkk/zigbee2mqtt/commit/57d031d54aadaf87513d2c7d32f3302db501be67))
* **ignore:** update zigbee-herdsman-converters to 15.46.0 ([#18421](https://github.com/Koenkk/zigbee2mqtt/issues/18421)) ([ced3d43](https://github.com/Koenkk/zigbee2mqtt/commit/ced3d43dad5f8a578f1875ffaf68ffb1d177c584))
* **ignore:** update zigbee-herdsman-converters to 15.47.0 ([#18430](https://github.com/Koenkk/zigbee2mqtt/issues/18430)) ([087b85c](https://github.com/Koenkk/zigbee2mqtt/commit/087b85cb9f3bc7a317dc22483461de32a9c1a0d8))
* **ignore:** update zigbee-herdsman-converters to 15.48.0 ([#18438](https://github.com/Koenkk/zigbee2mqtt/issues/18438)) ([d487f37](https://github.com/Koenkk/zigbee2mqtt/commit/d487f37a7a755e37caf3a8da4f8190981fdb5625))
* **ignore:** update zigbee-herdsman-converters to 15.49.0 ([#18443](https://github.com/Koenkk/zigbee2mqtt/issues/18443)) ([8139d7f](https://github.com/Koenkk/zigbee2mqtt/commit/8139d7f1f494b4051c1bba7ea453e76e4be77fad))
* **ignore:** update zigbee-herdsman-converters to 15.50.0 ([#18475](https://github.com/Koenkk/zigbee2mqtt/issues/18475)) ([3478e40](https://github.com/Koenkk/zigbee2mqtt/commit/3478e4001760541b65d9bfdbdcd1d082a3da8023))
* **ignore:** update zigbee-herdsman-converters to 15.50.1 ([#18487](https://github.com/Koenkk/zigbee2mqtt/issues/18487)) ([683d29f](https://github.com/Koenkk/zigbee2mqtt/commit/683d29f9f70f3149cbbff6b543d53af0f931e706))
* **ignore:** update zigbee2mqtt-frontend to 0.6.132 ([#18289](https://github.com/Koenkk/zigbee2mqtt/issues/18289)) ([05eff95](https://github.com/Koenkk/zigbee2mqtt/commit/05eff957eb3c5414df7bf2909b5b6d9ff6fdb258))
* **ignore:** update zigbee2mqtt-frontend to 0.6.133 ([#18390](https://github.com/Koenkk/zigbee2mqtt/issues/18390)) ([e1d52ae](https://github.com/Koenkk/zigbee2mqtt/commit/e1d52ae43aa132f296d151eced7d208cfb1b3a62))
* Use HA sensor device class `atmospheric_pressure` instead of `pressure` ([#18306](https://github.com/Koenkk/zigbee2mqtt/issues/18306)) ([1252f10](https://github.com/Koenkk/zigbee2mqtt/commit/1252f10d39beed640370410a45d5c2fdc504b440))
## [1.32.1](https://github.com/Koenkk/zigbee2mqtt/compare/1.32.0...1.32.1) (2023-07-08)
### Bug Fixes
* **ignore:** update zigbee-herdsman-converters to 15.33.1-hotfix.0 ([15601d6](https://github.com/Koenkk/zigbee2mqtt/commit/15601d6339cfc7408872a71071a98abadd9b33ff))
## [1.32.0](https://github.com/Koenkk/zigbee2mqtt/compare/1.31.2...1.32.0) (2023-07-01)
### Features
* Support Home Assistant water device_class ([#18066](https://github.com/Koenkk/zigbee2mqtt/issues/18066)) ([e083a6b](https://github.com/Koenkk/zigbee2mqtt/commit/e083a6bff7fafd17d5ff6ad4b87916b83727d8be))
* Support settable Home Assistant text ([#18114](https://github.com/Koenkk/zigbee2mqtt/issues/18114)) ([9474452](https://github.com/Koenkk/zigbee2mqtt/commit/94744525ba466c6512ab6a6181b3073970a02023))
### Bug Fixes
* Fix Home Assistant truncate error when `program` is `null`. https://github.com/Koenkk/zigbee2mqtt/issues/16460 ([11f0be5](https://github.com/Koenkk/zigbee2mqtt/commit/11f0be55d871363cb4c07adbbeac57fb4ddf479e))
* **ignore:** Better fix for [#17891](https://github.com/Koenkk/zigbee2mqtt/issues/17891) ([#17951](https://github.com/Koenkk/zigbee2mqtt/issues/17951)) ([a7e02a7](https://github.com/Koenkk/zigbee2mqtt/commit/a7e02a7be847418df463095b68951c1a1459ca83))
* **ignore:** Fix DeviceMessage.meta type ([8833947](https://github.com/Koenkk/zigbee2mqtt/commit/88339473ce7eb09add8f1836ab4c33b4a405d7e7))
* **ignore:** Fix e10dd893ab2875e5420952b4452bf75aeec93922 ([446dbbf](https://github.com/Koenkk/zigbee2mqtt/commit/446dbbf1fc0e07c61cd233c8b4ea509ce6423c86))
* **ignore:** update dependencies ([#17991](https://github.com/Koenkk/zigbee2mqtt/issues/17991)) ([e10dd89](https://github.com/Koenkk/zigbee2mqtt/commit/e10dd893ab2875e5420952b4452bf75aeec93922))
* **ignore:** update dependencies ([#18052](https://github.com/Koenkk/zigbee2mqtt/issues/18052)) ([1dc0b24](https://github.com/Koenkk/zigbee2mqtt/commit/1dc0b24e9a8ae9a03809aff5d3ff9758b63d9f22))
* **ignore:** update dependencies ([#18112](https://github.com/Koenkk/zigbee2mqtt/issues/18112)) ([57566c7](https://github.com/Koenkk/zigbee2mqtt/commit/57566c76ed8ccaabcdc32f84a7fddcf5da3b02b3))
* **ignore:** update zigbee-herdsman to 0.15.0 ([#17966](https://github.com/Koenkk/zigbee2mqtt/issues/17966)) ([05cab61](https://github.com/Koenkk/zigbee2mqtt/commit/05cab61e1faa15a9a72d87f8e9ec26e3d1eb4046))
* **ignore:** update zigbee-herdsman to 0.15.1 ([#18080](https://github.com/Koenkk/zigbee2mqtt/issues/18080)) ([17cff2a](https://github.com/Koenkk/zigbee2mqtt/commit/17cff2a26f16207bd30bb2659e11ce792d02dd75))
* **ignore:** update zigbee-herdsman to 0.15.2 ([#18091](https://github.com/Koenkk/zigbee2mqtt/issues/18091)) ([03005b3](https://github.com/Koenkk/zigbee2mqtt/commit/03005b38c86f79384e20bb240a8947ce969411c6))
* **ignore:** update zigbee-herdsman to 0.15.3 ([#18116](https://github.com/Koenkk/zigbee2mqtt/issues/18116)) ([2d62027](https://github.com/Koenkk/zigbee2mqtt/commit/2d62027e24ea2de401155e0bc7fabaee85fa7bab))
* **ignore:** update zigbee-herdsman to 0.16.0 ([#18124](https://github.com/Koenkk/zigbee2mqtt/issues/18124)) ([38c2ea5](https://github.com/Koenkk/zigbee2mqtt/commit/38c2ea5bf72f67f29b89dc84524e91923989fd27))
* **ignore:** update zigbee-herdsman-converters to 15.20.0 ([#17954](https://github.com/Koenkk/zigbee2mqtt/issues/17954)) ([0c7e7e5](https://github.com/Koenkk/zigbee2mqtt/commit/0c7e7e5089d1023150f23123df7eab90ea65fe59))
* **ignore:** update zigbee-herdsman-converters to 15.22.0 ([#18004](https://github.com/Koenkk/zigbee2mqtt/issues/18004)) ([b0b3aee](https://github.com/Koenkk/zigbee2mqtt/commit/b0b3aee6483efe9fbb2f434c44ed76d6b3a4e54a))
* **ignore:** update zigbee-herdsman-converters to 15.23.0 ([#18015](https://github.com/Koenkk/zigbee2mqtt/issues/18015)) ([4ad838c](https://github.com/Koenkk/zigbee2mqtt/commit/4ad838c114edc7dd5d9d104df9b2ce49933a8c20))
* **ignore:** update zigbee-herdsman-converters to 15.24.0 ([#18025](https://github.com/Koenkk/zigbee2mqtt/issues/18025)) ([c47f5df](https://github.com/Koenkk/zigbee2mqtt/commit/c47f5df021478e8997f13f06ea17591b745615e3))
* **ignore:** update zigbee-herdsman-converters to 15.25.0 ([#18056](https://github.com/Koenkk/zigbee2mqtt/issues/18056)) ([57aaa5a](https://github.com/Koenkk/zigbee2mqtt/commit/57aaa5a85aff308d4bd66353fd42969eb38a60d4))
* **ignore:** update zigbee-herdsman-converters to 15.26.0 ([#18067](https://github.com/Koenkk/zigbee2mqtt/issues/18067)) ([91d67a0](https://github.com/Koenkk/zigbee2mqtt/commit/91d67a0ef5135e08ac81171b78931b7903efcc5a))
* **ignore:** update zigbee-herdsman-converters to 15.27.0 ([#18075](https://github.com/Koenkk/zigbee2mqtt/issues/18075)) ([5777d76](https://github.com/Koenkk/zigbee2mqtt/commit/5777d76e5508d7dba4750aa5efc34977ba01de1a))
* **ignore:** update zigbee-herdsman-converters to 15.28.0 ([#18092](https://github.com/Koenkk/zigbee2mqtt/issues/18092)) ([6d3389b](https://github.com/Koenkk/zigbee2mqtt/commit/6d3389b409b003740ac4b2b90aa39a8ccbec26e3))
* **ignore:** update zigbee-herdsman-converters to 15.29.0 ([#18099](https://github.com/Koenkk/zigbee2mqtt/issues/18099)) ([a744838](https://github.com/Koenkk/zigbee2mqtt/commit/a744838e9c982461479f0b5273e25abd32c4074d))
* **ignore:** update zigbee-herdsman-converters to 15.30.0 ([#18115](https://github.com/Koenkk/zigbee2mqtt/issues/18115)) ([a56719d](https://github.com/Koenkk/zigbee2mqtt/commit/a56719d19ca32fabf375e293cdef0172826c8672))
* **ignore:** update zigbee-herdsman-converters to 15.31.0 ([#18125](https://github.com/Koenkk/zigbee2mqtt/issues/18125)) ([ed85367](https://github.com/Koenkk/zigbee2mqtt/commit/ed85367e5383b9a59a69fe2836b02763f6744849))
* **ignore:** update zigbee-herdsman-converters to 15.32.0 ([#18132](https://github.com/Koenkk/zigbee2mqtt/issues/18132)) ([61dd1dd](https://github.com/Koenkk/zigbee2mqtt/commit/61dd1dd96dc9154f2b46a635bf2ccaeac2d69ba5))
* **ignore:** update zigbee-herdsman-converters to 15.33.0 ([#18156](https://github.com/Koenkk/zigbee2mqtt/issues/18156)) ([81973c3](https://github.com/Koenkk/zigbee2mqtt/commit/81973c3a2a356c52859d167d3eedaf78f747b8e5))
* **ignore:** update zigbee-herdsman-converters to 15.33.1 ([#18161](https://github.com/Koenkk/zigbee2mqtt/issues/18161)) ([d1824f1](https://github.com/Koenkk/zigbee2mqtt/commit/d1824f169b71e0590dce14d7f451dbbb67bdf5d9))
## [1.31.0](https://github.com/Koenkk/zigbee2mqtt/compare/1.30.4...v1.31.0) (2023-06-01)
### Features
* **ignore:** update CI/CD ([b3de973](https://github.com/Koenkk/zigbee2mqtt/commit/b3de973af66e7c308987adeaab4d89759d4bfef0))
* **ignore:** update CI/CD ([0d17d26](https://github.com/Koenkk/zigbee2mqtt/commit/0d17d2613357db225f224bdbf191fbd9ad17b4a5))
* **ignore:** update zigbee-herdsman-converters to 15.6.0 ([#17774](https://github.com/Koenkk/zigbee2mqtt/issues/17774)) ([24baed3](https://github.com/Koenkk/zigbee2mqtt/commit/24baed3053d91276369d0cad02e96afee97329f8))
* **ignore:** update zigbee-herdsman-converters to 15.7.0 ([#17777](https://github.com/Koenkk/zigbee2mqtt/issues/17777)) ([1344ae0](https://github.com/Koenkk/zigbee2mqtt/commit/1344ae06163f5b6a3c68e532f39b379158040c6f))
### Bug Fixes
* Fix Home Assistant `Payload is not supported (e.g. open, closed, opening, closing, stopped): STOP` error. https://github.com/Koenkk/zigbee2mqtt/issues/17552 ([e6f9aed](https://github.com/Koenkk/zigbee2mqtt/commit/e6f9aeda06ec96c76c3d455bb016a10073d0bf54))
* **ignore:** Fix build ([#17838](https://github.com/Koenkk/zigbee2mqtt/issues/17838)) ([d119f60](https://github.com/Koenkk/zigbee2mqtt/commit/d119f609de683313335fbb37e2ce358a16fdc597))
* **ignore:** update dependencies ([#17811](https://github.com/Koenkk/zigbee2mqtt/issues/17811)) ([a71857c](https://github.com/Koenkk/zigbee2mqtt/commit/a71857c7236c66da577352160de96eacc683c7c3))
* **ignore:** update zigbee-herdsman to 0.14.117 ([#17770](https://github.com/Koenkk/zigbee2mqtt/issues/17770)) ([8457c37](https://github.com/Koenkk/zigbee2mqtt/commit/8457c3735b2f2c9c5106ce76fc7d2988f9eb1ea1))
* **ignore:** update zigbee-herdsman-converters to 15.10.0 ([#17797](https://github.com/Koenkk/zigbee2mqtt/issues/17797)) ([b7b3b51](https://github.com/Koenkk/zigbee2mqtt/commit/b7b3b51cfeb9b672f2cca128733b273f50966e19))
* **ignore:** update zigbee-herdsman-converters to 15.11.0 ([#17808](https://github.com/Koenkk/zigbee2mqtt/issues/17808)) ([2e8dfbb](https://github.com/Koenkk/zigbee2mqtt/commit/2e8dfbb96ecbebece84cc1aab12899162e27f82e))
* **ignore:** update zigbee-herdsman-converters to 15.12.0 ([#17837](https://github.com/Koenkk/zigbee2mqtt/issues/17837)) ([be82b73](https://github.com/Koenkk/zigbee2mqtt/commit/be82b737be5f7a7e58d653628ce66e0813fad111))
* **ignore:** update zigbee-herdsman-converters to 15.13.0 ([#17842](https://github.com/Koenkk/zigbee2mqtt/issues/17842)) ([b228d9d](https://github.com/Koenkk/zigbee2mqtt/commit/b228d9daf64c8d315803120814dc31272ee1c459))
* **ignore:** update zigbee-herdsman-converters to 15.13.1 ([#17851](https://github.com/Koenkk/zigbee2mqtt/issues/17851)) ([4b20dfa](https://github.com/Koenkk/zigbee2mqtt/commit/4b20dfafab6193f328aa9133d2b063284abf6cbf))
* **ignore:** update zigbee-herdsman-converters to 15.8.2 ([#17789](https://github.com/Koenkk/zigbee2mqtt/issues/17789)) ([8b579b6](https://github.com/Koenkk/zigbee2mqtt/commit/8b579b6533876f3b7440dc74b2b709cbfc7ccaf3))
* **ignore:** update zigbee-herdsman-converters to 15.9.0 ([#17791](https://github.com/Koenkk/zigbee2mqtt/issues/17791)) ([5b807c3](https://github.com/Koenkk/zigbee2mqtt/commit/5b807c36eced55e790a8393667e07680736f37be))
+4 -4
View File
@@ -1,8 +1,8 @@
# Contributing to Zigbee2MQTT
Everybody is invited and welcome to contribute to Zigbee2MQTT. Zigbee2MQTT is writen in JavaScript and is based upon [zigbee-herdsman](https://github.com/koenkk/zigbee-herdsman) and [zigbee-herdsman-converters](https://github.com/koenkk/zigbee-herdsman-converters). Zigbee-herdsman-converters contains all device definition, zigbee-herdsman is responsible for handling all communication with the adapter.
Everybody is invited and welcome to contribute to Zigbee2MQTT. Zigbee2MQTT is written in JavaScript and is based upon [zigbee-herdsman](https://github.com/koenkk/zigbee-herdsman) and [zigbee-herdsman-converters](https://github.com/koenkk/zigbee-herdsman-converters). Zigbee-herdsman-converters contains all device definitions, zigbee-herdsman is responsible for handling all communication with the adapter.
- Pull requests are always created against the [**dev**](https://github.com/Koenkk/zigbee2mqtt/tree/dev) branch.
- Easiest way to start developing Zigbee2MQTT is by setting up a development environment (aka bare-metal installation). You can follow this [guide](https://www.zigbee2mqtt.io/getting_started/running_zigbee2mqtt.html#running-zigbee2mqtt) to do this.
- You can run the tests locally by executing `npm test`. Zigbee2MQTT enforces 100% code coverage, in case you add new code check if you code is covered by running `npm run test-with-coverage`. The coverage report can be found under `coverage/lcov-report/index.html`. Linting is also enforced and can be run with `npm run eslint`.
- When you want to add support for a new devices no changes to Zigbee2MQTT have to be made, only to zigbee-herdsman-converters. You can find a guide for it [here](https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html).
- Easiest way to start developing Zigbee2MQTT is by setting up a development environment (aka bare-metal installation). You can follow this [guide](https://www.zigbee2mqtt.io/guide/installation/01_linux.html) to do this.
- You can run the tests locally by executing `npm test`. Zigbee2MQTT enforces 100% code coverage, in case you add new code check if your code is covered by running `npm run test-with-coverage`. The coverage report can be found under `coverage/lcov-report/index.html`. Linting is also enforced and can be run with `npm run eslint`.
- When you want to add support for a new device no changes to Zigbee2MQTT have to be made, only to zigbee-herdsman-converters. You can find a guide for it [here](https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html).
+36 -9
View File
@@ -35,26 +35,36 @@
</div>
<h1>Zigbee2MQTT 🌉 🐝</h1>
<p>
Allows you to use your Zigbee devices <b>without</b> the vendors bridge or gateway.
Allows you to use your Zigbee devices <b>without</b> the vendor's bridge or gateway.
</p>
<p>
It bridges events and allows you to control your Zigbee devices via MQTT. In this way you can integrate your Zigbee devices with whatever smart home infrastructure you are using.
</p>
</div>
## [Getting started](https://www.zigbee2mqtt.io/#getting-started)
## [Getting started](https://www.zigbee2mqtt.io/guide/getting-started)
The [documentation](https://www.zigbee2mqtt.io/) provides you all the information needed to get up and running! Make sure you don't skip sections if this is your first visit, as there might be important details in there for you.
If you aren't familiar with **Zigbee** terminology make sure you [read this](https://www.zigbee2mqtt.io/information/zigbee_network.html) to help you out.
If you aren't familiar with **Zigbee** terminology make sure you [read this](https://www.zigbee2mqtt.io/advanced/zigbee/01_zigbee_network.html) to help you out.
## [Integrations](https://www.zigbee2mqtt.io/#integration)
## [Integrations](https://www.zigbee2mqtt.io/guide/usage/integrations.html)
Zigbee2MQTT integrates well with (almost) every home automation solution because it uses MQTT. However the following integrations are worth mentioning:
<img align="left" height="100px" width="100px" src="https://user-images.githubusercontent.com/7738048/40914297-49e6e560-6800-11e8-8904-36cce896e5a8.png">
### [Home Assistant](https://www.home-assistant.io/)
- [Home Assistant](https://www.home-assistant.io/hassio/): Using [the official addon](https://github.com/zigbee2mqtt/hassio-zigbee2mqtt)
- Generic install or Hassbian: Using instructions [here](https://www.zigbee2mqtt.io/integration/home_assistant.html)
- [Home Assistant OS](https://www.home-assistant.io/installation/): Using [the official addon](https://github.com/zigbee2mqtt/hassio-zigbee2mqtt)
- Other installation: using instructions [here](https://www.zigbee2mqtt.io/guide/usage/integrations/home_assistant.html)
<br>
<img align="left" height="100px" width="100px" src="https://etc.athom.com/logo/white/256.png">
### [Homey](https://homey.app/)
- Integration implemented in the [Homey App](https://homey.app/nl-nl/app/com.gruijter.zigbee2mqtt/)
- Documentation and support in the [Homey Forum](https://community.homey.app/t/83214)
<br>
<img align="left" height="100px" width="100px" src="https://user-images.githubusercontent.com/2734836/47615848-b8dd8700-dabd-11e8-9d77-175002dd8987.png">
@@ -63,16 +73,33 @@ Zigbee2MQTT integrates well with (almost) every home automation solution because
<br>
<img align="left" height="100px" width="100px" src="./images/gladys-assistant-logo.jpg">
### [Gladys Assistant](https://gladysassistant.com/)
- Integration implemented natively in Gladys Assistant. Read documentation [here](https://gladysassistant.com/docs/integrations/zigbee2mqtt/)
<br>
<img align="left" height="100px" width="100px" src="https://forum.iobroker.net/assets/uploads/system/site-logo.png">
### [IoBroker](https://www.iobroker.net/)
- Integration implemented in IoBroker. Read documentation [here](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt)
<br>
## Architecture
![Architecture](images/architecture.png)
### Internal Architecture
Zigbee2MQTT is made up of three modules, each developed in its own Github project. Starting from the hardware (adapter) and moving up; [zigbee-herdsman](https://github.com/koenkk/zigbee-herdsman) connects to your Zigbee adapter an makes an API available to the higher levels of the stack. For e.g. Texas Instruments hardware, zigbee-herdsman uses the [TI zStack monitoring and test API](https://github.com/koenkk/zigbee-herdsman/raw/master/docs/Z-Stack%20Monitor%20and%20Test%20API.pdf) to communicate with the adapter. Zigbee-herdsman handles the core Zigbee communication. The module [zigbee-herdsman-converters](https://github.com/koenkk/zigbee-herdsman-converters) handles the mapping from individual device models to the Zigbee clusters they support. [Zigbee clusters](https://github.com/Koenkk/zigbee-herdsman/raw/master/docs/Zigbee%20Cluster%20Library%20Specification%20v7.pdf) are the layers of the Zigbee protocol on top of the base protocol that define things like how lights, sensors and switches talk to each other over the Zigbee network. Finally, the Zigbee2MQTT module drives zigbee-herdsman and maps the zigbee messages to MQTT messages. Zigbee2MQTT also keeps track of the state of the system. It uses a `database.db` file to store this state; a text file with a JSON database of connected devices and their capabilities.
Zigbee2MQTT is made up of three modules, each developed in its own Github project. Starting from the hardware (adapter) and moving up; [zigbee-herdsman](https://github.com/koenkk/zigbee-herdsman) connects to your Zigbee adapter and makes an API available to the higher levels of the stack. For e.g. Texas Instruments hardware, zigbee-herdsman uses the [TI zStack monitoring and test API](https://github.com/koenkk/zigbee-herdsman/raw/master/docs/Z-Stack%20Monitor%20and%20Test%20API.pdf) to communicate with the adapter. Zigbee-herdsman handles the core Zigbee communication. The module [zigbee-herdsman-converters](https://github.com/koenkk/zigbee-herdsman-converters) handles the mapping from individual device models to the Zigbee clusters they support. [Zigbee clusters](https://github.com/Koenkk/zigbee-herdsman/blob/master/docs/07-5123-08-Zigbee-Cluster-Library.pdf) are the layers of the Zigbee protocol on top of the base protocol that define things like how lights, sensors and switches talk to each other over the Zigbee network. Finally, the Zigbee2MQTT module drives zigbee-herdsman and maps the zigbee messages to MQTT messages. Zigbee2MQTT also keeps track of the state of the system. It uses a `database.db` file to store this state; a text file with a JSON database of connected devices and their capabilities. Zigbee2MQTT provides a [web-based interface](https://github.com/nurikk/zigbee2mqtt-frontend) that allows monitoring and configuration.
### Developing
Zigbee2MQTT uses TypeScript (partially for now). Therefore after making changes to files in the `lib/` directory you need to recompile Zigbee2MQTT. This can be done by executing `npm run build`. For faster development instead of running `npm run build` you can run `npm run build-watch` in another terminal session, this will recompile as you change files.
## Supported devices
See [Supported devices](https://www.zigbee2mqtt.io/information/supported_devices.html) to check whether your device is supported. There is quite an extensive list, including devices from vendors like Xiaomi, Ikea, Philips, OSRAM and more.
See [Supported devices](https://www.zigbee2mqtt.io/supported-devices) to check whether your device is supported. There is quite an extensive list, including devices from vendors like [Xiaomi](https://www.zigbee2mqtt.io/supported-devices/#v=Xiaomi), [Ikea](https://www.zigbee2mqtt.io/supported-devices/#v=IKEA), [Philips](https://www.zigbee2mqtt.io/supported-devices/#v=Philips), [OSRAM](https://www.zigbee2mqtt.io/supported-devices/#v=OSRAM) and more.
If it's not listed in [Supported devices](https://www.zigbee2mqtt.io/information/supported_devices.html), support can be added (fairly) easy, see [How to support new devices](https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html).
If it's not listed in [Supported devices](https://www.zigbee2mqtt.io/supported-devices), support can be added (fairly) easily, see [How to support new devices](https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html).
## Support & help
If you need assistance you can check [opened issues](https://github.com/Koenkk/zigbee2mqtt/issues). Feel free to help with Pull Requests when you were able to fix things or add new devices or just share the love on social media.
+11
View File
@@ -0,0 +1,11 @@
module.exports = {
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-typescript',
],
assumptions: {setPublicClassFields: true},
plugins: [
['@babel/plugin-proposal-decorators', {'legacy': true}],
['@babel/plugin-proposal-class-properties'],
],
};
+29
View File
@@ -0,0 +1,29 @@
# Home Assistant integration (MQTT discovery)
homeassistant: false
# Enable the frontend, runs on port 8080 by default
frontend: true
# MQTT settings
mqtt:
# MQTT base topic for zigbee2mqtt MQTT messages
base_topic: zigbee2mqtt
# MQTT server URL
server: 'mqtt://localhost'
# MQTT server authentication, uncomment if required:
# user: my_user
# password: my_password
# Serial settings
serial:
# Location of CC2531 USB sniffer
port: /dev/ttyACM0
# Advanced settings
advanced:
# Let Zigbee2MQTT generate a network key on first start
network_key: GENERATE
# Let Zigbee2MQTT generate a pan_id on first start
pan_id: GENERATE
# Let Zigbee2MQTT generate a ext_pan_id on first start
ext_pan_id: GENERATE
+17 -14
View File
@@ -1,25 +1,26 @@
FROM node:14-alpine3.12 as base
FROM alpine:3.18.4 as base
WORKDIR /app
RUN apk add --no-cache tzdata eudev
RUN apk add --no-cache tzdata eudev tini nodejs
COPY package.json ./
# Dependencies and build
FROM base as dependencies_and_build
# Dependencies
FROM base as dependencies
COPY package*.json tsconfig.json index.js ./
COPY lib ./lib
COPY npm-shrinkwrap.json ./
RUN apk add --no-cache --virtual .buildtools make gcc g++ python3 linux-headers git && \
npm ci --production && \
RUN apk add --no-cache --virtual .buildtools make gcc g++ python3 linux-headers git npm && \
npm ci --production --no-audit --no-optional --no-update-notifier && \
# Serialport needs to be rebuild for Alpine https://serialport.io/docs/9.x.x/guide-installation#alpine-linux
npm rebuild --build-from-source && \
apk del .buildtools
# Release
FROM base as release
COPY --from=dependencies /app/node_modules ./node_modules
COPY lib ./lib
COPY LICENSE index.js data/configuration.yaml ./
COPY --from=dependencies_and_build /app/node_modules ./node_modules
COPY dist ./dist
COPY package.json LICENSE index.js data/configuration.yaml data/configuration.example.yaml ./
COPY docker/docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
@@ -27,7 +28,9 @@ RUN chmod +x /usr/local/bin/docker-entrypoint.sh
RUN mkdir /app/data
ARG COMMIT
RUN echo "{\"hash\": \"$COMMIT\"}" > .hash.json
RUN echo "$COMMIT" > dist/.hash
ENV NODE_ENV production
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["npm", "start"]
CMD [ "/sbin/tini", "--", "node", "index.js"]
-1
View File
@@ -1 +0,0 @@
qemu-aarch64-static and qemu-arm-static are taken from https://github.com/resin-io/qemu/releases/tag/v2.9.0%2Bresin1
+1 -1
View File
@@ -11,7 +11,7 @@ echo "Using '$DATA' as data directory"
if [ ! -f "$DATA/configuration.yaml" ]; then
echo "Creating configuration file..."
cp /app/configuration.yaml "$DATA/configuration.yaml"
cp /app/configuration.example.yaml "$DATA/configuration.yaml"
fi
exec "$@"
Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

+87 -14
View File
@@ -1,29 +1,93 @@
const semver = require('semver');
const engines = require('./package.json').engines;
const indexJsRestart = 'indexjs.restart';
const fs = require('fs');
const os = require('os');
const path = require('path');
const {exec} = require('child_process');
const {rimrafSync} = require('rimraf');
require('source-map-support').install();
let controller;
let stopping = false;
const hashFile = path.join(__dirname, 'dist', '.hash');
async function restart() {
await stop(indexJsRestart);
await stop(true);
await start();
}
async function exit(code, reason) {
if (reason !== indexJsRestart) {
async function exit(code, restart) {
if (!restart) {
process.exit(code);
}
}
async function currentHash() {
const git = require('git-last-commit');
return new Promise((resolve) => {
git.getLastCommit((err, commit) => {
if (err) resolve('unknown');
else resolve(commit.shortHash);
});
});
}
async function writeHash() {
const hash = await currentHash();
fs.writeFileSync(hashFile, hash);
}
async function build(reason) {
return new Promise((resolve, reject) => {
process.stdout.write(`Building Zigbee2MQTT... (${reason})`);
rimrafSync('dist');
const env = {...process.env};
const _600mb = 629145600;
if (_600mb > os.totalmem() && !env.NODE_OPTIONS) {
// Prevent OOM on tsc compile for system with low memory
// https://github.com/Koenkk/zigbee2mqtt/issues/12034
env.NODE_OPTIONS = '--max_old_space_size=256';
}
exec('npm run build', {env, cwd: __dirname}, async (err, stdout, stderr) => {
if (err) {
process.stdout.write(', failed\n');
if (err.code === 134) {
process.stderr.write(
'\n\nBuild failed; ran out-of-memory, free some memory (RAM) and start again\n\n');
}
reject(err);
} else {
process.stdout.write(', finished\n');
resolve();
}
});
});
}
async function checkDist() {
if (!fs.existsSync(hashFile)) {
await build('initial build');
}
const distHash = fs.readFileSync(hashFile, 'utf-8');
const hash = await currentHash();
if (hash !== 'unknown' && distHash !== hash) {
await build('hash changed');
}
}
async function start() {
await checkDist();
const version = engines.node;
if (!semver.satisfies(process.version, version)) {
console.log(`\t\tZigbee2MQTT requires node version ${version}, you are running ${process.version}!\n`); // eslint-disable-line
}
// Validate settings
const settings = require('./lib/util/settings');
const settings = require('./dist/util/settings');
settings.reRead();
const errors = settings.validate();
if (errors.length > 0) {
@@ -33,28 +97,37 @@ async function start() {
for (const error of errors) {
console.log(`- ${error}`);
}
console.log(`\nIf you don't know how to solve this, read https://www.zigbee2mqtt.io/information/configuration.html`); // eslint-disable-line
console.log(`\nIf you don't know how to solve this, read https://www.zigbee2mqtt.io/guide/configuration`); // eslint-disable-line
console.log(`\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n`);
exit(1);
}
const Controller = require('./lib/controller');
const Controller = require('./dist/controller');
controller = new Controller(restart, exit);
await controller.start();
}
async function stop(reason=null) {
await controller.stop(reason);
async function stop(restart) {
await controller.stop(restart);
}
async function handleQuit() {
if (!stopping && controller) {
stopping = true;
await stop();
await stop(false);
}
}
process.on('SIGINT', handleQuit);
process.on('SIGTERM', handleQuit);
start();
if (require.main === module || require.main.filename.endsWith(path.sep + 'cli.js')) {
if (process.argv.length === 3 && process.argv[2] === 'writehash') {
writeHash();
} else {
process.on('SIGINT', handleQuit);
process.on('SIGTERM', handleQuit);
start();
}
} else {
process.on('SIGINT', handleQuit);
process.on('SIGTERM', handleQuit);
module.exports = {start};
}
-396
View File
@@ -1,396 +0,0 @@
const MQTT = require('./mqtt');
const Zigbee = require('./zigbee');
const EventBus = require('./eventBus');
const State = require('./state');
const logger = require('./util/logger');
const settings = require('./util/settings');
const objectAssignDeep = require('object-assign-deep');
const utils = require('./util/utils');
const stringify = require('json-stable-stringify-without-jsonify');
const assert = require('assert');
// Extensions
const ExtensionFrontend = require('./extension/frontend');
const ExtensionPublish = require('./extension/publish');
const ExtensionReceive = require('./extension/receive');
const ExtensionNetworkMap = require('./extension/networkMap');
const ExtensionSoftReset = require('./extension/legacy/softReset');
const ExtensionHomeAssistant = require('./extension/homeassistant');
const ExtensionConfigure = require('./extension/configure');
const ExtensionDeviceGroupMembership = require('./extension/legacy/deviceGroupMembership');
const ExtensionBridgeLegacy = require('./extension/legacy/bridgeLegacy');
const ExtensionBridge = require('./extension/bridge');
const ExtensionGroups = require('./extension/groups');
const ExtensionAvailability = require('./extension/availability');
const ExtensionBind = require('./extension/bind');
const ExtensionReport = require('./extension/legacy/report');
const ExtensionOnEvent = require('./extension/onEvent');
const ExtensionOTAUpdate = require('./extension/otaUpdate');
const ExtensionExternalConverters = require('./extension/externalConverters');
const ExtensionExternalExtension = require('./extension/externalExtension');
const AllExtensions = [
ExtensionPublish, ExtensionReceive, ExtensionNetworkMap, ExtensionSoftReset, ExtensionHomeAssistant,
ExtensionConfigure, ExtensionDeviceGroupMembership, ExtensionBridgeLegacy, ExtensionBridge, ExtensionGroups,
ExtensionAvailability, ExtensionBind, ExtensionReport, ExtensionOnEvent, ExtensionOTAUpdate,
ExtensionExternalConverters, ExtensionFrontend, ExtensionExternalExtension,
];
class Controller {
constructor(restartCallback, exitCallback) {
this.zigbee = new Zigbee();
this.mqtt = new MQTT();
this.eventBus = new EventBus();
this.state = new State(this.eventBus);
this.restartCallback = restartCallback;
this.exitCallback = exitCallback;
this.publishEntityState = this.publishEntityState.bind(this);
this.enableDisableExtension = this.enableDisableExtension.bind(this);
this.onZigbeeAdapterDisconnected = this.onZigbeeAdapterDisconnected.bind(this);
this.addExtension = this.addExtension.bind(this);
// Initialize extensions.
const args = [this.zigbee, this.mqtt, this.state, this.publishEntityState, this.eventBus];
this.extensions = [
new ExtensionBridge(...args, this.enableDisableExtension, this.restartCallback),
new ExtensionPublish(...args),
new ExtensionReceive(...args),
new ExtensionDeviceGroupMembership(...args),
new ExtensionConfigure(...args),
new ExtensionNetworkMap(...args),
new ExtensionGroups(...args),
new ExtensionBind(...args),
new ExtensionOnEvent(...args),
new ExtensionOTAUpdate(...args),
new ExtensionReport(...args),
];
if (settings.get().frontend) {
this.extensions.push(new ExtensionFrontend(...args));
}
if (settings.get().advanced.legacy_api) {
this.extensions.push(new ExtensionBridgeLegacy(...args));
}
if (settings.get().external_converters.length) {
this.extensions.push(new ExtensionExternalConverters(...args));
}
if (settings.get().homeassistant) {
this.extensions.push(new ExtensionHomeAssistant(...args));
}
/* istanbul ignore next */
if (settings.get().advanced.soft_reset_timeout !== 0) {
this.extensions.push(new ExtensionSoftReset(...args));
}
if (settings.get().advanced.availability_timeout) {
this.extensions.push(new ExtensionAvailability(...args));
}
this.extensions.push(new ExtensionExternalExtension(...args, this.addExtension, this.enableDisableExtension));
}
async start() {
this.state.start();
logger.logOutput();
const info = await utils.getZigbee2mqttVersion();
logger.info(`Starting Zigbee2MQTT version ${info.version} (commit #${info.commitHash})`);
// Start zigbee
try {
await this.zigbee.start();
this.callExtensionMethod('onZigbeeStarted', []);
this.zigbee.on('event', this.onZigbeeEvent.bind(this));
this.zigbee.on('adapterDisconnected', this.onZigbeeAdapterDisconnected);
} catch (error) {
logger.error('Failed to start zigbee');
// eslint-disable-next-line
logger.error('Check https://www.zigbee2mqtt.io/information/FAQ.html#help-zigbee2mqtt-fails-to-start for possible solutions');
logger.error('Exiting...');
logger.error(error.stack);
this.exitCallback(1);
}
// Log zigbee clients on startup
const devices = this.zigbee.getClients();
logger.info(`Currently ${devices.length} devices are joined:`);
for (const device of devices) {
const entity = this.zigbee.resolveEntity(device);
const model = entity.definition ?
`${entity.definition.model} - ${entity.definition.vendor} ${entity.definition.description}` :
'Not supported';
logger.info(`${entity.name} (${entity.device.ieeeAddr}): ${model} (${entity.device.type})`);
}
// Enable zigbee join.
if (settings.get().permit_join) {
logger.warn('`permit_join` set to `true` in configuration.yaml.');
logger.warn('Allowing new devices to join.');
logger.warn('Set `permit_join` to `false` once you joined all devices.');
}
try {
await this.zigbee.permitJoin(settings.get().permit_join);
} catch (error) {
logger.error(`Failed to set permit join to ${settings.get().permit_join}`);
}
// MQTT
this.mqtt.on('message', this.onMQTTMessage.bind(this));
await this.mqtt.connect();
// Send all cached states.
if (settings.get().advanced.cache_state_send_on_startup && settings.get().advanced.cache_state) {
for (const device of this.zigbee.getClients()) {
if (this.state.exists(device.ieeeAddr)) {
this.publishEntityState(device.ieeeAddr, this.state.get(device.ieeeAddr));
}
}
}
// Add devices which are in database but not in configuration to configuration
for (const device of this.zigbee.getClients()) {
if (!settings.getDevice(device.ieeeAddr)) {
settings.addDevice(device.ieeeAddr);
}
}
// Call extensions
await this.callExtensionMethod('onMQTTConnected', []);
}
async enableDisableExtension(enable, name) {
if (!enable) {
const extension = this.extensions.find((e) => e.constructor.name === name);
if (extension) {
await this.callExtensionMethod('stop', [], [extension]);
this.extensions.splice(this.extensions.indexOf(extension), 1);
}
} else {
const Extension = AllExtensions.find((e) => e.name === name);
assert(Extension, `Extension '${name}' does not exist`);
const extension = new Extension(this.zigbee, this.mqtt, this.state, this.publishEntityState, this.eventBus);
this.extensions.push(extension);
this.callExtensionMethod('onZigbeeStarted', [], [extension]);
this.callExtensionMethod('onMQTTConnected', [], [extension]);
}
}
addExtension(extension) {
this.extensions.push(extension);
}
async stop(reason=null) {
// Call extensions
await this.callExtensionMethod('stop', []);
// Wrap-up
this.state.stop();
await this.mqtt.disconnect();
try {
await this.zigbee.stop();
logger.info('Stopped Zigbee2MQTT');
this.exitCallback(0, reason);
} catch (error) {
logger.error('Failed to stop Zigbee2MQTT');
this.exitCallback(1, reason);
}
}
async onZigbeeAdapterDisconnected() {
logger.error('Adapter disconnected, stopping');
await this.stop();
}
async onZigbeeEvent(type, data) {
const resolvedEntity = this.zigbee.resolveEntity(data.device || data.ieeeAddr);
if (data.device && data.device.type === 'Coordinator') {
logger.debug('Ignoring message from coordinator');
return;
}
if (data.device && !settings.getDevice(data.device.ieeeAddr)) {
// Only deviceLeave doesn't have a device (not interesting to add to settings)
resolvedEntity.settings = {...settings.get().device_options, ...settings.addDevice(data.device.ieeeAddr)};
}
const name = resolvedEntity && resolvedEntity.settings ? resolvedEntity.settings.friendlyName : null;
if (type === 'message') {
logger.debug(
`Received Zigbee message from '${name}', type '${data.type}', cluster '${data.cluster}'` +
`, data '${stringify(data.data)}' from endpoint ${data.endpoint.ID}` +
(data.hasOwnProperty('groupID') ? ` with groupID ${data.groupID}` : ``),
);
} else if (type === 'deviceJoined') {
logger.info(`Device '${name}' joined`);
} else if (type === 'deviceInterview') {
if (data.status === 'successful') {
logger.info(`Successfully interviewed '${name}', device has successfully been paired`);
if (resolvedEntity.definition) {
const {vendor, description, model} = resolvedEntity.definition;
logger.info(`Device '${name}' is supported, identified as: ${vendor} ${description} (${model})`);
} else {
logger.warn(
`Device '${name}' with Zigbee model '${data.device.modelID}' and manufacturer name ` +
`'${data.device.manufacturerName}' is NOT supported, ` +
`please follow https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html`,
);
}
} else if (data.status === 'failed') {
logger.error(`Failed to interview '${name}', device has not successfully been paired`);
} else {
/* istanbul ignore else */
if (data.status === 'started') {
logger.info(`Starting interview of '${name}'`);
}
}
} else if (type === 'deviceAnnounce') {
logger.debug(`Device '${name}' announced itself`);
} else {
/* istanbul ignore else */
if (type === 'deviceLeave') {
logger.warn(`Device '${name || data.ieeeAddr}' left the network`);
this.state.remove(data.ieeeAddr);
}
}
// Call extensions
this.callExtensionMethod('onZigbeeEvent', [type, data, resolvedEntity]);
}
onMQTTMessage(payload) {
const {topic, message} = payload;
logger.debug(`Received MQTT message on '${topic}' with data '${message}'`);
// Call extensions
this.callExtensionMethod('onMQTTMessage', [topic, message]);
}
async publishEntityState(IDorName, payload, stateChangeReason=null) {
const resolvedEntity = this.zigbee.resolveEntity(IDorName);
if (!resolvedEntity || !resolvedEntity.settings) {
logger.error(`'${IDorName}' does not exist, skipping publish`);
return;
}
let messagePayload = {...payload};
const currentState = this.state.exists(resolvedEntity.settings.ID) ?
this.state.get(resolvedEntity.settings.ID) : {};
const newState = objectAssignDeep.noMutate(currentState, payload);
// Update state cache with new state.
this.state.set(resolvedEntity.settings.ID, newState, stateChangeReason);
if (settings.get().advanced.cache_state) {
// Add cached state to payload
messagePayload = newState;
}
const options = {
retain: utils.getObjectProperty(resolvedEntity.settings, 'retain', false),
qos: utils.getObjectProperty(resolvedEntity.settings, 'qos', 0),
};
const retention = utils.getObjectProperty(resolvedEntity.settings, 'retention', false);
if (retention !== false) {
options.properties = {messageExpiryInterval: retention};
}
const isDevice = resolvedEntity.type === 'device';
if (isDevice && settings.get().mqtt.include_device_information) {
const attributes = [
'ieeeAddr', 'networkAddress', 'type', 'manufacturerID', 'manufacturerName', 'powerSource',
'applicationVersion', 'stackVersion', 'zclVersion', 'hardwareVersion', 'dateCode', 'softwareBuildID',
];
messagePayload.device = {
friendlyName: resolvedEntity.name,
model: resolvedEntity.definition ? resolvedEntity.definition.model : 'unknown',
};
attributes.forEach((a) => messagePayload.device[a] = resolvedEntity.device[a]);
}
// Add lastseen
const lastSeen = settings.get().advanced.last_seen;
if (isDevice && lastSeen !== 'disable' && resolvedEntity.device.lastSeen) {
messagePayload.last_seen = utils.formatDate(resolvedEntity.device.lastSeen, lastSeen);
}
// Add device linkquality.
if (resolvedEntity.type === 'device' && resolvedEntity.device.linkquality !== undefined) {
messagePayload.linkquality = resolvedEntity.device.linkquality;
}
// filter mqtt message attributes
if (resolvedEntity.settings.filtered_attributes) {
resolvedEntity.settings.filtered_attributes.forEach((a) => delete messagePayload[a]);
}
if (Object.entries(messagePayload).length) {
const output = settings.get().experimental.output;
if (output === 'attribute_and_json' || output === 'json') {
await this.mqtt.publish(resolvedEntity.name, stringify(messagePayload), options);
}
if (output === 'attribute_and_json' || output === 'attribute') {
await this.iteratePayloadAttributeOutput(`${resolvedEntity.name}/`, messagePayload, options);
}
}
this.eventBus.emit('publishEntityState', {messagePayload, entity: resolvedEntity, stateChangeReason, payload});
}
async iteratePayloadAttributeOutput(topicRoot, payload, options) {
for (const [key, value] of Object.entries(payload)) {
let subPayload = value;
let message = null;
// Special cases
if (key === 'color' && utils.objectHasProperties(subPayload, ['r', 'g', 'b'])) {
subPayload = [subPayload.r, subPayload.g, subPayload.b];
}
// Check Array first, since it is also an Object
if (subPayload === null || subPayload === undefined) {
message = '';
} else if (Array.isArray(subPayload)) {
message = subPayload.map((x) => `${x}`).join(',');
} else if (typeof subPayload === 'object') {
this.iteratePayloadAttributeOutput(`${topicRoot}${key}-`, subPayload, options);
} else {
message = typeof subPayload === 'string' ? subPayload : stringify(subPayload);
}
if (message !== null) {
await this.mqtt.publish(`${topicRoot}${key}`, message, options);
}
}
}
async callExtensionMethod(method, parameters, extensions=null) {
for (const extension of extensions || this.extensions) {
if (extension[method]) {
try {
await extension[method](...parameters);
} catch (error) {
/* istanbul ignore next */
logger.error(`Failed to call '${extension.constructor.name}' '${method}' (${error.stack})`);
/* istanbul ignore next */
if (process.env.JEST_WORKER_ID !== undefined) {
throw error;
}
}
}
}
}
}
module.exports = Controller;
+328
View File
@@ -0,0 +1,328 @@
import MQTT from './mqtt';
import Zigbee from './zigbee';
import EventBus from './eventBus';
import State from './state';
import logger from './util/logger';
import * as settings from './util/settings';
import utils from './util/utils';
import stringify from 'json-stable-stringify-without-jsonify';
import assert from 'assert';
import bind from 'bind-decorator';
// Extensions
import ExtensionFrontend from './extension/frontend';
import ExtensionPublish from './extension/publish';
import ExtensionReceive from './extension/receive';
import ExtensionNetworkMap from './extension/networkMap';
import ExtensionSoftReset from './extension/legacy/softReset';
import ExtensionHomeAssistant from './extension/homeassistant';
import ExtensionConfigure from './extension/configure';
import ExtensionDeviceGroupMembership from './extension/legacy/deviceGroupMembership';
import ExtensionBridgeLegacy from './extension/legacy/bridgeLegacy';
import ExtensionBridge from './extension/bridge';
import ExtensionGroups from './extension/groups';
import ExtensionAvailability from './extension/availability';
import ExtensionBind from './extension/bind';
import ExtensionReport from './extension/legacy/report';
import ExtensionOnEvent from './extension/onEvent';
import ExtensionOTAUpdate from './extension/otaUpdate';
import ExtensionExternalConverters from './extension/externalConverters';
import ExtensionExternalExtension from './extension/externalExtension';
const AllExtensions = [
ExtensionPublish, ExtensionReceive, ExtensionNetworkMap, ExtensionSoftReset, ExtensionHomeAssistant,
ExtensionConfigure, ExtensionDeviceGroupMembership, ExtensionBridgeLegacy, ExtensionBridge, ExtensionGroups,
ExtensionBind, ExtensionReport, ExtensionOnEvent, ExtensionOTAUpdate,
ExtensionExternalConverters, ExtensionFrontend, ExtensionExternalExtension, ExtensionAvailability,
];
type ExtensionArgs = [Zigbee, MQTT, State, PublishEntityState, EventBus,
(enable: boolean, name: string) => Promise<void>, () => void, (extension: Extension) => Promise<void>];
export class Controller {
private eventBus: EventBus;
private zigbee: Zigbee;
private state: State;
private mqtt: MQTT;
private restartCallback: () => void;
private exitCallback: (code: number, restart: boolean) => void;
private extensions: Extension[];
private extensionArgs: ExtensionArgs;
constructor(restartCallback: () => void, exitCallback: (code: number, restart: boolean) => void) {
logger.init();
this.eventBus = new EventBus( /* istanbul ignore next */ (error) => {
logger.error(`Error: ${error.message}`);
logger.debug(error.stack);
});
this.zigbee = new Zigbee(this.eventBus);
this.mqtt = new MQTT(this.eventBus);
this.state = new State(this.eventBus, this.zigbee);
this.restartCallback = restartCallback;
this.exitCallback = exitCallback;
// Initialize extensions.
this.extensionArgs = [this.zigbee, this.mqtt, this.state, this.publishEntityState, this.eventBus,
this.enableDisableExtension, this.restartCallback, this.addExtension];
this.extensions = [
new ExtensionBridge(...this.extensionArgs),
new ExtensionPublish(...this.extensionArgs),
new ExtensionReceive(...this.extensionArgs),
new ExtensionDeviceGroupMembership(...this.extensionArgs),
new ExtensionConfigure(...this.extensionArgs),
new ExtensionNetworkMap(...this.extensionArgs),
new ExtensionGroups(...this.extensionArgs),
new ExtensionBind(...this.extensionArgs),
new ExtensionOnEvent(...this.extensionArgs),
new ExtensionOTAUpdate(...this.extensionArgs),
new ExtensionReport(...this.extensionArgs),
new ExtensionExternalExtension(...this.extensionArgs),
new ExtensionAvailability(...this.extensionArgs),
settings.get().frontend && new ExtensionFrontend(...this.extensionArgs),
settings.get().advanced.legacy_api && new ExtensionBridgeLegacy(...this.extensionArgs),
settings.get().external_converters.length && new ExtensionExternalConverters(...this.extensionArgs),
settings.get().homeassistant && new ExtensionHomeAssistant(...this.extensionArgs),
/* istanbul ignore next */
settings.get().advanced.soft_reset_timeout !== 0 && new ExtensionSoftReset(...this.extensionArgs),
].filter((n) => n);
}
async start(): Promise<void> {
this.state.start();
logger.logOutput();
const info = await utils.getZigbee2MQTTVersion();
logger.info(`Starting Zigbee2MQTT version ${info.version} (commit #${info.commitHash})`);
// Start zigbee
let startResult;
try {
startResult = await this.zigbee.start();
this.eventBus.onAdapterDisconnected(this, this.onZigbeeAdapterDisconnected);
} catch (error) {
logger.error('Failed to start zigbee');
logger.error('Check https://www.zigbee2mqtt.io/guide/installation/20_zigbee2mqtt-fails-to-start.html for possible solutions'); /* eslint-disable-line max-len */
logger.error('Exiting...');
logger.error(error.stack);
await this.exit(1);
}
// Disable some legacy options on new network creation
if (startResult === 'reset') {
settings.set(['advanced', 'homeassistant_legacy_entity_attributes'], false);
settings.set(['advanced', 'legacy_api'], false);
settings.set(['advanced', 'legacy_availability_payload'], false);
settings.set(['device_options', 'legacy'], false);
this.enableDisableExtension(false, 'BridgeLegacy');
}
// Log zigbee clients on startup
const devices = this.zigbee.devices(false);
logger.info(`Currently ${devices.length} devices are joined:`);
for (const device of devices) {
const model = device.definition ?
`${device.definition.model} - ${device.definition.vendor} ${device.definition.description}` :
'Not supported';
logger.info(`${device.name} (${device.ieeeAddr}): ${model} (${device.zh.type})`);
}
// Enable zigbee join
try {
if (settings.get().permit_join) {
logger.warn('`permit_join` set to `true` in configuration.yaml.');
logger.warn('Allowing new devices to join.');
logger.warn('Set `permit_join` to `false` once you joined all devices.');
}
await this.zigbee.permitJoin(settings.get().permit_join);
} catch (error) {
logger.error(`Failed to set permit join to ${settings.get().permit_join}`);
}
// MQTT
try {
await this.mqtt.connect();
} catch (error) {
logger.error(`MQTT failed to connect, exiting...`);
await this.zigbee.stop();
await this.exit(1);
}
// Call extensions
await this.callExtensions('start', [...this.extensions]);
// Send all cached states.
if (settings.get().advanced.cache_state_send_on_startup && settings.get().advanced.cache_state) {
for (const entity of [...devices, ...this.zigbee.groups()]) {
if (this.state.exists(entity)) {
this.publishEntityState(entity, this.state.get(entity), 'publishCached');
}
}
}
this.eventBus.onLastSeenChanged(this,
(data) => utils.publishLastSeen(data, settings.get(), false, this.publishEntityState));
logger.info(`Zigbee2MQTT started!`);
}
@bind async enableDisableExtension(enable: boolean, name: string): Promise<void> {
if (!enable) {
const extension = this.extensions.find((e) => e.constructor.name === name);
if (extension) {
await this.callExtensions('stop', [extension]);
this.extensions.splice(this.extensions.indexOf(extension), 1);
}
} else {
const Extension = AllExtensions.find((e) => e.name === name);
assert(Extension, `Extension '${name}' does not exist`);
const extension = new Extension(...this.extensionArgs);
this.extensions.push(extension);
await this.callExtensions('start', [extension]);
}
}
@bind async addExtension(extension: Extension): Promise<void> {
this.extensions.push(extension);
await this.callExtensions('start', [extension]);
}
async stop(restart = false): Promise<void> {
// Call extensions
await this.callExtensions('stop', this.extensions);
this.eventBus.removeListeners(this);
// Wrap-up
this.state.stop();
await this.mqtt.disconnect();
try {
await this.zigbee.stop();
logger.info('Stopped Zigbee2MQTT');
await this.exit(0, restart);
} catch (error) {
logger.error('Failed to stop Zigbee2MQTT');
await this.exit(1, restart);
}
}
async exit(code: number, restart = false): Promise<void> {
await logger.end();
this.exitCallback(code, restart);
}
@bind async onZigbeeAdapterDisconnected(): Promise<void> {
logger.error('Adapter disconnected, stopping');
await this.stop();
}
@bind async publishEntityState(entity: Group | Device, payload: KeyValue,
stateChangeReason?: StateChangeReason): Promise<void> {
let message = {...payload};
// Update state cache with new state.
const newState = this.state.set(entity, payload, stateChangeReason);
if (settings.get().advanced.cache_state) {
// Add cached state to payload
message = newState;
}
const options: MQTTOptions = {
retain: utils.getObjectProperty(entity.options, 'retain', false) as boolean,
qos: utils.getObjectProperty(entity.options, 'qos', 0) as 0 | 1 | 2,
};
const retention = utils.getObjectProperty(entity.options, 'retention', false);
if (retention !== false) {
options.properties = {messageExpiryInterval: retention as number};
}
if (entity.isDevice() && settings.get().mqtt.include_device_information) {
message.device = {
friendlyName: entity.name, model: entity.definition ? entity.definition.model : 'unknown',
ieeeAddr: entity.ieeeAddr, networkAddress: entity.zh.networkAddress, type: entity.zh.type,
manufacturerID: entity.zh.manufacturerID,
powerSource: entity.zh.powerSource, applicationVersion: entity.zh.applicationVersion,
stackVersion: entity.zh.stackVersion, zclVersion: entity.zh.zclVersion,
hardwareVersion: entity.zh.hardwareVersion, dateCode: entity.zh.dateCode,
softwareBuildID: entity.zh.softwareBuildID,
// Manufacturer name can contain \u0000, remove this.
// https://github.com/home-assistant/core/issues/85691
manufacturerName: entity.zh.manufacturerName?.split('\u0000')[0],
};
}
// Add lastseen
const lastSeen = settings.get().advanced.last_seen;
if (entity.isDevice() && lastSeen !== 'disable' && entity.zh.lastSeen) {
message.last_seen = utils.formatDate(entity.zh.lastSeen, lastSeen);
}
// Add device linkquality.
if (entity.isDevice() && entity.zh.linkquality !== undefined) {
message.linkquality = entity.zh.linkquality;
}
for (const extension of this.extensions) {
extension.adjustMessageBeforePublish?.(entity, message);
}
// Filter mqtt message attributes
utils.filterProperties(entity.options.filtered_attributes, message);
if (Object.entries(message).length) {
const output = settings.get().advanced.output;
if (output === 'attribute_and_json' || output === 'json') {
await this.mqtt.publish(entity.name, stringify(message), options);
}
if (output === 'attribute_and_json' || output === 'attribute') {
await this.iteratePayloadAttributeOutput(`${entity.name}/`, message, options);
}
}
this.eventBus.emitPublishEntityState({entity, message, stateChangeReason, payload});
}
async iteratePayloadAttributeOutput(topicRoot: string, payload: KeyValue, options: MQTTOptions): Promise<void> {
for (const [key, value] of Object.entries(payload)) {
let subPayload = value;
let message = null;
// Special cases
if (key === 'color' && utils.objectHasProperties(subPayload, ['r', 'g', 'b'])) {
subPayload = [subPayload.r, subPayload.g, subPayload.b];
}
// Check Array first, since it is also an Object
if (subPayload === null || subPayload === undefined) {
message = '';
} else if (Array.isArray(subPayload)) {
message = subPayload.map((x) => `${x}`).join(',');
} else if (typeof subPayload === 'object') {
await this.iteratePayloadAttributeOutput(`${topicRoot}${key}-`, subPayload, options);
} else {
message = typeof subPayload === 'string' ? subPayload : stringify(subPayload);
}
if (message !== null) {
await this.mqtt.publish(`${topicRoot}${key}`, message, options);
}
}
}
private async callExtensions(method: 'start' | 'stop', extensions: Extension[]): Promise<void> {
for (const extension of extensions) {
try {
await extension[method]?.();
} catch (error) {
/* istanbul ignore next */
logger.error(`Failed to call '${extension.constructor.name}' '${method}' (${error.stack})`);
}
}
}
}
module.exports = Controller;
-43
View File
@@ -1,43 +0,0 @@
const events = require('events');
const assert = require('assert');
const allowedEvents = [
'deviceRemoved', // Device has been removed
'deviceRenamed', // Device has been renamed
'groupRenamed', // Group has been renamed
'publishEntityState', // Entity state will be published
'stateChange', // Entity changes its state
'groupMembersChanged', // Members of a group has been changed
'reportingDisabled', // Reporting is disabled for a device
'devicesChanged', // Devices changed
];
class EventBus extends events.EventEmitter {
constructor() {
super();
this.callbackByExtension = {};
}
emit(event, data) {
assert(allowedEvents.includes(event), `Event '${event}' not supported`);
super.emit(event, data);
}
on(event, callback, extension=null) {
assert(allowedEvents.includes(event), `Event '${event}' not supported`);
if (extension) {
if (!this.callbackByExtension[extension]) this.callbackByExtension[extension] = [];
this.callbackByExtension[extension].push({event, callback});
}
super.on(event, callback);
}
removeListenersExtension(extension) {
for (const entry of this.callbackByExtension[extension] || []) {
super.removeListener(entry.event, entry.callback);
}
}
}
module.exports = EventBus;
+174
View File
@@ -0,0 +1,174 @@
import events from 'events';
events.captureRejections = true;
// eslint-disable-next-line
type ListenerKey = object;
export default class EventBus {
private callbacksByExtension: { [s: string]: { event: string, callback: (...args: unknown[]) => void }[] } = {};
private emitter = new events.EventEmitter();
constructor(onError: (error: Error) => void) {
this.emitter.setMaxListeners(100);
this.emitter.on('error', onError);
}
public emitAdapterDisconnected(): void {
this.emitter.emit('adapterDisconnected');
}
public onAdapterDisconnected(key: ListenerKey, callback: () => void): void {
this.on('adapterDisconnected', callback, key);
}
public emitPermitJoinChanged(data: eventdata.PermitJoinChanged): void {
this.emitter.emit('permitJoinChanged', data);
}
public onPermitJoinChanged(key: ListenerKey, callback: (data: eventdata.PermitJoinChanged) => void): void {
this.on('permitJoinChanged', callback, key);
}
public emitPublishAvailability(): void {
this.emitter.emit('publishAvailability');
}
public onPublishAvailability(key: ListenerKey, callback: () => void): void {
this.on('publishAvailability', callback, key);
}
public emitEntityRenamed(data: eventdata.EntityRenamed): void {
this.emitter.emit('deviceRenamed', data);
}
public onEntityRenamed(key: ListenerKey, callback: (data: eventdata.EntityRenamed) => void): void {
this.on('deviceRenamed', callback, key);
}
public emitDeviceRemoved(data: eventdata.DeviceRemoved): void {
this.emitter.emit('deviceRemoved', data);
}
public onDeviceRemoved(key: ListenerKey, callback: (data: eventdata.DeviceRemoved) => void): void {
this.on('deviceRemoved', callback, key);
}
public emitLastSeenChanged(data: eventdata.LastSeenChanged): void {
this.emitter.emit('lastSeenChanged', data);
}
public onLastSeenChanged(key: ListenerKey, callback: (data: eventdata.LastSeenChanged) => void): void {
this.on('lastSeenChanged', callback, key);
}
public emitDeviceNetworkAddressChanged(data: eventdata.DeviceNetworkAddressChanged): void {
this.emitter.emit('deviceNetworkAddressChanged', data);
}
public onDeviceNetworkAddressChanged(
key: ListenerKey, callback: (data: eventdata.DeviceNetworkAddressChanged) => void): void {
this.on('deviceNetworkAddressChanged', callback, key);
}
public emitDeviceAnnounce(data: eventdata.DeviceAnnounce): void {
this.emitter.emit('deviceAnnounce', data);
}
public onDeviceAnnounce(key: ListenerKey, callback: (data: eventdata.DeviceAnnounce) => void): void {
this.on('deviceAnnounce', callback, key);
}
public emitDeviceInterview(data: eventdata.DeviceInterview): void {
this.emitter.emit('deviceInterview', data);
}
public onDeviceInterview(key: ListenerKey, callback: (data: eventdata.DeviceInterview) => void): void {
this.on('deviceInterview', callback, key);
}
public emitDeviceJoined(data: eventdata.DeviceJoined): void {
this.emitter.emit('deviceJoined', data);
}
public onDeviceJoined(key: ListenerKey, callback: (data: eventdata.DeviceJoined) => void): void {
this.on('deviceJoined', callback, key);
}
public emitEntityOptionsChanged(data: eventdata.EntityOptionsChanged): void {
this.emitter.emit('entityOptionsChanged', data);
}
public onEntityOptionsChanged(key: ListenerKey, callback: (data: eventdata.EntityOptionsChanged) => void): void {
this.on('entityOptionsChanged', callback, key);
}
public emitDeviceLeave(data: eventdata.DeviceLeave): void {
this.emitter.emit('deviceLeave', data);
}
public onDeviceLeave(key: ListenerKey, callback: (data: eventdata.DeviceLeave) => void): void {
this.on('deviceLeave', callback, key);
}
public emitDeviceMessage(data: eventdata.DeviceMessage): void {
this.emitter.emit('deviceMessage', data);
}
public onDeviceMessage(key: ListenerKey, callback: (data: eventdata.DeviceMessage) => void): void {
this.on('deviceMessage', callback, key);
}
public emitMQTTMessage(data: eventdata.MQTTMessage): void {
this.emitter.emit('mqttMessage', data);
}
public onMQTTMessage(key: ListenerKey, callback: (data: eventdata.MQTTMessage) => void): void {
this.on('mqttMessage', callback, key);
}
public emitMQTTMessagePublished(data: eventdata.MQTTMessagePublished): void {
this.emitter.emit('mqttMessagePublished', data);
}
public onMQTTMessagePublished(key: ListenerKey, callback: (data: eventdata.MQTTMessagePublished) => void): void {
this.on('mqttMessagePublished', callback, key);
}
public emitPublishEntityState(data: eventdata.PublishEntityState): void {
this.emitter.emit('publishEntityState', data);
}
public onPublishEntityState(key: ListenerKey, callback: (data: eventdata.PublishEntityState) => void): void {
this.on('publishEntityState', callback, key);
}
public emitGroupMembersChanged(data: eventdata.GroupMembersChanged): void {
this.emitter.emit('groupMembersChanged', data);
}
public onGroupMembersChanged(key: ListenerKey, callback: (data: eventdata.GroupMembersChanged) => void): void {
this.on('groupMembersChanged', callback, key);
}
public emitDevicesChanged(): void {
this.emitter.emit('devicesChanged');
}
public onDevicesChanged(key: ListenerKey, callback: () => void): void {
this.on('devicesChanged', callback, key);
}
public emitScenesChanged(): void {
this.emitter.emit('scenesChanged');
}
public onScenesChanged(key: ListenerKey, callback: () => void): void {
this.on('scenesChanged', callback, key);
}
public emitReconfigure(data: eventdata.Reconfigure): void {
this.emitter.emit('reconfigure', data);
}
public onReconfigure(key: ListenerKey, callback: (data: eventdata.Reconfigure) => void): void {
this.on('reconfigure', callback, key);
}
public emitStateChange(data: eventdata.StateChange): void {
this.emitter.emit('stateChange', data);
}
public onStateChange(key: ListenerKey, callback: (data: eventdata.StateChange) => void): void {
this.on('stateChange', callback, key);
}
private on(event: string, callback: (...args: unknown[]) => void, key: ListenerKey): void {
if (!this.callbacksByExtension[key.constructor.name]) this.callbacksByExtension[key.constructor.name] = [];
this.callbacksByExtension[key.constructor.name].push({event, callback});
this.emitter.on(event, callback);
}
public removeListeners(key: ListenerKey): void {
this.callbacksByExtension[key.constructor.name]?.forEach(
(e) => this.emitter.removeListener(e.event, e.callback));
}
}
-227
View File
@@ -1,227 +0,0 @@
const logger = require('../util/logger');
const settings = require('../util/settings');
const utils = require('../util/utils');
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const Extension = require('./extension');
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/(.*)/availability`);
// Pingable end devices, some end devices should be pinged
// e.g. E11-G13 https://github.com/Koenkk/zigbee2mqtt/issues/775#issuecomment-453683846
const pingableEndDevices = [
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'E11-G13'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'E11-N1EA'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === '53170161'),
];
const Hours25 = 1000 * 60 * 60 * 25;
const AvailabilityLagRatio = 0.1;
function timeoutLag(timeout, ratio) {
const lag = timeout * ratio;
return Math.floor(Math.random() * Math.floor(lag));
}
/**
* This extensions pings devices to check if they are online.
*/
class Availability extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.availability_timeout = settings.get().advanced.availability_timeout;
this.timers = {};
this.state = {};
this.eventBus.on('deviceRemoved', (data) => this.onDeviceRemoved(data.resolvedEntity), this.constructor.name);
this.eventBus.on('deviceRenamed', (data) => this.onDeviceRenamed(data), this.constructor.name);
this.blocklist = settings.get().advanced.availability_blocklist
.concat(settings.get().advanced.availability_blacklist)
.map((e) => settings.getEntity(e).ID);
this.passlist = settings.get().advanced.availability_passlist
.concat(settings.get().advanced.availability_whitelist)
.map((e) => settings.getEntity(e).ID);
}
onDeviceRenamed(data) {
this.mqtt.publish(`${data.from}/availability`, null, {retain: true, qos: 0});
}
onDeviceRemoved(resolvedEntity) {
this.mqtt.publish(`${resolvedEntity.name}/availability`, null, {retain: true, qos: 0});
delete this.state[resolvedEntity.device.ieeeAddr];
clearTimeout(this.timers[resolvedEntity.device.ieeeAddr]);
}
inPasslistOrNotInBlocklist(device) {
const ieeeAddr = device.ieeeAddr;
const deviceSettings = settings.getDevice(ieeeAddr);
const name = deviceSettings.friendlyName;
// Passlist is not empty and device is in it, enable availability
if (this.passlist.length > 0) {
return this.passlist.includes(ieeeAddr) || (name && this.passlist.includes(name));
}
// Device is on blocklist, disable availability
if (this.blocklist.includes(ieeeAddr) || (name && this.blocklist.includes(name))) {
return false;
}
return true;
}
isPingable(device) {
if (pingableEndDevices.find((d) => d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
return true;
}
// Device is a mains powered router
return device.type === 'Router' && device.powerSource !== 'Battery';
}
onMQTTConnected() {
for (const device of this.zigbee.getClients()) {
// Mark all devices as online on start
const ieeeAddr = device.ieeeAddr;
this.publishAvailability(device, this.state.hasOwnProperty(ieeeAddr) ? this.state[ieeeAddr] : true, true);
if (this.inPasslistOrNotInBlocklist(device)) {
if (this.isPingable(device)) {
this.setTimerPingable(device);
} else {
this.timers[ieeeAddr] = setInterval(() => {
this.handleIntervalNotPingable(device);
}, utils.secondsToMilliseconds(300));
}
}
}
}
async onMQTTMessage(topic, message) {
// Clear topics for non-existing devices
const match = topic.match(topicRegex);
if (match && (!this.zigbee.resolveEntity(match[1]) || this.zigbee.resolveEntity(match[1]).name !== match[1])) {
this.mqtt.publish(`${match[1]}/availability`, null, {retain: true, qos: 0});
}
}
async handleIntervalPingable(device) {
// When a device is already unavailable, log the ping failed on 'debug' instead of 'error'.
const resolvedEntity = this.zigbee.resolveEntity(device.ieeeAddr);
if (!resolvedEntity) {
logger.debug(`Stop pinging '${device.ieeeAddr}', device is not known anymore`);
return;
}
const level = this.state.hasOwnProperty(device.ieeeAddr) && !this.state[device.ieeeAddr] ? 'debug' : 'error';
try {
await device.ping();
this.publishAvailability(device, true);
logger.debug(`Successfully pinged '${resolvedEntity.name}'`);
} catch (error) {
this.publishAvailability(device, false);
logger[level](`Failed to ping '${resolvedEntity.name}'`);
} finally {
this.setTimerPingable(device);
}
}
async handleIntervalNotPingable(device) {
const resolvedEntity = this.zigbee.resolveEntity(device.ieeeAddr);
if (!resolvedEntity || !device.lastSeen) {
return;
}
const ago = Date.now() - resolvedEntity.device.lastSeen;
logger.debug(`Non-pingable device '${resolvedEntity.name}' was last seen '${ago / 1000}' seconds ago.`);
if (ago > Hours25) {
this.publishAvailability(device, false);
}
}
setTimerPingable(device) {
const timeout = this.availability_timeout + timeoutLag(this.availability_timeout, AvailabilityLagRatio);
clearTimeout(this.timers[device.ieeeAddr]);
this.timers[device.ieeeAddr] = setTimeout(async () => {
await this.handleIntervalPingable(device);
}, utils.secondsToMilliseconds(timeout));
}
async stop() {
super.stop();
for (const timer of Object.values(this.timers)) {
clearTimeout(timer);
}
this.zigbee.getClients().forEach((device) => this.publishAvailability(device, false));
}
async onReconnect(device) {
const resolvedEntity = this.zigbee.resolveEntity(device);
if (resolvedEntity && resolvedEntity.definition) {
try {
for (const key of ['state', 'brightness', 'color', 'color_temp']) {
const converter = resolvedEntity.definition.toZigbee.find((tz) => tz.key.includes(key));
if (converter) {
await converter.convertGet(device.endpoints[0], key, {});
}
}
} catch (error) {
logger.error(`Failed to read state of '${resolvedEntity.name}' after reconnect`);
}
}
}
publishAvailability(device, available, force=false) {
const ieeeAddr = device.ieeeAddr;
if (this.state.hasOwnProperty(ieeeAddr) && !this.state[ieeeAddr] && available) {
this.onReconnect(device);
}
const deviceSettings = settings.getDevice(ieeeAddr);
const name = deviceSettings ? deviceSettings.friendlyName : ieeeAddr;
const topic = `${name}/availability`;
const payload = available ? 'online' : 'offline';
if (this.state[ieeeAddr] !== available || force) {
this.state[ieeeAddr] = available;
this.mqtt.publish(topic, payload, {retain: true, qos: 0});
}
}
onZigbeeEvent(type, data, resolvedEntity) {
const device = data.device;
if (!device) {
return;
}
if (this.inPasslistOrNotInBlocklist(device)) {
this.publishAvailability(data.device, true);
if (this.isPingable(device)) {
// When a zigbee message from a device is received we know the device is still alive.
// => reset the timer.
this.setTimerPingable(device);
const online = this.state.hasOwnProperty(device.ieeeAddr) && this.state[device.ieeeAddr];
if (online && type === 'deviceAnnounce' && !utils.isIkeaTradfriDevice(device)) {
/**
* In case the device is powered off AND on within the availability timeout,
* zigbee2qmtt does not detect the device as offline (device is still marked online).
* When a device is turned on again the state could be out of sync.
* https://github.com/Koenkk/zigbee2mqtt/issues/1383#issuecomment-489412168
* deviceAnnounce is typically send when a device comes online.
*
* This isn't needed for TRADFRI devices as they already send the state themself.
*/
this.onReconnect(device);
}
}
}
}
}
module.exports = Availability;
+214
View File
@@ -0,0 +1,214 @@
import Extension from './extension';
import logger from '../util/logger';
import utils from '../util/utils';
import * as settings from '../util/settings';
import debounce from 'debounce';
import bind from 'bind-decorator';
const retrieveOnReconnect = [
{keys: ['state']},
{keys: ['brightness'], condition: (state: KeyValue): boolean => state.state === 'ON'},
{keys: ['color', 'color_temp'], condition: (state: KeyValue): boolean => state.state === 'ON'},
];
export default class Availability extends Extension {
private timers: {[s: string]: NodeJS.Timeout} = {};
private availabilityCache: {[s: string]: boolean} = {};
private retrieveStateDebouncers: {[s: string]: () => void} = {};
private pingQueue: Device[] = [];
private pingQueueExecuting = false;
private getTimeout(device: Device): number {
if (typeof device.options.availability === 'object' && device.options.availability?.timeout != null) {
return utils.minutes(device.options.availability.timeout);
}
const key = this.isActiveDevice(device) ? 'active' : 'passive';
let value = settings.get().availability?.[key]?.timeout;
if (value == null) value = key == 'active' ? 10 : 1500;
return utils.minutes(value);
}
private isActiveDevice(device: Device): boolean {
return (device.zh.type === 'Router' && device.zh.powerSource !== 'Battery') ||
device.zh.powerSource === 'Mains (single phase)';
}
private isAvailable(entity: Device | Group): boolean {
if (entity.isDevice()) {
const ago = Date.now() - entity.zh.lastSeen;
return ago < this.getTimeout(entity);
} else {
return entity.membersDevices().length === 0 ||
entity.membersDevices().map((d) => this.availabilityCache[d.ieeeAddr]).includes(true);
}
}
private resetTimer(device: Device): void {
clearTimeout(this.timers[device.ieeeAddr]);
// If the timer triggers, the device is not available anymore otherwise resetTimer already have been called
if (this.isActiveDevice(device)) {
// If device did not check in, ping it, if that fails it will be marked as offline
this.timers[device.ieeeAddr] = setTimeout(
() => this.addToPingQueue(device), this.getTimeout(device) + utils.seconds(1));
} else {
this.timers[device.ieeeAddr] = setTimeout(
() => this.publishAvailability(device, true), this.getTimeout(device) + utils.seconds(1));
}
}
private addToPingQueue(device: Device): void {
this.pingQueue.push(device);
this.pingQueueExecuteNext();
}
private removeFromPingQueue(device: Device): void {
const index = this.pingQueue.findIndex((d) => d.ieeeAddr === device.ieeeAddr);
index != -1 && this.pingQueue.splice(index, 1);
}
private async pingQueueExecuteNext(): Promise<void> {
if (this.pingQueue.length === 0 || this.pingQueueExecuting) return;
this.pingQueueExecuting = true;
const device = this.pingQueue[0];
let pingedSuccessfully = false;
const available = this.availabilityCache[device.ieeeAddr] || this.isAvailable(device);
const attempts = available ? 2 : 1;
for (let i = 0; i < attempts; i++) {
try {
// Enable recovery if device is marked as available and first ping fails.
const disableRecovery = !(i == 1 && available);
await device.zh.ping(disableRecovery);
pingedSuccessfully = true;
logger.debug(`Successfully pinged '${device.name}' (attempt ${i + 1}/${attempts})`);
break;
} catch (error) {
logger.warn(`Failed to ping '${device.name}' (attempt ${i + 1}/${attempts}, ${error.message})`);
// Try again in 3 seconds.
const lastAttempt = i - 1 === attempts;
!lastAttempt && await utils.sleep(3);
}
}
this.publishAvailability(device, !pingedSuccessfully);
this.resetTimer(device);
this.removeFromPingQueue(device);
// Sleep 2 seconds before executing next ping
await utils.sleep(2);
this.pingQueueExecuting = false;
this.pingQueueExecuteNext();
}
override async start(): Promise<void> {
this.eventBus.onEntityRenamed(this, (data) => {
if (utils.isAvailabilityEnabledForEntity(data.entity, settings.get())) {
this.mqtt.publish(`${data.from}/availability`, null, {retain: true, qos: 1});
this.publishAvailability(data.entity, false, true);
}
});
this.eventBus.onDeviceRemoved(this, (data) => clearTimeout(this.timers[data.ieeeAddr]));
this.eventBus.onDeviceLeave(this, (data) => clearTimeout(this.timers[data.ieeeAddr]));
this.eventBus.onDeviceAnnounce(this, (data) => this.retrieveState(data.device));
this.eventBus.onLastSeenChanged(this, this.onLastSeenChanged);
this.eventBus.onPublishAvailability(this, this.publishAvailabilityForAllEntities);
this.eventBus.onGroupMembersChanged(this, (data) => this.publishAvailability(data.group, false));
this.publishAvailabilityForAllEntities();
}
@bind private publishAvailabilityForAllEntities(): void {
for (const entity of [...this.zigbee.devices(false), ...this.zigbee.groups()]) {
if (utils.isAvailabilityEnabledForEntity(entity, settings.get())) {
// Publish initial availability
this.publishAvailability(entity, true, false, true);
if (entity.isDevice()) {
this.resetTimer(entity);
// If an active device is initially unavailable, ping it.
if (this.isActiveDevice(entity) && !this.isAvailable(entity)) {
this.addToPingQueue(entity);
}
}
}
}
}
private publishAvailability(entity: Device | Group, logLastSeen: boolean,
forcePublish=false, skipGroups=false): void {
if (logLastSeen && entity.isDevice()) {
const ago = Date.now() - entity.zh.lastSeen;
if (this.isActiveDevice(entity)) {
logger.debug(`Active device '${entity.name}' was last seen ` +
`'${(ago / utils.minutes(1)).toFixed(2)}' minutes ago.`);
} else {
logger.debug(
`Passive device '${entity.name}' was last seen '${(ago / utils.hours(1)).toFixed(2)}' hours ago.`);
}
}
const available = this.isAvailable(entity);
if (!forcePublish && this.availabilityCache[entity.ID] == available) {
return;
}
if (entity.isDevice() && entity.ieeeAddr in this.availabilityCache && available &&
this.availabilityCache[entity.ieeeAddr] === false) {
logger.debug(`Device '${entity.name}' reconnected`);
this.retrieveState(entity);
}
const topic = `${entity.name}/availability`;
const payload = utils.availabilityPayload(available ? 'online' : 'offline', settings.get());
this.availabilityCache[entity.ID] = available;
this.mqtt.publish(topic, payload, {retain: true, qos: 1});
if (!skipGroups && entity.isDevice()) {
this.zigbee.groups().filter((g) => g.hasMember(entity))
.filter((g) => utils.isAvailabilityEnabledForEntity(g, settings.get()))
.forEach((g) => this.publishAvailability(g, false, forcePublish));
}
}
@bind private onLastSeenChanged(data: eventdata.LastSeenChanged): void {
if (utils.isAvailabilityEnabledForEntity(data.device, settings.get())) {
// Remove from ping queue, not necessary anymore since we know the device is online.
this.removeFromPingQueue(data.device);
this.resetTimer(data.device);
this.publishAvailability(data.device, false);
}
}
override async stop(): Promise<void> {
Object.values(this.timers).forEach((t) => clearTimeout(t));
super.stop();
}
private retrieveState(device: Device): void {
/**
* Retrieve state of a device in a debounced manner, this function is called on a 'deviceAnnounce' which a
* device can send multiple times after each other.
*/
if (device.definition && !device.zh.interviewing && !this.retrieveStateDebouncers[device.ieeeAddr]) {
this.retrieveStateDebouncers[device.ieeeAddr] = debounce(async () => {
logger.debug(`Retrieving state of '${device.name}' after reconnect`);
// Color and color temperature converters do both, only needs to be called once.
for (const item of retrieveOnReconnect) {
if (item.condition && this.state.get(device) && !item.condition(this.state.get(device))) continue;
const converter = device.definition.toZigbee.find((c) => c.key.find((k) => item.keys.includes(k)));
await converter?.convertGet?.(device.endpoint(), item.keys[0],
{message: this.state.get(device), mapped: device.definition})
.catch((e) => {
logger.error(`Failed to read state of '${device.name}' after reconnect (${e.message})`);
});
await utils.sleep(500);
}
}, utils.seconds(2));
}
this.retrieveStateDebouncers[device.ieeeAddr]?.();
}
}
-409
View File
@@ -1,409 +0,0 @@
const settings = require('../util/settings');
const logger = require('../util/logger');
const utils = require('../util/utils');
const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/(bind|unbind)/.+$`);
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/device/(bind|unbind)`);
const Extension = require('./extension');
const stringify = require('json-stable-stringify-without-jsonify');
const debounce = require('debounce');
const zigbeeHersdman = require('zigbee-herdsman');
const clusterCandidates = ['genScenes', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'closuresWindowCovering'];
// See zigbee-herdsman-converters devices.js
const defaultBindGroup = {type: 'group_number', ID: 901};
const defaultReportConfiguration = {
minimumReportInterval: 5, maximumReportInterval: 3600, reportableChange: 1,
};
const getColorCapabilities = async (endpoint) => {
if (endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities') == null) {
await endpoint.read('lightingColorCtrl', ['colorCapabilities']);
}
const value = endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities');
return {
colorTemperature: (value & 1<<4) > 0,
colorXY: (value & 1<<3) > 0,
};
};
const reportClusters = {
'genOnOff': [
{attribute: 'onOff', ...defaultReportConfiguration, minimumReportInterval: 0, reportableChange: 0},
],
'genLevelCtrl': [
{attribute: 'currentLevel', ...defaultReportConfiguration},
],
'lightingColorCtrl': [
{
attribute: 'colorTemperature', ...defaultReportConfiguration,
condition: async (endpoint) => (await getColorCapabilities(endpoint)).colorTemperature,
},
{
attribute: 'currentX', ...defaultReportConfiguration,
condition: async (endpoint) => (await getColorCapabilities(endpoint)).colorXY,
},
{
attribute: 'currentY', ...defaultReportConfiguration,
condition: async (endpoint) => (await getColorCapabilities(endpoint)).colorXY,
},
],
'closuresWindowCovering': [
{attribute: 'currentPositionLiftPercentage', ...defaultReportConfiguration},
{attribute: 'currentPositionTiltPercentage', ...defaultReportConfiguration},
],
};
const pollOnMessage = [
{
// On messages that have the cluster and type of below
cluster: {
manuSpecificPhilips: [
{type: 'commandHueNotification', data: {button: 2}},
{type: 'commandHueNotification', data: {button: 3}},
],
genLevelCtrl: [
{type: 'commandStep', data: {}},
{type: 'commandStepWithOnOff', data: {}},
{type: 'commandStop', data: {}},
{type: 'commandMoveWithOnOff', data: {}},
{type: 'commandStopWithOnOff', data: {}},
{type: 'commandMove', data: {}},
{type: 'commandMoveToLevelWithOnOff', data: {}},
],
},
// Read the following attributes
read: {cluster: 'genLevelCtrl', attributes: ['currentLevel']},
// When the bound devices/members of group have the following manufacturerIDs
manufacturerIDs: [
zigbeeHersdman.Zcl.ManufacturerCode.Philips,
zigbeeHersdman.Zcl.ManufacturerCode.ATMEL,
zigbeeHersdman.Zcl.ManufacturerCode.GLEDOPTO_CO_LTD,
zigbeeHersdman.Zcl.ManufacturerCode.MUELLER_LICHT_INT,
],
},
{
cluster: {
genLevelCtrl: [
{type: 'commandStepWithOnOff', data: {}},
{type: 'commandMoveWithOnOff', data: {}},
{type: 'commandStopWithOnOff', data: {}},
{type: 'commandMoveToLevelWithOnOff', data: {}},
],
genOnOff: [
{type: 'commandOn', data: {}},
{type: 'commandOff', data: {}},
{type: 'commandOffWithEffect', data: {}},
{type: 'commandToggle', data: {}},
],
manuSpecificPhilips: [
{type: 'commandHueNotification', data: {button: 1}},
{type: 'commandHueNotification', data: {button: 4}},
],
},
read: {cluster: 'genOnOff', attributes: ['onOff']},
manufacturerIDs: [
zigbeeHersdman.Zcl.ManufacturerCode.Philips,
zigbeeHersdman.Zcl.ManufacturerCode.ATMEL,
zigbeeHersdman.Zcl.ManufacturerCode.GLEDOPTO_CO_LTD,
zigbeeHersdman.Zcl.ManufacturerCode.MUELLER_LICHT_INT,
],
},
];
class Bind extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.legacyApi = settings.get().advanced.legacy_api;
this.eventBus.on(`groupMembersChanged`, (d) => this.groupMembersChanged(d));
this.pollDebouncers = {};
}
parseMQTTMessage(topic, message) {
let type = null;
let sourceKey = null;
let targetKey = null;
let clusters = null;
if (this.legacyApi && topic.match(legacyTopicRegex)) {
topic = topic.replace(`${settings.get().mqtt.base_topic}/bridge/`, '');
type = topic.split('/')[0];
sourceKey = topic.replace(`${type}/`, '');
targetKey = message;
} else if (topic.match(topicRegex)) {
type = topic.endsWith('unbind') ? 'unbind' : 'bind';
message = JSON.parse(message);
sourceKey = message.from;
targetKey = message.to;
clusters = message.clusters;
}
return {type, sourceKey, targetKey, clusters};
}
async onMQTTMessage(topic, message) {
const {type, sourceKey, targetKey, clusters} = this.parseMQTTMessage(topic, message);
if (!type) return null;
message = utils.parseJSON(message, message);
let error = null;
const source = this.zigbee.resolveEntity(sourceKey);
const target = targetKey === 'default_bind_group' ? defaultBindGroup : this.zigbee.resolveEntity(targetKey);
const responseData = {from: sourceKey, to: targetKey};
if (!source || source.type !== 'device') {
error = `Source device '${sourceKey}' does not exist`;
} else if (!target) {
error = `Target device or group '${targetKey}' does not exist`;
} else {
const sourceName = source.settings.friendlyName;
const targetName = targetKey === 'default_bind_group' ? targetKey : target.settings.friendlyName;
const successfulClusters = [];
const failedClusters = [];
const attemptedClusters = [];
let bindTarget = null;
if (target.type === 'group') bindTarget = target.group;
else if (target.type === 'group_number') bindTarget = target.ID;
else bindTarget = target.endpoint;
// Find which clusters are supported by both the source and target.
// Groups are assumed to support all clusters.
for (const cluster of clusterCandidates) {
if (clusters && !clusters.includes(cluster)) continue;
const targetValid = target.type === 'group' || target.type === 'group_number' ||
target.device.type === 'Coordinator' || target.endpoint.supportsInputCluster(cluster);
if (source.endpoint.supportsOutputCluster(cluster) && targetValid) {
logger.debug(`${type}ing cluster '${cluster}' from '${sourceName}' to '${targetName}'`);
attemptedClusters.push(cluster);
try {
if (type === 'bind') {
await source.endpoint.bind(cluster, bindTarget);
} else {
await source.endpoint.unbind(cluster, bindTarget);
}
successfulClusters.push(cluster);
logger.info(
`Successfully ${type === 'bind' ? 'bound' : 'unbound'} cluster '${cluster}' from ` +
`'${sourceName}' to '${targetName}'`,
);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish(
'bridge/log',
stringify({type: `device_${type}`,
message: {from: sourceName, to: targetName, cluster}}),
);
}
} catch (error) {
failedClusters.push(cluster);
logger.error(
`Failed to ${type} cluster '${cluster}' from '${sourceName}' to ` +
`'${targetName}' (${error})`,
);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish(
'bridge/log',
stringify({type: `device_${type}_failed`,
message: {from: sourceName, to: targetName, cluster}}),
);
}
}
}
}
if (attemptedClusters.length === 0) {
logger.error(`Nothing to ${type} from '${sourceName}' to '${targetName}'`);
error = `Nothing to ${type}`;
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish(
'bridge/log',
stringify({type: `device_${type}_failed`, message: {from: sourceName, to: targetName}}),
);
}
} else if (failedClusters.length === attemptedClusters.length) {
error = `Failed to ${type}`;
}
responseData[`clusters`] = successfulClusters;
responseData[`failed`] = failedClusters;
if (successfulClusters.length !== 0) {
if (type === 'bind') {
await this.setupReporting(source.endpoint.binds.filter((b) =>
successfulClusters.includes(b.cluster.name) && b.target === bindTarget));
} else if (target.type !== 'group_number') {
await this.disableUnnecessaryReportings(bindTarget);
}
}
}
const triggeredViaLegacyApi = topic.match(legacyTopicRegex);
if (!triggeredViaLegacyApi) {
const response = utils.getResponse(message, responseData, error);
await this.mqtt.publish(`bridge/response/device/${type}`, stringify(response));
}
if (error) {
logger.error(error);
} else {
this.eventBus.emit(`devicesChanged`);
}
}
async groupMembersChanged(data) {
const bindsToGroup = this.zigbee.getClients().map((c) => c.endpoints).flat().map((e) => e.binds)
.flat().filter((b) => b.target === data.group.group);
if (data.action === 'add') {
await this.setupReporting(bindsToGroup);
} else { // action === remove/remove_all
await this.disableUnnecessaryReportings(data.endpoint);
}
}
getSetupReportingEndpoints(bind, coordinatorEp) {
const endpoints = bind.target.constructor.name === 'Group' ? bind.target.members : [bind.target];
return endpoints.filter((e) => {
const supportsInputCluster = e.supportsInputCluster(bind.cluster.name);
const hasConfiguredReporting = !!e.configuredReportings.find((c) => c.cluster.name === bind.cluster.name);
const hasBind = !!e.binds.find((b) => b.cluster.name === bind.cluster.name && b.target === coordinatorEp);
return supportsInputCluster && !(hasBind && hasConfiguredReporting);
});
}
async setupReporting(binds) {
const coordinator = this.zigbee.getDevicesByType('Coordinator')[0];
const coordinatorEndpoint = coordinator.getEndpoint(1);
for (const bind of binds.filter((b) => b.cluster.name in reportClusters)) {
for (const endpoint of this.getSetupReportingEndpoints(bind, coordinatorEndpoint)) {
const entity = `${this.zigbee.resolveEntity(endpoint.getDevice()).name}/${endpoint.ID}`;
try {
await endpoint.bind(bind.cluster.name, coordinatorEndpoint);
const items = await reportClusters[bind.cluster.name]
.filter(async (a) => !a.condition || await a.condition(endpoint))
.map((a) => {
const result = {...a};
delete result.condition;
return result;
});
await endpoint.configureReporting(bind.cluster.name, items);
logger.info(`Succesfully setup reporting for '${entity}' cluster '${bind.cluster.name}'`);
} catch (error) {
logger.warn(`Failed to setup reporting for '${entity}' cluster '${bind.cluster.name}'`);
}
}
}
this.eventBus.emit(`devicesChanged`);
}
async disableUnnecessaryReportings(target) {
const coordinator = this.zigbee.getDevicesByType('Coordinator')[0];
const coordinatorEndpoint = coordinator.getEndpoint(1);
const endpoints = target.constructor.name === 'Group' ? target.members : [target];
for (const endpoint of endpoints) {
const entity = `${this.zigbee.resolveEntity(endpoint.getDevice()).name}/${endpoint.ID}`;
const boundClusters = endpoint.binds.filter((b) => b.target === coordinatorEndpoint)
.map((b) => b.cluster.name);
const requiredClusters = this.zigbee.getClients().map((c) => c.endpoints).flat().map((e) => e.binds)
.flat().filter((bind) => {
if (bind.target.constructor.name === 'Group') {
return bind.target.members.includes(endpoint);
} else {
return bind.target === endpoint;
}
}).map((b) => b.cluster.name).filter((v, i, a) => a.indexOf(v) === i);
for (const cluster of boundClusters.filter((c) => !requiredClusters.includes(c) && c in reportClusters)) {
try {
await endpoint.unbind(cluster, coordinatorEndpoint);
const items = await reportClusters[cluster]
.filter(async (a) => !a.condition || await a.condition(endpoint))
.map((a) => {
const result = {...a, maximumReportInterval: 0xFFFF};
delete result.condition;
return result;
});
await endpoint.configureReporting(cluster, items);
logger.info(`Succesfully disabled reporting for '${entity}' cluster '${cluster}'`);
} catch (error) {
logger.warn(`Failed to disable reporting for '${entity}' cluster '${cluster}'`);
}
}
this.eventBus.emit('reportingDisabled', {device: endpoint.getDevice()});
}
}
async onZigbeeEvent(type, data, resolvedEntity) {
if (type === 'message') {
this.poll(data);
}
}
poll(message) {
/**
* This method poll bound endpoints and group members for state changes.
*
* A use case is e.g. a Hue Dimmer switch bound to a Hue bulb.
* Hue bulbs only report their on/off state.
* When dimming the bulb via the dimmer switch the state is therefore not reported.
* When we receive a message from a Hue dimmer we read the brightness from the bulb (if bound).
*/
const polls = pollOnMessage.filter((p) =>
p.cluster[message.cluster] && p.cluster[message.cluster].find((c) => c.type === message.type &&
utils.equalsPartial(message.data, c.data)),
);
if (polls.length) {
let toPoll = [];
// Add bound devices
toPoll = toPoll.concat([].concat(...message.device.endpoints.map((e) =>
e.binds.map((e) => e).filter((e) => e.target))));
toPoll = toPoll.filter((e) => e.target.constructor.name === 'Endpoint');
toPoll = toPoll.filter((e) => e.target.getDevice().type !== 'Coordinator');
toPoll = toPoll.map((e) => e.target);
// If message is published to a group, add members of the group
const group = message.groupID !== 0 ? this.zigbee.getGroupByID(message.groupID) : null;
if (group) {
toPoll = toPoll.concat(group.members);
}
toPoll = new Set(toPoll);
for (const endpoint of toPoll) {
for (const poll of polls) {
if (!poll.manufacturerIDs.includes(endpoint.getDevice().manufacturerID)) {
continue;
}
const key = `${endpoint.deviceIeeeAddress}_${endpoint.ID}_${pollOnMessage.indexOf(poll)}`;
if (!this.pollDebouncers[key]) {
this.pollDebouncers[key] = debounce(async () => {
await endpoint.read(poll.read.cluster, poll.read.attributes);
}, 1000);
}
this.pollDebouncers[key]();
}
}
}
}
}
module.exports = Bind;
+504
View File
@@ -0,0 +1,504 @@
import * as settings from '../util/settings';
import logger from '../util/logger';
import utils from '../util/utils';
import Extension from './extension';
import stringify from 'json-stable-stringify-without-jsonify';
import debounce from 'debounce';
import * as zigbeeHerdsman from 'zigbee-herdsman/dist';
import bind from 'bind-decorator';
import Device from '../model/device';
import Group from '../model/group';
const legacyApi = settings.get().advanced.legacy_api;
const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/(bind|unbind)/.+$`);
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/device/(bind|unbind)`);
const allClusterCandidates = ['genScenes', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'closuresWindowCovering',
'hvacThermostat', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msRelativeHumidity',
'msSoilMoisture', 'msCO2'];
// See zigbee-herdsman-converters
const defaultBindGroup = {type: 'group_number', ID: 901, name: 'default_bind_group'};
const defaultReportConfiguration = {
minimumReportInterval: 5, maximumReportInterval: 3600, reportableChange: 1,
};
const getColorCapabilities = async (endpoint: zh.Endpoint): Promise<{colorTemperature: boolean, colorXY: boolean}> => {
if (endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities') == null) {
await endpoint.read('lightingColorCtrl', ['colorCapabilities']);
}
const value = endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities') as number;
return {
colorTemperature: (value & 1<<4) > 0,
colorXY: (value & 1<<3) > 0,
};
};
const reportClusters: {[s: string]:
{attribute: string, minimumReportInterval: number, maximumReportInterval: number, reportableChange: number
condition?: (endpoint: zh.Endpoint) => Promise<boolean>}[]} =
{
'genOnOff': [
{attribute: 'onOff', ...defaultReportConfiguration, minimumReportInterval: 0, reportableChange: 0},
],
'genLevelCtrl': [
{attribute: 'currentLevel', ...defaultReportConfiguration},
],
'lightingColorCtrl': [
{
attribute: 'colorTemperature', ...defaultReportConfiguration,
condition: async (endpoint): Promise<boolean> => (await getColorCapabilities(endpoint)).colorTemperature,
},
{
attribute: 'currentX', ...defaultReportConfiguration,
condition: async (endpoint): Promise<boolean> => (await getColorCapabilities(endpoint)).colorXY,
},
{
attribute: 'currentY', ...defaultReportConfiguration,
condition: async (endpoint): Promise<boolean> => (await getColorCapabilities(endpoint)).colorXY,
},
],
'closuresWindowCovering': [
{attribute: 'currentPositionLiftPercentage', ...defaultReportConfiguration},
{attribute: 'currentPositionTiltPercentage', ...defaultReportConfiguration},
],
};
type PollOnMessage = {
cluster: {[s: string]: {type: string, data: KeyValue}[]}
read: {cluster: string, attributes: string[], attributesForEndpoint?: (endpoint: zh.Endpoint) => Promise<string[]>}
manufacturerIDs: number[],
manufacturerNames: string [],
}[];
const pollOnMessage: PollOnMessage = [
{
// On messages that have the cluster and type of below
cluster: {
manuSpecificPhilips: [
{type: 'commandHueNotification', data: {button: 2}},
{type: 'commandHueNotification', data: {button: 3}},
],
genLevelCtrl: [
{type: 'commandStep', data: {}},
{type: 'commandStepWithOnOff', data: {}},
{type: 'commandStop', data: {}},
{type: 'commandMoveWithOnOff', data: {}},
{type: 'commandStopWithOnOff', data: {}},
{type: 'commandMove', data: {}},
{type: 'commandMoveToLevelWithOnOff', data: {}},
],
genScenes: [
{type: 'commandRecall', data: {}},
],
},
// Read the following attributes
read: {cluster: 'genLevelCtrl', attributes: ['currentLevel']},
// When the bound devices/members of group have the following manufacturerIDs
manufacturerIDs: [
zigbeeHerdsman.Zcl.ManufacturerCode.Philips,
zigbeeHerdsman.Zcl.ManufacturerCode.ATMEL,
zigbeeHerdsman.Zcl.ManufacturerCode.GLEDOPTO_CO_LTD,
zigbeeHerdsman.Zcl.ManufacturerCode.MUELLER_LICHT_INT,
zigbeeHerdsman.Zcl.ManufacturerCode.TELINK,
zigbeeHerdsman.Zcl.ManufacturerCode.BUSCH_JAEGER,
],
manufacturerNames: [
'GLEDOPTO',
'Trust International B.V.\u0000',
],
},
{
cluster: {
genLevelCtrl: [
{type: 'commandStepWithOnOff', data: {}},
{type: 'commandMoveWithOnOff', data: {}},
{type: 'commandStopWithOnOff', data: {}},
{type: 'commandMoveToLevelWithOnOff', data: {}},
],
genOnOff: [
{type: 'commandOn', data: {}},
{type: 'commandOff', data: {}},
{type: 'commandOffWithEffect', data: {}},
{type: 'commandToggle', data: {}},
],
genScenes: [
{type: 'commandRecall', data: {}},
],
manuSpecificPhilips: [
{type: 'commandHueNotification', data: {button: 1}},
{type: 'commandHueNotification', data: {button: 4}},
],
},
read: {cluster: 'genOnOff', attributes: ['onOff']},
manufacturerIDs: [
zigbeeHerdsman.Zcl.ManufacturerCode.Philips,
zigbeeHerdsman.Zcl.ManufacturerCode.ATMEL,
zigbeeHerdsman.Zcl.ManufacturerCode.GLEDOPTO_CO_LTD,
zigbeeHerdsman.Zcl.ManufacturerCode.MUELLER_LICHT_INT,
zigbeeHerdsman.Zcl.ManufacturerCode.TELINK,
zigbeeHerdsman.Zcl.ManufacturerCode.BUSCH_JAEGER,
],
manufacturerNames: [
'GLEDOPTO',
'Trust International B.V.\u0000',
],
},
{
cluster: {
genScenes: [
{type: 'commandRecall', data: {}},
],
},
read: {
cluster: 'lightingColorCtrl',
attributes: [] as string[],
// Since not all devices support the same attributes they need to be calculated dynamically
// depending on the capabilities of the endpoint.
attributesForEndpoint: async (endpoint): Promise<string[]> => {
const supportedAttrs = await getColorCapabilities(endpoint);
const readAttrs: string[] = [];
supportedAttrs.colorXY && readAttrs.push('currentX', 'currentY');
supportedAttrs.colorTemperature && readAttrs.push('colorTemperature');
return readAttrs;
},
},
manufacturerIDs: [
zigbeeHerdsman.Zcl.ManufacturerCode.Philips,
zigbeeHerdsman.Zcl.ManufacturerCode.ATMEL,
zigbeeHerdsman.Zcl.ManufacturerCode.GLEDOPTO_CO_LTD,
zigbeeHerdsman.Zcl.ManufacturerCode.MUELLER_LICHT_INT,
zigbeeHerdsman.Zcl.ManufacturerCode.TELINK,
// Note: ManufacturerCode.BUSCH_JAEGER is left out intentionally here as their devices don't support colors
],
manufacturerNames: [
'GLEDOPTO',
'Trust International B.V.\u0000',
],
},
];
interface ParsedMQTTMessage {
type: 'bind' | 'unbind', sourceKey: string, targetKey: string, clusters: string[], skipDisableReporting: boolean
}
export default class Bind extends Extension {
private pollDebouncers: {[s: string]: () => void} = {};
override async start(): Promise<void> {
this.eventBus.onDeviceMessage(this, this.poll);
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
this.eventBus.onGroupMembersChanged(this, this.onGroupMembersChanged);
}
private parseMQTTMessage(data: eventdata.MQTTMessage): ParsedMQTTMessage {
let type: 'bind' | 'unbind' = null;
let sourceKey = null;
let targetKey = null;
let clusters = null;
let skipDisableReporting = false;
if (legacyApi && data.topic.match(legacyTopicRegex)) {
const topic = data.topic.replace(`${settings.get().mqtt.base_topic}/bridge/`, '');
type = topic.split('/')[0] as 'bind' | 'unbind';
sourceKey = topic.replace(`${type}/`, '');
targetKey = data.message;
} else if (data.topic.match(topicRegex)) {
type = data.topic.endsWith('unbind') ? 'unbind' : 'bind';
const message = JSON.parse(data.message);
sourceKey = message.from;
targetKey = message.to;
clusters = message.clusters;
skipDisableReporting = 'skip_disable_reporting' in message ? message.skip_disable_reporting : false;
}
return {type, sourceKey, targetKey, clusters, skipDisableReporting};
}
@bind private async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const {type, sourceKey, targetKey, clusters, skipDisableReporting} = this.parseMQTTMessage(data);
if (!type) return null;
const message = utils.parseJSON(data.message, data.message);
let error = null;
const parsedSource = utils.parseEntityID(sourceKey);
const parsedTarget = utils.parseEntityID(targetKey);
const source = this.zigbee.resolveEntity(parsedSource.ID);
const target = targetKey === 'default_bind_group' ?
defaultBindGroup : this.zigbee.resolveEntity(parsedTarget.ID);
const responseData: KeyValue = {from: sourceKey, to: targetKey};
if (!source || !(source instanceof Device)) {
error = `Source device '${sourceKey}' does not exist`;
} else if (!target) {
error = `Target device or group '${targetKey}' does not exist`;
} else {
const successfulClusters: string[] = [];
const failedClusters = [];
const attemptedClusters = [];
const bindSource: zh.Endpoint = source.endpoint(parsedSource.endpoint);
let bindTarget: number | zh.Group | zh.Endpoint = null;
if (target instanceof Device) bindTarget = target.endpoint(parsedTarget.endpoint);
else if (target instanceof Group) bindTarget = target.zh;
else bindTarget = Number(target.ID);
// Find which clusters are supported by both the source and target.
// Groups are assumed to support all clusters.
const clusterCandidates = clusters ?? allClusterCandidates;
for (const cluster of clusterCandidates) {
let matchingClusters = false;
const anyClusterValid = utils.isZHGroup(bindTarget) || typeof bindTarget === 'number' ||
(target as Device).zh.type === 'Coordinator';
if (!anyClusterValid && utils.isEndpoint(bindTarget)) {
matchingClusters = ((bindTarget.supportsInputCluster(cluster) &&
bindSource.supportsOutputCluster(cluster)) ||
(bindSource.supportsInputCluster(cluster) &&
bindTarget.supportsOutputCluster(cluster)) );
}
const sourceValid = bindSource.supportsInputCluster(cluster) ||
bindSource.supportsOutputCluster(cluster);
if ( sourceValid && (anyClusterValid || matchingClusters)) {
logger.debug(`${type}ing cluster '${cluster}' from '${source.name}' to '${target.name}'`);
attemptedClusters.push(cluster);
try {
if (type === 'bind') {
await bindSource.bind(cluster, bindTarget);
} else {
await bindSource.unbind(cluster, bindTarget);
}
successfulClusters.push(cluster);
logger.info(
`Successfully ${type === 'bind' ? 'bound' : 'unbound'} cluster '${cluster}' from ` +
`'${source.name}' to '${target.name}'`,
);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish(
'bridge/log',
stringify({type: `device_${type}`,
message: {from: source.name, to: target.name, cluster}}),
);
}
} catch (error) {
failedClusters.push(cluster);
logger.error(
`Failed to ${type} cluster '${cluster}' from '${source.name}' to ` +
`'${target.name}' (${error})`,
);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish(
'bridge/log',
stringify({type: `device_${type}_failed`,
message: {from: source.name, to: target.name, cluster}}),
);
}
}
}
}
if (attemptedClusters.length === 0) {
logger.error(`Nothing to ${type} from '${source.name}' to '${target.name}'`);
error = `Nothing to ${type}`;
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish(
'bridge/log',
stringify({type: `device_${type}_failed`, message: {from: source.name, to: target.name}}),
);
}
} else if (failedClusters.length === attemptedClusters.length) {
error = `Failed to ${type}`;
}
responseData[`clusters`] = successfulClusters;
responseData[`failed`] = failedClusters;
if (successfulClusters.length !== 0) {
if (type === 'bind') {
await this.setupReporting(bindSource.binds.filter((b) =>
successfulClusters.includes(b.cluster.name) && b.target === bindTarget));
} else if ((typeof bindTarget !== 'number') && !skipDisableReporting) {
await this.disableUnnecessaryReportings(bindTarget);
}
}
}
const triggeredViaLegacyApi = data.topic.match(legacyTopicRegex);
if (!triggeredViaLegacyApi) {
const response = utils.getResponse(message, responseData, error);
await this.mqtt.publish(`bridge/response/device/${type}`, stringify(response));
}
if (error) {
logger.error(error);
} else {
this.eventBus.emitDevicesChanged();
}
}
@bind async onGroupMembersChanged(data: eventdata.GroupMembersChanged): Promise<void> {
if (data.action === 'add') {
const bindsToGroup = this.zigbee.devices(false).map((c) => c.zh.endpoints)
.reduce((a, v) => a.concat(v)).map((e) => e.binds)
.reduce((a, v) => a.concat(v)).filter((b) => b.target === data.group.zh);
await this.setupReporting(bindsToGroup);
} else { // action === remove/remove_all
if (!data.skipDisableReporting) {
await this.disableUnnecessaryReportings(data.endpoint);
}
}
}
getSetupReportingEndpoints(bind: zh.Bind, coordinatorEp: zh.Endpoint): zh.Endpoint[] {
const endpoints = utils.isEndpoint(bind.target) ? [bind.target] : bind.target.members;
return endpoints.filter((e) => {
const supportsInputCluster = e.supportsInputCluster(bind.cluster.name);
const hasConfiguredReporting = !!e.configuredReportings.find((c) => c.cluster.name === bind.cluster.name);
const hasBind = !!e.binds.find((b) => b.cluster.name === bind.cluster.name && b.target === coordinatorEp);
return supportsInputCluster && !(hasBind && hasConfiguredReporting);
});
}
async setupReporting(binds: zh.Bind[]): Promise<void> {
const coordinatorEndpoint = this.zigbee.firstCoordinatorEndpoint();
for (const bind of binds.filter((b) => b.cluster.name in reportClusters)) {
for (const endpoint of this.getSetupReportingEndpoints(bind, coordinatorEndpoint)) {
const entity = `${this.zigbee.resolveEntity(endpoint.getDevice()).name}/${endpoint.ID}`;
try {
await endpoint.bind(bind.cluster.name, coordinatorEndpoint);
const items = [];
for (const c of reportClusters[bind.cluster.name]) {
/* istanbul ignore else */
if (!c.condition || await c.condition(endpoint)) {
const i = {...c};
delete i.condition;
items.push(i);
}
}
await endpoint.configureReporting(bind.cluster.name, items);
logger.info(`Successfully setup reporting for '${entity}' cluster '${bind.cluster.name}'`);
} catch (error) {
logger.warn(`Failed to setup reporting for '${entity}' cluster '${bind.cluster.name}'`);
}
}
}
this.eventBus.emitDevicesChanged();
}
async disableUnnecessaryReportings(target: zh.Group | zh.Endpoint): Promise<void> {
const coordinator = this.zigbee.firstCoordinatorEndpoint();
const endpoints = utils.isEndpoint(target) ? [target] : target.members;
for (const endpoint of endpoints) {
const device = this.zigbee.resolveEntity(endpoint.getDevice()) as Device;
const entity = `${device.name}/${endpoint.ID}`;
const boundClusters = endpoint.binds.filter((b) => b.target === coordinator)
.map((b) => b.cluster.name);
const requiredClusters = this.zigbee.devices(false).map((c) => c.zh.endpoints)
.reduce((a, v) => a.concat(v))
.map((e) => e.binds).reduce((a, v) => a.concat(v)).filter((bind) => {
if (utils.isEndpoint(bind.target)) {
return bind.target === endpoint;
} else {
return bind.target.members.includes(endpoint);
}
}).map((b) => b.cluster.name).filter((v, i, a) => a.indexOf(v) === i);
for (const cluster of boundClusters.filter((c) => !requiredClusters.includes(c) && c in reportClusters)) {
try {
await endpoint.unbind(cluster, coordinator);
const items = [];
for (const item of reportClusters[cluster]) {
/* istanbul ignore else */
if (!item.condition || await item.condition(endpoint)) {
const i = {...item};
delete i.condition;
items.push({...i, maximumReportInterval: 0xFFFF});
}
}
await endpoint.configureReporting(cluster, items);
logger.info(`Successfully disabled reporting for '${entity}' cluster '${cluster}'`);
} catch (error) {
logger.warn(`Failed to disable reporting for '${entity}' cluster '${cluster}'`);
}
}
this.eventBus.emitReconfigure({device});
}
}
@bind async poll(data: eventdata.DeviceMessage): Promise<void> {
/**
* This method poll bound endpoints and group members for state changes.
*
* A use case is e.g. a Hue Dimmer switch bound to a Hue bulb.
* Hue bulbs only report their on/off state.
* When dimming the bulb via the dimmer switch the state is therefore not reported.
* When we receive a message from a Hue dimmer we read the brightness from the bulb (if bound).
*/
const polls = pollOnMessage.filter((p) =>
p.cluster[data.cluster]?.find((c) => c.type === data.type && utils.equalsPartial(data.data, c.data)));
if (polls.length) {
const toPoll: Set<zh.Endpoint> = new Set();
// Add bound devices
for (const endpoint of data.device.zh.endpoints) {
for (const bind of endpoint.binds) {
if (utils.isEndpoint(bind.target) && bind.target.getDevice().type !== 'Coordinator') {
toPoll.add(bind.target);
}
}
}
// If message is published to a group, add members of the group
const group = data.groupID && data.groupID !== 0 && this.zigbee.groupByID(data.groupID);
if (group) {
group.zh.members.forEach((m) => toPoll.add(m));
}
for (const endpoint of toPoll) {
for (const poll of polls) {
if ((!poll.manufacturerIDs.includes(endpoint.getDevice().manufacturerID) &&
!poll.manufacturerNames.includes(endpoint.getDevice().manufacturerName)) ||
!endpoint.supportsInputCluster(poll.read.cluster)) {
continue;
}
let readAttrs = poll.read.attributes;
if (poll.read.attributesForEndpoint) {
const attrsForEndpoint = await poll.read.attributesForEndpoint(endpoint);
readAttrs = [...poll.read.attributes, ...attrsForEndpoint];
}
const key = `${endpoint.getDevice().ieeeAddr}_${endpoint.ID}_${pollOnMessage.indexOf(poll)}`;
if (!this.pollDebouncers[key]) {
this.pollDebouncers[key] = debounce(async () => {
try {
await endpoint.read(poll.read.cluster, readAttrs);
} catch (error) {
logger.error(`Failed to poll ${readAttrs} from ` +
`${this.zigbee.resolveEntity(endpoint.getDevice()).name}`);
}
}, 1000);
}
this.pollDebouncers[key]();
}
}
}
}
}
-670
View File
@@ -1,670 +0,0 @@
const logger = require('../util/logger');
const utils = require('../util/utils');
const Extension = require('./extension');
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const settings = require('../util/settings');
const Transport = require('winston-transport');
const stringify = require('json-stable-stringify-without-jsonify');
const objectAssignDeep = require(`object-assign-deep`);
const {updatedDiff, addedDiff} = require('deep-object-diff');
const requestRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/request/(.*)`);
class Bridge extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus, enableDisableExtension, restartCallback) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.enableDisableExtension = enableDisableExtension;
this.restartCallback = restartCallback;
this.lastJoinedDeviceIeeeAddr = null;
this.setupMQTTLogging();
this.restartRequired = false;
this.requestLookup = {
'device/options': this.deviceOptions.bind(this),
'device/configure_reporting': this.deviceConfigureReporting.bind(this),
'device/remove': this.deviceRemove.bind(this),
'device/rename': this.deviceRename.bind(this),
'group/add': this.groupAdd.bind(this),
'group/options': this.groupOptions.bind(this),
'group/remove': this.groupRemove.bind(this),
'group/rename': this.groupRename.bind(this),
'permit_join': this.permitJoin.bind(this),
'restart': this.restart.bind(this),
'touchlink/factory_reset': this.touchlinkFactoryReset.bind(this),
'touchlink/identify': this.touchlinkIdentify.bind(this),
'touchlink/scan': this.touchlinkScan.bind(this),
'health_check': this.healthCheck.bind(this),
'options': this.bridgeOptions.bind(this),
// Below are deprecated
'config/last_seen': this.configLastSeen.bind(this),
'config/homeassistant': this.configHomeAssistant.bind(this),
'config/elapsed': this.configElapsed.bind(this),
'config/log_level': this.configLogLevel.bind(this),
};
}
async onMQTTConnected() {
this.zigbee2mqttVersion = await utils.getZigbee2mqttVersion();
this.coordinatorVersion = await this.zigbee.getCoordinatorVersion();
this.eventBus.on(`groupMembersChanged`, () => this.publishGroups());
this.eventBus.on(`devicesChanged`, () => {
this.publishDevices();
this.publishInfo();
});
this.eventBus.on(`deviceRenamed`, () => {
this.publishInfo();
});
this.eventBus.on(`groupRenamed`, () => {
this.publishInfo();
});
this.zigbee.on('permitJoinChanged', (data) => this.permitJoinChanged(data));
await this.publishInfo();
await this.publishDevices();
await this.publishGroups();
}
setupMQTTLogging() {
const mqtt = this.mqtt;
class EventTransport extends Transport {
log(info, callback) {
const payload = stringify({message: info.message, level: info.level});
mqtt.publish(`bridge/logging`, payload, {}, settings.get().mqtt.base_topic, true);
callback();
}
}
logger.addTransport(new EventTransport());
}
permitJoinChanged(data) {
if (!this.zigbee.isStopping()) {
this.publishInfo();
}
}
async onMQTTMessage(topic, message) {
const match = topic.match(requestRegex);
if (match && this.requestLookup[match[1].toLowerCase()]) {
message = utils.parseJSON(message, message);
try {
const response = await this.requestLookup[match[1].toLowerCase()](message);
await this.mqtt.publish(`bridge/response/${match[1]}`, stringify(response));
} catch (error) {
logger.error(`Request '${topic}' failed with error: '${error.message}'`);
const response = utils.getResponse(message, {}, error.message);
await this.mqtt.publish(`bridge/response/${match[1]}`, stringify(response));
}
}
}
async onZigbeeEvent(type, data, resolvedEntity) {
if (type === 'deviceJoined' && resolvedEntity) {
this.lastJoinedDeviceIeeeAddr = resolvedEntity.device.ieeeAddr;
}
if (['deviceJoined', 'deviceLeave', 'deviceInterview', 'deviceAnnounce'].includes(type)) {
let payload;
const ieeeAddress = data.device ? data.device.ieeeAddr : data.ieeeAddr;
if (type === 'deviceJoined') {
payload = {friendly_name: resolvedEntity.settings.friendlyName, ieee_address: ieeeAddress};
} else if (type === 'deviceInterview') {
payload = {
friendly_name: resolvedEntity.settings.friendlyName, status: data.status, ieee_address: ieeeAddress,
};
if (data.status === 'successful') {
const definition = resolvedEntity.definition;
payload.supported = !!definition;
payload.definition = this.getDefinitionPayload(definition);
}
} else if (type === 'deviceAnnounce') {
payload = {
friendly_name: resolvedEntity.settings.friendlyName, ieee_address: ieeeAddress,
};
} else payload = {ieee_address: ieeeAddress}; // deviceLeave
await this.mqtt.publish(
'bridge/event',
stringify({type: utils.toSnakeCase(type), data: payload}),
{retain: false, qos: 0},
);
}
if ('deviceLeave' === type || ('deviceInterview' === type && data.status !== 'started')) {
await this.publishDevices();
}
}
/**
* Requests
*/
async deviceOptions(message) {
return this.changeEntityOptions('device', message);
}
async groupOptions(message) {
return this.changeEntityOptions('group', message);
}
async bridgeOptions(message) {
if (typeof message !== 'object' || typeof message.options !== 'object') {
throw new Error(`Invalid payload`);
}
const diffUpdated = updatedDiff(settings.get(), message.options);
const diffAdded = addedDiff(settings.get(), message.options);
const newSettings = objectAssignDeep.noMutate(diffUpdated, diffAdded);
// deep-object-diff converts arrays to objects, set original array back here
const convertBackArray = (before, after) => {
for (const [key, afterValue] of Object.entries(after)) {
const beforeValue = before[key];
if (Array.isArray(beforeValue)) {
after[key] = beforeValue;
} else if (afterValue && typeof beforeValue === 'object') {
convertBackArray(beforeValue, afterValue);
}
}
};
convertBackArray(message.options, newSettings);
const restartRequired = settings.apply(newSettings);
if (restartRequired) this.restartRequired = true;
// Apply some settings on-the-fly.
if (newSettings.hasOwnProperty('permit_join')) {
await this.zigbee.permitJoin(newSettings.permit_join);
}
if (newSettings.hasOwnProperty('homeassistant')) {
this.enableDisableExtension(newSettings.homeassistant, 'HomeAssistant');
}
if (newSettings.hasOwnProperty('advanced') && newSettings.advanced.hasOwnProperty('log_level')) {
logger.setLevel(newSettings.advanced.log_level);
}
logger.info('Succesfully changed options');
this.publishInfo();
return utils.getResponse(message, {restart_required: this.restartRequired}, null);
}
async deviceRemove(message) {
return this.removeEntity('device', message);
}
async groupRemove(message) {
return this.removeEntity('group', message);
}
async healthCheck(message) {
return utils.getResponse(message, {healthy: true}, null);
}
async groupAdd(message) {
if (typeof message === 'object' && !message.hasOwnProperty('friendly_name')) {
throw new Error(`Invalid payload`);
}
const friendlyName = typeof message === 'object' ? message.friendly_name : message;
const ID = typeof message === 'object' && message.hasOwnProperty('id') ? message.id : null;
const group = settings.addGroup(friendlyName, ID);
this.zigbee.createGroup(group.ID);
this.publishGroups();
return utils.getResponse(message, {friendly_name: group.friendlyName, id: group.ID}, null);
}
async deviceRename(message) {
return this.renameEntity('device', message);
}
async groupRename(message) {
return this.renameEntity('group', message);
}
async restart(message) {
// Wait 500 ms before restarting so response can be send.
setTimeout(this.restartCallback, 500);
logger.info('Restarting Zigbee2MQTT');
return utils.getResponse(message, {}, null);
}
async permitJoin(message) {
if (typeof message === 'object' && !message.hasOwnProperty('value')) {
throw new Error('Invalid payload');
}
let value;
let time;
let resolvedEntity;
if (typeof message === 'object') {
value = message.value;
time = message.time;
if (message.device) {
resolvedEntity = this.zigbee.resolveEntity(message.device);
if (!resolvedEntity || resolvedEntity.type !== 'device') {
throw new Error(`Device '${message.device}' does not exist`);
}
}
} else {
value = message;
}
if (typeof value === 'string') {
value = value.toLowerCase() === 'true';
}
await this.zigbee.permitJoin(value, resolvedEntity, time);
const response = {value};
if (resolvedEntity) response.device = message.device;
if (time) response.time = message.time;
return utils.getResponse(message, response, null);
}
// Deprecated
configLastSeen(message) {
const allowed = ['disable', 'ISO_8601', 'epoch', 'ISO_8601_local'];
const value = this.getValue(message);
if (!allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
settings.set(['advanced', 'last_seen'], value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
// Deprecated
configHomeAssistant(message) {
const allowed = [true, false];
const value = this.getValue(message);
if (!allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
this.enableDisableExtension(value, 'HomeAssistant');
settings.set(['homeassistant'], value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
// Deprecated
configElapsed(message) {
const allowed = [true, false];
const value = this.getValue(message);
if (!allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
settings.set(['advanced', 'elapsed'], value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
// Deprecated
configLogLevel(message) {
const allowed = ['error', 'warn', 'info', 'debug'];
const value = this.getValue(message);
if (!allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
logger.setLevel(value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
async touchlinkIdentify(message) {
if (typeof message !== 'object' || !message.hasOwnProperty('ieee_address') ||
!message.hasOwnProperty('channel')) {
throw new Error('Invalid payload');
}
logger.info(`Start Touchlink identify of '${message.ieee_address}' on channel ${message.channel}`);
await this.zigbee.touchlinkIdentify(message.ieee_address, message.channel);
return utils.getResponse(message, {ieee_address: message.ieee_address, channel: message.channel}, null);
}
async touchlinkFactoryReset(message) {
let result = false;
const payload = {};
if (typeof message === 'object' && message.hasOwnProperty('ieee_address') &&
message.hasOwnProperty('channel')) {
logger.info(`Start Touchlink factory reset of '${message.ieee_address}' on channel ${message.channel}`);
result = await this.zigbee.touchlinkFactoryReset(message.ieee_address, message.channel);
payload.ieee_address = message.ieee_address;
payload.channel = message.channel;
} else {
logger.info('Start Touchlink factory reset of first found device');
result = await this.zigbee.touchlinkFactoryResetFirst();
}
if (result) {
logger.info('Successfully factory reset device through Touchlink');
return utils.getResponse(message, payload, null);
} else {
logger.error('Failed to factory reset device through Touchlink');
throw new Error('Failed to factory reset device through Touchlink');
}
}
async touchlinkScan(message) {
logger.info('Start Touchlink scan');
const result = await this.zigbee.touchlinkScan();
const found = result.map((r) => {
return {ieee_address: r.ieeeAddr, channel: r.channel};
});
logger.info('Finished Touchlink scan');
return utils.getResponse(message, {found}, null);
}
/**
* Utils
*/
getValue(message) {
if (typeof message === 'object') {
if (!message.hasOwnProperty('value')) {
throw new Error('No value given');
}
return message.value;
} else {
return message;
}
}
async changeEntityOptions(entityType, message) {
if (typeof message !== 'object' || !message.hasOwnProperty('id') || !message.hasOwnProperty('options')) {
throw new Error(`Invalid payload`);
}
const ID = message.id;
const entity = this.getEntity(entityType, ID);
settings.changeEntityOptions(ID, message.options);
const cleanup = (o) => {
delete o.friendlyName; delete o.friendly_name; delete o.ID; delete o.type; delete o.devices;
return o;
};
const oldOptions = cleanup(entity.settings);
const newOptions = cleanup(settings.getEntity(ID));
await this.publishInfo();
logger.info(`Changed config for ${entityType} ${ID}`);
return utils.getResponse(message, {from: oldOptions, to: newOptions, id: ID}, null);
}
async deviceConfigureReporting(message) {
if (typeof message !== 'object' || !message.hasOwnProperty('id') || !message.hasOwnProperty('cluster') ||
!message.hasOwnProperty('maximum_report_interval') || !message.hasOwnProperty('minimum_report_interval') ||
!message.hasOwnProperty('reportable_change') || !message.hasOwnProperty('attribute')) {
throw new Error(`Invalid payload`);
}
const ID = message.id;
const endpoint = this.getEntity('device', ID).endpoint;
const coordinator = this.zigbee.getDevicesByType('Coordinator')[0];
const coordinatorEndpoint = coordinator.getEndpoint(1);
await endpoint.bind(message.cluster, coordinatorEndpoint);
await endpoint.configureReporting(message.cluster, [{
attribute: message.attribute, minimumReportInterval: message.minimum_report_interval,
maximumReportInterval: message.maximum_report_interval, reportableChange: message.reportable_change,
}]);
this.publishDevices();
logger.info(`Configured reporting for '${message.id}', '${message.cluster}.${message.attribute}'`);
return utils.getResponse(message, {
id: message.id, cluster: message.cluster, maximum_report_interval: message.maximum_report_interval,
minimum_report_interval: message.minimum_report_interval, reportable_change: message.reportable_change,
attribute: message.attribute,
}, null);
}
renameEntity(entityType, message) {
const deviceAndHasLast = entityType === 'device' && typeof message === 'object' && message.last === true;
if (typeof message !== 'object' || (!message.hasOwnProperty('from') && !deviceAndHasLast) ||
!message.hasOwnProperty('to')) {
throw new Error(`Invalid payload`);
}
if (deviceAndHasLast && !this.lastJoinedDeviceIeeeAddr) {
throw new Error('No device has joined since start');
}
const from = deviceAndHasLast ? this.lastJoinedDeviceIeeeAddr : message.from;
const to = message.to;
const homeAssisantRename = message.hasOwnProperty('homeassistant_rename') ?
message.homeassistant_rename : false;
const entity = this.getEntity(entityType, from);
settings.changeFriendlyName(from, to);
// Clear retained messages
this.mqtt.publish(entity.name, '', {retain: true});
const oldFriendlyName = entity.settings.friendlyName;
if (entity.type === 'device') {
this.publishDevices();
this.eventBus.emit(`deviceRenamed`, {device: entity.device, homeAssisantRename, from: oldFriendlyName, to});
} else {
this.publishGroups();
this.eventBus.emit(`groupRenamed`, {group: entity.group, homeAssisantRename, from: oldFriendlyName, to});
}
// Repulish entity state
this.publishEntityState(to, {});
return utils.getResponse(
message,
{from: oldFriendlyName, to, homeassistant_rename: homeAssisantRename},
null,
);
}
async removeEntity(entityType, message) {
const ID = typeof message === 'object' ? message.id : message.trim();
const entity = this.getEntity(entityType, ID);
let block = false;
let force = false;
let blockForceLog = '';
if (entityType === 'device' && typeof message === 'object') {
block = !!message.block;
force = !!message.force;
blockForceLog = ` (block: ${block}, force: ${force})`;
} else if (entityType === 'group' && typeof message === 'object') {
force = !!message.force;
blockForceLog = ` (force: ${force})`;
}
try {
logger.info(`Removing ${entity.type} '${entity.settings.friendlyName}'${blockForceLog}`);
if (entity.type === 'device') {
if (block) {
settings.blockDevice(entity.settings.ID);
}
if (force) {
await entity.device.removeFromDatabase();
} else {
await entity.device.removeFromNetwork();
}
} else {
if (force) {
await entity.group.removeFromDatabase();
} else {
await entity.group.removeFromNetwork();
}
}
// Fire event
if (entity.type === 'device') {
this.eventBus.emit('deviceRemoved', {resolvedEntity: entity});
}
// Remove from configuration.yaml
if (entity.type === 'device') {
settings.removeDevice(entity.settings.ID);
} else {
settings.removeGroup(entity.settings.ID);
}
// Remove from state
this.state.remove(entity.settings.ID);
// Clear any retained messages
this.mqtt.publish(entity.name, '', {retain: true});
logger.info(`Successfully removed ${entity.type} '${entity.settings.friendlyName}'${blockForceLog}`);
if (entity.type === 'device') {
this.publishGroups();
this.publishDevices();
return utils.getResponse(message, {id: ID, block, force}, null);
} else {
this.publishGroups();
return utils.getResponse(message, {id: ID, force: force}, null);
}
} catch (error) {
throw new Error(
`Failed to remove ${entity.type} '${entity.settings.friendlyName}'${blockForceLog} (${error})`,
);
}
}
getEntity(type, ID) {
const entity = this.zigbee.resolveEntity(ID);
if (!entity || entity.type !== type) {
throw new Error(`${utils.capitalize(type)} '${ID}' does not exist`);
}
return entity;
}
async publishInfo() {
const config = objectAssignDeep.noMutate({}, settings.get());
delete config.advanced.network_key;
delete config.mqtt.password;
config.frontend && delete config.frontend.auth_token;
const payload = {
version: this.zigbee2mqttVersion.version,
commit: this.zigbee2mqttVersion.commitHash,
coordinator: this.coordinatorVersion,
network: utils.toSnakeCase(await this.zigbee.getNetworkParameters()),
log_level: logger.getLevel(),
permit_join: this.zigbee.getPermitJoin(),
permit_join_timeout: this.zigbee.getPermitJoinTimeout(),
restart_required: this.restartRequired,
config,
config_schema: settings.schema,
};
await this.mqtt.publish(
'bridge/info', stringify(payload), {retain: true, qos: 0}, settings.get().mqtt.base_topic, true);
}
async publishDevices() {
const devices = this.zigbee.getDevices().map((device) => {
const definition = zigbeeHerdsmanConverters.findByDevice(device);
const resolved = this.zigbee.resolveEntity(device);
const endpoints = {};
for (const endpoint of device.endpoints) {
const data = {
bindings: [],
configured_reportings: [],
clusters: {
input: endpoint.getInputClusters().map((c) => c.name),
output: endpoint.getOutputClusters().map((c) => c.name),
},
};
for (const bind of endpoint.binds) {
let target;
if (bind.target.constructor.name === 'Endpoint') {
target = {
type: 'endpoint', ieee_address: bind.target.getDevice().ieeeAddr, endpoint: bind.target.ID,
};
} else {
target = {type: 'group', id: bind.target.groupID};
}
data.bindings.push({cluster: bind.cluster.name, target});
}
for (const configuredReporting of endpoint.configuredReportings) {
data.configured_reportings.push({
cluster: configuredReporting.cluster.name,
attribute: configuredReporting.attribute.name || configuredReporting.attribute.ID,
minimum_report_interval: configuredReporting.minimumReportInterval,
maximum_report_interval: configuredReporting.maximumReportInterval,
reportable_change: configuredReporting.reportableChange,
});
}
endpoints[endpoint.ID] = data;
}
return {
ieee_address: device.ieeeAddr,
type: device.type,
network_address: device.networkAddress,
supported: !!definition,
friendly_name: resolved.name,
definition: this.getDefinitionPayload(definition),
power_source: device.powerSource,
software_build_id: device.softwareBuildID,
date_code: device.dateCode,
model_id: device.modelID,
interviewing: device.interviewing,
interview_completed: device.interviewCompleted,
endpoints,
};
});
await this.mqtt.publish(
'bridge/devices', stringify(devices), {retain: true, qos: 0}, settings.get().mqtt.base_topic, true);
}
async publishGroups() {
const groups = this.zigbee.getGroups().map((group) => {
const resolved = this.zigbee.resolveEntity(group);
return {
id: group.groupID,
friendly_name: group.groupID === 901 ? 'default_bind_group' : resolved.name,
members: group.members.map((m) => {
return {
ieee_address: m.deviceIeeeAddress,
endpoint: m.ID,
};
}),
};
});
await this.mqtt.publish(
'bridge/groups', stringify(groups), {retain: true, qos: 0}, settings.get().mqtt.base_topic, true);
}
getDefinitionPayload(definition) {
if (definition) {
return {
model: definition.model,
vendor: definition.vendor,
description: definition.description,
exposes: definition.exposes,
supports_ota: !!definition.ota,
};
} else {
return null;
}
}
}
module.exports = Bridge;
+720
View File
@@ -0,0 +1,720 @@
/* eslint-disable camelcase */
import logger from '../util/logger';
import utils from '../util/utils';
import * as settings from '../util/settings';
import Transport from 'winston-transport';
import bind from 'bind-decorator';
import stringify from 'json-stable-stringify-without-jsonify';
import objectAssignDeep from 'object-assign-deep';
import Extension from './extension';
import Device from '../model/device';
import Group from '../model/group';
import data from '../util/data';
import JSZip from 'jszip';
import fs from 'fs';
const requestRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/request/(.*)`);
type Scene = {id: number, name: string};
type DefinitionPayload = {
model: string, vendor: string, description: string, exposes: zhc.DefinitionExpose[], supports_ota:
boolean, icon: string, options: zhc.DefinitionExpose[],
};
export default class Bridge extends Extension {
private zigbee2mqttVersion: {commitHash: string, version: string};
private coordinatorVersion: zh.CoordinatorVersion;
private restartRequired = false;
private lastJoinedDeviceIeeeAddr: string;
private requestLookup: {[key: string]: (message: KeyValue | string) => Promise<MQTTResponse>};
override async start(): Promise<void> {
this.requestLookup = {
'device/options': this.deviceOptions,
'device/configure_reporting': this.deviceConfigureReporting,
'device/remove': this.deviceRemove,
'device/rename': this.deviceRename,
'group/add': this.groupAdd,
'group/options': this.groupOptions,
'group/remove': this.groupRemove,
'group/rename': this.groupRename,
'permit_join': this.permitJoin,
'restart': this.restart,
'backup': this.backup,
'touchlink/factory_reset': this.touchlinkFactoryReset,
'touchlink/identify': this.touchlinkIdentify,
'install_code/add': this.installCodeAdd,
'touchlink/scan': this.touchlinkScan,
'health_check': this.healthCheck,
'coordinator_check': this.coordinatorCheck,
'options': this.bridgeOptions,
// Below are deprecated
'config/last_seen': this.configLastSeen,
'config/homeassistant': this.configHomeAssistant,
'config/elapsed': this.configElapsed,
'config/log_level': this.configLogLevel,
};
const mqtt = this.mqtt;
class EventTransport extends Transport {
log(info: {message: string, level: string}, callback: () => void): void {
const payload = stringify({message: info.message, level: info.level});
mqtt.publish(`bridge/logging`, payload, {}, settings.get().mqtt.base_topic, true);
callback();
}
}
logger.addTransport(new EventTransport());
this.zigbee2mqttVersion = await utils.getZigbee2MQTTVersion();
this.coordinatorVersion = await this.zigbee.getCoordinatorVersion();
this.eventBus.onEntityRenamed(this, () => this.publishInfo());
this.eventBus.onGroupMembersChanged(this, () => this.publishGroups());
this.eventBus.onDevicesChanged(this, () => this.publishDevices() && this.publishInfo());
this.eventBus.onPermitJoinChanged(this, () => !this.zigbee.isStopping() && this.publishInfo());
this.eventBus.onScenesChanged(this, () => {
this.publishDevices();
this.publishGroups();
});
// Zigbee events
const publishEvent = (type: string, data: KeyValue): Promise<void> =>
this.mqtt.publish('bridge/event', stringify({type, data}), {retain: false, qos: 0});
this.eventBus.onDeviceJoined(this, (data) => {
this.lastJoinedDeviceIeeeAddr = data.device.ieeeAddr;
this.publishDevices();
publishEvent('device_joined', {friendly_name: data.device.name, ieee_address: data.device.ieeeAddr});
});
this.eventBus.onDeviceLeave(this, (data) => {
this.publishDevices();
publishEvent('device_leave', {ieee_address: data.ieeeAddr, friendly_name: data.name});
});
this.eventBus.onDeviceNetworkAddressChanged(this, () => this.publishDevices());
this.eventBus.onDeviceInterview(this, (data) => {
this.publishDevices();
const payload: KeyValue =
{friendly_name: data.device.name, status: data.status, ieee_address: data.device.ieeeAddr};
if (data.status === 'successful') {
payload.supported = !!data.device.definition;
payload.definition = this.getDefinitionPayload(data.device);
}
publishEvent('device_interview', payload);
});
this.eventBus.onDeviceAnnounce(this, (data) => {
this.publishDevices();
publishEvent('device_announce', {friendly_name: data.device.name, ieee_address: data.device.ieeeAddr});
});
await this.publishInfo();
await this.publishDevices();
await this.publishGroups();
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
}
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const match = data.topic.match(requestRegex);
const key = match?.[1]?.toLowerCase();
if (key in this.requestLookup) {
const message = utils.parseJSON(data.message, data.message);
try {
const response = await this.requestLookup[key](message);
await this.mqtt.publish(`bridge/response/${match[1]}`, stringify(response));
} catch (error) {
logger.error(`Request '${data.topic}' failed with error: '${error.message}'`);
logger.debug(error.stack);
const response = utils.getResponse(message, {}, error.message);
await this.mqtt.publish(`bridge/response/${match[1]}`, stringify(response));
}
}
}
/**
* Requests
*/
@bind async deviceOptions(message: KeyValue | string): Promise<MQTTResponse> {
return this.changeEntityOptions('device', message);
}
@bind async groupOptions(message: KeyValue | string): Promise<MQTTResponse> {
return this.changeEntityOptions('group', message);
}
@bind async bridgeOptions(message: KeyValue | string): Promise<MQTTResponse> {
if (typeof message !== 'object' || typeof message.options !== 'object') {
throw new Error(`Invalid payload`);
}
const newSettings = utils.computeSettingsToChange(settings.get(), message.options);
const restartRequired = settings.apply(newSettings);
if (restartRequired) this.restartRequired = true;
// Apply some settings on-the-fly.
if (newSettings.hasOwnProperty('permit_join')) {
await this.zigbee.permitJoin(newSettings.permit_join);
}
if (newSettings.hasOwnProperty('homeassistant')) {
await this.enableDisableExtension(newSettings.homeassistant, 'HomeAssistant');
}
if (newSettings.hasOwnProperty('advanced') && newSettings.advanced.hasOwnProperty('log_level')) {
logger.setLevel(newSettings.advanced.log_level);
}
logger.info('Successfully changed options');
this.publishInfo();
return utils.getResponse(message, {restart_required: this.restartRequired}, null);
}
@bind async deviceRemove(message: string | KeyValue): Promise<MQTTResponse> {
return this.removeEntity('device', message);
}
@bind async groupRemove(message: string | KeyValue): Promise<MQTTResponse> {
return this.removeEntity('group', message);
}
@bind async healthCheck(message: string | KeyValue): Promise<MQTTResponse> {
return utils.getResponse(message, {healthy: true}, null);
}
@bind async coordinatorCheck(message: string | KeyValue): Promise<MQTTResponse> {
const result = await this.zigbee.coordinatorCheck();
const missingRouters = result.missingRouters.map((d) => {
return {ieee_address: d.ieeeAddr, friendly_name: d.name};
});
return utils.getResponse(message, {missing_routers: missingRouters}, null);
}
@bind async groupAdd(message: string | KeyValue): Promise<MQTTResponse> {
if (typeof message === 'object' && !message.hasOwnProperty('friendly_name')) {
throw new Error(`Invalid payload`);
}
const friendlyName = typeof message === 'object' ? message.friendly_name : message;
const ID = typeof message === 'object' && message.hasOwnProperty('id') ? message.id : null;
const group = settings.addGroup(friendlyName, ID);
this.zigbee.createGroup(group.ID);
this.publishGroups();
return utils.getResponse(message, {friendly_name: group.friendly_name, id: group.ID}, null);
}
@bind async deviceRename(message: string | KeyValue): Promise<MQTTResponse> {
return this.renameEntity('device', message);
}
@bind async groupRename(message: string | KeyValue): Promise<MQTTResponse> {
return this.renameEntity('group', message);
}
@bind async restart(message: string | KeyValue): Promise<MQTTResponse> {
// Wait 500 ms before restarting so response can be send.
setTimeout(this.restartCallback, 500);
logger.info('Restarting Zigbee2MQTT');
return utils.getResponse(message, {}, null);
}
@bind async backup(message: string | KeyValue): Promise<MQTTResponse> {
await this.zigbee.backup();
const dataPath = data.getPath();
const files = utils.getAllFiles(dataPath).map((f) => [f, f.substring(dataPath.length + 1)])
.filter((f) => !f[1].startsWith('log'));
const zip = new JSZip();
files.forEach((f) => zip.file(f[1], fs.readFileSync(f[0])));
const base64Zip = await zip.generateAsync({type: 'base64'});
return utils.getResponse(message, {zip: base64Zip}, null);
}
@bind async installCodeAdd(message: KeyValue | string): Promise<MQTTResponse> {
if (typeof message === 'object' && !message.hasOwnProperty('value')) {
throw new Error('Invalid payload');
}
const value = typeof message === 'object' ? message.value : message;
await this.zigbee.addInstallCode(value);
logger.info('Successfully added new install code');
return utils.getResponse(message, {value}, null);
}
@bind async permitJoin(message: KeyValue | string): Promise<MQTTResponse> {
if (typeof message === 'object' && !message.hasOwnProperty('value')) {
throw new Error('Invalid payload');
}
let value: boolean | string;
let time: number;
let device: Device = null;
if (typeof message === 'object') {
value = message.value;
time = message.time;
if (message.device) {
const resolved = this.zigbee.resolveEntity(message.device);
if (resolved instanceof Device) {
device = resolved;
} else {
throw new Error(`Device '${message.device}' does not exist`);
}
}
} else {
value = message;
}
if (typeof value === 'string') {
value = value.toLowerCase() === 'true';
}
await this.zigbee.permitJoin(value, device, time);
const response: {value: boolean, device?: string, time?: number} = {value};
if (device && typeof message === 'object') response.device = message.device;
if (time && typeof message === 'object') response.time = message.time;
return utils.getResponse(message, response, null);
}
// Deprecated
@bind async configLastSeen(message: KeyValue | string): Promise<MQTTResponse> {
const allowed = ['disable', 'ISO_8601', 'epoch', 'ISO_8601_local'];
const value = this.getValue(message);
if (typeof value !== 'string' || !allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
settings.set(['advanced', 'last_seen'], value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
// Deprecated
@bind async configHomeAssistant(message: string | KeyValue): Promise<MQTTResponse> {
const allowed = [true, false];
const value = this.getValue(message);
if (typeof value !== 'boolean' || !allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
await this.enableDisableExtension(value, 'HomeAssistant');
settings.set(['homeassistant'], value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
// Deprecated
@bind async configElapsed(message: KeyValue | string): Promise<MQTTResponse> {
const allowed = [true, false];
const value = this.getValue(message);
if (typeof value !== 'boolean' || !allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
settings.set(['advanced', 'elapsed'], value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
// Deprecated
@bind async configLogLevel(message: KeyValue | string): Promise<MQTTResponse> {
const allowed = ['error', 'warn', 'info', 'debug'];
const value = this.getValue(message) as 'error' | 'warn' | 'info' | 'debug';
if (typeof value !== 'string' || !allowed.includes(value)) {
throw new Error(`'${value}' is not an allowed value, allowed: ${allowed}`);
}
logger.setLevel(value);
this.publishInfo();
return utils.getResponse(message, {value}, null);
}
@bind async touchlinkIdentify(message: KeyValue | string): Promise<MQTTResponse> {
if (typeof message !== 'object' || !message.hasOwnProperty('ieee_address') ||
!message.hasOwnProperty('channel')) {
throw new Error('Invalid payload');
}
logger.info(`Start Touchlink identify of '${message.ieee_address}' on channel ${message.channel}`);
await this.zigbee.touchlinkIdentify(message.ieee_address, message.channel);
return utils.getResponse(message, {ieee_address: message.ieee_address, channel: message.channel}, null);
}
@bind async touchlinkFactoryReset(message: KeyValue | string): Promise<MQTTResponse> {
let result = false;
const payload: {ieee_address?: string, channel?: number} = {};
if (typeof message === 'object' && message.hasOwnProperty('ieee_address') &&
message.hasOwnProperty('channel')) {
logger.info(`Start Touchlink factory reset of '${message.ieee_address}' on channel ${message.channel}`);
result = await this.zigbee.touchlinkFactoryReset(message.ieee_address, message.channel);
payload.ieee_address = message.ieee_address;
payload.channel = message.channel;
} else {
logger.info('Start Touchlink factory reset of first found device');
result = await this.zigbee.touchlinkFactoryResetFirst();
}
if (result) {
logger.info('Successfully factory reset device through Touchlink');
return utils.getResponse(message, payload, null);
} else {
logger.error('Failed to factory reset device through Touchlink');
throw new Error('Failed to factory reset device through Touchlink');
}
}
@bind async touchlinkScan(message: KeyValue | string): Promise<MQTTResponse> {
logger.info('Start Touchlink scan');
const result = await this.zigbee.touchlinkScan();
const found = result.map((r) => {
return {ieee_address: r.ieeeAddr, channel: r.channel};
});
logger.info('Finished Touchlink scan');
return utils.getResponse(message, {found}, null);
}
/**
* Utils
*/
getValue(message: KeyValue | string): string | boolean | number {
if (typeof message === 'object') {
if (!message.hasOwnProperty('value')) {
throw new Error('No value given');
}
return message.value;
} else {
return message;
}
}
async changeEntityOptions(entityType: 'device' | 'group', message: KeyValue | string): Promise<MQTTResponse> {
if (typeof message !== 'object' || !message.hasOwnProperty('id') || !message.hasOwnProperty('options')) {
throw new Error(`Invalid payload`);
}
const cleanup = (o: KeyValue): KeyValue => {
delete o.friendlyName; delete o.friendly_name; delete o.ID; delete o.type; delete o.devices;
return o;
};
const ID = message.id;
const entity = this.getEntity(entityType, ID);
const currentOptions = entityType === 'device' ? settings.get().devices[entity.ID] :
settings.get().groups[entity.ID];
const options = utils.computeSettingsToChange(currentOptions, message.options);
const oldOptions = objectAssignDeep({}, cleanup(entity.options));
const restartRequired = settings.changeEntityOptions(ID, options);
if (restartRequired) this.restartRequired = true;
const newOptions = cleanup(entity.options);
await this.publishInfo();
logger.info(`Changed config for ${entityType} ${ID}`);
this.eventBus.emitEntityOptionsChanged({from: oldOptions, to: newOptions, entity});
return utils.getResponse(
message,
{from: oldOptions, to: newOptions, id: ID, restart_required: this.restartRequired},
null,
);
}
@bind async deviceConfigureReporting(message: string | KeyValue): Promise<MQTTResponse> {
if (typeof message !== 'object' || !message.hasOwnProperty('id') || !message.hasOwnProperty('cluster') ||
!message.hasOwnProperty('maximum_report_interval') || !message.hasOwnProperty('minimum_report_interval') ||
!message.hasOwnProperty('reportable_change') || !message.hasOwnProperty('attribute')) {
throw new Error(`Invalid payload`);
}
const parsedID = utils.parseEntityID(message.id);
const endpoint = (this.getEntity('device', parsedID.ID) as Device).endpoint(parsedID.endpoint);
const coordinatorEndpoint = this.zigbee.firstCoordinatorEndpoint();
await endpoint.bind(message.cluster, coordinatorEndpoint);
await endpoint.configureReporting(message.cluster, [{
attribute: message.attribute, minimumReportInterval: message.minimum_report_interval,
maximumReportInterval: message.maximum_report_interval, reportableChange: message.reportable_change,
}], message.options);
this.publishDevices();
logger.info(`Configured reporting for '${message.id}', '${message.cluster}.${message.attribute}'`);
return utils.getResponse(message, {
id: message.id, cluster: message.cluster, maximum_report_interval: message.maximum_report_interval,
minimum_report_interval: message.minimum_report_interval, reportable_change: message.reportable_change,
attribute: message.attribute,
}, null);
}
async renameEntity(entityType: 'group' | 'device', message: string | KeyValue): Promise<MQTTResponse> {
const deviceAndHasLast = entityType === 'device' && typeof message === 'object' && message.last === true;
if (typeof message !== 'object' || (!message.hasOwnProperty('from') && !deviceAndHasLast) ||
!message.hasOwnProperty('to')) {
throw new Error(`Invalid payload`);
}
if (deviceAndHasLast && !this.lastJoinedDeviceIeeeAddr) {
throw new Error('No device has joined since start');
}
const from = deviceAndHasLast ? this.lastJoinedDeviceIeeeAddr : message.from;
const to = message.to;
const homeAssisantRename = message.hasOwnProperty('homeassistant_rename') ?
message.homeassistant_rename : false;
const entity = this.getEntity(entityType, from);
const oldFriendlyName = entity.options.friendly_name;
settings.changeFriendlyName(from, to);
// Clear retained messages
this.mqtt.publish(oldFriendlyName, '', {retain: true});
this.eventBus.emitEntityRenamed({entity: entity, homeAssisantRename, from: oldFriendlyName, to});
if (entity instanceof Device) {
this.publishDevices();
} else {
this.publishGroups();
this.publishInfo();
}
// Republish entity state
this.publishEntityState(entity, {});
return utils.getResponse(
message,
{from: oldFriendlyName, to, homeassistant_rename: homeAssisantRename},
null,
);
}
async removeEntity(entityType: 'group' | 'device', message: string | KeyValue): Promise<MQTTResponse> {
const ID = typeof message === 'object' ? message.id : message.trim();
const entity = this.getEntity(entityType, ID);
const friendlyName = entity.name;
const entityID = entity.ID;
let block = false;
let force = false;
let blockForceLog = '';
if (entityType === 'device' && typeof message === 'object') {
block = !!message.block;
force = !!message.force;
blockForceLog = ` (block: ${block}, force: ${force})`;
} else if (entityType === 'group' && typeof message === 'object') {
force = !!message.force;
blockForceLog = ` (force: ${force})`;
}
try {
logger.info(`Removing ${entityType} '${entity.name}'${blockForceLog}`);
const ieeeAddr = entity.isDevice() && entity.ieeeAddr;
const name = entity.name;
if (entity instanceof Device) {
if (block) {
settings.blockDevice(entity.ieeeAddr);
}
if (force) {
await entity.zh.removeFromDatabase();
} else {
await entity.zh.removeFromNetwork();
}
} else {
if (force) {
entity.zh.removeFromDatabase();
} else {
await entity.zh.removeFromNetwork();
}
}
// Fire event
if (entity instanceof Device) {
this.eventBus.emitDeviceRemoved({ieeeAddr, name});
}
// Remove from configuration.yaml
if (entity instanceof Device) {
settings.removeDevice(entityID as string);
} else {
settings.removeGroup(entityID);
}
// Remove from state
this.state.remove(entityID);
// Clear any retained messages
this.mqtt.publish(friendlyName, '', {retain: true});
logger.info(`Successfully removed ${entityType} '${friendlyName}'${blockForceLog}`);
if (entity instanceof Device) {
this.publishGroups();
this.publishDevices();
return utils.getResponse(message, {id: ID, block, force}, null);
} else {
this.publishGroups();
return utils.getResponse(message, {id: ID, force: force}, null);
}
} catch (error) {
throw new Error(
`Failed to remove ${entityType} '${friendlyName}'${blockForceLog} (${error})`,
);
}
}
getEntity(type: 'group' | 'device', ID: string): Device | Group {
const entity = this.zigbee.resolveEntity(ID);
if (!entity || entity.constructor.name.toLowerCase() !== type) {
throw new Error(`${utils.capitalize(type)} '${ID}' does not exist`);
}
return entity;
}
async publishInfo(): Promise<void> {
const config = objectAssignDeep({}, settings.get());
delete config.advanced.network_key;
delete config.mqtt.password;
config.frontend && delete config.frontend.auth_token;
const payload = {
version: this.zigbee2mqttVersion.version,
commit: this.zigbee2mqttVersion.commitHash,
coordinator: {
ieee_address: this.zigbee.firstCoordinatorEndpoint().getDevice().ieeeAddr,
...this.coordinatorVersion,
},
network: utils.toSnakeCase(await this.zigbee.getNetworkParameters()),
log_level: logger.getLevel(),
permit_join: this.zigbee.getPermitJoin(),
permit_join_timeout: this.zigbee.getPermitJoinTimeout(),
restart_required: this.restartRequired,
config,
config_schema: settings.schema,
};
await this.mqtt.publish(
'bridge/info', stringify(payload), {retain: true, qos: 0}, settings.get().mqtt.base_topic, true);
}
private getScenes(entity: zh.Endpoint | zh.Group): Scene[] {
const scenes: {[id: number]: Scene} = {};
const endpoints = utils.isEndpoint(entity) ? [entity] : entity.members;
const groupID = utils.isEndpoint(entity) ? 0 : entity.groupID;
for (const endpoint of endpoints) {
for (const [key, data] of Object.entries(endpoint.meta?.scenes || {})) {
const split = key.split('_');
const sceneID = parseInt(split[0], 10);
const sceneGroupID = parseInt(split[1], 10);
if (sceneGroupID === groupID) {
scenes[sceneID] = {id: sceneID, name: (data as KeyValue).name || `Scene ${sceneID}`};
}
}
}
return Object.values(scenes);
}
async publishDevices(): Promise<void> {
interface Data {
bindings: {cluster: string, target: {type: string, endpoint?: number, ieee_address?: string, id?: number}}[]
configured_reportings: {cluster: string, attribute: string | number,
minimum_report_interval: number, maximum_report_interval: number, reportable_change: number}[],
clusters: {input: string[], output: string[]}, scenes: Scene[]
}
const devices = this.zigbee.devices().map((device) => {
const endpoints: {[s: number]: Data} = {};
for (const endpoint of device.zh.endpoints) {
const data: Data = {
scenes: this.getScenes(endpoint),
bindings: [],
configured_reportings: [],
clusters: {
input: endpoint.getInputClusters().map((c) => c.name),
output: endpoint.getOutputClusters().map((c) => c.name),
},
};
for (const bind of endpoint.binds) {
const target = utils.isEndpoint(bind.target) ?
{type: 'endpoint', ieee_address: bind.target.getDevice().ieeeAddr, endpoint: bind.target.ID} :
{type: 'group', id: bind.target.groupID};
data.bindings.push({cluster: bind.cluster.name, target});
}
for (const configuredReporting of endpoint.configuredReportings) {
data.configured_reportings.push({
cluster: configuredReporting.cluster.name,
attribute: configuredReporting.attribute.name || configuredReporting.attribute.ID,
minimum_report_interval: configuredReporting.minimumReportInterval,
maximum_report_interval: configuredReporting.maximumReportInterval,
reportable_change: configuredReporting.reportableChange,
});
}
endpoints[endpoint.ID] = data;
}
return {
ieee_address: device.ieeeAddr,
type: device.zh.type,
network_address: device.zh.networkAddress,
supported: !!device.definition,
friendly_name: device.name,
disabled: !!device.options.disabled,
description: device.options.description,
definition: this.getDefinitionPayload(device),
power_source: device.zh.powerSource,
software_build_id: device.zh.softwareBuildID,
date_code: device.zh.dateCode,
model_id: device.zh.modelID,
interviewing: device.zh.interviewing,
interview_completed: device.zh.interviewCompleted,
manufacturer: device.zh.manufacturerName,
endpoints,
};
});
await this.mqtt.publish('bridge/devices', stringify(devices),
{retain: true, qos: 0}, settings.get().mqtt.base_topic, true);
}
async publishGroups(): Promise<void> {
const groups = this.zigbee.groups().map((g) => {
return {
id: g.ID,
friendly_name: g.ID === 901 ? 'default_bind_group' : g.name,
description: g.options.description,
scenes: this.getScenes(g.zh),
members: g.zh.members.map((e) => {
return {ieee_address: e.getDevice().ieeeAddr, endpoint: e.ID};
}),
};
});
await this.mqtt.publish(
'bridge/groups', stringify(groups), {retain: true, qos: 0}, settings.get().mqtt.base_topic, true);
}
getDefinitionPayload(device: Device): DefinitionPayload {
if (!device.definition) return null;
let icon = device.options.icon ? device.options.icon : device.definition.icon;
if (icon) {
icon = icon.replace('${zigbeeModel}', utils.sanitizeImageParameter(device.zh.modelID));
icon = icon.replace('${model}', utils.sanitizeImageParameter(device.definition.model));
}
return {
model: device.definition.model,
vendor: device.definition.vendor,
description: device.definition.description,
exposes: device.exposes(),
supports_ota: !!device.definition.ota,
options: device.definition.options,
icon,
};
}
}
-151
View File
@@ -1,151 +0,0 @@
const settings = require('../util/settings');
const utils = require('../util/utils');
const logger = require('../util/logger');
const Extension = require('./extension');
const stringify = require('json-stable-stringify-without-jsonify');
/**
* This extension calls the zigbee-herdsman-converters definition configure() method
*/
class Configure extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.configuring = new Set();
this.onReportingDisabled = this.onReportingDisabled.bind(this);
this.attempts = {};
this.topic = `${settings.get().mqtt.base_topic}/bridge/request/device/configure`;
this.legacyTopic = `${settings.get().mqtt.base_topic}/bridge/configure`;
this.eventBus.on(`reportingDisabled`, this.onReportingDisabled);
}
onReportingDisabled(data) {
// Disabling reporting unbinds some cluster which could be bound by configure, re-setup.
const device = data.device;
const resolvedEntity = this.zigbee.resolveEntity(device);
if (resolvedEntity.device.meta && resolvedEntity.device.meta.hasOwnProperty('configured')) {
delete device.meta.configured;
device.save();
}
if (this.shouldConfigure(resolvedEntity)) {
this.configure(resolvedEntity);
}
}
shouldConfigure(resolvedEntity) {
if (!resolvedEntity || !resolvedEntity.definition || !resolvedEntity.definition.configure) {
return false;
}
if (resolvedEntity.device.meta &&
resolvedEntity.device.meta.hasOwnProperty('configured') &&
resolvedEntity.device.meta.configured === resolvedEntity.definition.meta.configureKey) {
return false;
}
if (resolvedEntity.device.interviewing === true) {
return false;
}
return true;
}
async onMQTTMessage(topic, message) {
if (topic === this.legacyTopic) {
const resolvedEntity = this.zigbee.resolveEntity(message);
if (!resolvedEntity || resolvedEntity.type !== 'device') {
logger.error(`Device '${message}' does not exist`);
return;
}
if (!resolvedEntity.definition || !resolvedEntity.definition.configure) {
logger.warn(`Skipping configure of '${resolvedEntity.name}', device does not require this.`);
return;
}
this.configure(resolvedEntity, true);
} else if (topic === this.topic) {
message = utils.parseJSON(message, message);
const ID = typeof message === 'object' && message.hasOwnProperty('id') ? message.id : message;
let error = null;
const resolvedEntity = this.zigbee.resolveEntity(ID);
if (!resolvedEntity || resolvedEntity.type !== 'device') {
error = `Device '${ID}' does not exist`;
} else if (!resolvedEntity.definition || !resolvedEntity.definition.configure) {
error = `Device '${resolvedEntity.name}' cannot be configured`;
} else {
try {
await this.configure(resolvedEntity, true, true);
} catch (e) {
error = `Failed to configure (${e.message})`;
}
}
const response = utils.getResponse(message, {id: ID}, error);
await this.mqtt.publish(`bridge/response/device/configure`, stringify(response));
}
}
async onZigbeeStarted() {
this.coordinatorEndpoint = this.zigbee.getDevicesByType('Coordinator')[0].getEndpoint(1);
for (const device of this.zigbee.getClients()) {
const resolvedEntity = this.zigbee.resolveEntity(device);
if (this.shouldConfigure(resolvedEntity)) {
await this.configure(resolvedEntity);
}
}
}
onZigbeeEvent(type, data, resolvedEntity) {
const device = data.device;
if (type === 'deviceJoined' && device.meta.hasOwnProperty('configured')) {
delete device.meta.configured;
device.save();
}
if (this.shouldConfigure(resolvedEntity)) {
this.configure(resolvedEntity);
}
}
async configure(resolvedEntity, force=false, thowError=false) {
const device = resolvedEntity.device;
if (this.configuring.has(device.ieeeAddr) || (this.attempts[device.ieeeAddr] >= 3 && !force)) {
return false;
}
this.configuring.add(device.ieeeAddr);
if (!this.attempts.hasOwnProperty(device.ieeeAddr)) {
this.attempts[device.ieeeAddr] = 0;
}
logger.info(`Configuring '${resolvedEntity.name}'`);
try {
await resolvedEntity.definition.configure(device, this.coordinatorEndpoint, logger);
logger.info(`Successfully configured '${resolvedEntity.name}'`);
device.meta.configured = resolvedEntity.definition.meta.configureKey;
device.save();
this.eventBus.emit(`devicesChanged`);
} catch (error) {
this.attempts[device.ieeeAddr]++;
const attempt = this.attempts[device.ieeeAddr];
const msg = `Failed to configure '${resolvedEntity.name}', attempt ${attempt} (${error.stack})`;
logger.error(msg);
if (thowError) {
throw error;
}
}
this.configuring.delete(device.ieeeAddr);
}
}
module.exports = Configure;
+136
View File
@@ -0,0 +1,136 @@
import * as settings from '../util/settings';
import utils from '../util/utils';
import logger from '../util/logger';
import stringify from 'json-stable-stringify-without-jsonify';
import zhc from 'zigbee-herdsman-converters';
import Extension from './extension';
import bind from 'bind-decorator';
import Device from '../model/device';
/**
* This extension calls the zigbee-herdsman-converters definition configure() method
*/
export default class Configure extends Extension {
private configuring = new Set();
private attempts: {[s: string]: number} = {};
private topic = `${settings.get().mqtt.base_topic}/bridge/request/device/configure`;
private legacyTopic = `${settings.get().mqtt.base_topic}/bridge/configure`;
@bind private async onReconfigure(data: eventdata.Reconfigure): Promise<void> {
// Disabling reporting unbinds some cluster which could be bound by configure, re-setup.
if (data.device.zh.meta?.hasOwnProperty('configured')) {
delete data.device.zh.meta.configured;
data.device.zh.save();
}
await this.configure(data.device, 'reporting_disabled');
}
@bind private async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
if (data.topic === this.legacyTopic) {
const device = this.zigbee.resolveEntity(data.message);
if (!device || !(device instanceof Device)) {
logger.error(`Device '${data.message}' does not exist`);
return;
}
if (!device.definition || !device.definition.configure) {
logger.warn(`Skipping configure of '${device.name}', device does not require this.`);
return;
}
this.configure(device, 'mqtt_message', true);
} else if (data.topic === this.topic) {
const message = utils.parseJSON(data.message, data.message);
const ID = typeof message === 'object' && message.hasOwnProperty('id') ? message.id : message;
let error = null;
const device = this.zigbee.resolveEntity(ID);
if (!device || !(device instanceof Device)) {
error = `Device '${ID}' does not exist`;
} else if (!device.definition || !device.definition.configure) {
error = `Device '${device.name}' cannot be configured`;
} else {
try {
await this.configure(device, 'mqtt_message', true, true);
} catch (e) {
error = `Failed to configure (${e.message})`;
}
}
const response = utils.getResponse(message, {id: ID}, error);
await this.mqtt.publish(`bridge/response/device/configure`, stringify(response));
}
}
override async start(): Promise<void> {
setImmediate(async () => {
for (const device of this.zigbee.devices(false)) {
await this.configure(device, 'started');
}
});
this.eventBus.onDeviceJoined(this, (data) => {
if (data.device.zh.meta.hasOwnProperty('configured')) {
delete data.device.zh.meta.configured;
data.device.zh.save();
}
this.configure(data.device, 'zigbee_event');
});
this.eventBus.onDeviceInterview(this, (data) => this.configure(data.device, 'zigbee_event'));
this.eventBus.onLastSeenChanged(this, (data) => this.configure(data.device, 'zigbee_event'));
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
this.eventBus.onReconfigure(this, this.onReconfigure);
}
private async configure(device: Device, event: 'started' | 'zigbee_event' | 'reporting_disabled' | 'mqtt_message',
force=false, throwError=false): Promise<void> {
if (!force) {
if (device.options.disabled || !device.definition?.configure || !device.zh.interviewCompleted) {
return;
}
if (device.zh.meta?.hasOwnProperty('configured') &&
device.zh.meta.configured === zhc.getConfigureKey(device.definition)) {
return;
}
// Only configure end devices when it is active, otherwise it will likely fails as they are sleeping.
if (device.zh.type === 'EndDevice' && event !== 'zigbee_event') {
return;
}
}
if (this.configuring.has(device.ieeeAddr) || (this.attempts[device.ieeeAddr] >= 3 && !force)) {
return;
}
this.configuring.add(device.ieeeAddr);
if (!this.attempts.hasOwnProperty(device.ieeeAddr)) {
this.attempts[device.ieeeAddr] = 0;
}
logger.info(`Configuring '${device.name}'`);
try {
await device.definition.configure(device.zh, this.zigbee.firstCoordinatorEndpoint(), logger,
device.options);
logger.info(`Successfully configured '${device.name}'`);
device.zh.meta.configured = zhc.getConfigureKey(device.definition);
device.zh.save();
this.eventBus.emitDevicesChanged();
} catch (error) {
this.attempts[device.ieeeAddr]++;
const attempt = this.attempts[device.ieeeAddr];
const msg = `Failed to configure '${device.name}', attempt ${attempt} (${error.stack})`;
logger.error(msg);
if (throwError) {
throw error;
}
}
this.configuring.delete(device.ieeeAddr);
}
}
-54
View File
@@ -1,54 +0,0 @@
class Extension {
/**
* Besides intializing variables, the constructor should do nothing!
*
* @param {Zigbee} zigbee Zigbee controller
* @param {MQTT} mqtt MQTT controller
* @param {State} state State controller
* @param {Function} publishEntityState Method to publish device state to MQTT.
* @param {EventBus} eventBus The event bus
*/
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
this.zigbee = zigbee;
this.mqtt = mqtt;
this.state = state;
this.publishEntityState = publishEntityState;
this.eventBus = eventBus;
}
/**
* This method is called by the controller once Zigbee has been started.
*/
// onZigbeeStarted() {}
/**
* This method is called by the controller once connected to the MQTT server.
*/
// onMQTTConnected() {}
/**
* Is called when a Zigbee message from a device is received.
* @param {string} type Type of the message
* @param {Object} data Data of the message
* @param {Object?} resolvedEntity Resolved entity returned from this.zigbee.resolveEntity()
* @param {Object?} settingsDevice Device settings
*/
// onZigbeeEvent(type, data, resolvedEntity) {}
/**
* Is called when a MQTT message is received
* @param {string} topic Topic on which the message was received
* @param {Object} message The received message
* @return {boolean} if the message was handled
*/
// onMQTTMessage(topic, message) {}
/**
* Is called once the extension has to stop
*/
stop() {
this.eventBus.removeListenersExtension(this.constructor.name);
}
}
module.exports = Extension;
+53
View File
@@ -0,0 +1,53 @@
abstract class Extension {
protected zigbee: Zigbee;
protected mqtt: MQTT;
protected state: State;
protected publishEntityState: PublishEntityState;
protected eventBus: EventBus;
protected enableDisableExtension: (enable: boolean, name: string) => Promise<void>;
protected restartCallback: () => void;
protected addExtension: (extension: Extension) => Promise<void>;
/**
* Besides initializing variables, the constructor should do nothing!
*
* @param {Zigbee} zigbee Zigbee controller
* @param {MQTT} mqtt MQTT controller
* @param {State} state State controller
* @param {Function} publishEntityState Method to publish device state to MQTT.
* @param {EventBus} eventBus The event bus
* @param {enableDisableExtension} enableDisableExtension Enable/disable extension method
* @param {restartCallback} restartCallback Restart Zigbee2MQTT
* @param {addExtension} addExtension Add an extension
*/
constructor(zigbee: Zigbee, mqtt: MQTT, state: State, publishEntityState: PublishEntityState,
eventBus: EventBus, enableDisableExtension: (enable: boolean, name: string) => Promise<void>,
restartCallback: () => void, addExtension: (extension: Extension) => Promise<void>) {
this.zigbee = zigbee;
this.mqtt = mqtt;
this.state = state;
this.publishEntityState = publishEntityState;
this.eventBus = eventBus;
this.enableDisableExtension = enableDisableExtension;
this.restartCallback = restartCallback;
this.addExtension = addExtension;
}
/**
* Is called once the extension has to start
*/
/* istanbul ignore next */
async start(): Promise<void> {}
/**
* Is called once the extension has to stop
*/
async stop(): Promise<void> {
this.eventBus.removeListeners(this);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public adjustMessageBeforePublish(entity: Group | Device, message: KeyValue): void {}
}
export default Extension;
-18
View File
@@ -1,18 +0,0 @@
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const settings = require('../util/settings');
const Extension = require('./extension');
const utils = require('../util/utils');
class ExternalConverters extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
for (const definition of utils.getExternalConvertersDefinitions(settings)) {
const toAdd = {...definition};
delete toAdd['homeassistant'];
zigbeeHerdsmanConverters.addDeviceDefinition(toAdd);
}
}
}
module.exports = ExternalConverters;
+18
View File
@@ -0,0 +1,18 @@
import zhc from 'zigbee-herdsman-converters';
import * as settings from '../util/settings';
import utils from '../util/utils';
import Extension from './extension';
export default class ExternalConverters extends Extension {
constructor(zigbee: Zigbee, mqtt: MQTT, state: State, publishEntityState: PublishEntityState,
eventBus: EventBus, enableDisableExtension: (enable: boolean, name: string) => Promise<void>,
restartCallback: () => void, addExtension: (extension: Extension) => Promise<void>) {
super(zigbee, mqtt, state, publishEntityState, eventBus, enableDisableExtension, restartCallback, addExtension);
for (const definition of utils.getExternalConvertersDefinitions(settings.get())) {
const toAdd = {...definition};
delete toAdd['homeassistant'];
zhc.addDeviceDefinition(toAdd);
}
}
}
-113
View File
@@ -1,113 +0,0 @@
const settings = require('../util/settings');
const Extension = require('./extension');
const utils = require('../util/utils');
const fs = require('fs');
const data = require('./../util/data');
const path = require('path');
const logger = require('./../util/logger');
const stringify = require('json-stable-stringify-without-jsonify');
const requestRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/request/extension/(save|remove)`);
class ExternalExtension extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus, addExtension, enableDisableExtension) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.args = [zigbee, mqtt, state, publishEntityState, eventBus];
this.addExtension = addExtension;
this.enableDisableExtension = enableDisableExtension;
this.extensionsBaseDir = 'extension';
this.loadExtension = this.loadExtension.bind(this);
this.requestLookup = {
'save': this.saveExtension.bind(this),
'remove': this.removeExtension.bind(this),
};
this.loadUserDefinedExtensions();
}
getExtensionsBasePath() {
return data.joinPath(this.extensionsBaseDir);
}
getListOfUserDefinedExtensions() {
const basePath = this.getExtensionsBasePath();
if (fs.existsSync(basePath)) {
return fs.readdirSync(basePath).filter((f) => f.endsWith('.js')).map((fileName) => {
const extensonFilePath = path.join(basePath, fileName);
return {'name': fileName, 'code': fs.readFileSync(extensonFilePath, 'utf-8')};
});
} else {
return [];
}
}
removeExtension(message) {
const {name} = message;
const extensions = this.getListOfUserDefinedExtensions();
const extensionToBeRemoved = extensions.find((e) => e.name === name);
if (extensionToBeRemoved) {
this.enableDisableExtension(false, extensionToBeRemoved.name);
const basePath = this.getExtensionsBasePath();
const extensonFilePath = path.join(basePath, path.basename(name));
fs.unlinkSync(extensonFilePath);
this.publishExtensions();
logger.info(`Extension ${name} removed`);
return utils.getResponse(message, {}, null);
} else {
return utils.getResponse(message, {}, `Extension ${name} doesn't exists`);
}
}
saveExtension(message) {
const {name, code} = message;
const ModuleConstructor = utils.loadModuleFromText(code);
this.loadExtension(ModuleConstructor);
const basePath = this.getExtensionsBasePath();
/* istanbul ignore else */
if (!fs.existsSync(basePath)) {
fs.mkdirSync(basePath);
}
const extensonFilePath = path.join(basePath, path.basename(name));
fs.writeFileSync(extensonFilePath, code);
this.publishExtensions();
logger.info(`Extension ${name} loaded`);
return utils.getResponse(message, {}, null);
}
async onMQTTMessage(topic, message) {
const match = topic.match(requestRegex);
if (match && this.requestLookup[match[1].toLowerCase()]) {
message = utils.parseJSON(message, message);
try {
const response = await this.requestLookup[match[1].toLowerCase()](message);
await this.mqtt.publish(`bridge/response/extension/${match[1]}`, stringify(response));
} catch (error) {
logger.error(`Request '${topic}' failed with error: '${error.message}'`);
const response = utils.getResponse(message, {}, error.message);
await this.mqtt.publish(`bridge/response/extension/${match[1]}`, stringify(response));
}
}
}
loadExtension(ConstructorClass) {
this.enableDisableExtension(false, ConstructorClass.name);
this.addExtension(new ConstructorClass(...this.args, settings, logger));
}
loadUserDefinedExtensions() {
const extensions = this.getListOfUserDefinedExtensions();
extensions
.map(({code}) => utils.loadModuleFromText(code))
.map(this.loadExtension);
}
async onMQTTConnected() {
this.publishExtensions();
}
async publishExtensions() {
const extensions = this.getListOfUserDefinedExtensions();
await this.mqtt.publish('bridge/extensions', stringify(extensions), {
retain: true,
qos: 0,
}, settings.get().mqtt.base_topic, true);
}
}
module.exports = ExternalExtension;
+109
View File
@@ -0,0 +1,109 @@
import * as settings from '../util/settings';
import utils from '../util/utils';
import fs from 'fs';
import data from './../util/data';
import path from 'path';
import logger from './../util/logger';
import stringify from 'json-stable-stringify-without-jsonify';
import bind from 'bind-decorator';
import Extension from './extension';
const requestRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/request/extension/(save|remove)`);
export default class ExternalExtension extends Extension {
private requestLookup: {[s: string]: (message: KeyValue) => Promise<MQTTResponse>};
override async start(): Promise<void> {
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
this.requestLookup = {'save': this.saveExtension, 'remove': this.removeExtension};
this.loadUserDefinedExtensions();
await this.publishExtensions();
}
private getExtensionsBasePath(): string {
return data.joinPath('extension');
}
private getListOfUserDefinedExtensions(): {name: string, code: string}[] {
const basePath = this.getExtensionsBasePath();
if (fs.existsSync(basePath)) {
return fs.readdirSync(basePath).filter((f) => f.endsWith('.js')).map((fileName) => {
const extensionFilePath = path.join(basePath, fileName);
return {'name': fileName, 'code': fs.readFileSync(extensionFilePath, 'utf-8')};
});
} else {
return [];
}
}
@bind private async removeExtension(message: KeyValue): Promise<MQTTResponse> {
const {name} = message;
const extensions = this.getListOfUserDefinedExtensions();
const extensionToBeRemoved = extensions.find((e) => e.name === name);
if (extensionToBeRemoved) {
await this.enableDisableExtension(false, extensionToBeRemoved.name);
const basePath = this.getExtensionsBasePath();
const extensionFilePath = path.join(basePath, path.basename(name));
fs.unlinkSync(extensionFilePath);
this.publishExtensions();
logger.info(`Extension ${name} removed`);
return utils.getResponse(message, {}, null);
} else {
return utils.getResponse(message, {}, `Extension ${name} doesn't exists`);
}
}
@bind private async saveExtension(message: KeyValue): Promise<MQTTResponse> {
const {name, code} = message;
const ModuleConstructor = utils.loadModuleFromText(code, name) as typeof Extension;
await this.loadExtension(ModuleConstructor);
const basePath = this.getExtensionsBasePath();
/* istanbul ignore else */
if (!fs.existsSync(basePath)) {
fs.mkdirSync(basePath);
}
const extensionFilePath = path.join(basePath, path.basename(name));
fs.writeFileSync(extensionFilePath, code);
this.publishExtensions();
logger.info(`Extension ${name} loaded`);
return utils.getResponse(message, {}, null);
}
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const match = data.topic.match(requestRegex);
if (match && this.requestLookup[match[1].toLowerCase()]) {
const message = utils.parseJSON(data.message, data.message) as KeyValue;
try {
const response = await this.requestLookup[match[1].toLowerCase()](message);
await this.mqtt.publish(`bridge/response/extension/${match[1]}`, stringify(response));
} catch (error) {
logger.error(`Request '${data.topic}' failed with error: '${error.message}'`);
const response = utils.getResponse(message, {}, error.message);
await this.mqtt.publish(`bridge/response/extension/${match[1]}`, stringify(response));
}
}
}
@bind private async loadExtension(ConstructorClass: typeof Extension): Promise<void> {
await this.enableDisableExtension(false, ConstructorClass.name);
// @ts-ignore
await this.addExtension(new ConstructorClass(this.zigbee, this.mqtt, this.state, this.publishEntityState,
this.eventBus, settings, logger));
}
private loadUserDefinedExtensions(): void {
const extensions = this.getListOfUserDefinedExtensions();
extensions
.map(({code, name}) => utils.loadModuleFromText(code, name))
.map(this.loadExtension);
}
private async publishExtensions(): Promise<void> {
const extensions = this.getListOfUserDefinedExtensions();
await this.mqtt.publish('bridge/extensions', stringify(extensions), {
retain: true,
qos: 0,
}, settings.get().mqtt.base_topic, true);
}
}
-128
View File
@@ -1,128 +0,0 @@
const http = require('http');
const serveStatic = require('serve-static');
const finalhandler = require('finalhandler');
const Extension = require('./extension');
const logger = require('../util/logger');
const frontend = require('zigbee2mqtt-frontend');
const WebSocket = require('ws');
const url = require('url');
const settings = require('../util/settings');
const utils = require('../util/utils');
const stringify = require('json-stable-stringify-without-jsonify');
/**
* This extension servers the frontend
*/
class Frontend extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.onRequest = this.onRequest.bind(this);
this.onUpgrade = this.onUpgrade.bind(this);
this.mqttBaseTopic = settings.get().mqtt.base_topic;
this.onMQTTPublishedMessage = this.onMQTTPublishedMessage.bind(this);
this.mqtt.on('publishedMessage', this.onMQTTPublishedMessage);
this.onWebSocketConnection = this.onWebSocketConnection.bind(this);
this.server = http.createServer(this.onRequest);
this.server.on('upgrade', this.onUpgrade);
this.host = settings.get().frontend.host || '0.0.0.0';
this.port = settings.get().frontend.port || 8080;
this.authToken = settings.get().frontend.auth_token || false;
this.retainedMessages = new Map();
/* istanbul ignore next */
const options = {setHeaders: (res, path) => {
if (path.endsWith('index.html')) {
res.setHeader('Cache-Control', 'no-store');
}
}};
this.fileServer = serveStatic(frontend.getPath(), options);
this.wss = new WebSocket.Server({noServer: true});
this.wss.on('connection', this.onWebSocketConnection);
}
onZigbeeStarted() {
this.server.listen(this.port, this.host);
logger.info(`Started frontend on port ${this.host}:${this.port}`);
}
async stop() {
for (const client of this.wss.clients) {
client.send(stringify({topic: 'bridge/state', payload: 'offline'}));
client.close();
}
return new Promise((resolve) => {
this.server.close(resolve);
});
}
onRequest(request, response) {
this.fileServer(request, response, finalhandler(request, response));
}
authenticate(request, cb) {
const {query} = url.parse(request.url, true);
cb(!this.authToken || this.authToken === query.token);
}
onUpgrade(request, socket, head) {
this.wss.handleUpgrade(request, socket, head, (ws) => {
this.authenticate(request, (isAuthentificated) => {
if (isAuthentificated) {
this.wss.emit('connection', ws, request);
} else {
ws.close(4401, 'Unauthorized');
}
});
});
}
onWebSocketConnection(ws) {
ws.on('message', (message) => {
if (message) {
const {topic, payload} = utils.parseJSON(message, message);
this.mqtt.onMessage(`${this.mqttBaseTopic}/${topic}`, stringify(payload));
}
});
for (const [key, value] of this.retainedMessages) {
ws.send(stringify({topic: key, payload: value}));
}
for (const device of this.zigbee.getClients()) {
let payload = {};
const resolvedEntity = this.zigbee.resolveEntity(device);
if (this.state.exists(device.ieeeAddr)) {
payload = {...payload, ...this.state.get(device.ieeeAddr)};
}
const lastSeen = settings.get().advanced.last_seen;
if (lastSeen !== 'disable') {
payload.last_seen = utils.formatDate(resolvedEntity.device.lastSeen, lastSeen);
}
if (resolvedEntity.device.linkquality !== undefined) {
payload.linkquality = resolvedEntity.device.linkquality;
}
ws.send(stringify({topic: resolvedEntity.name, payload}));
}
}
onMQTTPublishedMessage(data) {
let {topic, payload, options} = data;
if (topic.startsWith(`${this.mqttBaseTopic}/`)) {
// Send topic without base_topic
topic = topic.substring(this.mqttBaseTopic.length + 1);
payload = utils.parseJSON(payload, payload);
if (options.retain) {
this.retainedMessages.set(topic, payload);
}
for (const client of this.wss.clients) {
if (client.readyState === WebSocket.OPEN) {
client.send(stringify({topic, payload}));
}
}
}
}
}
module.exports = Frontend;
+170
View File
@@ -0,0 +1,170 @@
import http from 'http';
import https from 'https';
import gzipStatic, {RequestHandler} from 'connect-gzip-static';
import finalhandler from 'finalhandler';
import logger from '../util/logger';
import frontend from 'zigbee2mqtt-frontend';
import WebSocket from 'ws';
import net from 'net';
import url from 'url';
import fs from 'fs';
import * as settings from '../util/settings';
import utils from '../util/utils';
import stringify from 'json-stable-stringify-without-jsonify';
import Extension from './extension';
import bind from 'bind-decorator';
/**
* This extension servers the frontend
*/
export default class Frontend extends Extension {
private mqttBaseTopic = settings.get().mqtt.base_topic;
private host = settings.get().frontend.host;
private port = settings.get().frontend.port;
private sslCert = settings.get().frontend.ssl_cert;
private sslKey = settings.get().frontend.ssl_key;
private authToken = settings.get().frontend.auth_token;
private retainedMessages = new Map();
private server: http.Server;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private fileServer: RequestHandler;
private wss: WebSocket.Server = null;
constructor(zigbee: Zigbee, mqtt: MQTT, state: State, publishEntityState: PublishEntityState,
eventBus: EventBus, enableDisableExtension: (enable: boolean, name: string) => Promise<void>,
restartCallback: () => void, addExtension: (extension: Extension) => Promise<void>) {
super(zigbee, mqtt, state, publishEntityState, eventBus, enableDisableExtension, restartCallback, addExtension);
this.eventBus.onMQTTMessagePublished(this, this.onMQTTPublishMessage);
}
private isHttpsConfigured():boolean {
if (this.sslCert && this.sslKey) {
if (!fs.existsSync(this.sslCert) || !fs.existsSync(this.sslKey)) {
logger.error(`defined ssl_cert '${this.sslCert}' or ssl_key '${this.sslKey}' file path does not exists, server won't be secured.`); /* eslint-disable-line max-len */
return false;
}
return true;
}
return false;
}
override async start(): Promise<void> {
if (this.isHttpsConfigured()) {
const serverOptions = {
key: fs.readFileSync(this.sslKey),
cert: fs.readFileSync(this.sslCert)};
this.server = https.createServer(serverOptions, this.onRequest);
} else {
this.server = http.createServer(this.onRequest);
}
this.server.on('upgrade', this.onUpgrade);
/* istanbul ignore next */
const options = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setHeaders: (res: any, path: string): void => {
if (path.endsWith('index.html')) {
res.setHeader('Cache-Control', 'no-store');
}
},
};
this.fileServer = gzipStatic(frontend.getPath(), options);
this.wss = new WebSocket.Server({noServer: true});
this.wss.on('connection', this.onWebSocketConnection);
if (this.host.startsWith('/')) {
this.server.listen(this.host);
logger.info(`Started frontend on socket ${this.host}`);
} else {
this.server.listen(this.port, this.host);
logger.info(`Started frontend on port ${this.host}:${this.port}`);
}
}
override async stop(): Promise<void> {
super.stop();
this.wss?.clients.forEach((client) => {
client.send(stringify({topic: 'bridge/state', payload: 'offline'}));
client.terminate();
});
this.wss?.close();
/* istanbul ignore else */
if (this.server) {
return new Promise((cb: () => void) => this.server.close(cb));
}
}
@bind private onRequest(request: http.IncomingMessage, response: http.ServerResponse): void {
// @ts-ignore
this.fileServer(request, response, finalhandler(request, response));
}
private authenticate(request: http.IncomingMessage, cb: (authenticate: boolean) => void): void {
const {query} = url.parse(request.url, true);
cb(!this.authToken || this.authToken === query.token);
}
@bind private onUpgrade(request: http.IncomingMessage, socket: net.Socket, head: Buffer): void {
this.wss.handleUpgrade(request, socket, head, (ws) => {
this.authenticate(request, (isAuthenticated) => {
if (isAuthenticated) {
this.wss.emit('connection', ws, request);
} else {
ws.close(4401, 'Unauthorized');
}
});
});
}
@bind private onWebSocketConnection(ws: WebSocket): void {
ws.on('error', (msg) => logger.error(`WebSocket error: ${msg.message}`));
ws.on('message', (data: Buffer, isBinary: boolean) => {
if (!isBinary && data) {
const message = data.toString();
const {topic, payload} = JSON.parse(message);
this.mqtt.onMessage(`${this.mqttBaseTopic}/${topic}`, Buffer.from(stringify(payload)));
}
});
for (const [key, value] of this.retainedMessages) {
ws.send(stringify({topic: key, payload: value}));
}
for (const device of this.zigbee.devices(false)) {
const payload = this.state.get(device);
const lastSeen = settings.get().advanced.last_seen;
/* istanbul ignore if */
if (lastSeen !== 'disable') {
payload.last_seen = utils.formatDate(device.zh.lastSeen, lastSeen);
}
if (device.zh.linkquality !== undefined) {
payload.linkquality = device.zh.linkquality;
}
ws.send(stringify({topic: device.name, payload}));
}
}
@bind private onMQTTPublishMessage(data: eventdata.MQTTMessagePublished): void {
if (data.topic.startsWith(`${this.mqttBaseTopic}/`)) {
// Send topic without base_topic
const topic = data.topic.substring(this.mqttBaseTopic.length + 1);
const payload = utils.parseJSON(data.payload, data.payload);
if (data.options.retain) {
this.retainedMessages.set(topic, payload);
}
if (this.wss) {
for (const client of this.wss.clients) {
/* istanbul ignore else */
if (client.readyState === WebSocket.OPEN) {
client.send(stringify({topic, payload}));
}
}
}
}
}
}
-331
View File
@@ -1,331 +0,0 @@
const settings = require('../util/settings');
const logger = require('../util/logger');
const Extension = require('./extension');
const utils = require('../util/utils');
const postfixes = utils.getEndpointNames();
const stringify = require('json-stable-stringify-without-jsonify');
const equals = require('fast-deep-equal/es6');
const topicRegex =
new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/group/members/(remove|add|remove_all)$`);
const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/(.+)/(remove|add|remove_all)$`);
const legacyTopicRegexRemoveAll = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/remove_all$`);
class Groups extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.onStateChange = this.onStateChange.bind(this);
this.legacyApi = settings.get().advanced.legacy_api;
this.lastOptimisticState = {};
}
async onZigbeeStarted() {
this.eventBus.on('stateChange', this.onStateChange);
await this.syncGroupsWithSettings();
}
async syncGroupsWithSettings() {
const settingsGroups = settings.getGroups();
const zigbeeGroups = this.zigbee.getGroups();
const addRemoveFromGroup = async (action, deviceName, groupName, endpoint, group) => {
try {
logger.info(`${action === 'add' ? 'Adding' : 'Removing'} '${deviceName}' to group '${groupName}'`);
if (action === 'remove') {
await endpoint.removeFromGroup(group);
} else {
await endpoint.addToGroup(group);
}
} catch (error) {
logger.error(`Failed to ${action} '${deviceName}' from '${groupName}'`);
}
};
for (const settingGroup of settingsGroups) {
const groupID = settingGroup.ID;
const zigbeeGroup = zigbeeGroups.find((g) => g.groupID === groupID) || this.zigbee.createGroup(groupID);
const settingsEntity = settingGroup.devices.map((d) => {
const entity = this.zigbee.resolveEntity(d);
if (!entity) logger.error(`Cannot find '${d}' of group '${settingGroup.friendlyName}'`);
return entity;
}).filter((e) => e != null);
// In settings but not in zigbee
for (const entity of settingsEntity) {
if (!zigbeeGroup.hasMember(entity.endpoint)) {
addRemoveFromGroup('add', entity.name, settingGroup.friendlyName, entity.endpoint, zigbeeGroup);
}
}
// In zigbee but not in settings
for (const endpoint of zigbeeGroup.members) {
if (!settingsEntity.find((e) => e.endpoint === endpoint)) {
const deviceName = settings.getDevice(endpoint.getDevice().ieeeAddr).friendlyName;
addRemoveFromGroup('remove', deviceName, settingGroup.friendlyName, endpoint, zigbeeGroup);
}
}
}
for (const zigbeeGroup of zigbeeGroups) {
if (!settingsGroups.find((g) => g.ID === zigbeeGroup.groupID)) {
for (const endpoint of zigbeeGroup.members) {
const deviceName = settings.getDevice(endpoint.getDevice().ieeeAddr).friendlyName;
addRemoveFromGroup('remove', deviceName, zigbeeGroup.groupID, endpoint, zigbeeGroup);
}
}
}
}
async onStateChange(data) {
const reason = 'group_optimistic';
if (data.reason === reason) {
return;
}
const properties = ['state', 'brightness', 'color_temp', 'color', 'color_mode'];
const payload = {};
properties.forEach((prop) => {
if (data.changed.hasOwnProperty(prop)) {
payload[prop] = data.changed[prop];
}
});
if (Object.keys(payload).length) {
const resolvedEntity = this.zigbee.resolveEntity(data.ID);
const zigbeeGroups = this.zigbee.getGroups().filter((zigbeeGroup) => {
const settingsGroup = settings.getGroup(zigbeeGroup.groupID);
return settingsGroup && settingsGroup.optimistic;
});
if (resolvedEntity.type === 'device') {
for (const zigbeeGroup of zigbeeGroups) {
if (zigbeeGroup.hasMember(resolvedEntity.endpoint) &&
!equals(this.lastOptimisticState[zigbeeGroup.groupID], payload)) {
if (!payload || payload.state !== 'OFF' || this.areAllMembersOff(zigbeeGroup)) {
this.lastOptimisticState[zigbeeGroup.groupID] = payload;
await this.publishEntityState(zigbeeGroup.groupID, payload, reason);
}
}
}
} else {
// Invalidate the last optimistic group state when group state is changed directly.
delete this.lastOptimisticState[resolvedEntity.group.groupID];
const groupIDsToPublish = new Set();
for (const member of resolvedEntity.group.members) {
await this.publishEntityState(member.getDevice().ieeeAddr, payload, reason);
for (const zigbeeGroup of zigbeeGroups) {
if (zigbeeGroup.hasMember(member)) {
if (!payload || payload.state !== 'OFF' || this.areAllMembersOff(zigbeeGroup)) {
groupIDsToPublish.add(zigbeeGroup.groupID);
}
}
}
}
groupIDsToPublish.delete(resolvedEntity.group.groupID);
for (const groupID of groupIDsToPublish) {
await this.publishEntityState(groupID, payload, reason);
}
}
}
}
areAllMembersOff(zigbeeGroup) {
for (const member of zigbeeGroup.members) {
const device = member.getDevice();
if (this.state.exists(device.ieeeAddr)) {
const state = this.state.get(device.ieeeAddr);
if (state && state.state === 'ON') {
return false;
}
}
}
return true;
}
parseMQTTMessage(topic, message) {
let type = null;
let resolvedEntityGroup = null;
let resolvedEntityDevice = null;
let hasEndpointName = null;
let error = null;
let groupKey = null;
let deviceKey = null;
let triggeredViaLegacyApi = false;
/* istanbul ignore else */
const topicRegexMatch = topic.match(topicRegex);
const legacyTopicRegexRemoveAllMatch = topic.match(legacyTopicRegexRemoveAll);
const legacyTopicRegexMatch = topic.match(legacyTopicRegex);
if (this.legacyApi && (legacyTopicRegexMatch || legacyTopicRegexRemoveAllMatch)) {
triggeredViaLegacyApi = true;
if (legacyTopicRegexMatch) {
resolvedEntityGroup = this.zigbee.resolveEntity(legacyTopicRegexMatch[1]);
type = legacyTopicRegexMatch[2];
if (!resolvedEntityGroup || resolvedEntityGroup.type !== 'group') {
logger.error(`Group '${legacyTopicRegexMatch[1]}' does not exist`);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {
friendly_name: message, group: legacyTopicRegexMatch[1], error: 'group doesn\'t exists',
};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_${type}_failed`, message: payload}),
);
}
return {};
}
} else {
type = 'remove_all';
}
resolvedEntityDevice = this.zigbee.resolveEntity(message);
if (!resolvedEntityDevice || !resolvedEntityDevice.type === 'device') {
logger.error(`Device '${message}' does not exist`);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {
friendly_name: message, group: legacyTopicRegexMatch[1], error: 'entity doesn\'t exists',
};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_${type}_failed`, message: payload}),
);
}
return {};
}
hasEndpointName = postfixes.find((p) => message.endsWith(`/${p}`));
} else if (topicRegexMatch) {
type = topicRegexMatch[1];
message = JSON.parse(message);
deviceKey = message.device;
if (type !== 'remove_all') {
groupKey = message.group;
resolvedEntityGroup = this.zigbee.resolveEntity(message.group);
if (!resolvedEntityGroup || resolvedEntityGroup.type !== 'group') {
error = `Group '${message.group}' does not exist`;
}
}
resolvedEntityDevice = this.zigbee.resolveEntity(message.device);
if (!error && (!resolvedEntityDevice || !resolvedEntityDevice.type === 'device')) {
error = `Device '${message.device}' does not exist`;
}
hasEndpointName = postfixes.find((p) => message.device.endsWith(`/${p}`));
}
return {
resolvedEntityGroup, resolvedEntityDevice, type, hasEndpointName, error, groupKey, deviceKey,
triggeredViaLegacyApi,
};
}
async onMQTTMessage(topic, message) {
let {
resolvedEntityGroup, resolvedEntityDevice, type, hasEndpointName, error, triggeredViaLegacyApi,
groupKey, deviceKey,
} = this.parseMQTTMessage(topic, message);
if (!type) return;
message = utils.parseJSON(message, message);
const responseData = {device: deviceKey};
if (groupKey) {
responseData.group = groupKey;
}
if (!error) {
try {
const keys = [
`${resolvedEntityDevice.device.ieeeAddr}/${resolvedEntityDevice.endpoint.ID}`,
`${resolvedEntityDevice.name}/${resolvedEntityDevice.endpoint.ID}`,
];
const definition = resolvedEntityDevice.definition;
const endpoints = definition && definition.endpoint ?
definition.endpoint(resolvedEntityDevice.device) : null;
const endpointName = endpoints ?
Object.entries(endpoints).find((e) => e[1] === resolvedEntityDevice.endpoint.ID)[0] : null;
if (endpointName) {
keys.push(`${resolvedEntityDevice.device.ieeeAddr}/${endpointName}`);
keys.push(`${resolvedEntityDevice.name}/${endpointName}`);
}
if (!hasEndpointName) {
keys.push(resolvedEntityDevice.name);
keys.push(resolvedEntityDevice.device.ieeeAddr);
}
if (type === 'add') {
logger.info(`Adding '${resolvedEntityDevice.name}' to '${resolvedEntityGroup.name}'`);
await resolvedEntityDevice.endpoint.addToGroup(resolvedEntityGroup.group);
settings.addDeviceToGroup(resolvedEntityGroup.settings.ID, keys);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: resolvedEntityDevice.name, group: resolvedEntityGroup.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_add`, message: payload}),
);
}
} else if (type === 'remove') {
logger.info(`Removing '${resolvedEntityDevice.name}' from '${resolvedEntityGroup.name}'`);
await resolvedEntityDevice.endpoint.removeFromGroup(resolvedEntityGroup.group);
settings.removeDeviceFromGroup(resolvedEntityGroup.settings.ID, keys);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: resolvedEntityDevice.name, group: resolvedEntityGroup.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_remove`, message: payload}),
);
}
} else { // remove_all
logger.info(`Removing '${resolvedEntityDevice.name}' from all groups`);
await resolvedEntityDevice.endpoint.removeFromAllGroups();
for (const settingsGroup of settings.getGroups()) {
settings.removeDeviceFromGroup(settingsGroup.ID, keys);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: resolvedEntityDevice.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_remove_all`, message: payload}),
);
}
}
}
} catch (e) {
error = `Failed to ${type} from group (${e.message})`;
}
}
if (!triggeredViaLegacyApi) {
const response = utils.getResponse(message, responseData, error);
await this.mqtt.publish(`bridge/response/group/members/${type}`, stringify(response));
}
if (error) {
logger.error(error);
} else {
this.eventBus.emit('groupMembersChanged',
{group: resolvedEntityGroup, action: type, endpoint: resolvedEntityDevice.endpoint});
}
}
}
module.exports = Groups;
+386
View File
@@ -0,0 +1,386 @@
import * as settings from '../util/settings';
import logger from '../util/logger';
import utils from '../util/utils';
import stringify from 'json-stable-stringify-without-jsonify';
import equals from 'fast-deep-equal/es6';
import bind from 'bind-decorator';
import Extension from './extension';
import Device from '../model/device';
import Group from '../model/group';
const topicRegex =
new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/group/members/(remove|add|remove_all)$`);
const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/(.+)/(remove|add|remove_all)$`);
const legacyTopicRegexRemoveAll = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/remove_all$`);
const stateProperties: {[s: string]: (value: string, exposes: zhc.DefinitionExpose[]) => boolean} = {
'state': () => true,
'brightness': (value, exposes) =>
!!exposes.find((e) => e.type === 'light' && e.features.find((f) => f.name === 'brightness')),
'color_temp': (value, exposes) =>
!!exposes.find((e) => e.type === 'light' && e.features.find((f) => f.name === 'color_temp')),
'color': (value, exposes) =>
!!exposes.find((e) => e.type === 'light' &&
e.features.find((f) => f.name === 'color_xy' || f.name === 'color_hs')),
'color_mode': (value, exposes) =>
!!exposes.find((e) => e.type === 'light' && (
(e.features.find((f) => f.name === `color_${value}`)) ||
(value === 'color_temp' && e.features.find((f) => f.name === 'color_temp')) )),
};
interface ParsedMQTTMessage {
type: 'remove' | 'add' | 'remove_all', resolvedEntityGroup: Group, resolvedEntityDevice: Device,
error: string, groupKey: string, deviceKey: string, triggeredViaLegacyApi: boolean,
skipDisableReporting: boolean, resolvedEntityEndpoint: zh.Endpoint,
}
export default class Groups extends Extension {
private legacyApi = settings.get().advanced.legacy_api;
private lastOptimisticState: {[s: string]: KeyValue} = {};
override async start(): Promise<void> {
this.eventBus.onStateChange(this, this.onStateChange);
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
await this.syncGroupsWithSettings();
}
private async syncGroupsWithSettings(): Promise<void> {
const settingsGroups = settings.getGroups();
const zigbeeGroups = this.zigbee.groups();
const addRemoveFromGroup = async (action: 'add' | 'remove', deviceName: string,
groupName: string | number, endpoint: zh.Endpoint, group: Group): Promise<void> => {
try {
logger.info(`${action === 'add' ? 'Adding' : 'Removing'} '${deviceName}' to group '${groupName}'`);
if (action === 'remove') {
await endpoint.removeFromGroup(group.zh);
} else {
await endpoint.addToGroup(group.zh);
}
} catch (error) {
logger.error(`Failed to ${action} '${deviceName}' from '${groupName}'`);
logger.debug(error.stack);
}
};
for (const settingGroup of settingsGroups) {
const groupID = settingGroup.ID;
const zigbeeGroup = zigbeeGroups.find((g) => g.ID === groupID) || this.zigbee.createGroup(groupID);
const settingsEndpoint = settingGroup.devices.map((d) => {
const parsed = utils.parseEntityID(d);
const entity = this.zigbee.resolveEntity(parsed.ID) as Device;
if (!entity) logger.error(`Cannot find '${d}' of group '${settingGroup.friendly_name}'`);
return {'endpoint': entity?.endpoint(parsed.endpoint), 'name': entity?.name};
}).filter((e) => e.endpoint != null);
// In settings but not in zigbee
for (const entity of settingsEndpoint) {
if (!zigbeeGroup.zh.hasMember(entity.endpoint)) {
addRemoveFromGroup('add', entity.name, settingGroup.friendly_name, entity.endpoint, zigbeeGroup);
}
}
// In zigbee but not in settings
for (const endpoint of zigbeeGroup.zh.members) {
if (!settingsEndpoint.find((e) => e.endpoint === endpoint)) {
const deviceName = settings.getDevice(endpoint.getDevice().ieeeAddr).friendly_name;
addRemoveFromGroup('remove', deviceName, settingGroup.friendly_name, endpoint, zigbeeGroup);
}
}
}
for (const zigbeeGroup of zigbeeGroups) {
if (!settingsGroups.find((g) => g.ID === zigbeeGroup.ID)) {
for (const endpoint of zigbeeGroup.zh.members) {
const deviceName = settings.getDevice(endpoint.getDevice().ieeeAddr).friendly_name;
addRemoveFromGroup('remove', deviceName, zigbeeGroup.ID, endpoint, zigbeeGroup);
}
}
}
}
@bind async onStateChange(data: eventdata.StateChange): Promise<void> {
const reason = 'groupOptimistic';
if (data.reason === reason || data.reason === 'publishCached') {
return;
}
const payload: KeyValue = {};
let endpointName: string = null;
for (let [prop, value] of Object.entries(data.update)) {
const endpointNameMatch = utils.endpointNames.find((n) => prop.endsWith(`_${n}`));
if (endpointNameMatch) {
prop = prop.substring(0, prop.length - endpointNameMatch.length - 1);
endpointName = endpointNameMatch;
}
if (prop in stateProperties) {
payload[prop] = value;
}
}
if (Object.keys(payload).length) {
const entity = data.entity;
const groups = this.zigbee.groups().filter((g) => {
return g.options && (!g.options.hasOwnProperty('optimistic') || g.options.optimistic);
});
if (entity instanceof Device) {
for (const group of groups) {
if (group.zh.hasMember(entity.endpoint(endpointName)) &&
!equals(this.lastOptimisticState[group.ID], payload) &&
this.shouldPublishPayloadForGroup(group, payload)) {
this.lastOptimisticState[group.ID] = payload;
await this.publishEntityState(group, payload, reason);
}
}
} else {
// Invalidate the last optimistic group state when group state is changed directly.
delete this.lastOptimisticState[entity.ID];
const groupsToPublish: Set<Group> = new Set();
for (const member of entity.zh.members) {
const device = this.zigbee.resolveEntity(member.getDevice()) as Device;
if (device.options.disabled) continue;
const exposes = device.exposes();
const memberPayload: KeyValue = {};
Object.keys(payload).forEach((key) => {
if (stateProperties[key](payload[key], exposes)) {
memberPayload[key] = payload[key];
}
});
const endpointName = device.endpointName(member);
if (endpointName) {
Object.keys(memberPayload).forEach((key) => {
memberPayload[`${key}_${endpointName}`] = memberPayload[key];
delete memberPayload[key];
});
}
await this.publishEntityState(device, memberPayload, reason);
for (const zigbeeGroup of groups) {
if (zigbeeGroup.zh.hasMember(member) &&
this.shouldPublishPayloadForGroup(zigbeeGroup, payload)) {
groupsToPublish.add(zigbeeGroup);
}
}
}
groupsToPublish.delete(entity);
for (const group of groupsToPublish) {
await this.publishEntityState(group, payload, reason);
}
}
}
}
private shouldPublishPayloadForGroup(group: Group, payload: KeyValue): boolean {
if (group.options.off_state === 'last_member_state') return true;
if (!payload || payload.state !== 'OFF') return true;
if (this.areAllMembersOff(group)) return true;
return false;
}
private areAllMembersOff(group: Group): boolean {
for (const member of group.zh.members) {
const device = this.zigbee.resolveEntity(member.getDevice());
if (this.state.exists(device)) {
const state = this.state.get(device);
if (state.state === 'ON') {
return false;
}
}
}
return true;
}
private parseMQTTMessage(data: eventdata.MQTTMessage): ParsedMQTTMessage {
let type: 'remove' | 'add' | 'remove_all' = null;
let resolvedEntityGroup: Group = null;
let resolvedEntityDevice: Device = null;
let resolvedEntityEndpoint: zh.Endpoint = null;
let error: string = null;
let groupKey: string = null;
let deviceKey: string = null;
let triggeredViaLegacyApi = false;
let skipDisableReporting = false;
/* istanbul ignore else */
const topicRegexMatch = data.topic.match(topicRegex);
const legacyTopicRegexRemoveAllMatch = data.topic.match(legacyTopicRegexRemoveAll);
const legacyTopicRegexMatch = data.topic.match(legacyTopicRegex);
if (this.legacyApi && (legacyTopicRegexMatch || legacyTopicRegexRemoveAllMatch)) {
triggeredViaLegacyApi = true;
if (legacyTopicRegexMatch) {
resolvedEntityGroup = this.zigbee.resolveEntity(legacyTopicRegexMatch[1]) as Group;
type = legacyTopicRegexMatch[2] as 'remove' | 'remove_all' | 'add';
if (!resolvedEntityGroup || !(resolvedEntityGroup instanceof Group)) {
logger.error(`Group '${legacyTopicRegexMatch[1]}' does not exist`);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: data.message,
group: legacyTopicRegexMatch[1], error: 'group doesn\'t exists'};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_${type}_failed`, message: payload}),
);
}
return null;
}
} else {
type = 'remove_all';
}
const parsedEntity = utils.parseEntityID(data.message);
resolvedEntityDevice = this.zigbee.resolveEntity(parsedEntity.ID) as Device;
if (!resolvedEntityDevice || !(resolvedEntityDevice instanceof Device)) {
logger.error(`Device '${data.message}' does not exist`);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {
friendly_name: data.message, group: legacyTopicRegexMatch[1], error: 'entity doesn\'t exists',
};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_${type}_failed`, message: payload}),
);
}
return null;
}
resolvedEntityEndpoint = resolvedEntityDevice.endpoint(parsedEntity.endpoint);
} else if (topicRegexMatch) {
type = topicRegexMatch[1] as 'remove' | 'add' | 'remove_all';
const message = JSON.parse(data.message);
deviceKey = message.device;
skipDisableReporting = 'skip_disable_reporting' in message ? message.skip_disable_reporting : false;
if (type !== 'remove_all') {
groupKey = message.group;
resolvedEntityGroup = this.zigbee.resolveEntity(message.group) as Group;
if (!resolvedEntityGroup || !(resolvedEntityGroup instanceof Group)) {
error = `Group '${message.group}' does not exist`;
}
}
const parsed = utils.parseEntityID(message.device);
resolvedEntityDevice = this.zigbee.resolveEntity(parsed.ID) as Device;
if (!error && (!resolvedEntityDevice || !(resolvedEntityDevice instanceof Device))) {
error = `Device '${message.device}' does not exist`;
}
if (!error) {
resolvedEntityEndpoint = resolvedEntityDevice.endpoint(parsed.endpoint);
}
}
return {
resolvedEntityGroup, resolvedEntityDevice, type, error, groupKey, deviceKey,
triggeredViaLegacyApi, skipDisableReporting, resolvedEntityEndpoint,
};
}
@bind private async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const parsed = this.parseMQTTMessage(data);
if (!parsed || !parsed.type) return;
let {
resolvedEntityGroup, resolvedEntityDevice, type, error, triggeredViaLegacyApi,
groupKey, deviceKey, skipDisableReporting, resolvedEntityEndpoint,
} = parsed;
const message = utils.parseJSON(data.message, data.message);
let changedGroups: Group[] = [];
const responseData: KeyValue = {device: deviceKey};
if (groupKey) {
responseData.group = groupKey;
}
if (!error) {
try {
const keys = [
`${resolvedEntityDevice.ieeeAddr}/${resolvedEntityEndpoint.ID}`,
`${resolvedEntityDevice.name}/${resolvedEntityEndpoint.ID}`,
];
const endpointNameLocal = resolvedEntityDevice.endpointName(resolvedEntityEndpoint);
if (endpointNameLocal) {
keys.push(`${resolvedEntityDevice.ieeeAddr}/${endpointNameLocal}`);
keys.push(`${resolvedEntityDevice.name}/${endpointNameLocal}`);
}
if (!endpointNameLocal) {
keys.push(resolvedEntityDevice.name);
keys.push(resolvedEntityDevice.ieeeAddr);
}
if (type === 'add') {
logger.info(`Adding '${resolvedEntityDevice.name}' to '${resolvedEntityGroup.name}'`);
await resolvedEntityEndpoint.addToGroup(resolvedEntityGroup.zh);
settings.addDeviceToGroup(resolvedEntityGroup.ID.toString(), keys);
changedGroups.push(resolvedEntityGroup);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: resolvedEntityDevice.name, group: resolvedEntityGroup.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_add`, message: payload}),
);
}
} else if (type === 'remove') {
logger.info(`Removing '${resolvedEntityDevice.name}' from '${resolvedEntityGroup.name}'`);
await resolvedEntityEndpoint.removeFromGroup(resolvedEntityGroup.zh);
settings.removeDeviceFromGroup(resolvedEntityGroup.ID.toString(), keys);
changedGroups.push(resolvedEntityGroup);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: resolvedEntityDevice.name, group: resolvedEntityGroup.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_remove`, message: payload}),
);
}
} else { // remove_all
logger.info(`Removing '${resolvedEntityDevice.name}' from all groups`);
changedGroups = this.zigbee.groups().filter((g) => g.zh.members.includes(resolvedEntityEndpoint));
await resolvedEntityEndpoint.removeFromAllGroups();
for (const settingsGroup of settings.getGroups()) {
settings.removeDeviceFromGroup(settingsGroup.ID.toString(), keys);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const payload = {friendly_name: resolvedEntityDevice.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `device_group_remove_all`, message: payload}),
);
}
}
}
} catch (e) {
error = `Failed to ${type} from group (${e.message})`;
logger.debug(e.stack);
}
}
if (!triggeredViaLegacyApi) {
const response = utils.getResponse(message, responseData, error);
await this.mqtt.publish(`bridge/response/group/members/${type}`, stringify(response));
}
if (error) {
logger.error(error);
} else {
for (const group of changedGroups) {
this.eventBus.emitGroupMembersChanged({
group, action: type, endpoint: resolvedEntityEndpoint, skipDisableReporting});
}
}
}
}
-932
View File
@@ -1,932 +0,0 @@
const settings = require('../util/settings');
const logger = require('../util/logger');
const utils = require('../util/utils');
const zigbee2mqttVersion = require('../../package.json').version;
const Extension = require('./extension');
const stringify = require('json-stable-stringify-without-jsonify');
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const assert = require('assert');
const sensorClick = {
type: 'sensor',
object_id: 'click',
discovery_payload: {
icon: 'mdi:toggle-switch',
value_template: '{{ value_json.click }}',
},
};
const defaultStatusTopic = 'homeassistant/status';
/**
* This extensions handles integration with HomeAssistant
*/
class HomeAssistant extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
// A map of all discoverd devices
this.discovered = {};
this.mapping = {};
this.discoveredTriggers = {};
this.legacyApi = settings.get().advanced.legacy_api;
if (!settings.get().advanced.cache_state) {
logger.warn('In order for HomeAssistant integration to work properly set `cache_state: true');
}
if (settings.get().experimental.output === 'attribute') {
throw new Error('Home Assitant integration is not possible with attribute output!');
}
this.discoveryTopic = settings.get().advanced.homeassistant_discovery_topic;
this.statusTopic = settings.get().advanced.homeassistant_status_topic;
this.eventBus.on('deviceRemoved', (data) => this.onDeviceRemoved(data.resolvedEntity), this.constructor.name);
this.eventBus.on('publishEntityState', (data) => this.onPublishEntityState(data), this.constructor.name);
this.eventBus.on('deviceRenamed', (data) =>
this.onDeviceRenamed(data.device, data.homeAssisantRename), this.constructor.name,
);
this.populateMapping();
}
populateMapping() {
for (const def of zigbeeHerdsmanConverters.definitions) {
this.mapping[def.model] = [];
if (['WXKG01LM', 'HS1EB/HS1EB-E', 'ICZB-KPD14S', 'TERNCY-SD01', 'TERNCY-PP01', 'ICZB-KPD18S',
'E1766', 'ZWallRemote0', 'ptvo.switch', '2AJZ4KPKEY', 'ZGRC-KEY-013', 'HGZB-02S', 'HGZB-045',
'HGZB-1S', 'AV2010/34', 'IM6001-BTP01', 'WXKG11LM', 'WXKG03LM', 'WXKG02LM_rev1', 'WXKG02LM_rev2',
'QBKG04LM', 'QBKG03LM', 'QBKG11LM', 'QBKG21LM', 'QBKG22LM', 'WXKG12LM', 'QBKG12LM',
'E1743'].includes(def.model)) {
// deprecated
this.mapping[def.model].push(sensorClick);
}
if (['ICTC-G-1'].includes(def.model)) {
// deprecated
this.mapping[def.model].push({
type: 'sensor',
object_id: 'brightness',
discovery_payload: {
unit_of_measurement: 'brightness',
icon: 'mdi:brightness-5',
value_template: '{{ value_json.brightness }}',
},
});
}
for (const expose of def.exposes) {
let discoveryEntry = null;
/* istanbul ignore else */
if (expose.type === 'light') {
const supportsXY = !!expose.features.find((e) => e.name === 'color_xy');
const supportsHS = !!expose.features.find((e) => e.name === 'color_hs');
const colorTemp = expose.features.find((e) => e.name === 'color_temp');
discoveryEntry = {
type: 'light',
object_id: expose.endpoint ? `light_${expose.endpoint}` : 'light',
discovery_payload: {
brightness: !!expose.features.find((e) => e.name === 'brightness'),
color_temp: !!colorTemp,
xy: supportsXY,
hs: !supportsXY && supportsHS,
schema: 'json',
command_topic: true,
brightness_scale: 254,
command_topic_prefix: expose.endpoint ? expose.endpoint : undefined,
state_topic_postfix: expose.endpoint ? expose.endpoint : undefined,
},
};
if (colorTemp) {
discoveryEntry.discovery_payload.max_mireds = colorTemp.value_max;
discoveryEntry.discovery_payload.min_mireds = colorTemp.value_min;
}
const effect = def.exposes.find((e) => e.type === 'enum' && e.name === 'effect');
if (effect) {
discoveryEntry.discovery_payload.effect = true;
discoveryEntry.discovery_payload.effect_list = effect.values;
}
} else if (expose.type === 'switch') {
const state = expose.features.find((f) => f.name === 'state');
discoveryEntry = {
type: 'switch',
object_id: expose.endpoint ? `switch_${expose.endpoint}` : 'switch',
discovery_payload: {
payload_off: state.value_off,
payload_on: state.value_on,
value_template: `{{ value_json.${state.property} }}`,
command_topic: true,
command_topic_prefix: expose.endpoint ? expose.endpoint : undefined,
},
};
const different = ['valve_detection', 'window_detection', 'auto_lock', 'away_mode'];
if (different.includes(state.property)) {
discoveryEntry.discovery_payload.command_topic_postfix = state.property;
discoveryEntry.discovery_payload.state_off = state.value_off;
discoveryEntry.discovery_payload.state_on = state.value_on;
discoveryEntry.discovery_payload.state_topic = true;
discoveryEntry.object_id = state.property;
if (state.property === 'window_detection') {
discoveryEntry.discovery_payload.icon = 'mdi:window-open-variant';
}
}
} else if (expose.type === 'climate') {
const setpointProperties = ['occupied_heating_setpoint', 'current_heating_setpoint'];
const setpoint = expose.features.find((f) => setpointProperties.includes(f.name));
assert(setpoint, 'No setpoint found');
const temperature = expose.features.find((f) => f.name === 'local_temperature');
assert(temperature, 'No temperature found');
discoveryEntry = {
type: 'climate',
object_id: expose.endpoint ? `climate_${expose.endpoint}` : 'climate',
discovery_payload: {
// Static
state_topic: false,
temperature_unit: 'C',
// Setpoint
temp_step: setpoint.value_step,
min_temp: setpoint.value_min.toString(),
max_temp: setpoint.value_max.toString(),
// Temperature
current_temperature_topic: true,
current_temperature_template: `{{ value_json.${temperature.property} }}`,
},
};
const mode = expose.features.find((f) => f.name === 'system_mode');
if (mode) {
if (mode.values.includes('sleep')) {
// 'sleep' is not supported by homeassistent, but is valid according to ZCL
// TRV that support sleep (e.g. Viessmann) will have it removed from here,
// this allows other expose consumers to still use it, e.g. the frontend.
mode.values.splice(mode.values.indexOf('sleep'), 1);
}
discoveryEntry.discovery_payload.mode_state_topic = true;
discoveryEntry.discovery_payload.mode_state_template = `{{ value_json.${mode.property} }}`;
discoveryEntry.discovery_payload.modes = mode.values;
discoveryEntry.discovery_payload.mode_command_topic = true;
}
const state = expose.features.find((f) => f.name === 'running_state');
if (state) {
discoveryEntry.discovery_payload.action_topic = true;
discoveryEntry.discovery_payload.action_template = `{% set values = ` +
`{'idle':'off','heat':'heating','cool':'cooling','fan only':'fan'}` +
` %}{{ values[value_json.${state.property}] }}`;
}
const coolingSetpoint = expose.features.find((f) => f.name === 'occupied_cooling_setpoint');
if (coolingSetpoint) {
discoveryEntry.discovery_payload.temperature_low_command_topic = setpoint.name;
discoveryEntry.discovery_payload.temperature_low_state_template =
`{{ value_json.${setpoint.property} }}`;
discoveryEntry.discovery_payload.temperature_low_state_topic = true;
discoveryEntry.discovery_payload.temperature_high_command_topic = coolingSetpoint.name;
discoveryEntry.discovery_payload.temperature_high_state_template =
`{{ value_json.${coolingSetpoint.property} }}`;
discoveryEntry.discovery_payload.temperature_high_state_topic = true;
} else {
discoveryEntry.discovery_payload.temperature_command_topic = setpoint.name;
discoveryEntry.discovery_payload.temperature_state_template =
`{{ value_json.${setpoint.property} }}`;
discoveryEntry.discovery_payload.temperature_state_topic = true;
}
const fanMode = expose.features.find((f) => f.name === 'fan_mode');
if (fanMode) {
discoveryEntry.discovery_payload.fan_modes = fanMode.values;
discoveryEntry.discovery_payload.fan_mode_command_topic = true;
discoveryEntry.discovery_payload.fan_mode_state_template =
`{{ value_json.${fanMode.property} }}`;
discoveryEntry.discovery_payload.fan_mode_state_topic = true;
}
const preset = expose.features.find((f) => f.name === 'preset');
if (preset) {
discoveryEntry.discovery_payload.hold_modes = preset.values;
discoveryEntry.discovery_payload.hold_command_topic = true;
discoveryEntry.discovery_payload.hold_state_template =
`{{ value_json.${preset.property} }}`;
discoveryEntry.discovery_payload.hold_state_topic = true;
}
const awayMode = expose.features.find((f) => f.name === 'away_mode');
if (awayMode) {
discoveryEntry.discovery_payload.away_mode_command_topic = true;
discoveryEntry.discovery_payload.away_mode_state_topic = true;
discoveryEntry.discovery_payload.away_mode_state_template =
`{{ value_json.${awayMode.property} }}`;
}
if (expose.endpoint) {
discoveryEntry.discovery_payload.state_topic_postfix = expose.endpoint;
}
} else if (expose.type === 'lock') {
assert(!expose.endpoint, `Endpoint not supported for lock type`);
const state = expose.features.find((f) => f.name === 'state');
assert(state, 'No state found');
discoveryEntry = {
type: 'lock',
object_id: 'lock',
discovery_payload: {
command_topic: true,
value_template: `{{ value_json.${state.property} }}`,
},
};
if (state.property === 'keypad_lockout') {
// deprecated: keypad_lockout is messy, but changing is breaking
discoveryEntry.discovery_payload.payload_lock = state.value_on;
discoveryEntry.discovery_payload.payload_unlock = state.value_off;
discoveryEntry.discovery_payload.state_topic = true;
discoveryEntry.object_id = 'keypad_lock';
} else if (state.property === 'child_lock') {
// deprecated: child_lock is messy, but changing is breaking
discoveryEntry.discovery_payload.payload_lock = state.value_on;
discoveryEntry.discovery_payload.payload_unlock = state.value_off;
discoveryEntry.discovery_payload.state_locked = 'LOCK';
discoveryEntry.discovery_payload.state_unlocked = 'UNLOCK';
discoveryEntry.discovery_payload.state_topic = true;
discoveryEntry.object_id = 'child_lock';
} else {
discoveryEntry.discovery_payload.state_locked = state.value_on;
discoveryEntry.discovery_payload.state_unlocked = state.value_off;
}
if (state.property !== 'state') {
discoveryEntry.discovery_payload.command_topic_postfix = state.property;
}
} else if (expose.type === 'cover') {
assert(!expose.endpoint, `Endpoint not supported for cover type`);
const hasPosition = expose.features.find((e) => e.name === 'position');
const hasTilt = expose.features.find((e) => e.name === 'tilt');
discoveryEntry = {
type: 'cover',
object_id: 'cover',
discovery_payload: {
command_topic: true,
state_topic: !hasPosition,
},
};
if (!hasPosition && !hasTilt) {
discoveryEntry.discovery_payload.optimistic = true;
}
if (hasPosition) {
discoveryEntry.discovery_payload = {...discoveryEntry.discovery_payload,
position_template: '{{ value_json.position }}',
set_position_template: '{ "position": {{ position }} }',
set_position_topic: true,
position_topic: true,
};
}
if (hasTilt) {
discoveryEntry.discovery_payload = {...discoveryEntry.discovery_payload,
tilt_command_topic: true,
tilt_status_topic: true,
tilt_status_template: '{{ value_json.tilt }}',
};
}
} else if (expose.type === 'fan') {
assert(!expose.endpoint, `Endpoint not supported for fan type`);
discoveryEntry = {
type: 'fan',
object_id: 'fan',
discovery_payload: {
state_topic: true,
state_value_template: '{{ value_json.fan_state }}',
command_topic: true,
command_topic_postfix: 'fan_state',
},
};
const speed = expose.features.find((e) => e.name === 'mode');
if (speed) {
discoveryEntry.discovery_payload.speed_state_topic = true;
discoveryEntry.discovery_payload.speed_command_topic = true;
discoveryEntry.discovery_payload.speed_value_template = '{{ value_json.fan_mode }}';
discoveryEntry.discovery_payload.speeds = speed.values;
}
} else if (expose.type === 'binary') {
const lookup = {
occupancy: {device_class: 'motion'},
battery_low: {device_class: 'battery'},
water_leak: {device_class: 'moisture'},
vibration: {device_class: 'vibration'},
contact: {device_class: 'door'},
smoke: {device_class: 'smoke'},
gas: {device_class: 'gas'},
carbon_monoxide: {device_class: 'safety'},
presence: {device_class: 'presence'},
};
discoveryEntry = {
type: 'binary_sensor',
object_id: expose.endpoint ? `${expose.name}_${expose.endpoint}` : `${expose.name}`,
discovery_payload: {
value_template: `{{ value_json.${expose.property} }}`,
payload_on: expose.value_on,
payload_off: expose.value_off,
...(lookup[expose.name] || {}),
},
};
} else if (expose.type === 'numeric') {
const lookup = {
battery: {device_class: 'battery'},
temperature: {device_class: 'temperature'},
humidity: {device_class: 'humidity'},
illuminance_lux: {device_class: 'illuminance'},
illuminance: {device_class: 'illuminance'},
soil_moisture: {icon: 'mdi:water-percent'},
position: {icon: 'mdi:valve'},
pressure: {device_class: 'pressure'},
power: {device_class: 'power'},
linkquality: {icon: 'mdi:signal'},
current: {device_class: 'current'},
voltage: {device_class: 'voltage'},
current_phase_b: {device_class: 'current'},
voltage_phase_b: {device_class: 'voltage'},
current_phase_c: {device_class: 'current'},
voltage_phase_c: {device_class: 'voltage'},
energy: {device_class: 'energy'},
smoke_density: {icon: 'mdi:google-circles-communities'},
gas_density: {icon: 'mdi:google-circles-communities'},
pm25: {icon: 'mdi:air-filter'},
pm10: {icon: 'mdi:air-filter'},
voc: {icon: 'mdi:air-filter'},
aqi: {icon: 'mdi:air-filter'},
hcho: {icon: 'mdi:air-filter'},
requested_brightness_level: {icon: 'mdi:brightness-5'},
requested_brightness_percent: {icon: 'mdi:brightness-5'},
eco2: {icon: 'mdi:molecule-co2'},
co2: {icon: 'mdi:molecule-co2'},
local_temperature: {device_class: 'temperature'},
x_axis: {icon: 'mdi:axis-x-arrow'},
y_axis: {icon: 'mdi:axis-y-arrow'},
z_axis: {icon: 'mdi:axis-z-arrow'},
};
discoveryEntry = {
type: 'sensor',
object_id: expose.endpoint ? `${expose.name}_${expose.endpoint}` : `${expose.name}`,
discovery_payload: {
value_template: `{{ value_json.${expose.property} }}`,
...(expose.unit && {unit_of_measurement: expose.unit}),
...lookup[expose.name],
},
};
} else if (expose.type === 'enum' || expose.type === 'text' || expose.type === 'composite') {
const ACCESS_STATE = 1;
if (expose.access & ACCESS_STATE) {
const lookup = {
action: {icon: 'mdi:gesture-double-tap'},
};
discoveryEntry = {
type: 'sensor',
object_id: expose.property,
discovery_payload: {
value_template: `{{ value_json.${expose.property} }}`,
...lookup[expose.name],
},
};
}
} else {
throw new Error(`Unsupported exposes type: '${expose.type}'`);
}
if (discoveryEntry) {
this.mapping[def.model].push(discoveryEntry);
}
}
}
for (const definition of utils.getExternalConvertersDefinitions(settings)) {
if (definition.hasOwnProperty('homeassistant')) {
this.mapping[definition.model] = definition.homeassistant;
}
}
}
onDeviceRemoved(resolvedEntity) {
logger.debug(`Clearing Home Assistant discovery topic for '${resolvedEntity.name}'`);
delete this.discovered[resolvedEntity.device.ieeeAddr];
for (const config of this.getConfigs(resolvedEntity)) {
const topic = this.getDiscoveryTopic(config, resolvedEntity.device);
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic, false, false);
}
}
async onPublishEntityState(data) {
/**
* In case we deal with a lightEndpoint configuration Zigbee2MQTT publishes
* e.g. {state_l1: ON, brightness_l1: 250} to zigbee2mqtt/mydevice.
* As the Home Assistant MQTT JSON light cannot be configured to use state_l1/brightness_l1
* as the state variables, the state topic is set to zigbee2mqtt/mydevice/l1.
* Here we retrieve all the attributes with the _l1 values and republish them on
* zigbee2mqtt/mydevice/l1.
*/
if (data.entity.definition && this.mapping[data.entity.definition.model]) {
for (const config of this.mapping[data.entity.definition.model]) {
const match = /light_(.*)/.exec(config['object_id']);
if (match) {
const endpoint = match[1];
const endpointRegExp = new RegExp(`(.*)_${endpoint}`);
const payload = {};
for (const key of Object.keys(data.messagePayload)) {
const keyMatch = endpointRegExp.exec(key);
if (keyMatch) {
payload[keyMatch[1]] = data.messagePayload[key];
}
}
await this.mqtt.publish(
`${data.entity.name}/${endpoint}`, stringify(payload), {},
);
}
}
}
/**
* Publish an empty value for click and action payload, in this way Home Assistant
* can use Home Assistant entities in automations.
* https://github.com/Koenkk/zigbee2mqtt/issues/959#issuecomment-480341347
*/
if (settings.get().advanced.homeassistant_legacy_triggers) {
const keys = ['action', 'click'].filter((k) =>
data.messagePayload.hasOwnProperty(k) && data.messagePayload[k] !== '');
for (const key of keys) {
this.publishEntityState(data.entity.device.ieeeAddr, {[key]: ''});
}
}
/**
* Implements the MQTT device trigger (https://www.home-assistant.io/integrations/device_trigger.mqtt/)
* The MQTT device trigger does not support JSON parsing, so it cannot listen to zigbee2mqtt/my_device
* Whenever a device publish an {action: *} we discover an MQTT device trigger sensor
* and republish it to zigbee2mqtt/my_devic/action
*/
if (data.entity.definition) {
const keys = ['action', 'click'].filter((k) => data.messagePayload[k] && data.messagePayload[k] !== '');
for (const key of keys) {
const value = data.messagePayload[key].toString();
await this.publishDeviceTriggerDiscover(data.entity, key, value);
await this.mqtt.publish(`${data.entity.name}/${key}`, value, {});
}
}
/**
* Publish a value for update_available (if not there yet) to prevent Home Assistant generating warnings of
* this value not being available.
*/
const supportsOTA = data.entity.definition && data.entity.definition.hasOwnProperty('ota');
const mockedValues = [
{
property: 'update_available',
condition: supportsOTA && this.legacyApi,
value: false,
},
{
property: 'update',
condition: supportsOTA,
value: {state: 'idle'},
},
{
property: 'water_leak',
condition: data.entity.device && data.entity.definition && this.mapping[data.entity.definition.model] &&
this.mapping[data.entity.definition.model].filter((c) => c.object_id === 'water_leak').length === 1,
value: false,
},
];
for (const entry of mockedValues) {
if (entry.condition && !data.messagePayload.hasOwnProperty(entry.property)) {
logger.debug(`Mocking '${entry.property}' value for Home Assistant`);
this.publishEntityState(data.entity.device.ieeeAddr, {[entry.property]: entry.value});
}
}
}
onDeviceRenamed(device, homeAssisantRename) {
logger.debug(`Refreshing Home Assistant discovery topic for '${device.ieeeAddr}'`);
const resolvedEntity = this.zigbee.resolveEntity(device);
// Clear before rename so Home Assistant uses new friendly_name
// https://github.com/Koenkk/zigbee2mqtt/issues/4096#issuecomment-674044916
if (homeAssisantRename) {
for (const config of this.getConfigs(resolvedEntity)) {
const topic = this.getDiscoveryTopic(config, device);
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic, false, false);
}
}
this.discover(resolvedEntity, true);
if (this.discoveredTriggers[device.ieeeAddr]) {
for (const config of this.discoveredTriggers[device.ieeeAddr]) {
const key = config.substring(0, config.indexOf('_'));
const value = config.substring(config.indexOf('_') + 1);
this.publishDeviceTriggerDiscover(resolvedEntity, key, value, true);
}
}
}
async onMQTTConnected() {
this.mqtt.subscribe(this.statusTopic);
this.mqtt.subscribe(defaultStatusTopic);
this.mqtt.subscribe(`${this.discoveryTopic}/#`);
// MQTT discovery of all paired devices on startup.
for (const device of this.zigbee.getClients()) {
const resolvedEntity = this.zigbee.resolveEntity(device);
this.discover(resolvedEntity, true);
}
}
getConfigs(resolvedEntity) {
if (!resolvedEntity || !resolvedEntity.definition || !this.mapping[resolvedEntity.definition.model]) return [];
let configs = this.mapping[resolvedEntity.definition.model].slice();
if (resolvedEntity.definition.hasOwnProperty('ota')) {
const updateStateSensor = {
type: 'sensor',
object_id: 'update_state',
discovery_payload: {
icon: 'mdi:update',
value_template: `{{ value_json['update']['state'] }}`,
},
};
configs.push(updateStateSensor);
if (this.legacyApi) {
const updateAvailableSensor = {
type: 'binary_sensor',
object_id: 'update_available',
discovery_payload: {
payload_on: true,
payload_off: false,
value_template: '{{ value_json.update_available}}',
},
};
configs.push(updateAvailableSensor);
}
}
if (resolvedEntity.settings.hasOwnProperty('legacy') && !resolvedEntity.settings.legacy) {
configs = configs.filter((c) => c !== sensorClick);
}
if (!settings.get().advanced.homeassistant_legacy_triggers) {
configs = configs.filter((c) => c.object_id !== 'action' && c.object_id !== 'click');
}
// deep clone of the config objects
configs = JSON.parse(JSON.stringify(configs));
if (resolvedEntity.settings.homeassistant) {
const s = resolvedEntity.settings.homeassistant;
configs = configs.filter((config) => !s.hasOwnProperty(config.object_id) || s[config.object_id] != null);
configs.forEach((config) => {
const configOverride = s[config.object_id];
if (configOverride) {
config.object_id = configOverride.object_id || config.object_id;
config.type = configOverride.type || config.type;
}
});
}
return configs;
}
discover(resolvedEntity, force=false) {
// Check if already discoverd and check if there are configs.
const {device, definition} = resolvedEntity;
const discover = force || !this.discovered[device.ieeeAddr];
if (!discover || !device || !definition || !this.mapping[definition.model] || device.interviewing ||
(resolvedEntity.settings.hasOwnProperty('homeassistant') && !resolvedEntity.settings.homeassistant)) {
return;
}
const friendlyName = resolvedEntity.settings.friendlyName;
this.getConfigs(resolvedEntity).forEach((config) => {
const payload = {...config.discovery_payload};
let stateTopic = `${settings.get().mqtt.base_topic}/${friendlyName}`;
if (payload.state_topic_postfix) {
stateTopic += `/${payload.state_topic_postfix}`;
delete payload.state_topic_postfix;
}
if (!payload.hasOwnProperty('state_topic') || payload.state_topic) {
payload.state_topic = stateTopic;
} else {
/* istanbul ignore else */
if (payload.hasOwnProperty('state_topic')) {
delete payload.state_topic;
}
}
if (payload.position_topic) {
payload.position_topic = stateTopic;
}
if (payload.tilt_status_topic) {
payload.tilt_status_topic = stateTopic;
}
payload.json_attributes_topic = stateTopic;
// Set (unique) name, separate by space if friendlyName contains space.
const nameSeparator = friendlyName.includes('_') ? '_' : ' ';
payload.name = friendlyName;
if (config.object_id.startsWith(config.type) && config.object_id.includes('_')) {
payload.name += `${nameSeparator}${config.object_id.split(/_(.+)/)[1]}`;
} else if (!config.object_id.startsWith(config.type)) {
payload.name += `${nameSeparator}${config.object_id.replace(/_/g, nameSeparator)}`;
}
// Set unique_id
payload.unique_id = `${resolvedEntity.settings.ID}_${config.object_id}_${settings.get().mqtt.base_topic}`;
// Attributes for device registry
payload.device = this.getDevicePayload(resolvedEntity);
// Availability payload
payload.availability = [{topic: `${settings.get().mqtt.base_topic}/bridge/state`}];
if (settings.get().advanced.availability_timeout) {
payload.availability.push({topic: `${settings.get().mqtt.base_topic}/${friendlyName}/availability`});
}
if (payload.command_topic) {
payload.command_topic = `${settings.get().mqtt.base_topic}/${friendlyName}/`;
if (payload.command_topic_prefix) {
payload.command_topic += `${payload.command_topic_prefix}/`;
delete payload.command_topic_prefix;
}
payload.command_topic += 'set';
if (payload.command_topic_postfix) {
payload.command_topic += `/${payload.command_topic_postfix}`;
delete payload.command_topic_postfix;
}
}
if (payload.set_position_topic && payload.command_topic) {
payload.set_position_topic = payload.command_topic;
}
if (payload.tilt_command_topic && payload.command_topic) {
// Home Assistant does not support templates to set tilt (as of 2019-08-17),
// so we (have to) use a subtopic.
payload.tilt_command_topic = payload.command_topic + '/tilt';
}
if (payload.mode_state_topic) {
payload.mode_state_topic = stateTopic;
}
if (payload.mode_command_topic) {
payload.mode_command_topic = `${stateTopic}/set/system_mode`;
}
if (payload.hold_command_topic) {
payload.hold_command_topic = `${stateTopic}/set/preset`;
}
if (payload.hold_state_topic) {
payload.hold_state_topic = stateTopic;
}
if (payload.away_mode_state_topic) {
payload.away_mode_state_topic = stateTopic;
}
if (payload.away_mode_command_topic) {
payload.away_mode_command_topic = `${stateTopic}/set/away_mode`;
}
if (payload.current_temperature_topic) {
payload.current_temperature_topic = stateTopic;
}
if (payload.temperature_state_topic) {
payload.temperature_state_topic = stateTopic;
}
if (payload.temperature_low_state_topic) {
payload.temperature_low_state_topic = stateTopic;
}
if (payload.temperature_high_state_topic) {
payload.temperature_high_state_topic = stateTopic;
}
if (payload.speed_state_topic) {
payload.speed_state_topic = stateTopic;
}
if (payload.temperature_command_topic) {
payload.temperature_command_topic = `${stateTopic}/set/${payload.temperature_command_topic}`;
}
if (payload.temperature_low_command_topic) {
payload.temperature_low_command_topic = `${stateTopic}/set/${payload.temperature_low_command_topic}`;
}
if (payload.temperature_high_command_topic) {
payload.temperature_high_command_topic = `${stateTopic}/set/${payload.temperature_high_command_topic}`;
}
if (payload.fan_mode_state_topic) {
payload.fan_mode_state_topic = stateTopic;
}
if (payload.fan_mode_command_topic) {
payload.fan_mode_command_topic = `${stateTopic}/set/fan_mode`;
}
if (payload.speed_command_topic) {
payload.speed_command_topic = `${stateTopic}/set/fan_mode`;
}
if (payload.action_topic) {
payload.action_topic = stateTopic;
}
// Override configuration with user settings.
if (resolvedEntity.settings.hasOwnProperty('homeassistant')) {
const add = (obj) => {
Object.keys(obj).forEach((key) => {
if (['type', 'object_id'].includes(key)) {
return;
} else if (['number', 'string', 'boolean'].includes(typeof obj[key])) {
payload[key] = obj[key];
} else if (obj[key] === null) {
delete payload[key];
} else if (key === 'device' && typeof obj[key] === 'object') {
Object.keys(obj['device']).forEach((key) => {
payload['device'][key] = obj['device'][key];
});
}
});
};
add(resolvedEntity.settings.homeassistant);
if (resolvedEntity.settings.homeassistant.hasOwnProperty(config.object_id)) {
add(resolvedEntity.settings.homeassistant[config.object_id]);
}
}
const topic = this.getDiscoveryTopic(config, device);
this.mqtt.publish(topic, stringify(payload), {retain: true, qos: 0}, this.discoveryTopic, false, false);
});
this.discovered[device.ieeeAddr] = true;
}
onMQTTMessage(topic, message) {
const discoveryRegex = new RegExp(`${this.discoveryTopic}/(.*)/(.*)/(.*)/config`);
const discoveryMatch = topic.match(discoveryRegex);
const isDeviceAutomation = discoveryMatch && discoveryMatch[1] === 'device_automation';
if (discoveryMatch) {
// Clear outdated discovery configs and remember already discoverd device_automations
try {
message = JSON.parse(message);
const baseTopic = settings.get().mqtt.base_topic + '/';
if (isDeviceAutomation && (!message.topic || !message.topic.startsWith(baseTopic))) {
return;
}
if (!isDeviceAutomation &&
(!message.availability || !message.availability[0].topic.startsWith(baseTopic))) {
return;
}
} catch (e) {
return;
}
const ieeeAddr = discoveryMatch[2];
const resolvedEntity = this.zigbee.resolveEntity(ieeeAddr);
let clear = !resolvedEntity || !resolvedEntity.definition;
// Only save when topic matches otherwise config is not updated when renamed by editing configuration.yaml
if (resolvedEntity) {
const key = `${discoveryMatch[3].substring(0, discoveryMatch[3].indexOf('_'))}`;
const triggerTopic = `${settings.get().mqtt.base_topic}/${resolvedEntity.name}/${key}`;
if (isDeviceAutomation && message.topic === triggerTopic) {
if (!this.discoveredTriggers[ieeeAddr]) {
this.discoveredTriggers[ieeeAddr] = new Set();
}
this.discoveredTriggers[ieeeAddr].add(discoveryMatch[3]);
}
}
if (!clear && !isDeviceAutomation) {
const type = discoveryMatch[1];
const objectID = discoveryMatch[3];
clear = !this.getConfigs(resolvedEntity).find((c) => c.type === type && c.object_id === objectID);
}
// Device was flagged to be excluded from homeassistant discovery
clear = clear || (resolvedEntity.settings.hasOwnProperty('homeassistant') &&
!resolvedEntity.settings.homeassistant);
if (clear) {
logger.debug(`Clearing Home Assistant config '${topic}'`);
topic = topic.substring(this.discoveryTopic.length + 1);
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic, false, false);
}
} else if ((topic === this.statusTopic || topic === defaultStatusTopic) && message.toLowerCase() === 'online') {
const timer = setTimeout(async () => {
// Publish all device states.
for (const device of this.zigbee.getClients()) {
if (this.state.exists(device.ieeeAddr)) {
this.publishEntityState(device.ieeeAddr, this.state.get(device.ieeeAddr));
}
}
clearTimeout(timer);
}, 30000);
}
}
onZigbeeEvent(type, data, resolvedEntity) {
if (resolvedEntity && type !== 'deviceLeave' && this.mqtt.isConnected()) {
this.discover(resolvedEntity);
}
}
getDevicePayload(resolvedEntity) {
return {
identifiers: [`zigbee2mqtt_${resolvedEntity.settings.ID}`],
name: resolvedEntity.settings.friendlyName,
sw_version: `Zigbee2MQTT ${zigbee2mqttVersion}`,
model: `${resolvedEntity.definition.description} (${resolvedEntity.definition.model})`,
manufacturer: resolvedEntity.definition.vendor,
};
}
getDiscoveryTopic(config, device) {
return `${config.type}/${device.ieeeAddr}/${config.object_id}/config`;
}
async publishDeviceTriggerDiscover(entity, key, value, force=false) {
if (entity.settings.hasOwnProperty('homeassistant') &&
(entity.settings.homeassistant == null || entity.settings.homeassistant.device_automation == null)) {
return;
}
const device = entity.device;
if (!this.discoveredTriggers[device.ieeeAddr]) {
this.discoveredTriggers[device.ieeeAddr] = new Set();
}
const discoveredKey = `${key}_${value}`;
if (this.discoveredTriggers[device.ieeeAddr].has(discoveredKey) && !force) {
return;
}
const config = {
type: 'device_automation',
object_id: `${key}_${value}`,
discovery_payload: {
automation_type: 'trigger',
type: key,
},
};
const topic = this.getDiscoveryTopic(config, device);
const payload = {
...config.discovery_payload,
subtype: value,
payload: value,
topic: `${settings.get().mqtt.base_topic}/${entity.name}/${key}`,
device: this.getDevicePayload(entity),
};
await this.mqtt.publish(topic, stringify(payload), {retain: true, qos: 0}, this.discoveryTopic, false, false);
this.discoveredTriggers[device.ieeeAddr].add(discoveredKey);
}
// Only for homeassistant.test.js
_getMapping() {
return this.mapping;
}
_clearDiscoveredTrigger() {
this.discoveredTriggers = new Set();
}
}
module.exports = HomeAssistant;
File diff suppressed because it is too large Load Diff
@@ -1,41 +1,21 @@
const settings = require('../../util/settings');
const logger = require('../../util/logger');
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const utils = require('../../util/utils');
const assert = require('assert');
const Extension = require('../extension');
const stringify = require('json-stable-stringify-without-jsonify');
import * as settings from '../../util/settings';
import logger from '../../util/logger';
import zigbeeHerdsmanConverters from 'zigbee-herdsman-converters';
import utils from '../../util/utils';
import assert from 'assert';
import Extension from '../extension';
import stringify from 'json-stable-stringify-without-jsonify';
import bind from 'bind-decorator';
const configRegex =
new RegExp(`${settings.get().mqtt.base_topic}/bridge/config/((?:\\w+/get)|(?:\\w+/factory_reset)|(?:\\w+))`);
const allowedLogLevels = ['error', 'warn', 'info', 'debug'];
class BridgeLegacy extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
export default class BridgeLegacy extends Extension {
private lastJoinedDeviceName: string = null;
private supportedOptions: {[s: string]: (topic: string, message: string) => Promise<void> | void};
// Bind functions
this.permitJoin = this.permitJoin.bind(this);
this.lastSeen = this.lastSeen.bind(this);
this.elapsed = this.elapsed.bind(this);
this.reset = this.reset.bind(this);
this.logLevel = this.logLevel.bind(this);
this.devices = this.devices.bind(this);
this.groups = this.groups.bind(this);
this.rename = this.rename.bind(this);
this.renameLast = this.renameLast.bind(this);
this.remove = this.remove.bind(this);
this.forceRemove = this.forceRemove.bind(this);
this.ban = this.ban.bind(this);
this.deviceOptions = this.deviceOptions.bind(this);
this.addGroup = this.addGroup.bind(this);
this.removeGroup = this.removeGroup.bind(this);
this.whitelist = this.whitelist.bind(this);
this.touchlinkFactoryReset = this.touchlinkFactoryReset.bind(this);
this.lastJoinedDeviceName = null;
// Set supported options
override async start(): Promise<void> {
this.supportedOptions = {
'permit_join': this.permitJoin,
'last_seen': this.lastSeen,
@@ -57,24 +37,32 @@ class BridgeLegacy extends Extension {
'whitelist': this.whitelist,
'touchlink/factory_reset': this.touchlinkFactoryReset,
};
this.eventBus.onDeviceJoined(this, (data) => this.onZigbeeEvent_('deviceJoined', data, data.device));
this.eventBus.onDeviceInterview(this, (data) => this.onZigbeeEvent_('deviceInterview', data, data.device));
this.eventBus.onDeviceAnnounce(this, (data) => this.onZigbeeEvent_('deviceAnnounce', data, data.device));
this.eventBus.onDeviceLeave(this, (data) => this.onZigbeeEvent_('deviceLeave', data, null));
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
await this.publish();
}
whitelist(topic, message) {
@bind whitelist(topic: string, message: string): void {
try {
const entity = settings.getEntity(message);
const entity = settings.getDevice(message);
assert(entity, `Entity '${message}' does not exist`);
settings.whitelistDevice(entity.ID);
logger.info(`Whitelisted '${entity.friendlyName}'`);
settings.addDeviceToPasslist(entity.ID.toString());
logger.info(`Whitelisted '${entity.friendly_name}'`);
this.mqtt.publish(
'bridge/log',
stringify({type: 'device_whitelisted', message: {friendly_name: entity.friendlyName}}),
stringify({type: 'device_whitelisted', message: {friendly_name: entity.friendly_name}}),
);
} catch (error) {
logger.error(`Failed to whitelist '${message}' '${error}'`);
}
}
deviceOptions(topic, message) {
@bind deviceOptions(topic: string, message: string): void {
let json = null;
try {
json = JSON.parse(message);
@@ -88,18 +76,18 @@ class BridgeLegacy extends Extension {
return;
}
const entity = settings.getEntity(json.friendly_name);
const entity = settings.getDevice(json.friendly_name);
assert(entity, `Entity '${json.friendly_name}' does not exist`);
settings.changeEntityOptions(entity.ID, json.options);
settings.changeEntityOptions(entity.ID.toString(), json.options);
logger.info(`Changed device specific options of '${json.friendly_name}' (${stringify(json.options)})`);
}
async permitJoin(topic, message) {
@bind async permitJoin(topic: string, message: string): Promise<void> {
await this.zigbee.permitJoin(message.toLowerCase() === 'true');
this.publish();
}
async reset(topic, message) {
@bind async reset(): Promise<void> {
try {
await this.zigbee.reset('soft');
logger.info('Soft resetted ZNP');
@@ -108,7 +96,7 @@ class BridgeLegacy extends Extension {
}
}
lastSeen(topic, message) {
@bind lastSeen(topic: string, message: string): void {
const allowed = ['disable', 'ISO_8601', 'epoch', 'ISO_8601_local'];
if (!allowed.includes(message)) {
logger.error(`${message} is not an allowed value, possible: ${allowed}`);
@@ -119,7 +107,7 @@ class BridgeLegacy extends Extension {
logger.info(`Set last_seen to ${message}`);
}
elapsed(topic, message) {
@bind elapsed(topic: string, message: string): void {
const allowed = ['true', 'false'];
if (!allowed.includes(message)) {
logger.error(`${message} is not an allowed value, possible: ${allowed}`);
@@ -130,8 +118,8 @@ class BridgeLegacy extends Extension {
logger.info(`Set elapsed to ${message}`);
}
logLevel(topic, message) {
const level = message.toLowerCase();
@bind logLevel(topic: string, message: string): void {
const level = message.toLowerCase() as 'error' | 'warn' | 'info' | 'debug';
if (allowedLogLevels.includes(level)) {
logger.info(`Switching log level to '${level}'`);
logger.setLevel(level);
@@ -142,30 +130,29 @@ class BridgeLegacy extends Extension {
this.publish();
}
async devices(topic, message) {
@bind async devices(topic: string): Promise<void> {
const coordinator = await this.zigbee.getCoordinatorVersion();
const devices = this.zigbee.getDevices().map((device) => {
const payload = {
const devices = this.zigbee.devices().map((device) => {
const payload: KeyValue = {
ieeeAddr: device.ieeeAddr,
type: device.type,
networkAddress: device.networkAddress,
type: device.zh.type,
networkAddress: device.zh.networkAddress,
};
if (device.type !== 'Coordinator') {
const definition = zigbeeHerdsmanConverters.findByDevice(device);
const friendlyDevice = settings.getDevice(device.ieeeAddr);
payload.model = definition ? definition.model : device.modelID;
if (device.zh.type !== 'Coordinator') {
const definition = zigbeeHerdsmanConverters.findByDevice(device.zh);
payload.model = definition ? definition.model : device.zh.modelID;
payload.vendor = definition ? definition.vendor : '-';
payload.description = definition ? definition.description : '-';
payload.friendly_name = friendlyDevice ? friendlyDevice.friendly_name : device.ieeeAddr;
payload.manufacturerID = device.manufacturerID;
payload.manufacturerName = device.manufacturerName;
payload.powerSource = device.powerSource;
payload.modelID = device.modelID;
payload.hardwareVersion = device.hardwareVersion;
payload.softwareBuildID = device.softwareBuildID;
payload.dateCode = device.dateCode;
payload.lastSeen = device.lastSeen;
payload.friendly_name = device.name;
payload.manufacturerID = device.zh.manufacturerID;
payload.manufacturerName = device.zh.manufacturerName;
payload.powerSource = device.zh.powerSource;
payload.modelID = device.zh.modelID;
payload.hardwareVersion = device.zh.hardwareVersion;
payload.softwareBuildID = device.zh.softwareBuildID;
payload.dateCode = device.zh.dateCode;
payload.lastSeen = device.zh.lastSeen;
} else {
payload.friendly_name = 'Coordinator';
payload.softwareBuildID = coordinator.type;
@@ -185,17 +172,15 @@ class BridgeLegacy extends Extension {
}
}
groups(topic, message) {
@bind groups(): void {
const payload = settings.getGroups().map((g) => {
const group = {...g};
delete group.friendlyName;
return group;
return {...g, ID: Number(g.ID)};
});
this.mqtt.publish('bridge/log', stringify({type: 'groups', message: payload}));
}
rename(topic, message) {
@bind rename(topic: string, message: string): void {
const invalid =
`Invalid rename message format expected {"old": "friendly_name", "new": "new_name"} got ${message}`;
@@ -216,7 +201,7 @@ class BridgeLegacy extends Extension {
this._renameInternal(json.old, json.new);
}
renameLast(topic, message) {
@bind renameLast(topic: string, message: string): void {
if (!this.lastJoinedDeviceName) {
logger.error(`Cannot rename last joined device, no device has joined during this session`);
return;
@@ -225,15 +210,15 @@ class BridgeLegacy extends Extension {
this._renameInternal(this.lastJoinedDeviceName, message);
}
_renameInternal(from, to) {
_renameInternal(from: string, to: string): void {
try {
const isGroup = settings.getGroup(from) !== null;
settings.changeFriendlyName(from, to);
logger.info(`Successfully renamed - ${from} to ${to} `);
const entity = this.zigbee.resolveEntity(to);
const eventData = isGroup ? {group: entity.group} : {device: entity.device, from, to};
eventData.homeAssisantRename = false;
this.eventBus.emit(`${isGroup ? 'group' : 'device'}Renamed`, eventData);
if (entity.isDevice()) {
this.eventBus.emitEntityRenamed({homeAssisantRename: false, from, to, entity});
}
this.mqtt.publish(
'bridge/log',
@@ -244,7 +229,7 @@ class BridgeLegacy extends Extension {
}
}
addGroup(topic, message) {
@bind addGroup(topic: string, message: string): void {
let id = null;
let name = null;
try {
@@ -273,15 +258,15 @@ class BridgeLegacy extends Extension {
logger.info(`Added group '${name}'`);
}
removeGroup(topic, message) {
@bind removeGroup(topic: string, message: string): void {
const name = message;
const entity = this.zigbee.resolveEntity(message);
assert(entity && entity.type === 'group', `Group '${message}' does not exist`);
const entity = this.zigbee.resolveEntity(message) as Group;
assert(entity && entity.isGroup(), `Group '${message}' does not exist`);
if (topic.includes('force')) {
entity.group.removeFromDatabase();
entity.zh.removeFromDatabase();
} else {
entity.group.removeFromNetwork();
entity.zh.removeFromNetwork();
}
settings.removeGroup(message);
@@ -289,21 +274,21 @@ class BridgeLegacy extends Extension {
logger.info(`Removed group '${name}'`);
}
async forceRemove(topic, message) {
@bind async forceRemove(topic: string, message: string): Promise<void> {
await this.removeForceRemoveOrBan('force_remove', message);
}
async remove(topic, message) {
@bind async remove(topic: string, message: string): Promise<void> {
await this.removeForceRemoveOrBan('remove', message);
}
async ban(topic, message) {
@bind async ban(topic: string, message: string): Promise<void> {
await this.removeForceRemoveOrBan('ban', message);
}
async removeForceRemoveOrBan(action, message) {
const entity = this.zigbee.resolveEntity(message.trim());
const lookup = {
@bind async removeForceRemoveOrBan(action: string, message: string): Promise<void> {
const entity = this.zigbee.resolveEntity(message.trim()) as Device;
const lookup: KeyValue = {
ban: ['banned', 'Banning', 'ban'],
force_remove: ['force_removed', 'Force removing', 'force remove'],
remove: ['removed', 'Removing', 'remove'],
@@ -316,64 +301,64 @@ class BridgeLegacy extends Extension {
return;
}
const cleanup = () => {
const ieeeAddr = entity.ieeeAddr;
const name = entity.name;
const cleanup = (): void => {
// Fire event
this.eventBus.emit('deviceRemoved', {resolvedEntity: entity});
this.eventBus.emitDeviceRemoved({ieeeAddr, name});
// Remove from configuration.yaml
settings.removeDevice(entity.settings.ID);
settings.removeDevice(entity.ieeeAddr);
// Remove from state
this.state.remove(entity.settings.ID);
this.state.remove(ieeeAddr);
logger.info(`Successfully ${lookup[action][0]} ${entity.settings.friendlyName}`);
logger.info(`Successfully ${lookup[action][0]} ${entity.name}`);
this.mqtt.publish('bridge/log', stringify({type: `device_${lookup[action][0]}`, message}));
};
try {
logger.info(`${lookup[action][1]} '${entity.settings.friendlyName}'`);
logger.info(`${lookup[action][1]} '${entity.name}'`);
if (action === 'force_remove') {
await entity.device.removeFromDatabase();
await entity.zh.removeFromDatabase();
} else {
await entity.device.removeFromNetwork();
await entity.zh.removeFromNetwork();
}
cleanup();
} catch (error) {
logger.error(`Failed to ${lookup[action][2]} ${entity.settings.friendlyName} (${error})`);
logger.error(`Failed to ${lookup[action][2]} ${entity.name} (${error})`);
// eslint-disable-next-line
logger.error(`See https://www.zigbee2mqtt.io/information/mqtt_topics_and_message_structure.html#zigbee2mqttbridgeconfigremove for more info`);
logger.error(`See https://www.zigbee2mqtt.io/guide/usage/mqtt_topics_and_messages.html#zigbee2mqtt-bridge-request for more info`);
this.mqtt.publish('bridge/log', stringify({type: `device_${lookup[action][0]}_failed`, message}));
}
if (action === 'ban') {
settings.banDevice(entity.settings.ID);
settings.blockDevice(ieeeAddr);
}
}
async onMQTTConnected() {
await this.publish();
}
async onMQTTMessage(topic, message) {
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const {topic, message} = data;
if (!topic.match(configRegex)) {
return false;
return;
}
const option = topic.match(configRegex)[1];
if (!this.supportedOptions.hasOwnProperty(option)) {
return false;
return;
}
await this.supportedOptions[option](topic, message);
return true;
return;
}
async publish() {
const info = await utils.getZigbee2mqttVersion();
async publish(): Promise<void> {
const info = await utils.getZigbee2MQTTVersion();
const coordinator = await this.zigbee.getCoordinatorVersion();
const topic = `bridge/config`;
const payload = {
@@ -388,7 +373,7 @@ class BridgeLegacy extends Extension {
await this.mqtt.publish(topic, stringify(payload), {retain: true, qos: 0});
}
onZigbeeEvent(type, data, resolvedEntity) {
onZigbeeEvent_(type: string, data: KeyValue, resolvedEntity: Device): void {
if (type === 'deviceJoined' && resolvedEntity) {
this.lastJoinedDeviceName = resolvedEntity.name;
}
@@ -436,7 +421,7 @@ class BridgeLegacy extends Extension {
} else {
/* istanbul ignore else */
if (type === 'deviceLeave') {
const name = resolvedEntity ? resolvedEntity.name : data.ieeeAddr;
const name = data.ieeeAddr;
const meta = {friendly_name: name};
this.mqtt.publish(
'bridge/log',
@@ -446,7 +431,7 @@ class BridgeLegacy extends Extension {
}
}
async touchlinkFactoryReset() {
@bind async touchlinkFactoryReset(): Promise<void> {
logger.info('Starting touchlink factory reset...');
this.mqtt.publish(
'bridge/log',
@@ -469,5 +454,3 @@ class BridgeLegacy extends Extension {
}
}
}
module.exports = BridgeLegacy;
@@ -1,50 +0,0 @@
/* istanbul ignore file */
const settings = require('../../util/settings');
const logger = require('../../util/logger');
const Extension = require('../extension');
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/device/(.+)/get_group_membership$`);
class DeviceGroupMembership extends Extension {
async onMQTTMessage(topic, message) {
const match = topic.match(topicRegex);
if (!match) {
return null;
}
const entity = this.zigbee.resolveEntity(match[1]);
if (!entity || entity.type !== 'device') {
logger.error(`Device '${match[1]}' does not exist`);
return;
}
const response = await entity.endpoint.command(
`genGroups`, 'getMembership', {groupcount: 0, grouplist: []}, {}, true,
);
if (!response) {
logger.warn(`Couldn't get group membership of ${entity.device.ieeeAddr}`);
return;
}
let {grouplist, capacity} = response;
grouplist = grouplist.map((gid) => {
const g = settings.getGroup(gid);
return g ? g.friendlyName : gid;
});
const msgGroupList = `${entity.device.ieeeAddr} is in groups [${grouplist}]`;
let msgCapacity;
if (capacity === 254) {
msgCapacity = 'it can be a part of at least 1 more group';
} else {
msgCapacity = `its remaining group capacity is ${capacity === 255 ? 'unknown' : capacity}`;
}
logger.info(`${msgGroupList} and ${msgCapacity}`);
this.publishEntityState(entity.device.ieeeAddr, {group_list: grouplist, group_capacity: capacity});
}
}
module.exports = DeviceGroupMembership;
@@ -0,0 +1,56 @@
/* istanbul ignore file */
import * as settings from '../../util/settings';
import logger from '../../util/logger';
import utils from '../../util/utils';
import Extension from '../extension';
import bind from 'bind-decorator';
import Device from '../../model/device';
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/device/(.+)/get_group_membership$`);
export default class DeviceGroupMembership extends Extension {
override async start(): Promise<void> {
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
}
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const match = data.topic.match(topicRegex);
if (!match) {
return null;
}
const parsed = utils.parseEntityID(match[1]);
const device = this.zigbee.resolveEntity(parsed.ID) as Device;
if (!device || !(device instanceof Device)) {
logger.error(`Device '${match[1]}' does not exist`);
return;
}
const endpoint = device.endpoint(parsed.endpoint);
const response = await endpoint.command(
`genGroups`, 'getMembership', {groupcount: 0, grouplist: []}, {},
);
if (!response) {
logger.warn(`Couldn't get group membership of ${device.ieeeAddr}`);
return;
}
let {grouplist, capacity} = response;
grouplist = grouplist.map((gid: string) => {
const g = settings.getGroup(gid);
return g ? g.friendly_name : gid;
});
const msgGroupList = `${device.ieeeAddr} is in groups [${grouplist}]`;
let msgCapacity;
if (capacity === 254) {
msgCapacity = 'it can be a part of at least 1 more group';
} else {
msgCapacity = `its remaining group capacity is ${capacity === 255 ? 'unknown' : capacity}`;
}
logger.info(`${msgGroupList} and ${msgCapacity}`);
this.publishEntityState(device, {group_list: grouplist, group_capacity: capacity});
}
}
@@ -1,37 +1,40 @@
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const logger = require('../../util/logger');
const settings = require('../../util/settings');
const ZNLDP12LM = zigbeeHerdsmanConverters.devices.find((d) => d.model === 'ZNLDP12LM');
const utils = require('../../util/utils');
const Extension = require('../extension');
import zigbeeHerdsmanConverters from 'zigbee-herdsman-converters';
import logger from '../../util/logger';
import * as settings from '../../util/settings';
import Extension from '../extension';
const defaultConfiguration = {
minimumReportInterval: 3, maximumReportInterval: 300, reportableChange: 1,
};
const ZNLDP12LM = zigbeeHerdsmanConverters.definitions.find((d) => d.model === 'ZNLDP12LM');
const devicesNotSupportingReporting = [
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'CC2530.ROUTER'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'BASICZBR3'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'ZM-CSW032-D'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'TS0001'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'TS0115'),
zigbeeHerdsmanConverters.definitions.find((d) => d.model === 'CC2530.ROUTER'),
zigbeeHerdsmanConverters.definitions.find((d) => d.model === 'BASICZBR3'),
zigbeeHerdsmanConverters.definitions.find((d) => d.model === 'ZM-CSW032-D'),
zigbeeHerdsmanConverters.definitions.find((d) => d.model === 'TS0001'),
zigbeeHerdsmanConverters.definitions.find((d) => d.model === 'TS0115'),
];
const reportKey = 1;
const getColorCapabilities = async (endpoint) => {
const getColorCapabilities = async (endpoint: zh.Endpoint): Promise<{colorTemperature: boolean, colorXY: boolean}> => {
if (endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities') === undefined) {
await endpoint.read('lightingColorCtrl', ['colorCapabilities']);
}
const value = endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities');
const value = endpoint.getClusterAttributeValue('lightingColorCtrl', 'colorCapabilities') as number;
return {
colorTemperature: (value & 1<<4) > 0,
colorXY: (value & 1<<3) > 0,
};
};
const clusters = {
const clusters: {[s: string]:
{attribute: string, minimumReportInterval: number, maximumReportInterval: number, reportableChange: number
condition?: (endpoint: zh.Endpoint) => Promise<boolean>}[]} =
{
'genOnOff': [
{attribute: 'onOff', ...defaultConfiguration, minimumReportInterval: 0, reportableChange: 0},
],
@@ -41,15 +44,15 @@ const clusters = {
'lightingColorCtrl': [
{
attribute: 'colorTemperature', ...defaultConfiguration,
condition: async (endpoint) => (await getColorCapabilities(endpoint)).colorTemperature,
condition: async (endpoint): Promise<boolean> => (await getColorCapabilities(endpoint)).colorTemperature,
},
{
attribute: 'currentX', ...defaultConfiguration,
condition: async (endpoint) => (await getColorCapabilities(endpoint)).colorXY,
condition: async (endpoint): Promise<boolean> => (await getColorCapabilities(endpoint)).colorXY,
},
{
attribute: 'currentY', ...defaultConfiguration,
condition: async (endpoint) => (await getColorCapabilities(endpoint)).colorXY,
condition: async (endpoint): Promise<boolean> => (await getColorCapabilities(endpoint)).colorXY,
},
],
'closuresWindowCovering': [
@@ -58,15 +61,12 @@ const clusters = {
],
};
class Report extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.queue = new Set();
this.failed = new Set();
this.enabled = settings.get().advanced.report;
}
export default class Report extends Extension {
private queue: Set<string> = new Set();
private failed: Set<string> = new Set();
private enabled = settings.get().advanced.report;
shouldIgnoreClusterForDevice(cluster, definition) {
shouldIgnoreClusterForDevice(cluster: string, definition: zhc.Definition): boolean {
if (definition === ZNLDP12LM && cluster === 'closuresWindowCovering') {
// Device announces it but doesn't support it
// https://github.com/Koenkk/zigbee2mqtt/issues/2611
@@ -76,9 +76,7 @@ class Report extends Extension {
return false;
}
async setupReporting(resolvedEntity) {
const {device, definition} = resolvedEntity;
async setupReporting(device: Device): Promise<void> {
if (this.queue.has(device.ieeeAddr) || this.failed.has(device.ieeeAddr)) return;
this.queue.add(device.ieeeAddr);
@@ -86,9 +84,10 @@ class Report extends Extension {
const term2 = this.enabled ? 'setup' : 'disabled';
try {
for (const ep of device.endpoints) {
for (const ep of device.zh.endpoints) {
for (const [cluster, configuration] of Object.entries(clusters)) {
if (ep.supportsInputCluster(cluster) && !this.shouldIgnoreClusterForDevice(cluster, definition)) {
if (ep.supportsInputCluster(cluster) &&
!this.shouldIgnoreClusterForDevice(cluster, device.definition)) {
logger.debug(`${term1} reporting for '${device.ieeeAddr}' - ${ep.ID} - ${cluster}`);
const items = [];
@@ -102,8 +101,8 @@ class Report extends Extension {
}
this.enabled ?
await ep.bind(cluster, this.coordinatorEndpoint) :
await ep.unbind(cluster, this.coordinatorEndpoint);
await ep.bind(cluster, this.zigbee.firstCoordinatorEndpoint()) :
await ep.unbind(cluster, this.zigbee.firstCoordinatorEndpoint());
await ep.configureReporting(cluster, items);
logger.info(
@@ -114,13 +113,13 @@ class Report extends Extension {
}
if (this.enabled) {
device.meta.reporting = reportKey;
device.zh.meta.reporting = reportKey;
} else {
delete device.meta.reporting;
this.eventBus.emit('reportingDisabled', {device});
delete device.zh.meta.reporting;
this.eventBus.emitReconfigure({device});
}
this.eventBus.emit(`devicesChanged`);
this.eventBus.emitDevicesChanged();
} catch (error) {
logger.error(
`Failed to ${term1.toLowerCase()} reporting for '${device.ieeeAddr}' - ${error.stack}`,
@@ -129,15 +128,13 @@ class Report extends Extension {
this.failed.add(device.ieeeAddr);
}
device.save();
device.zh.save();
this.queue.delete(device.ieeeAddr);
}
shouldSetupReporting(resolvedEntity, messageType) {
if (!resolvedEntity || !resolvedEntity.device || !resolvedEntity.definition ||
messageType === 'deviceLeave') return false;
shouldSetupReporting(device: Device, messageType: string): boolean {
if (!device || !device.zh || !device.definition) return false;
const {device, definition} = resolvedEntity;
// Handle messages of type endDeviceAnnce and devIncoming.
// This message is typically send when a device comes online after being powered off
// Ikea TRADFRI tend to forget their reporting after powered off.
@@ -146,48 +143,52 @@ class Report extends Extension {
// else reconfigure is done in zigbee-herdsman-converters ikea.js/bulbOnEvent
// configuredReportings are saved since Zigbee2MQTT 1.17.0
// https://github.com/Koenkk/zigbee2mqtt/issues/966
if (this.enabled && messageType === 'deviceAnnounce' && utils.isIkeaTradfriDevice(device) &&
device.endpoints.filter((e) => e.configuredReportings.length === 0).length === device.endpoints.length) {
if (this.enabled && messageType === 'deviceAnnounce' && device.isIkeaTradfri() &&
device.zh.endpoints.filter((e) => e.configuredReportings.length === 0).length ===
device.zh.endpoints.length) {
return true;
}
// These do not support reproting.
// https://github.com/Koenkk/zigbee-herdsman/issues/110
const philipsIgnoreSw = ['5.127.1.26581', '5.130.1.30000'];
if (device.manufacturerName === 'Philips' && philipsIgnoreSw.includes(device.softwareBuildID)) return false;
if (device.zh.manufacturerName === 'Philips' &&
philipsIgnoreSw.includes(device.zh.softwareBuildID)) return false;
if (resolvedEntity.device.interviewing === true) return false;
if (device.type !== 'Router' || device.powerSource === 'Battery') return false;
if (device.zh.interviewing === true) return false;
if (device.zh.type !== 'Router' || device.zh.powerSource === 'Battery') return false;
// Gledopto devices don't support reporting.
if (devicesNotSupportingReporting.includes(definition) || definition.vendor === 'Gledopto') return false;
if (devicesNotSupportingReporting.includes(device.definition) ||
device.definition.vendor === 'Gledopto') return false;
if (this.enabled && device.meta.hasOwnProperty('reporting') && device.meta.reporting === reportKey) {
if (this.enabled && device.zh.meta.hasOwnProperty('reporting') &&
device.zh.meta.reporting === reportKey) {
return false;
}
if (!this.enabled && !device.meta.hasOwnProperty('reporting')) {
if (!this.enabled && !device.zh.meta.hasOwnProperty('reporting')) {
return false;
}
return true;
}
async onZigbeeStarted() {
this.coordinatorEndpoint = this.zigbee.getDevicesByType('Coordinator')[0].getEndpoint(1);
for (const device of this.zigbee.getClients()) {
const resolvedEntity = this.zigbee.resolveEntity(device);
if (this.shouldSetupReporting(resolvedEntity, null)) {
await this.setupReporting(resolvedEntity);
override async start(): Promise<void> {
for (const device of this.zigbee.devices(false)) {
if (this.shouldSetupReporting(device, null)) {
await this.setupReporting(device);
}
}
this.eventBus.onDeviceAnnounce(this, (data) => this.onZigbeeEvent_('deviceAnnounce', data.device));
this.eventBus.onDeviceMessage(this, (data) => this.onZigbeeEvent_('dummy', data.device));
this.eventBus.onDeviceJoined(this, (data) => this.onZigbeeEvent_('dummy', data.device));
this.eventBus.onDeviceNetworkAddressChanged(this, (data) => this.onZigbeeEvent_('dummy', data.device));
}
async onZigbeeEvent(type, data, resolvedEntity) {
if (this.shouldSetupReporting(resolvedEntity, type)) {
await this.setupReporting(resolvedEntity);
async onZigbeeEvent_(type: string, device: Device): Promise<void> {
if (this.shouldSetupReporting(device, type)) {
await this.setupReporting(device);
}
}
}
module.exports = Report;
@@ -1,33 +1,35 @@
/* istanbul ignore file */
// DEPRECATED
const settings = require('../../util/settings');
const logger = require('../../util/logger');
const utils = require('../../util/utils');
const Extension = require('../extension');
import * as settings from '../../util/settings';
import logger from '../../util/logger';
import utils from '../../util/utils';
import Extension from '../extension';
/**
* This extensions soft resets the ZNP after a certain timeout.
*/
class SoftReset extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.timer = null;
this.timeout = utils.secondsToMilliseconds(settings.get().advanced.soft_reset_timeout);
}
export default class SoftReset extends Extension {
private timer: NodeJS.Timeout = null;
private timeout = utils.seconds(settings.get().advanced.soft_reset_timeout);
onZigbeeStarted() {
logger.debug(`Soft reset timeout set to ${utils.millisecondsToSeconds(this.timeout)} seconds`);
override async start(): Promise<void> {
logger.debug(`Soft reset timeout set to ${this.timeout / 1000} seconds`);
this.resetTimer();
this.eventBus.onDeviceMessage(this, () => this.resetTimer());
this.eventBus.onDeviceAnnounce(this, () => this.resetTimer());
this.eventBus.onDeviceNetworkAddressChanged(this, () => this.resetTimer());
this.eventBus.onDeviceJoined(this, () => this.resetTimer());
this.eventBus.onDeviceInterview(this, () => this.resetTimer());
}
clearTimer() {
private clearTimer(): void {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
resetTimer() {
private resetTimer(): void {
if (this.timeout === 0) {
return;
}
@@ -36,7 +38,7 @@ class SoftReset extends Extension {
this.timer = setTimeout(() => this.handleTimeout(), this.timeout);
}
async handleTimeout() {
private async handleTimeout(): Promise<void> {
logger.warn('Soft reset timeout triggered');
try {
@@ -57,10 +59,4 @@ class SoftReset extends Extension {
this.resetTimer();
}
onZigbeeEvent() {
this.resetTimer();
}
}
module.exports = SoftReset;
@@ -1,27 +1,36 @@
const settings = require('../util/settings');
const utils = require('../util/utils');
const logger = require('../util/logger');
const Extension = require('./extension');
const stringify = require('json-stable-stringify-without-jsonify');
import * as settings from '../util/settings';
import utils from '../util/utils';
import logger from '../util/logger';
import stringify from 'json-stable-stringify-without-jsonify';
import Extension from './extension';
import bind from 'bind-decorator';
interface Link {
source: {ieeeAddr: string, networkAddress: number}, target: {ieeeAddr: string, networkAddress: number},
linkquality: number, depth: number, routes: zh.RoutingTableEntry[],
sourceIeeeAddr: string, targetIeeeAddr: string, sourceNwkAddr: number, lqi: number, relationship: number,
}
interface Topology {
nodes: {
ieeeAddr: string, friendlyName: string, type: string, networkAddress: number, manufacturerName: string,
modelID: string, failed: string[], lastSeen: number,
definition: {model: string, vendor: string, supports: string, description: string}}[],
links: Link[],
}
/**
* This extension creates a network map
*/
class NetworkMap extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
export default class NetworkMap extends Extension {
private legacyApi = settings.get().advanced.legacy_api;
private legacyTopic = `${settings.get().mqtt.base_topic}/bridge/networkmap`;
private legacyTopicRoutes = `${settings.get().mqtt.base_topic}/bridge/networkmap/routes`;
private topic = `${settings.get().mqtt.base_topic}/bridge/request/networkmap`;
private supportedFormats: {[s: string]: (topology: Topology) => KeyValue | string};
this.legacyApi = settings.get().advanced.legacy_api;
this.legacyTopic = `${settings.get().mqtt.base_topic}/bridge/networkmap`;
this.legacyTopicRoutes = `${settings.get().mqtt.base_topic}/bridge/networkmap/routes`;
this.topic = `${settings.get().mqtt.base_topic}/bridge/request/networkmap`;
// Bind
this.raw = this.raw.bind(this);
this.graphviz = this.graphviz.bind(this);
this.plantuml = this.plantuml.bind(this);
// Set supported formats
override async start(): Promise<void> {
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
this.supportedFormats = {
'raw': this.raw,
'graphviz': this.graphviz,
@@ -29,22 +38,22 @@ class NetworkMap extends Extension {
};
}
async onMQTTMessage(topic, message) {
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
/* istanbul ignore else */
if (this.legacyApi) {
if ((topic === this.legacyTopic || topic === this.legacyTopicRoutes) &&
this.supportedFormats.hasOwnProperty(message)) {
const includeRoutes = topic === this.legacyTopicRoutes;
if ((data.topic === this.legacyTopic || data.topic === this.legacyTopicRoutes) &&
this.supportedFormats.hasOwnProperty(data.message)) {
const includeRoutes = data.topic === this.legacyTopicRoutes;
const topology = await this.networkScan(includeRoutes);
let converted = this.supportedFormats[message](topology);
converted = message === 'raw' ? stringify(converted) : converted;
this.mqtt.publish(`bridge/networkmap/${message}`, converted, {});
let converted = this.supportedFormats[data.message](topology);
converted = data.message === 'raw' ? stringify(converted) : converted;
this.mqtt.publish(`bridge/networkmap/${data.message}`, converted as string, {});
}
}
if (topic === this.topic) {
if (data.topic === this.topic) {
const message = utils.parseJSON(data.message, data.message);
try {
message = utils.parseJSON(message, message);
const type = typeof message === 'object' ? message.type : message;
if (!this.supportedFormats.hasOwnProperty(type)) {
throw new Error(`Type '${type}' not supported, allowed are: ${Object.keys(this.supportedFormats)}`);
@@ -66,11 +75,11 @@ class NetworkMap extends Extension {
}
}
raw(topology) {
@bind raw(topology: Topology): KeyValue {
return topology;
}
graphviz(topology) {
@bind graphviz(topology: Topology): string {
const colors = settings.get().map_options.graphviz.colors;
let text = 'digraph G {\nnode[shape=record];\n';
@@ -84,7 +93,7 @@ class NetworkMap extends Extension {
// Add the device short network address, ieeaddr and scan note (if any)
labels.push(
`${node.ieeeAddr} (${node.networkAddress})` +
`${node.ieeeAddr} (${utils.toNetworkAddressHex(node.networkAddress)})` +
((node.failed && node.failed.length) ? `failed: ${node.failed.join(',')}` : ''),
);
@@ -102,7 +111,7 @@ class NetworkMap extends Extension {
let lastSeen = 'unknown';
const date = node.type === 'Coordinator' ? Date.now() : node.lastSeen;
if (date) {
lastSeen = utils.formatDate(date, 'relative');
lastSeen = utils.formatDate(date, 'relative') as string;
}
labels.push(lastSeen);
@@ -132,7 +141,7 @@ class NetworkMap extends Extension {
(!e.routes.length) ? 'penwidth=0.5, ' : 'penwidth=2, ';
const lineWeight = (!e.routes.length) ? `weight=0, color="${colors.line.inactive}", ` :
`weight=1, color="${colors.line.active}", `;
const textRoutes = e.routes.map((r) => r.destinationAddress);
const textRoutes = e.routes.map((r) => utils.toNetworkAddressHex(r.destinationAddress));
const lineLabels = (!e.routes.length) ? `label="${e.linkquality}"` :
`label="${e.linkquality} (routes: ${textRoutes.join(',')})"`;
text += ` "${node.ieeeAddr}" -> "${e.target.ieeeAddr}"`;
@@ -145,7 +154,7 @@ class NetworkMap extends Extension {
return text.replace(/\0/g, '');
}
plantuml(topology) {
@bind plantuml(topology: Topology): string {
const text = [];
text.push(`' paste into: https://www.planttext.com/`);
@@ -160,14 +169,14 @@ class NetworkMap extends Extension {
// Add the device short network address, ieeaddr and scan note (if any)
text.push(
`${node.ieeeAddr} (${node.networkAddress})` +
`${node.ieeeAddr} (${utils.toNetworkAddressHex(node.networkAddress)})` +
((node.failed && node.failed.length) ? ` failed: ${node.failed.join(',')}` : ''),
);
// Add the device model
if (node.type !== 'Coordinator') {
text.push(`---`);
const definition = this.zigbee.resolveEntity(node.ieeeAddr).definition;
const definition = (this.zigbee.resolveEntity(node.ieeeAddr) as Device).definition;
if (definition) {
text.push(`${definition.vendor} ${definition.description} (${definition.model})`);
} else {
@@ -180,7 +189,7 @@ class NetworkMap extends Extension {
let lastSeen = 'unknown';
const date = node.type === 'Coordinator' ? Date.now() : node.lastSeen;
if (date) {
lastSeen = utils.formatDate(date, 'relative');
lastSeen = utils.formatDate(date, 'relative') as string;
}
text.push(`---`);
text.push(lastSeen);
@@ -203,59 +212,72 @@ class NetworkMap extends Extension {
return text.join(`\n`);
}
async networkScan(includeRoutes) {
async networkScan(includeRoutes: boolean): Promise<Topology> {
logger.info(`Starting network scan (includeRoutes '${includeRoutes}')`);
const devices = this.zigbee.getDevices().filter((d) => d.type !== 'GreenPower');
const lqis = new Map();
const routingTables = new Map();
const failed = new Map();
const devices = this.zigbee.devices().filter((d) => d.zh.type !== 'GreenPower' && !d.options.disabled);
const lqis: Map<Device, zh.LQI> = new Map();
const routingTables: Map<Device, zh.RoutingTable> = new Map();
const failed: Map<Device, string[]> = new Map();
for (const device of devices.filter((d) => d.type != 'EndDevice')) {
for (const device of devices.filter((d) => d.zh.type != 'EndDevice')) {
failed.set(device, []);
await utils.sleep(1); // sleep 1 second between each scan to reduce stress on network.
const resolvedEntity = this.zigbee.resolveEntity(device);
const doRequest = async <T>(request: () => Promise<T>, firstAttempt = true): Promise<T> => {
try {
return await request();
} catch (error) {
if (!firstAttempt) {
throw error;
} else {
// Network is possibly congested, sleep 5 seconds to let the network settle.
await utils.sleep(5);
return doRequest(request, false);
}
}
};
try {
const result = await device.lqi();
const result = await doRequest<zh.LQI>(async () => device.zh.lqi());
lqis.set(device, result);
logger.debug(`LQI succeeded for '${resolvedEntity.name}'`);
logger.debug(`LQI succeeded for '${device.name}'`);
} catch (error) {
failed.get(device).push('lqi');
logger.error(`Failed to execute LQI for '${resolvedEntity.name}'`);
logger.error(`Failed to execute LQI for '${device.name}'`);
logger.debug(error.stack);
}
if (includeRoutes) {
try {
const result = await device.routingTable();
const result = await doRequest(async () => device.zh.routingTable());
routingTables.set(device, result);
logger.debug(`Routing table succeeded for '${resolvedEntity.name}'`);
logger.debug(`Routing table succeeded for '${device.name}'`);
} catch (error) {
failed.get(device).push('routingTable');
logger.error(`Failed to execute routing table for '${resolvedEntity.name}'`);
logger.error(`Failed to execute routing table for '${device.name}'`);
}
}
}
logger.info(`Network scan finished`);
const networkMap = {nodes: [], links: []};
const topology: Topology = {nodes: [], links: []};
// Add nodes
for (const device of devices) {
const resolvedEntity = this.zigbee.resolveEntity(device);
const definition = resolvedEntity.definition ? {
model: resolvedEntity.definition.model,
vendor: resolvedEntity.definition.vendor,
description: resolvedEntity.definition.description,
supports: Array.from(new Set((resolvedEntity.definition.exposes).map((e) => {
return e.hasOwnProperty('name') ?
e.name :
const definition = device.definition ? {
model: device.definition.model,
vendor: device.definition.vendor,
description: device.definition.description,
supports: Array.from(new Set((device.exposes()).map((e) => {
return e.hasOwnProperty('name') ? e.name :
`${e.type} (${e.features.map((f) => f.name).join(', ')})`;
}))).join(', '),
} : null;
networkMap.nodes.push({
ieeeAddr: device.ieeeAddr, friendlyName: resolvedEntity.name, type: device.type,
networkAddress: device.networkAddress, manufacturerName: device.manufacturerName,
modelID: device.modelID, failed: failed.get(device), lastSeen: device.lastSeen,
topology.nodes.push({
ieeeAddr: device.ieeeAddr, friendlyName: device.name, type: device.zh.type,
networkAddress: device.zh.networkAddress, manufacturerName: device.zh.manufacturerName,
modelID: device.zh.modelID, failed: failed.get(device), lastSeen: device.zh.lastSeen,
definition,
});
}
@@ -270,14 +292,14 @@ class NetworkMap extends Extension {
// Some Xiaomi devices return 0x00 as the neighbor ieeeAddr (obviously not correct).
// Determine the correct ieeeAddr based on the networkAddress.
const neighborDevice = this.zigbee.getDeviceByNetworkAddress(neighbor.networkAddress);
const neighborDevice = this.zigbee.deviceByNetworkAddress(neighbor.networkAddress);
if (neighbor.ieeeAddr === '0x0000000000000000' && neighborDevice) {
neighbor.ieeeAddr = neighborDevice.ieeeAddr;
}
const link = {
const link: Link = {
source: {ieeeAddr: neighbor.ieeeAddr, networkAddress: neighbor.networkAddress},
target: {ieeeAddr: device.ieeeAddr, networkAddress: device.networkAddress},
target: {ieeeAddr: device.ieeeAddr, networkAddress: device.zh.networkAddress},
linkquality: neighbor.linkquality, depth: neighbor.depth, routes: [],
// DEPRECATED:
sourceIeeeAddr: neighbor.ieeeAddr, targetIeeeAddr: device.ieeeAddr,
@@ -291,12 +313,10 @@ class NetworkMap extends Extension {
.filter((t) => t.status === 'ACTIVE' && t.nextHop === neighbor.networkAddress);
}
networkMap.links.push(link);
topology.links.push(link);
}
});
return networkMap;
return topology;
}
}
module.exports = NetworkMap;
-38
View File
@@ -1,38 +0,0 @@
const Extension = require('./extension');
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
/**
* This extension calls the zigbee-herdsman-converters onEvent.
*/
class OnEvent extends Extension {
async onZigbeeStarted() {
for (const device of this.zigbee.getClients()) {
const resolvedEntity = this.zigbee.resolveEntity(device);
this.callOnEvent(resolvedEntity, 'start', {});
}
}
onZigbeeEvent(type, data, resolvedEntity) {
if (resolvedEntity && resolvedEntity.type === 'device') {
this.callOnEvent(resolvedEntity, type, data);
}
}
async stop() {
super.stop();
for (const device of this.zigbee.getClients()) {
const resolvedEntity = this.zigbee.resolveEntity(device);
this.callOnEvent(resolvedEntity, 'stop', {});
}
}
callOnEvent(resolvedEntity, type, data) {
zigbeeHerdsmanConverters.onEvent(type, data, resolvedEntity.device, resolvedEntity.settings);
if (resolvedEntity.definition && resolvedEntity.definition.onEvent) {
resolvedEntity.definition.onEvent(type, data, resolvedEntity.device, resolvedEntity.settings);
}
}
}
module.exports = OnEvent;
+50
View File
@@ -0,0 +1,50 @@
import zhc from 'zigbee-herdsman-converters';
import Extension from './extension';
/**
* This extension calls the zigbee-herdsman-converters onEvent.
*/
export default class OnEvent extends Extension {
override async start(): Promise<void> {
for (const device of this.zigbee.devices(false)) {
this.callOnEvent(device, 'start', {});
}
this.eventBus.onDeviceMessage(this, (data) => this.callOnEvent(data.device, 'message', this.convertData(data)));
this.eventBus.onDeviceJoined(this,
(data) => this.callOnEvent(data.device, 'deviceJoined', this.convertData(data)));
this.eventBus.onDeviceInterview(this,
(data) => this.callOnEvent(data.device, 'deviceInterview', this.convertData(data)));
this.eventBus.onDeviceAnnounce(this,
(data) => this.callOnEvent(data.device, 'deviceAnnounce', this.convertData(data)));
this.eventBus.onDeviceNetworkAddressChanged(this,
(data) => this.callOnEvent(data.device, 'deviceNetworkAddressChanged', this.convertData(data)));
this.eventBus.onEntityOptionsChanged(this,
(data) => {
if (data.entity.isDevice()) {
this.callOnEvent(data.entity, 'deviceOptionsChanged', data)
.then(() => this.eventBus.emitDevicesChanged());
}
});
}
private convertData(data: KeyValue): KeyValue {
return {...data, device: data.device.zh};
}
override async stop(): Promise<void> {
super.stop();
for (const device of this.zigbee.devices(false)) {
await this.callOnEvent(device, 'stop', {});
}
}
private async callOnEvent(device: Device, type: string, data: KeyValue): Promise<void> {
const state = this.state.get(device);
zhc.onEvent(type, data, device.zh, device.options, state);
if (device.definition?.onEvent) {
await device.definition.onEvent(type, data, device.zh, device.options, state);
}
}
}
-267
View File
@@ -1,267 +0,0 @@
const settings = require('../util/settings');
const logger = require('../util/logger');
const stringify = require('json-stable-stringify-without-jsonify');
const utils = require('../util/utils');
const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/ota_update/.+$`);
const tradfriOTA = require('zigbee-herdsman-converters/lib/ota/tradfri');
const topicRegex =
new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/device/ota_update/(update|check)`, 'i');
const Extension = require('./extension');
class OTAUpdate extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.inProgress = new Set();
this.lastChecked = {};
this.legacyApi = settings.get().advanced.legacy_api;
if (settings.get().advanced.ikea_ota_use_test_url) {
tradfriOTA.useTestURL();
}
}
onMQTTConnected() {
for (const device of this.zigbee.getClients()) {
// In case Zigbee2MQTT is restared during an update, progress and remaining values are still in state.
// remove them.
this.removeProgressAndRemainingFromState(device);
}
}
removeProgressAndRemainingFromState(device) {
this.state.removeKey(device.ieeeAddr, ['update', 'progress']);
this.state.removeKey(device.ieeeAddr, ['update', 'remaining']);
}
async onZigbeeEvent(type, data, resolvedEntity) {
if (settings.get().ota.disable_automatic_update_check) return;
if (data.type !== 'commandQueryNextImageRequest' || !resolvedEntity || !resolvedEntity.definition) return;
const supportsOTA = resolvedEntity.definition.hasOwnProperty('ota');
if (supportsOTA) {
// When a device does a next image request, it will usually do it a few times after each other
// with only 10 - 60 seconds inbetween. It doesn't make sense to check for a new update
// each time, so this interval can be set by the user. The default is 1,440 minutes (one day).
const updateCheckInterval = settings.get().ota.update_check_interval * 1000 * 60;
const check = this.lastChecked.hasOwnProperty(data.device.ieeeAddr) ?
(Date.now() - this.lastChecked[data.device.ieeeAddr]) > updateCheckInterval : true;
if (!check || this.inProgress.has(data.device.ieeeAddr)) return;
this.lastChecked[data.device.ieeeAddr] = Date.now();
const available = await resolvedEntity.definition.ota.isUpdateAvailable(data.device, logger, data.data);
const payload = this.getEntityPublishPayload(available ? 'available' : 'idle');
this.publishEntityState(data.device.ieeeAddr, payload);
if (available) {
const message = `Update available for '${resolvedEntity.settings.friendly_name}'`;
logger.info(message);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: 'available', device: resolvedEntity.settings.friendly_name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message, meta}),
);
}
}
}
// Respond to the OTA request:
// - In case we don't support OTA: respond with NO_IMAGE_AVAILABLE (0x98) (so the client stops requesting OTAs)
// - In case we do support OTA: respond with ABORT (0x95) as we don't want to update now.
const endpoint = data.device.endpoints.find((e) => e.supportsOutputCluster('genOta'));
if (endpoint) {
// Some devices send OTA requests without defining OTA cluster as input cluster.
await endpoint.commandResponse('genOta', 'queryNextImageResponse', {status: supportsOTA ? 0x95 : 0x98});
}
}
async readSoftwareBuildIDAndDateCode(device, update) {
try {
const endpoint = device.endpoints.find((e) => e.supportsInputCluster('genBasic'));
const result = await endpoint.read('genBasic', ['dateCode', 'swBuildId']);
if (update) {
device.softwareBuildID = result.swBuildId;
device.dateCode = result.dateCode;
device.save();
}
return {softwareBuildID: result.swBuildId, dateCode: result.dateCode};
} catch (e) {
return null;
}
}
getEntityPublishPayload(state, progress=null, remaining=null) {
const payload = {update: {state}};
if (progress !== null) payload.update.progress = progress;
if (remaining !== null) payload.update.remaining = Math.round(remaining);
/* istanbul ignore else */
if (this.legacyApi) {
payload.update_available = state === 'available';
}
return payload;
}
async onMQTTMessage(topic, message) {
if ((!this.legacyApi || !topic.match(legacyTopicRegex)) && !topic.match(topicRegex)) {
return null;
}
message = utils.parseJSON(message, message);
const ID = typeof message === 'object' && message.hasOwnProperty('id') ? message.id : message;
const resolvedEntity = this.zigbee.resolveEntity(ID);
const type = topic.substring(topic.lastIndexOf('/') + 1);
const responseData = {id: ID};
let error = null;
if (!resolvedEntity || resolvedEntity.type !== 'device') {
error = `Device '${ID}' does not exist`;
} else if (!resolvedEntity.definition || !resolvedEntity.definition.ota) {
error = `Device '${resolvedEntity.name}' does not support OTA updates`;
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `not_supported`, device: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: error, meta}),
);
}
} else if (this.inProgress.has(resolvedEntity.device.ieeeAddr)) {
error = `Update or check for update already in progress for '${resolvedEntity.name}'`;
} else {
this.inProgress.add(resolvedEntity.device.ieeeAddr);
if (type === 'check') {
const msg = `Checking if update available for '${resolvedEntity.name}'`;
logger.info(msg);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `checking_if_available`, device: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: msg, meta}),
);
}
try {
const available = await resolvedEntity.definition.ota.isUpdateAvailable(
resolvedEntity.device, logger,
);
const msg = `${available ? 'Update' : 'No update'} available for '${resolvedEntity.name}'`;
logger.info(msg);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: available ? 'available' : 'not_available', device: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: msg, meta}),
);
}
const payload = this.getEntityPublishPayload(available ? 'available' : 'idle');
this.publishEntityState(resolvedEntity.device.ieeeAddr, payload);
this.lastChecked[resolvedEntity.device.ieeeAddr] = Date.now();
responseData.updateAvailable = available;
} catch (e) {
error = `Failed to check if update available for '${resolvedEntity.name}' (${e.message})`;
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `check_failed`, device: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: error, meta}),
);
}
}
} else { // type === 'update'
const msg = `Updating '${resolvedEntity.name}' to latest firmware`;
logger.info(msg);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_in_progress`, device: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: msg, meta}),
);
}
try {
const onProgress = (progress, remaining) => {
let msg = `Update of '${resolvedEntity.name}' at ${progress.toFixed(2)}%`;
if (remaining) {
msg += `, ≈ ${Math.round(remaining / 60)} minutes remaining`;
}
logger.info(msg);
const payload = this.getEntityPublishPayload('updating', progress, remaining);
this.publishEntityState(resolvedEntity.device.ieeeAddr, payload);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_progress`, device: resolvedEntity.name, progress};
this.mqtt.publish('bridge/log', stringify({type: `ota_update`, message: msg, meta}));
}
};
const from_ = await this.readSoftwareBuildIDAndDateCode(resolvedEntity.device, false);
await resolvedEntity.definition.ota.updateToLatest(resolvedEntity.device, logger, onProgress);
const to = await this.readSoftwareBuildIDAndDateCode(resolvedEntity.device, true);
const [fromS, toS] = [stringify(from_), stringify(to)];
const msg = `Finished update of '${resolvedEntity.name}'` +
(to ? `, from '${fromS}' to '${toS}'` : ``);
logger.info(msg);
this.removeProgressAndRemainingFromState(resolvedEntity.device);
const payload = this.getEntityPublishPayload('idle');
this.publishEntityState(resolvedEntity.device.ieeeAddr, payload);
responseData.from = from_ ? utils.toSnakeCase(from_) : null;
responseData.to = to ? utils.toSnakeCase(to) : null;
this.eventBus.emit(`devicesChanged`);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_succeeded`, device: resolvedEntity.name, from: from_, to};
this.mqtt.publish('bridge/log', stringify({type: `ota_update`, message, meta}));
}
} catch (e) {
error = `Update of '${resolvedEntity.name}' failed (${e.message})`;
this.removeProgressAndRemainingFromState(resolvedEntity.device);
const payload = this.getEntityPublishPayload('available');
this.publishEntityState(resolvedEntity.device.ieeeAddr, payload);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_failed`, device: resolvedEntity.name};
this.mqtt.publish('bridge/log', stringify({type: `ota_update`, message: error, meta}));
}
}
}
this.inProgress.delete(resolvedEntity.device.ieeeAddr);
}
const triggeredViaLegacyApi = topic.match(legacyTopicRegex);
if (!triggeredViaLegacyApi) {
const response = utils.getResponse(message, responseData, error);
await this.mqtt.publish(`bridge/response/device/ota_update/${type}`, stringify(response));
}
if (error) {
logger.error(error);
}
}
}
module.exports = OTAUpdate;
+317
View File
@@ -0,0 +1,317 @@
import * as settings from '../util/settings';
import logger from '../util/logger';
import stringify from 'json-stable-stringify-without-jsonify';
import utils from '../util/utils';
import * as tradfriOTA from 'zigbee-herdsman-converters/lib/ota/tradfri';
import * as zigbeeOTA from 'zigbee-herdsman-converters/lib/ota/zigbeeOTA';
import Extension from './extension';
import bind from 'bind-decorator';
import Device from '../model/device';
import dataDir from '../util/data';
import * as URI from 'uri-js';
import path from 'path';
function isValidUrl(url: string): boolean {
let parsed;
try {
parsed = URI.parse(url);
} catch (_) {
// istanbul ignore next
return false;
}
return parsed.scheme === 'http' || parsed.scheme === 'https';
}
type UpdateState = 'updating' | 'idle' | 'available';
interface UpdatePayload {
update_available?: boolean
// eslint-disable-next-line camelcase
update: {
progress?: number, remaining?: number, state: UpdateState,
installed_version: number | null, latest_version: number | null
}
}
const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/ota_update/.+$`);
const topicRegex =
new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/device/ota_update/(update|check)`, 'i');
export default class OTAUpdate extends Extension {
private inProgress = new Set();
private lastChecked: {[s: string]: number} = {};
private legacyApi = settings.get().advanced.legacy_api;
override async start(): Promise<void> {
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
this.eventBus.onDeviceMessage(this, this.onZigbeeEvent);
if (settings.get().ota.ikea_ota_use_test_url) {
tradfriOTA.useTestURL();
}
// Let zigbeeOTA module know if the override index file is provided
let overrideOTAIndex = settings.get().ota.zigbee_ota_override_index_location;
if (overrideOTAIndex) {
// If the file name is not a full path, then treat it as a relative to the data directory
if (!isValidUrl(overrideOTAIndex) && !path.isAbsolute(overrideOTAIndex)) {
overrideOTAIndex = dataDir.joinPath(overrideOTAIndex);
}
zigbeeOTA.useIndexOverride(overrideOTAIndex);
}
// In order to support local firmware files we need to let zigbeeOTA know where the data directory is
zigbeeOTA.setDataDir(dataDir.getPath());
// In case Zigbee2MQTT is restared during an update, progress and remaining values are still in state.
// remove them.
for (const device of this.zigbee.devices(false)) {
this.removeProgressAndRemainingFromState(device);
}
}
private removeProgressAndRemainingFromState(device: Device): void {
delete this.state.get(device).update?.progress;
delete this.state.get(device).update?.remaining;
}
@bind private async onZigbeeEvent(data: eventdata.DeviceMessage): Promise<void> {
if (data.type !== 'commandQueryNextImageRequest' || !data.device.definition ||
this.inProgress.has(data.device.ieeeAddr)) return;
logger.debug(`Device '${data.device.name}' requested OTA`);
const automaticOTACheckDisabled = settings.get().ota.disable_automatic_update_check;
let supportsOTA = data.device.definition.hasOwnProperty('ota');
if (supportsOTA && !automaticOTACheckDisabled) {
// When a device does a next image request, it will usually do it a few times after each other
// with only 10 - 60 seconds inbetween. It doesn't make sense to check for a new update
// each time, so this interval can be set by the user. The default is 1,440 minutes (one day).
const updateCheckInterval = settings.get().ota.update_check_interval * 1000 * 60;
const check = this.lastChecked.hasOwnProperty(data.device.ieeeAddr) ?
(Date.now() - this.lastChecked[data.device.ieeeAddr]) > updateCheckInterval : true;
if (!check) return;
this.lastChecked[data.device.ieeeAddr] = Date.now();
let availableResult: zhc.OtaUpdateAvailableResult = null;
try {
availableResult = await data.device.definition.ota.isUpdateAvailable(data.device.zh, logger, data.data);
} catch (e) {
supportsOTA = false;
logger.debug(`Failed to check if update available for '${data.device.name}' (${e.message})`);
}
const payload = this.getEntityPublishPayload(data.device, availableResult ?? 'idle');
this.publishEntityState(data.device, payload);
if (availableResult?.available) {
const message = `Update available for '${data.device.name}'`;
logger.info(message);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: 'available', device: data.device.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message, meta}),
);
}
}
}
// Respond to the OTA request: respond with NO_IMAGE_AVAILABLE (0x98) (so the client stops requesting OTAs)
const endpoint = data.device.zh.endpoints.find((e) => e.supportsOutputCluster('genOta')) || data.endpoint;
await endpoint.commandResponse('genOta', 'queryNextImageResponse', {status: 0x98});
logger.debug(`Responded to OTA request of '${data.device.name}' with 'NO_IMAGE_AVAILABLE'`);
}
private async readSoftwareBuildIDAndDateCode(device: Device, sendWhen: 'active' | 'immediate'):
Promise<{softwareBuildID: string, dateCode: string}> {
try {
const endpoint = device.zh.endpoints.find((e) => e.supportsInputCluster('genBasic'));
const result = await endpoint.read('genBasic', ['dateCode', 'swBuildId'], {sendWhen});
return {softwareBuildID: result.swBuildId, dateCode: result.dateCode};
} catch (e) {
return null;
}
}
private getEntityPublishPayload(device: Device, state: zhc.OtaUpdateAvailableResult | UpdateState,
progress: number=null, remaining: number=null): UpdatePayload {
const deviceUpdateState = this.state.get(device).update;
const payload: UpdatePayload = {update: {
state: typeof state === 'string' ? state : (state.available ? 'available' : 'idle'),
installed_version: typeof state === 'string' ?
deviceUpdateState?.installed_version : state.currentFileVersion,
latest_version: typeof state === 'string' ?
deviceUpdateState?.latest_version : state.otaFileVersion,
}};
if (progress !== null) payload.update.progress = progress;
if (remaining !== null) payload.update.remaining = Math.round(remaining);
/* istanbul ignore else */
if (this.legacyApi) {
payload.update_available = typeof state === 'string' ? state === 'available' : state.available;
}
return payload;
}
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
if ((!this.legacyApi || !data.topic.match(legacyTopicRegex)) && !data.topic.match(topicRegex)) {
return null;
}
const message = utils.parseJSON(data.message, data.message);
const ID = (typeof message === 'object' && message.hasOwnProperty('id') ? message.id : message) as string;
const device = this.zigbee.resolveEntity(ID);
const type = data.topic.substring(data.topic.lastIndexOf('/') + 1);
const responseData: {id: string, updateAvailable?: boolean, from?: string, to?: string}= {id: ID};
let error = null;
let errorStack = null;
if (!(device instanceof Device)) {
error = `Device '${ID}' does not exist`;
} else if (!device.definition || !device.definition.ota) {
error = `Device '${device.name}' does not support OTA updates`;
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `not_supported`, device: device.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: error, meta}),
);
}
} else if (this.inProgress.has(device.ieeeAddr)) {
error = `Update or check for update already in progress for '${device.name}'`;
} else {
this.inProgress.add(device.ieeeAddr);
if (type === 'check') {
const msg = `Checking if update available for '${device.name}'`;
logger.info(msg);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `checking_if_available`, device: device.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: msg, meta}),
);
}
try {
const availableResult = await device.definition.ota.isUpdateAvailable(device.zh, logger);
const msg = `${availableResult.available ? 'Update' : 'No update'} available for '${device.name}'`;
logger.info(msg);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {
status: availableResult.available ? 'available' : 'not_available', device: device.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: msg, meta}),
);
}
const payload = this.getEntityPublishPayload(device, availableResult);
this.publishEntityState(device, payload);
this.lastChecked[device.ieeeAddr] = Date.now();
responseData.updateAvailable = availableResult.available;
} catch (e) {
error = `Failed to check if update available for '${device.name}' (${e.message})`;
errorStack = e.stack;
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `check_failed`, device: device.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: error, meta}),
);
}
}
} else { // type === 'update'
const msg = `Updating '${device.name}' to latest firmware`;
logger.info(msg);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_in_progress`, device: device.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, message: msg, meta}),
);
}
try {
const onProgress = (progress: number, remaining: number): void => {
let msg = `Update of '${device.name}' at ${progress.toFixed(2)}%`;
if (remaining) {
msg += `, ≈ ${Math.round(remaining / 60)} minutes remaining`;
}
logger.info(msg);
const payload = this.getEntityPublishPayload(device, 'updating', progress, remaining);
this.publishEntityState(device, payload);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_progress`, device: device.name, progress};
this.mqtt.publish('bridge/log', stringify({type: `ota_update`, message: msg, meta}));
}
};
const from_ = await this.readSoftwareBuildIDAndDateCode(device, 'immediate');
const fileVersion = await device.definition.ota.updateToLatest(device.zh, logger, onProgress);
logger.info(`Finished update of '${device.name}'`);
this.eventBus.emitReconfigure({device});
this.removeProgressAndRemainingFromState(device);
const payload = this.getEntityPublishPayload(device,
{available: false, currentFileVersion: fileVersion, otaFileVersion: fileVersion});
this.publishEntityState(device, payload);
const to = await this.readSoftwareBuildIDAndDateCode(device, 'active');
const [fromS, toS] = [stringify(from_), stringify(to)];
logger.info(`Device '${device.name}' was updated from '${fromS}' to '${toS}'`);
responseData.from = from_ ? utils.toSnakeCase(from_) : null;
responseData.to = to ? utils.toSnakeCase(to) : null;
this.eventBus.emitDevicesChanged();
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_succeeded`, device: device.name, from: from_, to};
this.mqtt.publish('bridge/log', stringify({type: `ota_update`, message, meta}));
}
} catch (e) {
logger.debug(`Update of '${device.name}' failed (${e})`);
error = `Update of '${device.name}' failed (${e.message})`;
errorStack = e.stack;
this.removeProgressAndRemainingFromState(device);
const payload = this.getEntityPublishPayload(device, 'available');
this.publishEntityState(device, payload);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {status: `update_failed`, device: device.name};
this.mqtt.publish('bridge/log', stringify({type: `ota_update`, message: error, meta}));
}
}
}
this.inProgress.delete(device.ieeeAddr);
}
const triggeredViaLegacyApi = data.topic.match(legacyTopicRegex);
if (!triggeredViaLegacyApi) {
const response = utils.getResponse(message, responseData, error);
await this.mqtt.publish(`bridge/response/device/ota_update/${type}`, stringify(response));
}
if (error) {
logger.error(error);
errorStack && logger.debug(errorStack);
}
}
}
-293
View File
@@ -1,293 +0,0 @@
const settings = require('../util/settings');
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const logger = require('../util/logger');
const utils = require('../util/utils');
const assert = require('assert');
const Extension = require('./extension');
const stringify = require('json-stable-stringify-without-jsonify');
const topicRegex = new RegExp(`^(.+?)(?:/(${utils.getEndpointNames().join('|')}))?/(get|set)(?:/(.+))?`);
const stateValues = ['on', 'off', 'toggle', 'open', 'close', 'stop', 'lock', 'unlock'];
const groupConverters = [
zigbeeHerdsmanConverters.toZigbeeConverters.light_onoff_brightness,
zigbeeHerdsmanConverters.toZigbeeConverters.light_color_colortemp,
zigbeeHerdsmanConverters.toZigbeeConverters.effect,
zigbeeHerdsmanConverters.toZigbeeConverters.ignore_transition,
zigbeeHerdsmanConverters.toZigbeeConverters.cover_position_tilt,
zigbeeHerdsmanConverters.toZigbeeConverters.thermostat_occupied_heating_setpoint,
zigbeeHerdsmanConverters.toZigbeeConverters.tint_scene,
zigbeeHerdsmanConverters.toZigbeeConverters.light_brightness_move,
zigbeeHerdsmanConverters.toZigbeeConverters.light_brightness_step,
zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_step,
zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_move,
zigbeeHerdsmanConverters.toZigbeeConverters.light_hue_saturation_move,
zigbeeHerdsmanConverters.toZigbeeConverters.light_hue_saturation_step,
];
class EntityPublish extends Extension {
parseTopic(topic) {
const match = topic.match(topicRegex);
if (!match) {
return null;
}
const ID = match[1].replace(`${settings.get().mqtt.base_topic}/`, '');
// If we didn't replace base_topic we received something we don't care about
if (ID === match[1] || ID.match(/bridge/)) {
return null;
}
return {ID: ID, endpointName: match[2] || '', type: match[3], attribute: match[4]};
}
async onMQTTMessage(topic, message) {
topic = this.parseTopic(topic);
if (!topic) {
return false;
}
const entityKey = `${topic.ID}` + (topic.endpointName ? `/${topic.endpointName}` : '');
const resolvedEntity = this.zigbee.resolveEntity(entityKey);
if (!resolvedEntity) {
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const message = {friendly_name: entityKey};
this.mqtt.publish(
'bridge/log',
stringify({type: `entity_not_found`, message}),
);
}
logger.error(`Entity '${entityKey}' is unknown`);
return;
}
// Get entity details
let converters = null;
let target = null;
let options = {};
let device = null;
let definition = null;
let membersState = null;
assert(resolvedEntity.type === 'device' || resolvedEntity.type === 'group');
if (resolvedEntity.type === 'device') {
if (!resolvedEntity.definition) {
logger.warn(`Device with modelID '${resolvedEntity.device.modelID}' is not supported.`);
logger.warn(`Please see: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html`);
return;
}
device = resolvedEntity.device;
definition = resolvedEntity.definition;
target = resolvedEntity.endpoint;
converters = resolvedEntity.definition.toZigbee;
options = resolvedEntity.settings;
} else {
target = resolvedEntity.group;
options = resolvedEntity.settings;
definition = resolvedEntity.group.members
.map((e) => zigbeeHerdsmanConverters.findByDevice(e.getDevice())).filter((d) => d);
converters = new Set(groupConverters);
for (const d of definition) {
d.toZigbee.forEach(converters.add, converters);
}
converters = [...converters];
membersState = {};
for (const member of resolvedEntity.group.members) {
const ieeeAddr = member.getDevice().ieeeAddr;
membersState[ieeeAddr] = this.state.get(ieeeAddr);
}
}
// Convert the MQTT message to a Zigbee message.
let json = {};
if (topic.hasOwnProperty('attribute') && topic.attribute) {
try {
json[topic.attribute] = JSON.parse(message);
} catch (e) {
json[topic.attribute] = message;
}
} else {
try {
json = JSON.parse(message);
} catch (e) {
if (stateValues.includes(message.toLowerCase())) {
json = {state: message};
} else {
logger.error(`Invalid JSON '${message}', skipping...`);
return false;
}
}
}
if (!json) {
logger.error(`Invalid JSON '${message}', skipping...`);
return;
}
/**
* Home Assistant always publishes 'state', even when e.g. only setting
* the color temperature. This would lead to 2 zigbee publishes, where the first one
* (state) is probably unecessary.
*/
const entityState = this.state.get(resolvedEntity.settings.ID) || {};
if (settings.get().homeassistant) {
const hasColorTemp = json.hasOwnProperty('color_temp');
const hasColor = json.hasOwnProperty('color');
const hasBrightness = json.hasOwnProperty('brightness');
const isOn = entityState && entityState.state === 'ON' ? true : false;
if (isOn && (hasColorTemp || hasColor) && !hasBrightness) {
delete json.state;
logger.debug('Skipping state because of Home Assistant');
}
}
/**
* Order state & brightness based on current bulb state
*
* Not all bulbs support setting the color/color_temp while it is off
* this results in inconsistant behavior between different vendors.
*
* bulb on => move state & brightness to the back
* bulb off => move state & brightness to the front
*/
const entries = Object.entries(json);
const sorter = typeof json.state === 'string' && json.state.toLowerCase() === 'off' ? 1 : -1;
entries.sort((a, b) => (['state', 'brightness', 'brightness_percent'].includes(a[0]) ? sorter : sorter * -1));
// For each attribute call the corresponding converter
const usedConverters = {};
for (let [key, value] of entries) {
let endpointName = topic.endpointName;
let actualTarget = target;
// When the key has a endpointName included (e.g. state_right), this will override the target.
if (resolvedEntity.type === 'device' && key.includes('_')) {
const endpointNameMatch = utils.getEndpointNames().find((n) => key.endsWith(`_${n}`));
if (endpointNameMatch) {
endpointName = endpointNameMatch;
key = key.replace(`_${endpointNameMatch}`, '');
const device = target.getDevice();
actualTarget = device.getEndpoint(definition.endpoint(device)[endpointName]);
if (!actualTarget) {
logger.error(`Device '${resolvedEntity.name}' has no endpoint '${endpointName}'`);
continue;
}
}
}
const endpointOrGroupID = actualTarget.constructor.name == 'Group' ? actualTarget.groupID : actualTarget.ID;
if (!usedConverters.hasOwnProperty(endpointOrGroupID)) usedConverters[endpointOrGroupID] = [];
const converter = converters.find((c) => c.key.includes(key));
if (topic.type === 'set' && usedConverters[endpointOrGroupID].includes(converter)) {
// Use a converter for set only once
// (e.g. light_onoff_brightness converters can convert state and brightness)
continue;
}
if (!converter) {
logger.error(`No converter available for '${key}' (${json[key]})`);
continue;
}
// Converter didn't return a result, skip
const meta = {
endpoint_name: endpointName,
options,
message: {...json},
logger,
device,
state: entityState,
membersState,
mapped: definition,
};
// Strip endpoint name from meta.message properties.
if (meta.endpoint_name) {
for (const [key, value] of Object.entries(meta.message)) {
if (key.endsWith(meta.endpoint_name)) {
delete meta.message[key];
const keyWithoutEndpoint = key.substring(0, key.length - meta.endpoint_name.length - 1);
meta.message[keyWithoutEndpoint] = value;
}
}
}
try {
if (topic.type === 'set' && converter.convertSet) {
logger.debug(`Publishing '${topic.type}' '${key}' to '${resolvedEntity.name}'`);
const result = await converter.convertSet(actualTarget, key, value, meta);
const isGroup = actualTarget.constructor.name == 'Group';
// Optimistic behaviour of groups and devices is different.
const publishOptimistic = isGroup || (!options.hasOwnProperty('optimistic') || options.optimistic);
if (result && result.state && publishOptimistic) {
const msg = result.state;
if (endpointName) {
for (const key of ['state', 'brightness', 'color', 'color_temp']) {
if (msg.hasOwnProperty(key)) {
msg[`${key}_${endpointName}`] = msg[key];
delete msg[key];
}
}
}
this.publishEntityState(resolvedEntity.settings.ID, msg);
}
if (result && result.membersState && publishOptimistic) {
for (const [ieeeAddr, state] of Object.entries(result.membersState)) {
this.publishEntityState(ieeeAddr, state);
}
}
// 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 or for forcing a state read for devices that don't
// automatically report a new state when set.
// When reporting is requested for a device (report: true in device-specific settings) we won't
// ever issue a read here, as we assume the device will properly report changes.
// Only do this when the retrieve_state option is enabled for this device.
// retrieve_state == decprecated
if (
resolvedEntity.type === 'device' && result && result.hasOwnProperty('readAfterWriteTime') &&
resolvedEntity.settings.retrieve_state
) {
setTimeout(() => converter.convertGet(actualTarget, key, meta), result.readAfterWriteTime);
}
} else if (topic.type === 'get' && converter.convertGet) {
logger.debug(`Publishing get '${topic.type}' '${key}' to '${resolvedEntity.name}'`);
await converter.convertGet(actualTarget, key, meta);
} else {
logger.error(`No converter available for '${topic.type}' '${key}' (${json[key]})`);
continue;
}
} catch (error) {
const message =
`Publish '${topic.type}' '${key}' to '${resolvedEntity.name}' failed: '${error}'`;
logger.error(message);
logger.debug(error.stack);
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
const meta = {friendly_name: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `zigbee_publish_error`, message, meta}),
);
}
}
usedConverters[endpointOrGroupID].push(converter);
}
return true;
}
}
module.exports = EntityPublish;
+303
View File
@@ -0,0 +1,303 @@
import * as settings from '../util/settings';
import zigbeeHerdsmanConverters from 'zigbee-herdsman-converters';
import * as philips from 'zigbee-herdsman-converters/lib/philips';
import logger from '../util/logger';
import utils from '../util/utils';
import Extension from './extension';
import stringify from 'json-stable-stringify-without-jsonify';
import Group from '../model/group';
import Device from '../model/device';
import bind from 'bind-decorator';
const topicRegex = new RegExp(`^(.+?)(?:/(${utils.endpointNames.join('|')}|\\d+))?/(get|set)(?:/(.+))?`);
const propertyEndpointRegex = new RegExp(`^(.*?)_(${utils.endpointNames.join('|')})$`);
const stateValues = ['on', 'off', 'toggle', 'open', 'close', 'stop', 'lock', 'unlock'];
const sceneConverterKeys = ['scene_store', 'scene_add', 'scene_remove', 'scene_remove_all', 'scene_rename'];
// Legacy: don't provide default converters anymore, this is required by older z2m installs not saving group members
const defaultGroupConverters = [
zigbeeHerdsmanConverters.toZigbeeConverters.light_onoff_brightness,
zigbeeHerdsmanConverters.toZigbeeConverters.light_color_colortemp,
philips.tz.effect, // Support Hue effects for groups
zigbeeHerdsmanConverters.toZigbeeConverters.ignore_transition,
zigbeeHerdsmanConverters.toZigbeeConverters.cover_position_tilt,
zigbeeHerdsmanConverters.toZigbeeConverters.thermostat_occupied_heating_setpoint,
zigbeeHerdsmanConverters.toZigbeeConverters.tint_scene,
zigbeeHerdsmanConverters.toZigbeeConverters.light_brightness_move,
zigbeeHerdsmanConverters.toZigbeeConverters.light_brightness_step,
zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_step,
zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_move,
zigbeeHerdsmanConverters.toZigbeeConverters.light_hue_saturation_move,
zigbeeHerdsmanConverters.toZigbeeConverters.light_hue_saturation_step,
];
interface ParsedTopic {ID: string, endpoint: string, attribute: string, type: 'get' | 'set'}
export default class Publish extends Extension {
async start(): Promise<void> {
this.eventBus.onMQTTMessage(this, this.onMQTTMessage);
}
parseTopic(topic: string): ParsedTopic | null {
const match = topic.match(topicRegex);
if (!match) {
return null;
}
const ID = match[1].replace(`${settings.get().mqtt.base_topic}/`, '');
// If we didn't replace base_topic we received something we don't care about
if (ID === match[1] || ID.match(/bridge/)) {
return null;
}
return {ID: ID, endpoint: match[2], type: match[3] as 'get' | 'set', attribute: match[4]};
}
parseMessage(parsedTopic: ParsedTopic, data: eventdata.MQTTMessage): KeyValue | null {
if (parsedTopic.attribute) {
try {
return {[parsedTopic.attribute]: JSON.parse(data.message)};
} catch (e) {
return {[parsedTopic.attribute]: data.message};
}
} else {
try {
return JSON.parse(data.message);
} catch (e) {
if (stateValues.includes(data.message.toLowerCase())) {
return {state: data.message};
} else {
return null;
}
}
}
}
legacyLog(payload: KeyValue): void {
/* istanbul ignore else */
if (settings.get().advanced.legacy_api) {
this.mqtt.publish('bridge/log', stringify(payload));
}
}
legacyRetrieveState(re: Device | Group, converter: zhc.ToZigbeeConverter, result: zhc.ToZigbeeConverterResult,
target: zh.Endpoint | zh.Group, key: string, meta: zhc.ToZigbeeConverterGetMeta): void {
// 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 or for forcing a state read for devices that don't
// automatically report a new state when set.
// When reporting is requested for a device (report: true in device-specific settings) we won't
// ever issue a read here, as we assume the device will properly report changes.
// Only do this when the retrieve_state option is enabled for this device.
// retrieve_state == deprecated
if (re instanceof Device && result && result.hasOwnProperty('readAfterWriteTime') &&
re.options.retrieve_state
) {
setTimeout(() => converter.convertGet(target, key, meta), result.readAfterWriteTime);
}
}
updateMessageHomeAssistant(message: KeyValue, entityState: KeyValue): void {
/**
* Home Assistant always publishes 'state', even when e.g. only setting
* the color temperature. This would lead to 2 zigbee publishes, where the first one
* (state) is probably unnecessary.
*/
if (settings.get().homeassistant) {
const hasColorTemp = message.hasOwnProperty('color_temp');
const hasColor = message.hasOwnProperty('color');
const hasBrightness = message.hasOwnProperty('brightness');
const isOn = entityState.state === 'ON' ? true : false;
if (isOn && (hasColorTemp || hasColor) && !hasBrightness) {
delete message.state;
logger.debug('Skipping state because of Home Assistant');
}
}
}
@bind async onMQTTMessage(data: eventdata.MQTTMessage): Promise<void> {
const parsedTopic = this.parseTopic(data.topic);
if (!parsedTopic) return;
const re = this.zigbee.resolveEntity(parsedTopic.ID);
if (re == null) {
this.legacyLog({type: `entity_not_found`, message: {friendly_name: parsedTopic.ID}});
logger.error(`Entity '${parsedTopic.ID}' is unknown`);
return;
}
// Get entity details
const definition = re instanceof Device ? re.definition : re.membersDefinitions();
const target = re instanceof Group ? re.zh : re.endpoint(parsedTopic.endpoint);
if (target == null) {
logger.error(`Device '${re.name}' has no endpoint '${parsedTopic.endpoint}'`);
return;
}
const device = re instanceof Device ? re.zh : null;
const entitySettings = re.options;
const entityState = this.state.get(re);
const membersState = re instanceof Group ?
Object.fromEntries(re.zh.members.map((e) => [e.getDevice().ieeeAddr,
this.state.get(this.zigbee.resolveEntity(e.getDevice().ieeeAddr))])) : null;
let converters: zhc.ToZigbeeConverter[];
{
if (Array.isArray(definition)) {
const c = new Set(definition.map((d) => d.toZigbee).flat());
// @ts-expect-error
if (c.size == 0) converters = defaultGroupConverters;
else converters = Array.from(c);
} else if (definition) {
converters = definition.toZigbee;
} else {
converters = [zigbeeHerdsmanConverters.toZigbeeConverters.read,
zigbeeHerdsmanConverters.toZigbeeConverters.write];
}
}
// Convert the MQTT message to a Zigbee message.
const message = this.parseMessage(parsedTopic, data);
if (message == null) {
logger.error(`Invalid message '${message}', skipping...`);
return;
}
this.updateMessageHomeAssistant(message, entityState);
/**
* Order state & brightness based on current bulb state
*
* Not all bulbs support setting the color/color_temp while it is off
* this results in inconsistent behavior between different vendors.
*
* bulb on => move state & brightness to the back
* bulb off => move state & brightness to the front
*/
const entries = Object.entries(message);
const sorter = typeof message.state === 'string' && message.state.toLowerCase() === 'off' ? 1 : -1;
entries.sort((a) => (['state', 'brightness', 'brightness_percent'].includes(a[0]) ? sorter : sorter * -1));
// For each attribute call the corresponding converter
const usedConverters: {[s: number]: zhc.ToZigbeeConverter[]} = {};
const toPublish: {[s: number | string]: KeyValue} = {};
const toPublishEntity: {[s: number | string]: Device | Group} = {};
const addToToPublish = (entity: Device | Group, payload: KeyValue): void => {
const ID = entity.ID;
if (!(ID in toPublish)) {
toPublish[ID] = {};
toPublishEntity[ID] = entity;
}
toPublish[ID] = {...toPublish[ID], ...payload};
};
for (let [key, value] of entries) {
let endpointName = parsedTopic.endpoint;
let localTarget = target;
let endpointOrGroupID = utils.isEndpoint(target) ? target.ID : target.groupID;
// When the key has a endpointName included (e.g. state_right), this will override the target.
const propertyEndpointMatch = key.match(propertyEndpointRegex);
if (re instanceof Device && propertyEndpointMatch) {
endpointName = propertyEndpointMatch[2];
key = propertyEndpointMatch[1];
localTarget = re.endpoint(endpointName);
if (localTarget == null) {
logger.error(`Device '${re.name}' has no endpoint '${endpointName}'`);
continue;
}
endpointOrGroupID = localTarget.ID;
}
if (!usedConverters.hasOwnProperty(endpointOrGroupID)) usedConverters[endpointOrGroupID] = [];
const converter = converters.find((c) => c.key.includes(key));
if (parsedTopic.type === 'set' && usedConverters[endpointOrGroupID].includes(converter)) {
// Use a converter for set only once
// (e.g. light_onoff_brightness converters can convert state and brightness)
continue;
}
if (!converter) {
logger.error(`No converter available for '${key}' (${stringify(message[key])})`);
continue;
}
// If the endpoint_name name is a number, try to map it to a friendlyName
if (!isNaN(Number(endpointName)) && re.isDevice() && utils.isEndpoint(localTarget) &&
re.endpointName(localTarget)) {
endpointName = re.endpointName(localTarget);
}
// Converter didn't return a result, skip
const meta = {endpoint_name: endpointName, options: entitySettings, message: {...message}, logger, device,
state: entityState, membersState, mapped: definition};
// Strip endpoint name from meta.message properties.
if (endpointName) {
for (const [key, value] of Object.entries(meta.message)) {
if (key.endsWith(endpointName)) {
delete meta.message[key];
const keyWithoutEndpoint = key.substring(0, key.length - endpointName.length - 1);
meta.message[keyWithoutEndpoint] = value;
}
}
}
try {
if (parsedTopic.type === 'set' && converter.convertSet) {
logger.debug(`Publishing '${parsedTopic.type}' '${key}' to '${re.name}'`);
const result = await converter.convertSet(localTarget, key, value, meta);
const optimistic = !entitySettings.hasOwnProperty('optimistic') || entitySettings.optimistic;
if (result && result.state && optimistic) {
const msg = result.state;
if (endpointName) {
for (const key of Object.keys(msg)) {
msg[`${key}_${endpointName}`] = msg[key];
delete msg[key];
}
}
// filter out attribute listed in filtered_optimistic
utils.filterProperties(entitySettings.filtered_optimistic, msg);
addToToPublish(re, msg);
}
if (result && result.membersState && optimistic) {
for (const [ieeeAddr, state] of Object.entries(result.membersState)) {
addToToPublish(this.zigbee.resolveEntity(ieeeAddr), state);
}
}
this.legacyRetrieveState(re, converter, result, localTarget, key, meta);
} else if (parsedTopic.type === 'get' && converter.convertGet) {
logger.debug(`Publishing get '${parsedTopic.type}' '${key}' to '${re.name}'`);
await converter.convertGet(localTarget, key, meta);
} else {
logger.error(`No converter available for '${parsedTopic.type}' '${key}' (${message[key]})`);
continue;
}
} catch (error) {
const message =
`Publish '${parsedTopic.type}' '${key}' to '${re.name}' failed: '${error}'`;
logger.error(message);
logger.debug(error.stack);
this.legacyLog({type: `zigbee_publish_error`, message, meta: {friendly_name: re.name}});
}
usedConverters[endpointOrGroupID].push(converter);
}
for (const [ID, payload] of Object.entries(toPublish)) {
if (Object.keys(payload).length != 0) {
this.publishEntityState(toPublishEntity[ID], payload);
}
}
const scenesChanged = Object.values(usedConverters)
.some((cl) => cl.some((c) => c.key.some((k) => sceneConverterKeys.includes(k))));
if (scenesChanged) {
this.eventBus.emitScenesChanged();
}
}
}
-173
View File
@@ -1,173 +0,0 @@
const settings = require('../util/settings');
const logger = require('../util/logger');
const utils = require('../util/utils');
const debounce = require('debounce');
const Extension = require('./extension');
const stringify = require('json-stable-stringify-without-jsonify');
class Receive extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.elapsed = {};
this.debouncers = {};
this.eventBus.on('publishEntityState', (data) => this.onPublishEntityState(data));
}
async onZigbeeStarted() {
this.coordinator = this.zigbee.getDevicesByType('Coordinator')[0];
}
async onPublishEntityState(data) {
/**
* Prevent that outdated properties are being published.
* In case that e.g. the state is currently held back by a debounce and a new state is published
* remove it from the to be send debounced message.
*/
if (data.entity.type === 'device' && this.debouncers[data.entity.device.ieeeAddr] &&
data.stateChangeReason !== 'publishDebounce') {
for (const key of Object.keys(data.payload)) {
delete this.debouncers[data.entity.device.ieeeAddr].payload[key];
}
}
}
publishDebounce(ieeeAddr, payload, time, debounceIgnore) {
if (!this.debouncers[ieeeAddr]) {
this.debouncers[ieeeAddr] = {
payload: {},
publish: debounce(() => {
this.publishEntityState(ieeeAddr, this.debouncers[ieeeAddr].payload, 'publishDebounce');
this.debouncers[ieeeAddr].payload = {};
}, time * 1000),
};
}
if (this.isPayloadConflicted(payload, this.debouncers[ieeeAddr].payload, debounceIgnore)) {
// publish previous payload immediately
this.debouncers[ieeeAddr].publish.flush();
}
// extend debounced payload with current
this.debouncers[ieeeAddr].payload = {...this.debouncers[ieeeAddr].payload, ...payload};
this.debouncers[ieeeAddr].publish();
}
// if debounce_ignore are specified (Array of strings)
// then all newPayload values with key present in debounce_ignore
// should equal or be undefined in oldPayload
// otherwise payload is conflicted
isPayloadConflicted(newPayload, oldPayload, debounceIgnore) {
let result = false;
Object.keys(oldPayload)
.filter((key) => (debounceIgnore || []).includes(key))
.forEach((key) => {
if (typeof newPayload[key] !== 'undefined' && newPayload[key] !== oldPayload[key]) {
result = true;
}
});
return result;
}
shouldProcess(type, data, resolvedEntity) {
if (type !== 'message' || !resolvedEntity) {
return false;
}
if (!resolvedEntity.definition) {
if (data.device.interviewing) {
logger.debug(`Skipping message, definition is undefined and still interviewing`);
} else {
logger.warn(
`Received message from unsupported device with Zigbee model '${data.device.modelID}' ` +
`and manufacturer name '${data.device.manufacturerName}'`);
logger.warn(`Please see: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html.`);
}
return false;
}
return true;
}
onZigbeeEvent(type, data, resolvedEntity) {
/**
* Handling of re-transmitted Xiaomi messages.
* https://github.com/Koenkk/zigbee2mqtt/issues/1238
* https://github.com/Koenkk/zigbee2mqtt/issues/3592
*
* Some Xiaomi router devices re-transmit messages from Xiaomi end devices.
* The network address of these message is set to the one of the Xiaomi router.
* Therefore it looks like if the message came from the Xiaomi router, while in
* fact it came from the end device.
* Handling these message would result in false state updates.
* The group ID attribute of these message defines the network address of the end device.
*/
if (type === 'message' && utils.isXiaomiDevice(data.device) && data.device.type === 'Router' && data.groupID) {
logger.debug('Handling re-transmitted Xiaomi message');
data.device = this.zigbee.getDeviceByNetworkAddress(data.groupID);
resolvedEntity = this.zigbee.resolveEntity(data.device);
}
if (!this.shouldProcess(type, data, resolvedEntity)) {
return;
}
const converters = resolvedEntity.definition.fromZigbee.filter((c) => {
const type = Array.isArray(c.type) ? c.type.includes(data.type) : c.type === data.type;
return c.cluster === data.cluster && type;
});
// Check if there is an available converter, genOta messages are not interesting.
if (!converters.length && !['genOta', 'genTime', 'genBasic'].includes(data.cluster)) {
logger.debug(
`No converter available for '${resolvedEntity.definition.model}' with cluster '${data.cluster}' ` +
`and type '${data.type}' and data '${stringify(data.data)}'`,
);
return;
}
// Convert this Zigbee message to a MQTT message.
// Get payload for the message.
// - 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.
const publish = (payload) => {
if (settings.get().advanced.elapsed) {
const now = Date.now();
if (this.elapsed[data.device.ieeeAddr]) {
payload.elapsed = now - this.elapsed[data.device.ieeeAddr];
}
this.elapsed[data.device.ieeeAddr] = now;
}
// Check if we have to debounce
if (resolvedEntity.settings.debounce) {
this.publishDebounce(
data.device.ieeeAddr, payload, resolvedEntity.settings.debounce,
resolvedEntity.settings.debounce_ignore,
);
} else {
this.publishEntityState(data.device.ieeeAddr, payload);
}
};
const meta = {device: data.device, logger, state: this.state.get(data.device.ieeeAddr)};
let payload = {};
converters.forEach((converter) => {
const converted = converter.convert(
resolvedEntity.definition, data, publish, resolvedEntity.settings, meta,
);
if (converted) {
payload = {...payload, ...converted};
}
});
if (Object.keys(payload).length) {
publish(payload);
}
}
}
module.exports = Receive;
+168
View File
@@ -0,0 +1,168 @@
import * as settings from '../util/settings';
import logger from '../util/logger';
import debounce from 'debounce';
import Extension from './extension';
import stringify from 'json-stable-stringify-without-jsonify';
import bind from 'bind-decorator';
import utils from '../util/utils';
type DebounceFunction = (() => void) & { clear(): void; } & { flush(): void; };
export default class Receive extends Extension {
private elapsed: {[s: string]: number} = {};
private debouncers: {[s: string]: {payload: KeyValue, publish: DebounceFunction }} = {};
async start(): Promise<void> {
this.eventBus.onPublishEntityState(this, this.onPublishEntityState);
this.eventBus.onDeviceMessage(this, this.onDeviceMessage);
}
@bind async onPublishEntityState(data: eventdata.PublishEntityState): Promise<void> {
/**
* Prevent that outdated properties are being published.
* In case that e.g. the state is currently held back by a debounce and a new state is published
* remove it from the to be send debounced message.
*/
if (data.entity.isDevice() && this.debouncers[data.entity.ieeeAddr] &&
data.stateChangeReason !== 'publishDebounce' && data.stateChangeReason !== 'lastSeenChanged') {
for (const key of Object.keys(data.payload)) {
delete this.debouncers[data.entity.ieeeAddr].payload[key];
}
}
}
publishDebounce(device: Device, payload: KeyValue, time: number, debounceIgnore: string[]): void {
if (!this.debouncers[device.ieeeAddr]) {
this.debouncers[device.ieeeAddr] = {
payload: {},
publish: debounce(() => {
this.publishEntityState(device, this.debouncers[device.ieeeAddr].payload, 'publishDebounce');
this.debouncers[device.ieeeAddr].payload = {};
}, time * 1000),
};
}
if (this.isPayloadConflicted(payload, this.debouncers[device.ieeeAddr].payload, debounceIgnore)) {
// publish previous payload immediately
this.debouncers[device.ieeeAddr].publish.flush();
}
// extend debounced payload with current
this.debouncers[device.ieeeAddr].payload = {...this.debouncers[device.ieeeAddr].payload, ...payload};
// Update state cache right away. This makes sure that during debouncing cached state is always up to date.
// ( Update right away as "lastSeenChanged" event might occur while debouncer is still active.
// And if that happens it would cause old message to be published from cache.
// By updating cache we make sure that state cache is always up-to-date.
this.state.set(device, this.debouncers[device.ieeeAddr].payload);
this.debouncers[device.ieeeAddr].publish();
}
// if debounce_ignore are specified (Array of strings)
// then all newPayload values with key present in debounce_ignore
// should equal or be undefined in oldPayload
// otherwise payload is conflicted
isPayloadConflicted(newPayload: KeyValue, oldPayload: KeyValue, debounceIgnore: string[] | null): boolean {
let result = false;
Object.keys(oldPayload)
.filter((key) => (debounceIgnore || []).includes(key))
.forEach((key) => {
if (typeof newPayload[key] !== 'undefined' && newPayload[key] !== oldPayload[key]) {
result = true;
}
});
return result;
}
shouldProcess(data: eventdata.DeviceMessage): boolean {
if (!data.device.definition) {
if (data.device.zh.interviewing) {
logger.debug(`Skipping message, definition is undefined and still interviewing`);
} else {
logger.warn(
`Received message from unsupported device with Zigbee model '${data.device.zh.modelID}' ` +
`and manufacturer name '${data.device.zh.manufacturerName}'`);
// eslint-disable-next-line max-len
logger.warn(`Please see: https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html`);
}
return false;
}
return true;
}
@bind async onDeviceMessage(data: eventdata.DeviceMessage): Promise<void> {
/* istanbul ignore next */
if (!data.device) return;
if (!this.shouldProcess(data)) {
utils.publishLastSeen({device: data.device, reason: 'messageEmitted'},
settings.get(), true, this.publishEntityState);
return;
}
const converters = data.device.definition.fromZigbee.filter((c) => {
const type = Array.isArray(c.type) ? c.type.includes(data.type) : c.type === data.type;
return c.cluster === data.cluster && type;
});
// Check if there is an available converter, genOta messages are not interesting.
const ignoreClusters: (string | number)[] = ['genOta', 'genTime', 'genBasic', 'genPollCtrl'];
if (converters.length == 0 && !ignoreClusters.includes(data.cluster)) {
logger.debug(`No converter available for '${data.device.definition.model}' with ` +
`cluster '${data.cluster}' and type '${data.type}' and data '${stringify(data.data)}'`);
utils.publishLastSeen({device: data.device, reason: 'messageEmitted'},
settings.get(), true, this.publishEntityState);
return;
}
// Convert this Zigbee message to a MQTT message.
// Get payload for the message.
// - 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.
const publish = (payload: KeyValue): void => {
if (settings.get().advanced.elapsed) {
const now = Date.now();
if (this.elapsed[data.device.ieeeAddr]) {
payload.elapsed = now - this.elapsed[data.device.ieeeAddr];
}
this.elapsed[data.device.ieeeAddr] = now;
}
// Check if we have to debounce
if (data.device.options.debounce) {
this.publishDebounce(data.device, payload, data.device.options.debounce,
data.device.options.debounce_ignore);
} else {
this.publishEntityState(data.device, payload);
}
};
const meta = {device: data.device.zh, logger, state: this.state.get(data.device)};
let payload: KeyValue = {};
for (const converter of converters) {
try {
const converted = await converter.convert(
data.device.definition, data, publish, data.device.options, meta);
if (converted) {
payload = {...payload, ...converted};
}
} catch (error) /* istanbul ignore next */ {
logger.error(`Exception while calling fromZigbee converter: ${error.message}}`);
logger.debug(error.stack);
}
}
if (Object.keys(payload).length) {
publish(payload);
} else {
utils.publishLastSeen({device: data.device, reason: 'messageEmitted'},
settings.get(), true, this.publishEntityState);
}
}
}
+79
View File
@@ -0,0 +1,79 @@
/* eslint-disable brace-style */
import * as settings from '../util/settings';
import zigbeeHerdsmanConverters from 'zigbee-herdsman-converters';
export default class Device {
public zh: zh.Device;
private _definition: zhc.Definition;
private _definitionModelID: string;
get ieeeAddr(): string {return this.zh.ieeeAddr;}
get ID(): string {return this.zh.ieeeAddr;}
get options(): DeviceOptions {return {...settings.get().device_options, ...settings.getDevice(this.ieeeAddr)};}
get name(): string {
return this.zh.type === 'Coordinator' ? 'Coordinator' : this.options?.friendly_name || this.ieeeAddr;
}
get definition(): zhc.Definition {
// Some devices can change modelID, reconsider the definition in that case.
// https://github.com/Koenkk/zigbee-herdsman-converters/issues/3016
if (!this.zh.interviewing && (!this._definition || this._definitionModelID !== this.zh.modelID)) {
this._definition = zigbeeHerdsmanConverters.findByDevice(this.zh);
this._definitionModelID = this.zh.modelID;
}
return this._definition;
}
constructor(device: zh.Device) {
this.zh = device;
}
exposes(): zhc.DefinitionExpose[] {
/* istanbul ignore if */
if (typeof this.definition.exposes == 'function') {
return this.definition.exposes(this.zh, this.options);
} else {
return this.definition.exposes;
}
}
ensureInSettings(): void {
if (this.zh.type !== 'Coordinator' && !settings.getDevice(this.zh.ieeeAddr)) {
settings.addDevice(this.zh.ieeeAddr);
}
}
endpoint(key?: string | number): zh.Endpoint {
let endpoint: zh.Endpoint;
if (key == null || key == '') key = 'default';
if (!isNaN(Number(key))) {
endpoint = this.zh.getEndpoint(Number(key));
} else if (this.definition?.endpoint) {
const ID = this.definition?.endpoint?.(this.zh)[key];
if (ID) endpoint = this.zh.getEndpoint(ID);
else if (key === 'default') endpoint = this.zh.endpoints[0];
else return null;
} else {
/* istanbul ignore next */
if (key !== 'default') return null;
endpoint = this.zh.endpoints[0];
}
return endpoint;
}
endpointName(endpoint: zh.Endpoint): string {
let name = null;
if (this.definition?.endpoint) {
name = Object.entries(this.definition?.endpoint(this.zh)).find((e) => e[1] == endpoint.ID)[0];
}
/* istanbul ignore next */
return name === 'default' ? null : name;
}
isIkeaTradfri(): boolean {return this.zh.manufacturerID === 4476;}
isDevice(): this is Device {return true;}
/* istanbul ignore next */
isGroup(): this is Group {return false;}
}
+33
View File
@@ -0,0 +1,33 @@
/* eslint-disable brace-style */
import * as settings from '../util/settings';
import zigbeeHerdsmanConverters from 'zigbee-herdsman-converters';
export default class Group {
public zh: zh.Group;
private resolveDevice: (ieeeAddr: string) => Device;
get ID(): number {return this.zh.groupID;}
get options(): GroupOptions {return {...settings.getGroup(this.ID)};}
get name(): string {return this.options?.friendly_name || this.ID.toString();}
constructor(group: zh.Group, resolveDevice: (ieeeAddr: string) => Device) {
this.zh = group;
this.resolveDevice = resolveDevice;
}
hasMember(device: Device): boolean {
return !!device.zh.endpoints.find((e) => this.zh.members.includes(e));
}
membersDevices(): Device[] {
return this.zh.members.map((e) => this.resolveDevice(e.getDevice().ieeeAddr)).filter((d) => d);
}
membersDefinitions(): zhc.Definition[] {
return this.zh.members.map((m) =>
zigbeeHerdsmanConverters.findByDevice(m.getDevice())).filter((d) => d) as zhc.Definition[];
}
isDevice(): this is Device {return false;}
isGroup(): this is Group {return true;}
}
-145
View File
@@ -1,145 +0,0 @@
const mqtt = require('mqtt');
const logger = require('./util/logger');
const settings = require('./util/settings');
const fs = require('fs');
const events = require('events');
class MQTT extends events.EventEmitter {
constructor() {
super();
this.onMessage = this.onMessage.bind(this);
this.publishedTopics = new Set();
}
async connect() {
const mqttSettings = settings.get().mqtt;
logger.info(`Connecting to MQTT server at ${mqttSettings.server}`);
const options = {
will: {
topic: `${settings.get().mqtt.base_topic}/bridge/state`,
payload: 'offline',
retain: settings.get().mqtt.force_disable_retain ? false : true,
},
};
if (mqttSettings.version) {
options.protocolVersion = mqttSettings.version;
}
if (mqttSettings.keepalive) {
logger.debug(`Using MQTT keepalive: ${mqttSettings.keepalive}`);
options.keepalive = mqttSettings.keepalive;
}
if (mqttSettings.ca) {
logger.debug(`MQTT SSL/TLS: Path to CA certificate = ${mqttSettings.ca}`);
options.ca = fs.readFileSync(mqttSettings.ca);
}
if (mqttSettings.key && mqttSettings.cert) {
logger.debug(`MQTT SSL/TLS: Path to client key = ${mqttSettings.key}`);
logger.debug(`MQTT SSL/TLS: Path to client certificate = ${mqttSettings.cert}`);
options.key = fs.readFileSync(mqttSettings.key);
options.cert = fs.readFileSync(mqttSettings.cert);
}
if (mqttSettings.user && mqttSettings.password) {
logger.debug(`Using MQTT login with username: ${mqttSettings.user}`);
options.username = mqttSettings.user;
options.password = mqttSettings.password;
} else {
logger.debug(`Using MQTT anonymous login`);
}
if (mqttSettings.client_id) {
logger.debug(`Using MQTT client ID: '${mqttSettings.client_id}'`);
options.clientId = mqttSettings.client_id;
}
if (mqttSettings.hasOwnProperty('reject_unauthorized') && !mqttSettings.reject_unauthorized) {
logger.debug(`MQTT reject_unauthorized set false, ignoring certificate warnings.`);
options.rejectUnauthorized = false;
}
// Set timer at interval to check if connected to MQTT server.
const interval = 10 * 1000; // seconds * 1000.
this.connectionTimer = setInterval(() => {
if (this.client.reconnecting) {
logger.error('Not connected to MQTT server!');
}
}, interval);
return new Promise((resolve) => {
this.client = mqtt.connect(mqttSettings.server, options);
const self = this;
this.client.on('connect', () => {
logger.info('Connected to MQTT server');
self.subscribe(`${settings.get().mqtt.base_topic}/#`);
self.publish('bridge/state', 'online', {retain: true, qos: 0});
resolve();
});
this.client.on('message', this.onMessage);
});
}
async disconnect() {
clearTimeout(this.connectionTimer);
this.connectionTimer = null;
await this.publish('bridge/state', 'offline', {retain: true, qos: 0});
logger.info('Disconnecting from MQTT server');
this.client.end();
}
subscribe(topic) {
this.client.subscribe(topic);
}
onMessage(topic, message) {
// Since we subscribe to zigbee2mqtt/# we also receive the message we send ourselves, skip these.
if (!this.publishedTopics.has(topic)) {
this.emit('message', {topic, message: message + ''});
}
}
isConnected() {
return this.client && !this.client.reconnecting;
}
async publish(topic, payload, options, base=settings.get().mqtt.base_topic, skipLog=false, skipReceive=true) {
topic = `${base}/${topic}`;
options = {qos: 0, retain: false, ...options};
if (skipReceive) {
this.publishedTopics.add(topic);
}
if (!this.isConnected()) {
if (!skipLog) {
logger.error(`Not connected to MQTT server!`);
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
}
return;
}
if (!skipLog) {
logger.info(`MQTT publish: topic '${topic}', payload '${payload}'`);
}
const actualOptions = {...options};
if (settings.get().mqtt.force_disable_retain) {
actualOptions.retain = false;
}
return new Promise((resolve) => {
this.client.publish(topic, payload, actualOptions, () => {
this.emit('publishedMessage', {topic, payload, options});
resolve();
});
});
}
}
module.exports = MQTT;
+196
View File
@@ -0,0 +1,196 @@
import * as mqtt from 'mqtt';
import logger from './util/logger';
import * as settings from './util/settings';
import utils from './util/utils';
import fs from 'fs';
import bind from 'bind-decorator';
import type {QoS} from 'mqtt-packet';
export default class MQTT {
private publishedTopics: Set<string> = new Set();
private connectionTimer: NodeJS.Timeout;
private client: mqtt.MqttClient;
private eventBus: EventBus;
private initialConnect = true;
private republishRetainedTimer: NodeJS.Timeout;
private retainedMessages: {[s: string]: {payload: string, options: MQTTOptions,
skipLog: boolean, skipReceive: boolean, topic: string, base: string}} = {};
constructor(eventBus: EventBus) {
this.eventBus = eventBus;
}
async connect(): Promise<void> {
const mqttSettings = settings.get().mqtt;
logger.info(`Connecting to MQTT server at ${mqttSettings.server}`);
const options: mqtt.IClientOptions = {
will: {
topic: `${settings.get().mqtt.base_topic}/bridge/state`,
payload: Buffer.from(utils.availabilityPayload('offline', settings.get())),
retain: settings.get().mqtt.force_disable_retain ? false : true,
qos: 1,
},
};
if (mqttSettings.version) {
options.protocolVersion = mqttSettings.version;
}
if (mqttSettings.keepalive) {
logger.debug(`Using MQTT keepalive: ${mqttSettings.keepalive}`);
options.keepalive = mqttSettings.keepalive;
}
if (mqttSettings.ca) {
logger.debug(`MQTT SSL/TLS: Path to CA certificate = ${mqttSettings.ca}`);
options.ca = fs.readFileSync(mqttSettings.ca);
}
if (mqttSettings.key && mqttSettings.cert) {
logger.debug(`MQTT SSL/TLS: Path to client key = ${mqttSettings.key}`);
logger.debug(`MQTT SSL/TLS: Path to client certificate = ${mqttSettings.cert}`);
options.key = fs.readFileSync(mqttSettings.key);
options.cert = fs.readFileSync(mqttSettings.cert);
}
if (mqttSettings.user && mqttSettings.password) {
logger.debug(`Using MQTT login with username: ${mqttSettings.user}`);
options.username = mqttSettings.user;
options.password = mqttSettings.password;
} else {
logger.debug(`Using MQTT anonymous login`);
}
if (mqttSettings.client_id) {
logger.debug(`Using MQTT client ID: '${mqttSettings.client_id}'`);
options.clientId = mqttSettings.client_id;
}
if (mqttSettings.hasOwnProperty('reject_unauthorized') && !mqttSettings.reject_unauthorized) {
logger.debug(`MQTT reject_unauthorized set false, ignoring certificate warnings.`);
options.rejectUnauthorized = false;
}
return new Promise((resolve, reject) => {
this.client = mqtt.connect(mqttSettings.server, options);
// @ts-ignore https://github.com/Koenkk/zigbee2mqtt/issues/9822
this.client.stream.setMaxListeners(0);
this.eventBus.onPublishAvailability(this, () => this.publishStateOnline());
const onConnect = this.onConnect;
this.client.on('connect', async () => {
await onConnect();
resolve();
});
this.client.on('error', (err) => {
logger.error(`MQTT error: ${err.message}`);
reject(err);
});
this.client.on('message', this.onMessage);
});
}
@bind private async onConnect(): Promise<void> {
// Set timer at interval to check if connected to MQTT server.
clearTimeout(this.connectionTimer);
this.connectionTimer = setInterval(() => {
if (this.client.reconnecting) {
logger.error('Not connected to MQTT server!');
}
}, utils.seconds(10));
logger.info('Connected to MQTT server');
await this.publishStateOnline();
if (!this.initialConnect) {
this.republishRetainedTimer = setTimeout(() => {
// Republish retained messages in case MQTT broker does not persist them.
// https://github.com/Koenkk/zigbee2mqtt/issues/9629
Object.values(this.retainedMessages).forEach((e) =>
this.publish(e.topic, e.payload, e.options, e.base, e.skipLog, e.skipReceive));
}, 2000);
}
this.initialConnect = false;
this.subscribe(`${settings.get().mqtt.base_topic}/#`);
}
async publishStateOnline(): Promise<void> {
await this.publish('bridge/state', utils.availabilityPayload('online', settings.get()), {retain: true, qos: 0});
}
async disconnect(): Promise<void> {
clearTimeout(this.connectionTimer);
await this.publish('bridge/state', utils.availabilityPayload('offline', settings.get()),
{retain: true, qos: 0});
this.eventBus.removeListeners(this);
logger.info('Disconnecting from MQTT server');
this.client.end();
}
subscribe(topic: string): void {
this.client.subscribe(topic);
}
@bind public onMessage(topic: string, message: Buffer): void {
// Since we subscribe to zigbee2mqtt/# we also receive the message we send ourselves, skip these.
if (!this.publishedTopics.has(topic)) {
logger.debug(`Received MQTT message on '${topic}' with data '${message.toString()}'`);
this.eventBus.emitMQTTMessage({topic, message: message.toString()});
}
if (this.republishRetainedTimer && topic === `${settings.get().mqtt.base_topic}/bridge/info`) {
clearTimeout(this.republishRetainedTimer);
this.republishRetainedTimer = null;
}
}
isConnected(): boolean {
return this.client && !this.client.reconnecting;
}
async publish(topic: string, payload: string, options: MQTTOptions={},
base=settings.get().mqtt.base_topic, skipLog=false, skipReceive=true,
): Promise<void> {
const defaultOptions: {qos: QoS, retain: boolean} = {qos: 0, retain: false};
topic = `${base}/${topic}`;
if (skipReceive) {
this.publishedTopics.add(topic);
}
if (options.retain) {
if (payload) {
this.retainedMessages[topic] =
{payload, options, skipReceive, skipLog, topic: topic.substring(base.length + 1), base};
} else {
delete this.retainedMessages[topic];
}
}
this.eventBus.emitMQTTMessagePublished({topic, payload, options: {...defaultOptions, ...options}});
if (!this.isConnected()) {
if (!skipLog) {
logger.error(`Not connected to MQTT server!`);
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
}
return;
}
if (!skipLog) {
logger.info(`MQTT publish: topic '${topic}', payload '${payload}'`);
}
const actualOptions: mqtt.IClientPublishOptions = {...defaultOptions, ...options};
if (settings.get().mqtt.force_disable_retain) {
actualOptions.retain = false;
}
return new Promise((resolve) => {
this.client.publish(topic, payload, actualOptions, () => resolve());
});
}
}
-122
View File
@@ -1,122 +0,0 @@
const logger = require('./util/logger');
const data = require('./util/data');
const settings = require('./util/settings');
const fs = require('fs');
const objectAssignDeep = require('object-assign-deep');
const saveInterval = 1000 * 60 * 5; // 5 minutes
const dontCacheProperties = [
'action', 'action_.*', 'button', 'button_left', 'button_right', 'click', 'forgotten', 'keyerror',
'step_size', 'transition_time', 'group_list', 'group_capacity', 'no_occupancy_since',
'step_mode', 'transition_time', 'duration', 'elapsed', 'from_side', 'to_side',
];
class State {
constructor(eventBus) {
this.state = {};
this.file = data.joinPath('state.json');
this.timer = null;
this.eventBus = eventBus;
}
start() {
this._load();
// Save the state on every interval
this.clearTimer();
this.timer = setInterval(() => this.save(), saveInterval);
}
clearTimer() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
stop() {
this.clearTimer();
this.save();
}
_load() {
if (fs.existsSync(this.file)) {
try {
this.state = JSON.parse(fs.readFileSync(this.file, 'utf8'));
logger.debug(`Loaded state from file ${this.file}`);
} catch (e) {
logger.debug(`Failed to load state from file ${this.file} (corrupt file?)`);
}
} else {
logger.debug(`Can't load state from file ${this.file} (doesn't exist)`);
}
}
save() {
if (settings.get().advanced.cache_state_persistent) {
logger.debug(`Saving state to file ${this.file}`);
const json = JSON.stringify(this.state, null, 4);
try {
fs.writeFileSync(this.file, json, 'utf8');
} catch (e) {
logger.error(`Failed to write state to '${this.file}' (${e.message})`);
}
} else {
logger.debug(`Not saving state`);
}
}
exists(ID) {
return this.state.hasOwnProperty(ID);
}
get(ID) {
return this.state[ID];
}
set(ID, state, reason=null) {
const toState = objectAssignDeep.noMutate(state);
const fromState = this.state[ID];
const changed = {};
for (const property of Object.keys(toState)) {
if (dontCacheProperties.find((p) => property.match(p))) {
delete toState[property];
}
if (!fromState || toState[property] !== fromState[property]) {
changed[property] = toState[property];
}
}
this.state[ID] = toState;
this.eventBus.emit('stateChange', {ID, from: fromState, to: state, reason, changed});
}
removeKey(ID, path) {
if (this.exists(ID)) {
let state = this.state[ID];
for (let i = 0; i < path.length; i++) {
const key = path[i];
if (i === path.length - 1) {
delete state[key];
} else {
if (state[key]) {
state = state[key];
} else {
break;
}
}
}
}
}
remove(ID) {
if (this.exists(ID)) {
delete this.state[ID];
}
}
}
module.exports = State;
+96
View File
@@ -0,0 +1,96 @@
import logger from './util/logger';
import data from './util/data';
import * as settings from './util/settings';
import utils from './util/utils';
import fs from 'fs';
import objectAssignDeep from 'object-assign-deep';
const saveInterval = 1000 * 60 * 5; // 5 minutes
const dontCacheProperties = [
'action', 'action_.*', 'button', 'button_left', 'button_right', 'click', 'forgotten', 'keyerror',
'step_size', 'transition_time', 'group_list', 'group_capacity', 'no_occupancy_since',
'step_mode', 'transition_time', 'duration', 'elapsed', 'from_side', 'to_side',
];
class State {
private state: {[s: string | number]: KeyValue} = {};
private file = data.joinPath('state.json');
private timer: NodeJS.Timeout = null;
constructor(private readonly eventBus: EventBus, private readonly zigbee: Zigbee) {
this.eventBus = eventBus;
this.zigbee = zigbee;
}
start(): void {
this.load();
// Save the state on every interval
this.timer = setInterval(() => this.save(), saveInterval);
}
stop(): void {
// Remove any invalid states (ie when the device has left the network) when the system is stopped
Object.keys(this.state)
.filter((k) => typeof k === 'string' && !this.zigbee.resolveEntity(k)) // string key = ieeeAddr
.forEach((k) => delete this.state[k]);
clearTimeout(this.timer);
this.save();
}
private load(): void {
if (fs.existsSync(this.file)) {
try {
this.state = JSON.parse(fs.readFileSync(this.file, 'utf8'));
logger.debug(`Loaded state from file ${this.file}`);
} catch (e) {
logger.debug(`Failed to load state from file ${this.file} (corrupt file?)`);
}
} else {
logger.debug(`Can't load state from file ${this.file} (doesn't exist)`);
}
}
private save(): void {
if (settings.get().advanced.cache_state_persistent) {
logger.debug(`Saving state to file ${this.file}`);
const json = JSON.stringify(this.state, null, 4);
try {
fs.writeFileSync(this.file, json, 'utf8');
} catch (e) {
logger.error(`Failed to write state to '${this.file}' (${e.message})`);
}
} else {
logger.debug(`Not saving state`);
}
}
exists(entity: Device | Group): boolean {
return this.state.hasOwnProperty(entity.ID);
}
get(entity: Group | Device): KeyValue {
return this.state[entity.ID] || {};
}
set(entity: Group | Device, update: KeyValue, reason: string=null): KeyValue {
const fromState = this.state[entity.ID] || {};
const toState = objectAssignDeep({}, fromState, update);
const newCache = {...toState};
const entityDontCacheProperties = entity.options.filtered_cache || [];
utils.filterProperties(dontCacheProperties.concat(entityDontCacheProperties), newCache);
this.state[entity.ID] = newCache;
this.eventBus.emitStateChange({entity, from: fromState, to: toState, reason, update});
return toState;
}
remove(ID: string | number): void {
delete this.state[ID];
}
}
export default State;
+3
View File
@@ -0,0 +1,3 @@
declare module 'json-stable-stringify-without-jsonify' {
export default function (obj: unknown): string;
}
+3
View File
@@ -0,0 +1,3 @@
declare module 'mkdir-recursive' {
export function mkdirSync(path: string): void;
}
+319
View File
@@ -0,0 +1,319 @@
/* eslint-disable camelcase */
import type {
Device as ZHDevice,
Group as ZHGroup,
Endpoint as ZHEndpoint,
} from 'zigbee-herdsman/dist/controller/model';
import type {
NetworkParameters as ZHNetworkParameters,
CoordinatorVersion as ZHCoordinatorVersion,
LQI as ZHLQI,
RoutingTable as ZHRoutingTable,
RoutingTableEntry as ZHRoutingTableEntry,
} from 'zigbee-herdsman/dist/adapter/tstype';
import type {
Cluster as ZHCluster,
} from 'zigbee-herdsman/dist/zcl/tstype';
import type {
FrameControl as ZHFrameControl,
} from 'zigbee-herdsman/dist/zcl';
import type * as ZHEvents from 'zigbee-herdsman/dist/controller/events';
import type TypeEventBus from 'lib/eventBus';
import type TypeMQTT from 'lib/mqtt';
import type TypeState from 'lib/state';
import type TypeZigbee from 'lib/zigbee';
import type TypeDevice from 'lib/model/device';
import type TypeGroup from 'lib/model/group';
import type TypeExtension from 'lib/extension/extension';
import type {QoS} from 'mqtt-packet';
declare global {
// Define some class types as global
type EventBus = TypeEventBus;
type MQTT = TypeMQTT;
type Zigbee = TypeZigbee;
type Group = TypeGroup;
type Device = TypeDevice;
type State = TypeState;
type Extension = TypeExtension;
// Types
interface MQTTResponse {data: KeyValue, status: 'error' | 'ok', error?: string, transaction?: string}
interface MQTTOptions {qos?: QoS, retain?: boolean, properties?: {messageExpiryInterval: number}}
type StateChangeReason = 'publishDebounce' | 'groupOptimistic' | 'lastSeenChanged' | 'publishCached';
type PublishEntityState = (entity: Device | Group, payload: KeyValue,
stateChangeReason?: StateChangeReason) => Promise<void>;
type RecursivePartial<T> = {[P in keyof T]?: RecursivePartial<T[P]>;};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface KeyValue {[s: string]: any}
// zigbee-herdsman
namespace zh {
type Endpoint = ZHEndpoint;
type Device = ZHDevice;
type Group = ZHGroup;
type LQI = ZHLQI;
type RoutingTable = ZHRoutingTable;
type RoutingTableEntry = ZHRoutingTableEntry;
type CoordinatorVersion = ZHCoordinatorVersion;
type NetworkParameters = ZHNetworkParameters;
type Cluster = ZHCluster;
interface Bind {
cluster: zh.Cluster;
target: zh.Endpoint | zh.Group;
}
}
// zigbee-herdsman-converters
namespace zhc {
interface Logger {
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
debug: (message: string) => void;
}
interface ToZigbeeConverterGetMeta {message?: KeyValue, mapped?: Definition | Definition[]}
interface ToZigbeeConverterResult {state: KeyValue,
membersState: {[s: string]: KeyValue}, readAfterWriteTime?: number}
interface ToZigbeeConverter {
key: string[],
convertGet?: (entity: zh.Endpoint | zh.Group, key: string, meta: ToZigbeeConverterGetMeta) => Promise<void>
convertSet?: (entity: zh.Endpoint | zh.Group, key: string, value: KeyValue | string | number,
meta: {state: KeyValue}) => Promise<ToZigbeeConverterResult>
}
interface FromZigbeeConverter {
cluster: string,
type: string[] | string,
convert: (model: Definition, msg: KeyValue, publish: (payload: KeyValue) => void, options: KeyValue,
meta: {state: KeyValue, logger: Logger, device: zh.Device}) => Promise<KeyValue>,
}
interface DefinitionExposeFeature {name: string, label: string, endpoint?: string,
property: string, value_max?: number, value_min?: number, unit?: string,
value_off?: string, value_on?: string, value_step?: number, values: string[], access: number}
interface DefinitionExpose {
type: string, name?: string, label?: string, features?: DefinitionExposeFeature[],
endpoint?: string, values?: string[], value_off?: string, value_on?: string, value_step?: number,
access: number, property: string, unit?: string,
value_min?: number, value_max?: number}
interface OtaUpdateAvailableResult {available: boolean, currentFileVersion: number, otaFileVersion: number}
interface Definition {
model: string,
zigbeeModel: string[],
endpoint?: (device: zh.Device) => {[s: string]: number}
toZigbee: ToZigbeeConverter[]
fromZigbee: FromZigbeeConverter[]
icon?: string
description: string
options: zhc.DefinitionExpose[],
vendor: string
exposes: DefinitionExpose[] | ((device: zh.Device, options: KeyValue) => DefinitionExpose[])
configure?: (device: zh.Device, coordinatorEndpoint: zh.Endpoint, logger: Logger,
options?: DeviceOptions) => Promise<void>;
onEvent?: (type: string, data: KeyValue, device: zh.Device,
settings: KeyValue, state: KeyValue) => Promise<void>;
ota?: {
isUpdateAvailable: (device: zh.Device, logger: Logger, data?: KeyValue)
=> Promise<OtaUpdateAvailableResult>;
updateToLatest: (device: zh.Device, logger: Logger,
onProgress: (progress: number, remaining: number) => void) => Promise<number>;
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ExternalDefinition = Definition & {homeassistant: any};
}
namespace eventdata {
type EntityRenamed = { entity: Device | Group, homeAssisantRename: boolean, from: string, to: string };
type DeviceRemoved = { ieeeAddr: string, name: string };
type MQTTMessage = { topic: string, message: string };
type MQTTMessagePublished = { topic: string, payload: string, options: {retain: boolean, qos: number} };
type StateChange = {
entity: Device | Group, from: KeyValue, to: KeyValue, reason: string | null, update: KeyValue };
type PermitJoinChanged = ZHEvents.PermitJoinChangedPayload;
type LastSeenChanged = { device: Device,
reason: 'deviceAnnounce' | 'networkAddress' | 'deviceJoined' | 'messageEmitted' | 'messageNonEmitted'; };
type DeviceNetworkAddressChanged = { device: Device };
type DeviceAnnounce = { device: Device };
type DeviceInterview = { device: Device, status: 'started' | 'successful' | 'failed' };
type DeviceJoined = { device: Device };
type EntityOptionsChanged = { entity: Device | Group, from: KeyValue, to: KeyValue };
type Reconfigure = { device: Device };
type DeviceLeave = { ieeeAddr: string, name: string };
type GroupMembersChanged = {group: Group, action: 'remove' | 'add' | 'remove_all',
endpoint: zh.Endpoint, skipDisableReporting: boolean };
type PublishEntityState = {entity: Group | Device, message: KeyValue, stateChangeReason: StateChangeReason,
payload: KeyValue};
type DeviceMessage = {
type: ZHEvents.MessagePayloadType;
device: Device;
endpoint: zh.Endpoint;
linkquality: number;
groupID: number;
cluster: string | number;
data: KeyValue | Array<string | number>;
meta: {zclTransactionSequenceNumber?: number; manufacturerCode?: number; frameControl?: ZHFrameControl;};
};
}
// Settings
// eslint-disable camelcase
interface Settings {
homeassistant?: {
discovery_topic: string,
status_topic: string,
legacy_entity_attributes: boolean,
legacy_triggers: boolean,
},
permit_join?: boolean,
availability?: {
active: {timeout: number},
passive: {timeout: number}
},
external_converters: string[],
mqtt: {
base_topic: string,
include_device_information: boolean,
force_disable_retain: boolean
version?: 3 | 4 | 5,
user?: string,
password?: string,
server: string,
ca?: string,
keepalive?: number,
key?: string,
cert?: string,
client_id?: string,
reject_unauthorized?: boolean,
},
serial: {
disable_led: boolean,
port?: string,
adapter?: 'deconz' | 'zstack' | 'ezsp' | 'zigate',
baudrate?: number,
rtscts?: boolean,
},
passlist: string[],
blocklist: string[],
map_options: {
graphviz: {
colors: {
fill: {
enddevice: string,
coordinator: string,
router: string,
},
font: {
coordinator: string,
router: string,
enddevice: string,
},
line: {
active: string,
inactive: string,
},
},
},
},
ota: {
update_check_interval: number,
disable_automatic_update_check: boolean,
zigbee_ota_override_index_location?: string,
ikea_ota_use_test_url?: boolean,
},
frontend?: {
auth_token?: string,
host?: string,
port?: number,
url?: string,
ssl_cert?: string,
ssl_key?: string,
},
devices?: {[s: string]: DeviceOptions},
groups?: {[s: string]: GroupOptions},
device_options: KeyValue,
advanced: {
legacy_api: boolean,
legacy_availability_payload: boolean,
log_rotation: boolean,
log_symlink_current: boolean,
log_output: ('console' | 'file' | 'syslog')[],
log_directory: string,
log_file: string,
log_level: 'debug' | 'info' | 'error' | 'warn',
log_syslog: KeyValue,
pan_id: number | 'GENERATE',
ext_pan_id: number[] | 'GENERATE',
channel: number,
adapter_concurrent: number | null,
adapter_delay: number | null,
cache_state: boolean,
cache_state_persistent: boolean,
cache_state_send_on_startup: boolean,
last_seen: 'disable' | 'ISO_8601' | 'ISO_8601_local' | 'epoch',
elapsed: boolean,
network_key: number[] | 'GENERATE',
timestamp_format: string,
output: 'json' | 'attribute' | 'attribute_and_json',
transmit_power?: number,
// Everything below is deprecated
availability_timeout?: number,
availability_blocklist?: string[],
availability_passlist?: string[],
availability_blacklist?: string[],
availability_whitelist?: string[],
soft_reset_timeout: number,
report: boolean,
},
}
interface DeviceOptions {
ID?: string,
disabled?: boolean,
retention?: number,
availability?: boolean | {timeout: number},
optimistic?: boolean,
retrieve_state?: boolean,
debounce?: number,
debounce_ignore?: string[],
filtered_attributes?: string[],
filtered_cache?: string[],
filtered_optimistic?: string[],
icon?: string,
homeassistant?: KeyValue,
legacy?: boolean,
friendly_name: string,
description?: string,
qos?: 0 | 1 | 2,
}
interface GroupOptions {
devices?: string[],
ID?: number,
optimistic?: boolean,
off_state?: 'all_members_off' | 'last_member_state'
filtered_attributes?: string[],
filtered_cache?: string[],
filtered_optimistic?: string[],
retrieve_state?: boolean,
homeassistant?: KeyValue,
friendly_name: string,
description?: string,
qos?: 0 | 1 | 2,
}
}
+9
View File
@@ -0,0 +1,9 @@
declare module 'zigbee-herdsman-converters' {
export function findByDevice(device: zh.Device): zhc.Definition;
export function getConfigureKey(definition: zhc.Definition): string | number;
export const toZigbeeConverters: {[s: string]: zhc.ToZigbeeConverter};
export const definitions: zhc.Definition[];
export function addDeviceDefinition(definition: zhc.Definition): Promise<void>;
export function onEvent(type: string, data: KeyValue, device: zh.Device, settings: KeyValue,
state: KeyValue): Promise<void>;
}
+9
View File
@@ -0,0 +1,9 @@
declare module 'zigbee2mqtt-frontend' {
export function getPath(): string;
}
declare module 'connect-gzip-static' {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type RequestHandler = (req: any, res: any) => void;
export default function gzipStatic(root: string, options?: Record<string, unknown>): RequestHandler;
}
-22
View File
@@ -1,22 +0,0 @@
const path = require('path');
let dataPath = null;
function load() {
if (process.env.ZIGBEE2MQTT_DATA) {
dataPath = process.env.ZIGBEE2MQTT_DATA;
} else {
dataPath = path.join(__dirname, '..', '..', 'data');
dataPath = path.normalize(dataPath);
}
}
load();
module.exports = {
joinPath: (file) => path.join(dataPath, file),
getPath: () => dataPath,
// For test only.
_reload: () => load(),
};
+29
View File
@@ -0,0 +1,29 @@
import path from 'path';
let dataPath: string = null;
function load(): void {
if (process.env.ZIGBEE2MQTT_DATA) {
dataPath = process.env.ZIGBEE2MQTT_DATA;
} else {
dataPath = path.join(__dirname, '..', '..', 'data');
dataPath = path.normalize(dataPath);
}
}
load();
function joinPath(file: string): string {
return path.resolve(dataPath, file);
}
function getPath(): string {
return dataPath;
}
// eslint-disable-next-line camelcase
function testingOnlyReload(): void {
load();
}
export default {joinPath, getPath, testingOnlyReload};
-152
View File
@@ -1,152 +0,0 @@
const winston = require('winston');
const moment = require('moment');
const settings = require('./settings');
const path = require('path');
const fs = require('fs');
const fx = require('mkdir-recursive');
const rimraf = require('rimraf');
const colorizer = winston.format.colorize();
const assert = require('assert');
// What transports to enable
const output = settings.get().advanced.log_output;
// Directory to log to
const timestamp = moment(Date.now()).format('YYYY-MM-DD.HH-mm-ss');
const directory = settings.get().advanced.log_directory.replace('%TIMESTAMP%', timestamp);
const logFilename = settings.get().advanced.log_file.replace('%TIMESTAMP%', timestamp);
// Make sure that log directoy exsists when not logging to stdout only
if (output.includes('file')) {
fx.mkdirSync(directory);
}
const z2mToWinstonLevel = (level) => level === 'warn' ? 'warning' : level;
const winstonToZ2mLevel = (level) => level === 'warning' ? 'warn' : level;
// Determine the log level.
let level = settings.get().advanced.log_level;
const validLevels = ['info', 'error', 'warn', 'debug'];
assert(validLevels.includes(level), `'${level}' is not a valid log_level, use one of '${validLevels.join(', ')}'`);
level = z2mToWinstonLevel(level);
const levelWithCompensatedLength = {
'info': 'info ',
'error': 'error',
'warn': 'warn ',
'debug': 'debug',
};
/* istanbul ignore next */
const timestampFormat = () => moment().format(settings.get().advanced.timestamp_format);
// Setup default console logger
const transportsToUse = [
new winston.transports.Console({
level,
silent: !output.includes('console'),
format: winston.format.combine(
winston.format.timestamp({format: timestampFormat}),
winston.format.printf(/* istanbul ignore next */(info) => {
let {timestamp, level, message} = info;
level = winstonToZ2mLevel(level);
const prefix = colorizer.colorize(level, `Zigbee2MQTT:${levelWithCompensatedLength[level]}`);
return `${prefix} ${timestamp.split('.')[0]}: ${message}`;
}),
),
}),
];
// Add file logger when enabled
// NOTE: the initiation of the logger, even when not added as transport tries to create the logging directory
const transportFileOptions = {
filename: path.join(directory, logFilename),
json: false,
level,
format: winston.format.combine(
winston.format.timestamp({format: timestampFormat}),
winston.format.printf(/* istanbul ignore next */(info) => {
let {timestamp, level, message} = info;
level = winstonToZ2mLevel(level);
return `${levelWithCompensatedLength[level]} ${timestamp.split('.')[0]}: ${message}`;
}),
),
};
if (settings.get().advanced.log_rotation) {
transportFileOptions.tailable = true;
transportFileOptions.maxFiles = 3; // Keep last 3 files
transportFileOptions.maxsize = 10000000; // 10MB
}
if (output.includes('file')) {
transportsToUse.push(new winston.transports.File(transportFileOptions));
}
/* istanbul ignore next */
if (output.includes('syslog')) {
require('winston-syslog').Syslog;
const options = {
app_name: 'Zigbee2MQTT',
format: winston.format.printf(/* istanbul ignore next */(info) => {
return `${info.message}`;
}),
...settings.get().advanced.log_syslog,
};
if (options.hasOwnProperty('type')) options.type = options.type.toString();
transportsToUse.push(new winston.transports.Syslog(options));
}
// Create logger
const logger = winston.createLogger({transports: transportsToUse, levels: winston.config.syslog.levels});
// Cleanup any old log directory.
function cleanup() {
if (settings.get().advanced.log_directory.includes('%TIMESTAMP%')) {
const rootDirectory = path.join(directory, '..');
let directories = fs.readdirSync(rootDirectory).map((d) => {
d = path.join(rootDirectory, d);
return {path: d, birth: fs.statSync(d).mtime};
});
directories.sort((a, b) => b.birth - a.birth);
directories = directories.slice(10, directories.length);
directories.forEach((dir) => {
logger.debug(`Removing old log directory '${dir.path}'`);
rimraf.sync(dir.path);
});
}
}
// Print to user what logging is enabled
function logOutput() {
if (output.includes('file')) {
if (output.includes('console')) {
logger.info(`Logging to console and directory: '${directory}' filename: ${logFilename}`);
} else {
logger.info(`Logging to directory: '${directory}' filename: ${logFilename}`);
}
logger.cleanup();
} else if (output.includes('console')) {
logger.info(`Logging to console only'`);
}
}
logger.addTransport = (transport) => {
transport.level = transportsToUse[0].level;
logger.add(transport);
};
logger.cleanup = cleanup;
logger.logOutput = logOutput;
logger.getLevel = () => winstonToZ2mLevel(transportsToUse[0].level);
logger.setLevel = (level) => {
level = z2mToWinstonLevel(level);
logger.transports.forEach((transport) => transport.level = level);
};
// winston.config.syslog.levels doesnt have warn, but is required for syslog.
/* istanbul ignore next */
logger.warn = (message) => logger.warning(message);
module.exports = logger;
+225
View File
@@ -0,0 +1,225 @@
import winston from 'winston';
import moment from 'moment';
import * as settings from './settings';
import path from 'path';
import fs from 'fs';
import fx from 'mkdir-recursive';
import {rimrafSync} from 'rimraf';
import assert from 'assert';
const colorizer = winston.format.colorize();
type Z2MLogLevel = 'warn' | 'debug' | 'info' | 'error';
type WinstonLogLevel = 'warning' | 'debug' | 'info' | 'error';
const z2mToWinstonLevel = (level: Z2MLogLevel): WinstonLogLevel => level === 'warn' ? 'warning' : level;
const winstonToZ2mLevel = (level: WinstonLogLevel): Z2MLogLevel => level === 'warning' ? 'warn' : level;
const levelWithCompensatedLength: {[s: string]: string} = {
'info': 'info ',
'error': 'error',
'warn': 'warn ',
'debug': 'debug',
};
let logger: winston.Logger;
let fileTransport : winston.transport;
let output: string[];
let directory: string;
let logFilename: string;
let transportsToUse: winston.transport[];
function init(): void {
// What transports to enable
output = settings.get().advanced.log_output;
// Directory to log to
const timestamp = moment(Date.now()).format('YYYY-MM-DD.HH-mm-ss');
directory = settings.get().advanced.log_directory.replace('%TIMESTAMP%', timestamp);
logFilename = settings.get().advanced.log_file.replace('%TIMESTAMP%', timestamp);
// Make sure that log directory exists when not logging to stdout only
if (output.includes('file')) {
fx.mkdirSync(directory);
if (settings.get().advanced.log_symlink_current) {
const current = settings.get().advanced.log_directory.replace('%TIMESTAMP%', 'current');
const actual = './' + timestamp;
/* istanbul ignore next */
if (fs.existsSync(current)) {
fs.unlinkSync(current);
}
fs.symlinkSync(actual, current);
}
}
// Determine the log level.
const z2mLevel = settings.get().advanced.log_level;
const validLevels = ['info', 'error', 'warn', 'debug'];
assert(validLevels.includes(z2mLevel),
`'${z2mLevel}' is not valid log_level, use one of '${validLevels.join(', ')}'`);
const level = z2mToWinstonLevel(z2mLevel);
const timestampFormat = (): string => moment().format(settings.get().advanced.timestamp_format);
// Setup default console logger
transportsToUse = [
new winston.transports.Console({
level,
silent: !output.includes('console'),
format: winston.format.combine(
winston.format.timestamp({format: timestampFormat}),
winston.format.printf(/* istanbul ignore next */(info) => {
const {timestamp, level, message} = info;
const l = winstonToZ2mLevel(level as WinstonLogLevel);
const plainPrefix = `Zigbee2MQTT:${levelWithCompensatedLength[l]}`;
let prefix = plainPrefix;
if (process.stdout.isTTY) {
prefix = colorizer.colorize(l, plainPrefix);
}
return `${prefix} ${timestamp.split('.')[0]}: ${message}`;
}),
),
}),
];
// Add file logger when enabled
// NOTE: the initiation of the logger, even when not added as transport tries to create the logging directory
const transportFileOptions: KeyValue = {
filename: path.join(directory, logFilename),
json: false,
level,
format: winston.format.combine(
winston.format.timestamp({format: timestampFormat}),
winston.format.printf(/* istanbul ignore next */(info) => {
const {timestamp, level, message} = info;
const l = winstonToZ2mLevel(level as WinstonLogLevel);
return `${levelWithCompensatedLength[l]} ${timestamp.split('.')[0]}: ${message}`;
}),
),
};
if (settings.get().advanced.log_rotation) {
transportFileOptions.tailable = true;
transportFileOptions.maxFiles = 3; // Keep last 3 files
transportFileOptions.maxsize = 10000000; // 10MB
}
if (output.includes('file')) {
fileTransport = new winston.transports.File(transportFileOptions);
transportsToUse.push(fileTransport);
}
/* istanbul ignore next */
if (output.includes('syslog')) {
// eslint-disable-next-line
require('winston-syslog').Syslog;
const options: KeyValue = {
app_name: 'Zigbee2MQTT',
format: winston.format.printf(/* istanbul ignore next */(info) => {
return `${info.message}`;
}),
...settings.get().advanced.log_syslog,
};
if (options.hasOwnProperty('type')) options.type = options.type.toString();
// @ts-ignore
transportsToUse.push(new winston.transports.Syslog(options));
}
logger = winston.createLogger({transports: transportsToUse, levels: winston.config.syslog.levels});
}
// Cleanup any old log directory.
function cleanup(): void {
if (settings.get().advanced.log_directory.includes('%TIMESTAMP%')) {
const rootDirectory = path.join(directory, '..');
let directories = fs.readdirSync(rootDirectory).map((d) => {
d = path.join(rootDirectory, d);
return {path: d, birth: fs.statSync(d).mtime};
});
directories.sort((a: KeyValue, b: KeyValue) => b.birth - a.birth);
directories = directories.slice(10, directories.length);
directories.forEach((dir) => {
logger.debug(`Removing old log directory '${dir.path}'`);
rimrafSync(dir.path);
});
}
}
// Print to user what logging is enabled
function logOutput(): void {
if (output.includes('file')) {
if (output.includes('console')) {
logger.info(`Logging to console and directory: '${directory}' filename: ${logFilename}`);
} else {
logger.info(`Logging to directory: '${directory}' filename: ${logFilename}`);
}
cleanup();
} else if (output.includes('console')) {
logger.info(`Logging to console only'`);
}
}
function addTransport(transport: winston.transport): void {
transport.level = transportsToUse[0].level;
logger.add(transport);
}
function getLevel(): Z2MLogLevel {
return winstonToZ2mLevel(transportsToUse[0].level as WinstonLogLevel);
}
function setLevel(level: Z2MLogLevel): void {
logger.transports.forEach((transport) => transport.level = z2mToWinstonLevel(level as Z2MLogLevel));
}
function warn(message: string): void {
// winston.config.syslog.levels doesn't have warn, but is required for syslog.
logger.warning(message);
}
function warning(message: string): void {
logger.warning(message);
}
function info(message: string): void {
logger.info(message);
}
function debug(message: string): void {
logger.debug(message);
}
function error(message: string): void {
logger.error(message);
}
// Workaround for https://github.com/winstonjs/winston/issues/1629.
// https://github.com/Koenkk/zigbee2mqtt/pull/10905
/* istanbul ignore next */
async function end(): Promise<void> {
logger.end();
await new Promise<void>((resolve) => {
if (!fileTransport) {
process.nextTick(resolve);
} else {
// @ts-ignore
if (fileTransport._dest) {
// @ts-ignore
fileTransport._dest.on('finish', resolve);
} else {
// @ts-ignore
fileTransport.on('open', () => fileTransport._dest.on('finish', resolve));
}
}
});
}
export default {
init, logOutput, warn, warning, error, info, debug, setLevel, getLevel, cleanup, addTransport, end,
winston: (): winston.Logger => logger,
};
-700
View File
@@ -1,700 +0,0 @@
const data = require('./data');
const utils = require('./utils');
// DEPRECATED ZIGBEE2MQTT_CONFIG: https://github.com/Koenkk/zigbee2mqtt/issues/4697
const file = process.env.ZIGBEE2MQTT_CONFIG || data.joinPath('configuration.yaml');
const objectAssignDeep = require(`object-assign-deep`);
const path = require('path');
const yaml = require('./yaml');
const Ajv = require('ajv');
const schema = require('./settings.schema.json');
const ajvSetting = new Ajv({allErrors: true}).compile(schema);
const ajvRestartRequired = new Ajv({allErrors: true})
.addKeyword('requiresRestart', {validate: (v) => !v}).compile(schema);
const defaults = {
passlist: [],
blocklist: [],
// Deprecated: use block/passlist
whitelist: [],
ban: [],
permit_join: false,
mqtt: {
include_device_information: false,
/**
* Configurable force disable retain flag on mqtt publish.
* https://github.com/Koenkk/zigbee2mqtt/pull/4948
*/
force_disable_retain: false,
},
serial: {
disable_led: false,
},
device_options: {},
map_options: {
graphviz: {
colors: {
fill: {
enddevice: '#fff8ce',
coordinator: '#e04e5d',
router: '#4ea3e0',
},
font: {
coordinator: '#ffffff',
router: '#ffffff',
enddevice: '#000000',
},
line: {
active: '#009900',
inactive: '#994444',
},
},
},
},
experimental: {
// json or attribute or attribute_and_json
output: 'json',
},
advanced: {
legacy_api: true,
log_rotation: true,
log_output: ['console', 'file'],
log_directory: path.join(data.getPath(), 'log', '%TIMESTAMP%'),
log_file: 'log.txt',
log_level: /* istanbul ignore next */ process.env.DEBUG ? 'debug' : 'info',
log_syslog: {},
soft_reset_timeout: 0,
pan_id: 0x1a62,
ext_pan_id: [0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD],
channel: 11,
adapter_concurrent: null,
adapter_delay: null,
// Availability timeout in seconds, disabled by default.
availability_timeout: 0,
availability_blocklist: [],
availability_passlist: [],
// Deprecated, use block/passlist
availability_blacklist: [],
availability_whitelist: [],
/**
* 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
*
* Therefore Zigbee2MQTT BY DEFAULT caches all values and resend it with every message.
* advanced.cache_state in configuration.yaml allows to configure this.
* https://www.zigbee2mqtt.io/configuration/configuration.html
*/
cache_state: true,
cache_state_persistent: true,
cache_state_send_on_startup: true,
/**
* Add a last_seen attribute to mqtt messages, contains date/time of zigbee message arrival
* "ISO_8601": ISO 8601 format
* "ISO_8601_local": Local ISO 8601 format (instead of UTC-based)
* "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],
/**
* Enables reporting feature
*/
report: false,
/**
* Home Assistant discovery topic
*/
homeassistant_discovery_topic: 'homeassistant',
/**
* Home Assistant status topic
*/
homeassistant_status_topic: 'hass/status',
/**
* Home Assistant legacy triggers, when enabled:
* - Zigbee2mqt will send an empty 'action' or 'click' after one has been send
* - A 'sensor_action' and 'sensor_click' will be discoverd
*/
homeassistant_legacy_triggers: true,
/**
* Configurable timestampFormat
* https://github.com/Koenkk/zigbee2mqtt/commit/44db557a0c83f419d66755d14e460cd78bd6204e
*/
timestamp_format: 'YYYY-MM-DD HH:mm:ss',
},
ota: {
/**
* Minimal time delta in minutes between polling third party server for potential firmware updates
*/
update_check_interval: 24 * 60,
/**
* Completely disallow Zigbee devices to initiate a search for a potential firmware update.
* If set to true, only a user-initiated update search will be possible.
*/
disable_automatic_update_check: false,
},
external_converters: [],
};
let _settings;
let _settingsWithDefaults;
function write() {
const settings = get();
const toWrite = objectAssignDeep.noMutate(settings);
// Read settings to check if we have to split devices/groups into separate file.
const actual = yaml.read(file);
// In case the setting is defined in a separte file (e.g. !secret network_key) update it there.
for (const path of [
['mqtt', 'user'],
['mqtt', 'password'],
['advanced', 'network_key'],
['frontend', 'auth_token'],
]) {
if (actual[path[0]] && actual[path[0]][path[1]]) {
const match = /!(.*) (.*)/g.exec(actual[path[0]][path[1]]);
if (match) {
yaml.updateIfChanged(data.joinPath(`${match[1]}.yaml`), match[2], toWrite[path[0]][path[1]]);
toWrite[path[0]][path[1]] = actual[path[0]][path[1]];
}
}
}
// Write devices/groups to separate file if required.
const writeDevicesOrGroups = (type) => {
if (typeof actual[type] === 'string' || Array.isArray(actual[type])) {
const fileToWrite = Array.isArray(actual[type]) ? actual[type][0] : actual[type];
const content = objectAssignDeep.noMutate(settings[type]);
// If an array, only write to first file and only devices which are not in the other files.
if (Array.isArray(actual[type])) {
actual[type].filter((f, i) => i !== 0)
.map((f) => yaml.readIfExists(data.joinPath(f), {}))
.map((c) => Object.keys(c))
.forEach((k) => delete content[k]);
}
yaml.writeIfChanged(data.joinPath(fileToWrite), content);
toWrite[type] = actual[type];
}
};
writeDevicesOrGroups('devices');
writeDevicesOrGroups('groups');
yaml.writeIfChanged(file, toWrite);
_settings = read();
_settingsWithDefaults = objectAssignDeep.noMutate(defaults, get());
}
function validate() {
try {
get();
} catch (error) {
if (error.name === 'YAMLException') {
return [
`Your YAML file: '${error.file}' is invalid ` +
`(use https://jsonformatter.org/yaml-validator to find and fix the issue)`,
];
}
return [error.message];
}
if (!ajvSetting(_settings)) {
return ajvSetting.errors.map((v) => `${v.dataPath.substring(1)} ${v.message}`);
}
const errors = [];
if (_settings.advanced && _settings.advanced.network_key && typeof _settings.advanced.network_key === 'string' &&
_settings.advanced.network_key !== 'GENERATE') {
errors.push(`advanced.network_key: should be array or 'GENERATE' (is '${_settings.advanced.network_key}')`);
}
if (_settings.advanced && _settings.advanced.pan_id && typeof _settings.advanced.pan_id === 'string' &&
_settings.advanced.pan_id !== 'GENERATE') {
errors.push(`advanced.pan_id: should be number or 'GENERATE' (is '${_settings.advanced.pan_id}')`);
}
// Verify that all friendly names are unique
const names = [];
const check = (name) => {
if (names.includes(name)) errors.push(`Duplicate friendly_name '${name}' found`);
errors.push(...utils.validateFriendlyName(name));
names.push(name);
};
const settingsWithDefaults = getWithDefaults();
Object.values(settingsWithDefaults.devices).forEach((d) => check(d.friendly_name));
Object.values(settingsWithDefaults.groups).forEach((g) => check(g.friendly_name));
if (settingsWithDefaults.mqtt.version !== 5) {
for (const device of Object.values(settingsWithDefaults.devices)) {
if (device.retention) {
errors.push('MQTT retention requires protocol version 5');
}
}
}
const checkAvailabilityList = (list, type) => {
list.forEach((e) => {
if (!getEntity(e)) {
errors.push(`Non-existing entity '${e}' specified in '${type}'`);
}
});
};
checkAvailabilityList(settingsWithDefaults.advanced.availability_blacklist, 'availability_blacklist');
checkAvailabilityList(settingsWithDefaults.advanced.availability_whitelist, 'availability_whitelist');
checkAvailabilityList(settingsWithDefaults.advanced.availability_blocklist, 'availability_blocklist');
checkAvailabilityList(settingsWithDefaults.advanced.availability_passlist, 'availability_passlist');
return errors;
}
function read() {
const s = yaml.read(file);
// Read !secret MQTT username and password if set
const interpetValue = (value) => {
const re = /!(.*) (.*)/g;
const match = re.exec(value);
if (match) {
const file = data.joinPath(`${match[1]}.yaml`);
const key = match[2];
return yaml.read(file)[key];
} else {
return value;
}
};
if (s.mqtt && s.mqtt.user && s.mqtt.password) {
s.mqtt.user = interpetValue(s.mqtt.user);
s.mqtt.password = interpetValue(s.mqtt.password);
}
if (s.advanced && s.advanced.network_key) {
s.advanced.network_key = interpetValue(s.advanced.network_key);
}
if (s.frontend && s.frontend.auth_token) {
s.frontend.auth_token = interpetValue(s.frontend.auth_token);
}
// Read devices/groups configuration from separate file if specified.
const readDevicesOrGroups = (type) => {
if (typeof s[type] === 'string' || Array.isArray(s[type])) {
const files = Array.isArray(s[type]) ? s[type] : [s[type]];
s[type] = {};
for (const file of files) {
const content = yaml.readIfExists(data.joinPath(file), {});
s[type] = objectAssignDeep.noMutate(s[type], content);
}
}
};
readDevicesOrGroups('devices');
readDevicesOrGroups('groups');
return s;
}
function applyEnvironmentVariables(settings) {
const iterate = (obj, path) => {
Object.keys(obj).forEach((key) => {
if (key !== 'type') {
if (key !== 'properties') {
const type = (obj[key].type || 'object').toString();
const envPart = path.reduce((acc, val) => `${acc}${val}_`, '');
const envVariableName = (`ZIGBEE2MQTT_CONFIG_${envPart}${key}`).toUpperCase();
if (process.env[envVariableName]) {
const setting = path.reduce((acc, val, index) => {
acc[val] = acc[val] || {};
return acc[val];
}, settings);
if (type.indexOf('object') >= 0 || type.indexOf('array') >= 0) {
setting[key] = JSON.parse(process.env[envVariableName]);
} else if (type.indexOf('number') >= 0) {
setting[key] = process.env[envVariableName] * 1;
} else if (type.indexOf('boolean') >= 0) {
setting[key] = process.env[envVariableName].toLowerCase() === 'true';
} else {
/* istanbul ignore else */
if (type.indexOf('string') >= 0) {
setting[key] = process.env[envVariableName];
}
}
}
}
if (typeof obj[key] === 'object') {
const newPath = [...path];
if (key !== 'properties') {
newPath.push(key);
}
iterate(obj[key], newPath);
}
}
});
};
iterate(schema.properties, []);
}
function get() {
if (!_settings) {
_settings = read();
applyEnvironmentVariables(_settings);
}
return _settings;
}
function getWithDefaults() {
if (!_settingsWithDefaults) {
_settingsWithDefaults = objectAssignDeep.noMutate(defaults, get());
}
if (!_settingsWithDefaults.devices) {
_settingsWithDefaults.devices = {};
}
if (!_settingsWithDefaults.groups) {
_settingsWithDefaults.groups = {};
}
return _settingsWithDefaults;
}
function set(path, value) {
let settings = get();
for (let i = 0; i < path.length; i++) {
const key = path[i];
if (i === path.length - 1) {
settings[key] = value;
} else {
if (!settings[key]) {
settings[key] = {};
}
settings = settings[key];
}
}
write();
}
function apply(newSettings) {
ajvSetting(newSettings);
const errors = ajvSetting.errors && ajvSetting.errors.filter((e) => e.keyword !== 'required');
if (errors.length) {
const error = errors[0];
throw new Error(`${error.dataPath.substring(1)} ${error.message}`);
}
get(); // Ensure _settings is intialized.
_settings = objectAssignDeep.noMutate(_settings, newSettings);
write();
ajvRestartRequired(newSettings);
const restartRequired = ajvRestartRequired.errors &&
!!ajvRestartRequired.errors.find((e) => e.keyword === 'requiresRestart');
return restartRequired;
}
function getGroup(IDorName) {
const settings = getWithDefaults();
const byID = settings.groups[IDorName];
if (byID) {
return {optimistic: true, devices: [], ...byID, ID: Number(IDorName), friendlyName: byID.friendly_name};
}
for (const [ID, group] of Object.entries(settings.groups)) {
if (group.friendly_name === IDorName) {
return {optimistic: true, devices: [], ...group, ID: Number(ID), friendlyName: group.friendly_name};
}
}
return null;
}
function getGroups() {
const settings = getWithDefaults();
return Object.entries(settings.groups).map(([ID, group]) => {
return {optimistic: true, devices: [], ...group, ID: Number(ID), friendlyName: group.friendly_name};
});
}
function getGroupThrowIfNotExists(IDorName) {
const group = getGroup(IDorName);
if (!group) {
throw new Error(`Group '${IDorName}' does not exist`);
}
return group;
}
function getDevice(IDorName) {
const settings = getWithDefaults();
const byID = settings.devices[IDorName];
if (byID) {
return {...byID, ID: IDorName, friendlyName: byID.friendly_name};
}
for (const [ID, device] of Object.entries(settings.devices)) {
if (device.friendly_name === IDorName) {
return {...device, ID, friendlyName: device.friendly_name};
}
}
return null;
}
function getDeviceThrowIfNotExists(IDorName) {
const device = getDevice(IDorName);
if (!device) {
throw new Error(`Device '${IDorName}' does not exist`);
}
return device;
}
function getEntity(IDorName) {
const device = getDevice(IDorName);
if (device) {
return {...device, type: 'device'};
}
const group = getGroup(IDorName);
if (group) {
return {...group, type: 'group'};
}
return null;
}
function addDevice(ID) {
if (getDevice(ID)) {
throw new Error(`Device '${ID}' already exists`);
}
const settings = get();
if (!settings.devices) {
settings.devices = {};
}
settings.devices[ID] = {friendly_name: ID};
write();
return getDevice(ID);
}
// Legacy: can be removed after bridgeLegacy has been removed
function whitelistDevice(ID) {
const settings = get();
if (!settings.whitelist) {
settings.whitelist = [];
}
if (settings.whitelist.includes(ID)) {
throw new Error(`Device '${ID}' already whitelisted`);
}
settings.whitelist.push(ID);
write();
}
function blockDevice(ID) {
const settings = get();
if (!settings.blocklist) {
settings.blocklist = [];
}
settings.blocklist.push(ID);
write();
}
function banDevice(ID) {
const settings = get();
if (!settings.ban) {
settings.ban = [];
}
settings.ban.push(ID);
write();
}
function removeDevice(IDorName) {
const device = getDeviceThrowIfNotExists(IDorName);
const settings = get();
delete settings.devices[device.ID];
write();
}
function addGroup(name, ID=null) {
utils.validateFriendlyName(name, true);
if (getGroup(name) || getDevice(name)) {
throw new Error(`friendly_name '${name}' is already in use`);
}
const settings = get();
if (!settings.groups) {
settings.groups = {};
}
if (ID == null) {
// look for free ID
ID = '1';
while (settings.groups.hasOwnProperty(ID)) {
ID = (Number.parseInt(ID) + 1).toString();
}
} else {
// ensure provided ID is not in use
ID = ID.toString();
if (settings.groups.hasOwnProperty(ID)) {
throw new Error(`group id '${ID}' is already in use`);
}
}
settings.groups[ID] = {friendly_name: name};
write();
return getGroup(ID);
}
function groupHasDevice(group, keys) {
for (const device of group.devices) {
const index = keys.indexOf(device);
if (index != -1) {
return keys[index];
}
}
return false;
}
function addDeviceToGroup(groupIDorName, keys) {
const groupID = getGroupThrowIfNotExists(groupIDorName).ID;
const settings = get();
const group = settings.groups[groupID];
if (!group.devices) {
group.devices = [];
}
if (!groupHasDevice(group, keys)) {
group.devices.push(keys[0]);
write();
}
}
function removeDeviceFromGroup(groupIDorName, keys) {
const groupID = getGroupThrowIfNotExists(groupIDorName).ID;
const settings = get();
const group = settings.groups[groupID];
if (!group.devices) {
group.devices = [];
}
const key = groupHasDevice(group, keys);
if (key) {
group.devices = group.devices.filter((d) => d != key);
write();
}
}
function removeGroup(groupIDorName) {
const groupID = getGroupThrowIfNotExists(groupIDorName).ID;
const settings = get();
delete settings.groups[groupID];
write();
}
function changeEntityOptions(IDorName, newOptions) {
const settings = get();
delete newOptions.friendly_name;
delete newOptions.devices;
if (getDevice(IDorName)) {
objectAssignDeep(settings.devices[getDevice(IDorName).ID], newOptions);
} else if (getGroup(IDorName)) {
objectAssignDeep(settings.groups[getGroup(IDorName).ID], newOptions);
} else {
throw new Error(`Device or group '${IDorName}' does not exist`);
}
write();
}
function changeFriendlyName(IDorName, newName) {
utils.validateFriendlyName(newName, true);
if (getGroup(newName) || getDevice(newName)) {
throw new Error(`friendly_name '${newName}' is already in use`);
}
const settings = get();
if (getDevice(IDorName)) {
settings.devices[getDevice(IDorName).ID].friendly_name = newName;
} else if (getGroup(IDorName)) {
settings.groups[getGroup(IDorName).ID].friendly_name = newName;
} else {
throw new Error(`Device or group '${IDorName}' does not exist`);
}
write();
}
module.exports = {
validate,
get: getWithDefaults,
set,
apply,
getDevice,
getGroup,
getGroups,
getEntity,
whitelistDevice,
banDevice,
blockDevice,
addDevice,
removeDevice,
addGroup,
removeGroup,
addDeviceToGroup,
removeDeviceFromGroup,
changeEntityOptions,
changeFriendlyName,
schema,
reRead: () => {
_settings = null;
get();
_settingsWithDefaults = null;
getWithDefaults();
},
// For tests only
_write: write,
_clear: () => {
_settings = null;
_settingsWithDefaults = null;
},
_getDefaults: () => defaults,
};
File diff suppressed because it is too large Load Diff
+733
View File
@@ -0,0 +1,733 @@
import data from './data';
import utils from './utils';
import objectAssignDeep from 'object-assign-deep';
import path from 'path';
import yaml from './yaml';
import Ajv, {ValidateFunction} from 'ajv';
import schemaJson from './settings.schema.json';
export let schema = schemaJson;
// @ts-ignore
schema = {};
objectAssignDeep(schema, schemaJson);
// Remove legacy settings from schema
{
delete schema.properties.advanced.properties.homeassistant_discovery_topic;
delete schema.properties.advanced.properties.homeassistant_legacy_entity_attributes;
delete schema.properties.advanced.properties.homeassistant_legacy_triggers;
delete schema.properties.advanced.properties.homeassistant_status_topic;
delete schema.properties.advanced.properties.soft_reset_timeout;
delete schema.properties.advanced.properties.report;
delete schema.properties.advanced.properties.baudrate;
delete schema.properties.advanced.properties.rtscts;
delete schema.properties.advanced.properties.ikea_ota_use_test_url;
delete schema.properties.experimental;
delete schemaJson.properties.whitelist;
delete schemaJson.properties.ban;
}
// DEPRECATED ZIGBEE2MQTT_CONFIG: https://github.com/Koenkk/zigbee2mqtt/issues/4697
const file = process.env.ZIGBEE2MQTT_CONFIG ?? data.joinPath('configuration.yaml');
const ajvSetting = new Ajv({allErrors: true}).addKeyword('requiresRestart').compile(schemaJson);
const ajvRestartRequired = new Ajv({allErrors: true})
.addKeyword({keyword: 'requiresRestart', validate: (s: unknown) => !s}).compile(schemaJson);
const ajvRestartRequiredDeviceOptions = new Ajv({allErrors: true})
.addKeyword({keyword: 'requiresRestart', validate: (s: unknown) => !s}).compile(schemaJson.definitions.device);
const ajvRestartRequiredGroupOptions = new Ajv({allErrors: true})
.addKeyword({keyword: 'requiresRestart', validate: (s: unknown) => !s}).compile(schemaJson.definitions.group);
const defaults: RecursivePartial<Settings> = {
permit_join: false,
external_converters: [],
mqtt: {
base_topic: 'zigbee2mqtt',
include_device_information: false,
force_disable_retain: false,
},
serial: {
disable_led: false,
},
passlist: [],
blocklist: [],
map_options: {
graphviz: {
colors: {
fill: {
enddevice: '#fff8ce',
coordinator: '#e04e5d',
router: '#4ea3e0',
},
font: {
coordinator: '#ffffff',
router: '#ffffff',
enddevice: '#000000',
},
line: {
active: '#009900',
inactive: '#994444',
},
},
},
},
ota: {
update_check_interval: 24 * 60,
disable_automatic_update_check: false,
},
device_options: {},
advanced: {
legacy_api: true,
legacy_availability_payload: true,
log_rotation: true,
log_symlink_current: false,
log_output: ['console', 'file'],
log_directory: path.join(data.getPath(), 'log', '%TIMESTAMP%'),
log_file: 'log.txt',
log_level: /* istanbul ignore next */ process.env.DEBUG ? 'debug' : 'info',
log_syslog: {},
pan_id: 0x1a62,
ext_pan_id: [0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD],
channel: 11,
adapter_concurrent: null,
adapter_delay: null,
cache_state: true,
cache_state_persistent: true,
cache_state_send_on_startup: true,
last_seen: 'disable',
elapsed: false,
network_key: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
timestamp_format: 'YYYY-MM-DD HH:mm:ss',
output: 'json',
// Everything below is deprecated
availability_blocklist: [],
availability_passlist: [],
availability_blacklist: [],
availability_whitelist: [],
soft_reset_timeout: 0,
report: false,
},
};
let _settings: Partial<Settings>;
let _settingsWithDefaults: Settings;
function loadSettingsWithDefaults(): void {
_settingsWithDefaults = objectAssignDeep({}, defaults, getInternalSettings()) as Settings;
if (!_settingsWithDefaults.devices) {
_settingsWithDefaults.devices = {};
}
if (!_settingsWithDefaults.groups) {
_settingsWithDefaults.groups = {};
}
if (_settingsWithDefaults.homeassistant) {
const defaults = {discovery_topic: 'homeassistant', status_topic: 'hass/status',
legacy_entity_attributes: true, legacy_triggers: true};
const sLegacy = {};
if (_settingsWithDefaults.advanced) {
for (const key of ['homeassistant_legacy_triggers', 'homeassistant_discovery_topic',
'homeassistant_legacy_entity_attributes', 'homeassistant_status_topic']) {
// @ts-ignore
if (_settingsWithDefaults.advanced[key] !== undefined) {
// @ts-ignore
sLegacy[key.replace('homeassistant_', '')] = _settingsWithDefaults.advanced[key];
}
}
}
const s = typeof _settingsWithDefaults.homeassistant === 'object' ? _settingsWithDefaults.homeassistant : {};
// @ts-ignore
_settingsWithDefaults.homeassistant = {};
objectAssignDeep(_settingsWithDefaults.homeassistant, defaults, sLegacy, s);
}
if (_settingsWithDefaults.availability || _settingsWithDefaults.advanced?.availability_timeout) {
const defaults = {};
const s = typeof _settingsWithDefaults.availability === 'object' ? _settingsWithDefaults.availability : {};
// @ts-ignore
_settingsWithDefaults.availability = {};
objectAssignDeep(_settingsWithDefaults.availability, defaults, s);
}
if (_settingsWithDefaults.frontend) {
const defaults = {port: 8080, auth_token: false, host: '0.0.0.0'};
const s = typeof _settingsWithDefaults.frontend === 'object' ? _settingsWithDefaults.frontend : {};
// @ts-ignore
_settingsWithDefaults.frontend = {};
objectAssignDeep(_settingsWithDefaults.frontend, defaults, s);
}
if (_settings.advanced?.hasOwnProperty('baudrate') && _settings.serial?.baudrate == null) {
// @ts-ignore
_settingsWithDefaults.serial.baudrate = _settings.advanced.baudrate;
}
if (_settings.advanced?.hasOwnProperty('rtscts') && _settings.serial?.rtscts == null) {
// @ts-ignore
_settingsWithDefaults.serial.rtscts = _settings.advanced.rtscts;
}
if (_settings.advanced?.hasOwnProperty('ikea_ota_use_test_url') && _settings.ota?.ikea_ota_use_test_url == null) {
// @ts-ignore
_settingsWithDefaults.ota.ikea_ota_use_test_url = _settings.advanced.ikea_ota_use_test_url;
}
// @ts-ignore
if (_settings.experimental?.hasOwnProperty('transmit_power') && _settings.advanced?.transmit_power == null) {
// @ts-ignore
_settingsWithDefaults.advanced.transmit_power = _settings.experimental.transmit_power;
}
// @ts-ignore
if (_settings.experimental?.hasOwnProperty('output') && _settings.advanced?.output == null) {
// @ts-ignore
_settingsWithDefaults.advanced.output = _settings.experimental.output;
}
// @ts-ignore
_settingsWithDefaults.ban && _settingsWithDefaults.blocklist.push(..._settingsWithDefaults.ban);
// @ts-ignore
_settingsWithDefaults.whitelist && _settingsWithDefaults.passlist.push(..._settingsWithDefaults.whitelist);
}
function parseValueRef(text: string): {filename: string, key: string} | null {
const match = /!(.*) (.*)/g.exec(text);
if (match) {
let filename = match[1];
// This is mainly for backward compatibility.
if (!filename.endsWith('.yaml') && !filename.endsWith('.yml')) {
filename += '.yaml';
}
return {filename, key: match[2]};
} else {
return null;
}
}
function write(): void {
const settings = getInternalSettings();
const toWrite: KeyValue = objectAssignDeep({}, settings);
// Read settings to check if we have to split devices/groups into separate file.
const actual = yaml.read(file);
// In case the setting is defined in a separate file (e.g. !secret network_key) update it there.
for (const path of [
['mqtt', 'server'],
['mqtt', 'user'],
['mqtt', 'password'],
['advanced', 'network_key'],
['frontend', 'auth_token'],
]) {
if (actual[path[0]] && actual[path[0]][path[1]]) {
const ref = parseValueRef(actual[path[0]][path[1]]);
if (ref) {
yaml.updateIfChanged(data.joinPath(ref.filename), ref.key, toWrite[path[0]][path[1]]);
toWrite[path[0]][path[1]] = actual[path[0]][path[1]];
}
}
}
// Write devices/groups to separate file if required.
const writeDevicesOrGroups = (type: 'devices' | 'groups'): void => {
if (typeof actual[type] === 'string' || (Array.isArray(actual[type]) && actual[type].length > 0)) {
const fileToWrite = Array.isArray(actual[type]) ? actual[type][0] : actual[type];
const content = objectAssignDeep({}, settings[type]);
// If an array, only write to first file and only devices which are not in the other files.
if (Array.isArray(actual[type])) {
actual[type].filter((f: string, i: number) => i !== 0)
.map((f: string) => yaml.readIfExists(data.joinPath(f), {}))
.map((c: KeyValue) => Object.keys(c))
.forEach((k: string) => delete content[k]);
}
yaml.writeIfChanged(data.joinPath(fileToWrite), content);
toWrite[type] = actual[type];
}
};
writeDevicesOrGroups('devices');
writeDevicesOrGroups('groups');
yaml.writeIfChanged(file, toWrite);
_settings = read();
loadSettingsWithDefaults();
}
export function validate(): string[] {
try {
getInternalSettings();
} catch (error) {
if (error.name === 'YAMLException') {
return [
`Your YAML file: '${error.file}' is invalid ` +
`(use https://jsonformatter.org/yaml-validator to find and fix the issue)`,
];
}
return [error.message];
}
if (!ajvSetting(_settings)) {
return ajvSetting.errors.map((v) => `${v.instancePath.substring(1)} ${v.message}`);
}
const errors = [];
if (_settings.advanced && _settings.advanced.network_key && typeof _settings.advanced.network_key === 'string' &&
_settings.advanced.network_key !== 'GENERATE') {
errors.push(`advanced.network_key: should be array or 'GENERATE' (is '${_settings.advanced.network_key}')`);
}
if (_settings.advanced && _settings.advanced.pan_id && typeof _settings.advanced.pan_id === 'string' &&
_settings.advanced.pan_id !== 'GENERATE') {
errors.push(`advanced.pan_id: should be number or 'GENERATE' (is '${_settings.advanced.pan_id}')`);
}
if (_settings.advanced && _settings.advanced.ext_pan_id && typeof _settings.advanced.ext_pan_id === 'string' &&
_settings.advanced.ext_pan_id !== 'GENERATE') {
errors.push(`advanced.ext_pan_id: should be array or 'GENERATE' (is '${_settings.advanced.ext_pan_id}')`);
}
// Verify that all friendly names are unique
const names: string[] = [];
const check = (e: DeviceOptions | GroupOptions): void => {
if (names.includes(e.friendly_name)) errors.push(`Duplicate friendly_name '${e.friendly_name}' found`);
errors.push(...utils.validateFriendlyName(e.friendly_name));
names.push(e.friendly_name);
if (e.qos != null && ![0, 1, 2].includes(e.qos)) {
errors.push(`QOS for '${e.friendly_name}' not valid, should be 0, 1 or 2 got ${e.qos}`);
}
};
const settingsWithDefaults = get();
Object.values(settingsWithDefaults.devices).forEach((d) => check(d));
Object.values(settingsWithDefaults.groups).forEach((g) => check(g));
if (settingsWithDefaults.mqtt.version !== 5) {
for (const device of Object.values(settingsWithDefaults.devices)) {
if (device.retention) {
errors.push('MQTT retention requires protocol version 5');
}
}
}
const checkAvailabilityList = (list: string[], type: string): void => {
list.forEach((e) => {
if (!getDevice(e)) {
errors.push(`Non-existing entity '${e}' specified in '${type}'`);
}
});
};
checkAvailabilityList(settingsWithDefaults.advanced.availability_blacklist, 'availability_blacklist');
checkAvailabilityList(settingsWithDefaults.advanced.availability_whitelist, 'availability_whitelist');
checkAvailabilityList(settingsWithDefaults.advanced.availability_blocklist, 'availability_blocklist');
checkAvailabilityList(settingsWithDefaults.advanced.availability_passlist, 'availability_passlist');
return errors;
}
function read(): Settings {
const s = yaml.read(file) as Settings;
applyEnvironmentVariables(s);
// Read !secret MQTT username and password if set
// eslint-disable-next-line
const interpretValue = (value: any): any => {
const ref = parseValueRef(value);
if (ref) {
return yaml.read(data.joinPath(ref.filename))[ref.key];
} else {
return value;
}
};
if (s.mqtt?.user) {
s.mqtt.user = interpretValue(s.mqtt.user);
}
if (s.mqtt?.password) {
s.mqtt.password = interpretValue(s.mqtt.password);
}
if (s.mqtt?.server) {
s.mqtt.server = interpretValue(s.mqtt.server);
}
if (s.advanced?.network_key) {
s.advanced.network_key = interpretValue(s.advanced.network_key);
}
if (s.frontend?.auth_token) {
s.frontend.auth_token = interpretValue(s.frontend.auth_token);
}
// Read devices/groups configuration from separate file if specified.
const readDevicesOrGroups = (type: 'devices' | 'groups'): void => {
if (typeof s[type] === 'string' || (Array.isArray(s[type]) && Array(s[type]).length > 0)) {
/* eslint-disable-line */ // @ts-ignore
const files: string[] = Array.isArray(s[type]) ? s[type] : [s[type]];
s[type] = {};
for (const file of files) {
const content = yaml.readIfExists(data.joinPath(file), {});
/* eslint-disable-line */ // @ts-ignore
s[type] = objectAssignDeep.noMutate(s[type], content);
}
}
};
readDevicesOrGroups('devices');
readDevicesOrGroups('groups');
return s;
}
function applyEnvironmentVariables(settings: Partial<Settings>): void {
const iterate = (obj: KeyValue, path: string[]): void => {
Object.keys(obj).forEach((key) => {
if (key !== 'type') {
if (key !== 'properties' && obj[key]) {
const type = (obj[key].type || 'object').toString();
const envPart = path.reduce((acc, val) => `${acc}${val}_`, '');
const envVariableName = (`ZIGBEE2MQTT_CONFIG_${envPart}${key}`).toUpperCase();
if (process.env[envVariableName]) {
const setting = path.reduce((acc, val) => {
/* eslint-disable-line */ // @ts-ignore
acc[val] = acc[val] || {};
/* eslint-disable-line */ // @ts-ignore
return acc[val];
}, settings);
if (type.indexOf('object') >= 0 || type.indexOf('array') >= 0) {
try {
setting[key] = JSON.parse(process.env[envVariableName]);
} catch (error) {
setting[key] = process.env[envVariableName];
}
} else if (type.indexOf('number') >= 0) {
/* eslint-disable-line */ // @ts-ignore
setting[key] = process.env[envVariableName] * 1;
} else if (type.indexOf('boolean') >= 0) {
setting[key] = process.env[envVariableName].toLowerCase() === 'true';
} else {
/* istanbul ignore else */
if (type.indexOf('string') >= 0) {
setting[key] = process.env[envVariableName];
}
}
}
}
if (typeof obj[key] === 'object' && obj[key]) {
const newPath = [...path];
if (key !== 'properties' && key !== 'oneOf' && !Number.isInteger(Number(key))) {
newPath.push(key);
}
iterate(obj[key], newPath);
}
}
});
};
iterate(schemaJson.properties, []);
}
function getInternalSettings(): Partial<Settings> {
if (!_settings) {
_settings = read();
}
return _settings;
}
export function get(): Settings {
if (!_settingsWithDefaults) {
loadSettingsWithDefaults();
}
return _settingsWithDefaults;
}
export function set(path: string[], value: string | number | boolean | KeyValue): void {
/* eslint-disable-next-line */
let settings: any = getInternalSettings();
for (let i = 0; i < path.length; i++) {
const key = path[i];
if (i === path.length - 1) {
settings[key] = value;
} else {
if (!settings[key]) {
settings[key] = {};
}
settings = settings[key];
}
}
write();
}
export function apply(newSettings: Record<string, unknown>): boolean {
ajvSetting(newSettings);
const errors = ajvSetting.errors && ajvSetting.errors.filter((e) => e.keyword !== 'required');
if (errors.length) {
const error = errors[0];
throw new Error(`${error.instancePath.substring(1)} ${error.message}`);
}
getInternalSettings(); // Ensure _settings is initialized.
/* eslint-disable-line */ // @ts-ignore
_settings = objectAssignDeep.noMutate(_settings, newSettings);
write();
ajvRestartRequired(newSettings);
const restartRequired = ajvRestartRequired.errors &&
!!ajvRestartRequired.errors.find((e) => e.keyword === 'requiresRestart');
return restartRequired;
}
export function getGroup(IDorName: string | number): GroupOptions {
const settings = get();
const byID = settings.groups[IDorName];
if (byID) {
return {devices: [], ...byID, ID: Number(IDorName)};
}
for (const [ID, group] of Object.entries(settings.groups)) {
if (group.friendly_name === IDorName) {
return {devices: [], ...group, ID: Number(ID)};
}
}
return null;
}
export function getGroups(): GroupOptions[] {
const settings = get();
return Object.entries(settings.groups).map(([ID, group]) => {
return {devices: [], ...group, ID: Number(ID)};
});
}
function getGroupThrowIfNotExists(IDorName: string): GroupOptions {
const group = getGroup(IDorName);
if (!group) {
throw new Error(`Group '${IDorName}' does not exist`);
}
return group;
}
export function getDevice(IDorName: string): DeviceOptions {
const settings = get();
const byID = settings.devices[IDorName];
if (byID) {
return {...byID, ID: IDorName};
}
for (const [ID, device] of Object.entries(settings.devices)) {
if (device.friendly_name === IDorName) {
return {...device, ID};
}
}
return null;
}
function getDeviceThrowIfNotExists(IDorName: string): DeviceOptions {
const device = getDevice(IDorName);
if (!device) {
throw new Error(`Device '${IDorName}' does not exist`);
}
return device;
}
export function addDevice(ID: string): DeviceOptions {
if (getDevice(ID)) {
throw new Error(`Device '${ID}' already exists`);
}
const settings = getInternalSettings();
if (!settings.devices) {
settings.devices = {};
}
settings.devices[ID] = {friendly_name: ID};
write();
return getDevice(ID);
}
export function addDeviceToPasslist(ID: string): void {
const settings = getInternalSettings();
if (!settings.passlist) {
settings.passlist = [];
}
if (settings.passlist.includes(ID)) {
throw new Error(`Device '${ID}' already in passlist`);
}
settings.passlist.push(ID);
write();
}
export function blockDevice(ID: string): void {
const settings = getInternalSettings();
if (!settings.blocklist) {
settings.blocklist = [];
}
settings.blocklist.push(ID);
write();
}
export function removeDevice(IDorName: string): void {
const device = getDeviceThrowIfNotExists(IDorName);
const settings = getInternalSettings();
delete settings.devices[device.ID];
// Remove device from groups
if (settings.groups) {
const regex =
new RegExp(`^(${device.friendly_name}|${device.ID})(/(\\d|${utils.endpointNames.join('|')}))?$`);
for (const group of Object.values(settings.groups).filter((g) => g.devices)) {
group.devices = group.devices.filter((device) => !device.match(regex));
}
}
write();
}
export function addGroup(name: string, ID?: string): GroupOptions {
utils.validateFriendlyName(name, true);
if (getGroup(name) || getDevice(name)) {
throw new Error(`friendly_name '${name}' is already in use`);
}
const settings = getInternalSettings();
if (!settings.groups) {
settings.groups = {};
}
if (ID == null) {
// look for free ID
ID = '1';
while (settings.groups.hasOwnProperty(ID)) {
ID = (Number.parseInt(ID) + 1).toString();
}
} else {
// ensure provided ID is not in use
ID = ID.toString();
if (settings.groups.hasOwnProperty(ID)) {
throw new Error(`Group ID '${ID}' is already in use`);
}
}
settings.groups[ID] = {friendly_name: name};
write();
return getGroup(ID);
}
function groupGetDevice(group: {devices?: string[]}, keys: string[]): string {
for (const device of group.devices ?? []) {
if (keys.includes(device)) return device;
}
return null;
}
export function addDeviceToGroup(IDorName: string, keys: string[]): void {
const groupID = getGroupThrowIfNotExists(IDorName).ID;
const settings = getInternalSettings();
const group = settings.groups[groupID];
if (!groupGetDevice(group, keys)) {
if (!group.devices) group.devices = [];
group.devices.push(keys[0]);
write();
}
}
export function removeDeviceFromGroup(IDorName: string, keys: string[]): void {
const groupID = getGroupThrowIfNotExists(IDorName).ID;
const settings = getInternalSettings();
const group = settings.groups[groupID];
if (!group.devices) {
return;
}
const key = groupGetDevice(group, keys);
if (key) {
group.devices = group.devices.filter((d) => d != key);
write();
}
}
export function removeGroup(IDorName: string | number): void {
const groupID = getGroupThrowIfNotExists(IDorName.toString()).ID;
const settings = getInternalSettings();
delete settings.groups[groupID];
write();
}
export function changeEntityOptions(IDorName: string, newOptions: KeyValue): boolean {
const settings = getInternalSettings();
delete newOptions.friendly_name;
delete newOptions.devices;
let validator: ValidateFunction;
if (getDevice(IDorName)) {
objectAssignDeep(settings.devices[getDevice(IDorName).ID], newOptions);
utils.removeNullPropertiesFromObject(settings.devices[getDevice(IDorName).ID]);
validator = ajvRestartRequiredDeviceOptions;
} else if (getGroup(IDorName)) {
objectAssignDeep(settings.groups[getGroup(IDorName).ID], newOptions);
utils.removeNullPropertiesFromObject(settings.groups[getGroup(IDorName).ID]);
validator = ajvRestartRequiredGroupOptions;
} else {
throw new Error(`Device or group '${IDorName}' does not exist`);
}
write();
validator(newOptions);
const restartRequired = validator.errors && !!validator.errors.find((e) => e.keyword === 'requiresRestart');
return restartRequired;
}
export function changeFriendlyName(IDorName: string, newName: string): void {
utils.validateFriendlyName(newName, true);
if (getGroup(newName) || getDevice(newName)) {
throw new Error(`friendly_name '${newName}' is already in use`);
}
const settings = getInternalSettings();
if (getDevice(IDorName)) {
settings.devices[getDevice(IDorName).ID].friendly_name = newName;
} else if (getGroup(IDorName)) {
settings.groups[getGroup(IDorName).ID].friendly_name = newName;
} else {
throw new Error(`Device or group '${IDorName}' does not exist`);
}
write();
}
export function reRead(): void {
_settings = null;
getInternalSettings();
_settingsWithDefaults = null;
get();
}
export const testing = {
write,
clear: (): void => {
_settings = null;
_settingsWithDefaults = null;
},
defaults,
};
-260
View File
@@ -1,260 +0,0 @@
const equals = require('fast-deep-equal/es6');
const humanizeDuration = require('humanize-duration');
const data = require('./data');
const vm = require('vm');
const fs = require('fs');
const path = require('path');
// Xiaomi uses 4151 and 4447 (lumi.plug) as manufacturer ID.
const xiaomiManufacturerID = [4151, 4447];
const ikeaTradfriManufacturerID = [4476];
// construct a local ISO8601 string (instead of UTC-based)
// Example:
// - ISO8601 (UTC) = 2019-03-01T15:32:45.941+0000
// - ISO8601 (local) = 2019-03-01T16:32:45.941+0100 (for timezone GMT+1)
function toLocalISOString(dDate) {
const tzOffset = -dDate.getTimezoneOffset();
const plusOrMinus = tzOffset >= 0 ? '+' : '-';
const pad = function(num) {
const norm = Math.floor(Math.abs(num));
return (norm < 10 ? '0' : '') + norm;
};
return dDate.getFullYear() +
'-' + pad(dDate.getMonth() + 1) +
'-' + pad(dDate.getDate()) +
'T' + pad(dDate.getHours()) +
':' + pad(dDate.getMinutes()) +
':' + pad(dDate.getSeconds()) +
plusOrMinus + pad(tzOffset / 60) +
':' + pad(tzOffset % 60);
}
const endpointNames = [
'left', 'right', 'center', 'bottom_left', 'bottom_right', 'default',
'top_left', 'top_right', 'white', 'rgb', 'cct', 'system', 'top', 'bottom', 'center_left', 'center_right',
'ep1', 'ep2', 'row_1', 'row_2', 'row_3', 'row_4', 'relay',
'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8',
'l9', 'l10', 'l11', 'l12', 'l13', 'l14', 'l15', 'l16',
'button_1', 'button_2', 'button_3', 'button_4', 'button_5',
'button_6', 'button_7', 'button_8', 'button_9', 'button_10',
'button_11', 'button_12', 'button_13', 'button_14', 'button_15',
'button_16', 'button_17', 'button_18', 'button_19', 'button_20',
'button_light', 'button_fan_high', 'button_fan_med', 'button_fan_low',
'heat', 'cool', 'water', 'meter',
];
function capitalize(s) {
return s[0].toUpperCase() + s.slice(1);
}
async function getZigbee2mqttVersion() {
return new Promise((resolve, reject) => {
const git = require('git-last-commit');
const packageJSON = require('../../package.json');
const version = packageJSON.version;
git.getLastCommit((err, commit) => {
let commitHash = null;
if (err) {
try {
commitHash = require('../../.hash.json').hash;
} catch (error) {
commitHash = 'unknown';
}
} else {
commitHash = commit.shortHash;
}
resolve({commitHash, version});
});
});
}
async function getDependencyVersion(depend) {
return new Promise((resolve, reject) => {
const packageJSON = require('../../node_modules/'+depend+'/package.json');
const version = packageJSON.version;
resolve({version});
});
}
function formatDate(date, type) {
let result;
switch (type) {
case 'ISO_8601':
result = new Date(date).toISOString();
break;
case 'ISO_8601_local':
result = toLocalISOString(new Date(date));
break;
case 'epoch':
result = date;
break;
case 'relative':
// https://github.com/EvanHahn/HumanizeDuration.js#options
result = humanizeDuration(Date.now() - date, {language: 'en', largest: 2, round: true}) + ' ago';
break;
default:
throw new Error(`Unsupported type '${type}'`);
}
return result;
}
function objectHasProperties(object, properties) {
for (const property of properties) {
if (!object.hasOwnProperty(property)) {
return false;
}
}
return true;
}
function equalsPartial(object, expected) {
for (const [key, value] of Object.entries(expected)) {
if (!equals(object[key], value)) {
return false;
}
}
return true;
}
function getObjectProperty(object, key, defaultValue) {
return object.hasOwnProperty(key) ? object[key] : defaultValue;
}
function getResponse(request, data, error) {
const response = {data, status: error ? 'error' : 'ok'};
if (error) response.error = error;
if (typeof request === 'object' && request.hasOwnProperty('transaction')) {
response.transaction = request.transaction;
}
return response;
}
function parseJSON(value, failedReturnValue) {
try {
return JSON.parse(value);
} catch (e) {
return failedReturnValue;
}
}
function loadModuleFromText(moduleCode) {
const moduleFakePath = path.join(__dirname, 'externally-loaded.js');
const sandbox = {
require: require,
module: {},
console,
setTimeout,
clearTimeout,
setInterval,
clearInterval,
setImmediate,
clearImmediate,
};
vm.runInNewContext(moduleCode, sandbox, moduleFakePath);
return sandbox.module.exports;
}
function loadModuleFromFile(modulePath) {
const moduleCode = fs.readFileSync(modulePath, {encoding: 'utf8'});
return loadModuleFromText(moduleCode);
}
function* getExternalConvertersDefinitions(settings) {
const externalConverters = settings.get().external_converters;
for (const moduleName of externalConverters) {
let converter;
if (moduleName.endsWith('.js')) {
converter = loadModuleFromFile(data.joinPath(moduleName));
} else {
converter = require(moduleName);
}
if (Array.isArray(converter)) {
for (const item of converter) {
yield item;
}
} else {
yield converter;
}
}
}
function toSnakeCase(value) {
if (typeof value === 'object') {
value = {...value};
for (const key of Object.keys(value)) {
const keySnakeCase = toSnakeCase(key);
if (key !== keySnakeCase) {
value[keySnakeCase] = value[key];
delete value[key];
}
}
return value;
} else {
return value.replace(/\.?([A-Z])/g, (x, y) => '_' + y.toLowerCase()).replace(/^_/, '').replace('_i_d', '_id');
}
}
function validateFriendlyName(name, throwFirstError=false) {
const errors = [];
for (const endpointName of endpointNames) {
if (name.toLowerCase().endsWith('/' + endpointName)) {
errors.push(`friendly_name is not allowed to end with: '/${endpointName}'`);
}
}
if (name.length === 0) errors.push(`friendly_name must be at least 1 char long`);
if (name.endsWith('/') || name.startsWith('/')) errors.push(`friendly_name is not allowed to end or start with /`);
if (name.endsWith(String.fromCharCode(0))) errors.push(`friendly_name is not allowed to contain null char`);
if (endpointNames.includes(name)) errors.push(`Following friendly_name are not allowed: '${endpointNames}'`);
if (name.match(/.*\/\d*$/)) errors.push(`Friendly name cannot end with a "/DIGIT" ('${name}')`);
if (name.includes('#') || name.includes('+')) {
errors.push(`MQTT wildcard (+ and #) not allowed in friendly_name ('${name}')`);
}
if (throwFirstError && errors.length) {
throw new Error(errors[0]);
}
return errors;
}
function sleep(seconds) {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}
module.exports = {
millisecondsToSeconds: (milliseconds) => milliseconds / 1000,
secondsToMilliseconds: (seconds) => seconds * 1000,
getZigbee2mqttVersion,
getDependencyVersion,
objectHasProperties,
toSnakeCase,
sleep,
getObjectProperty,
getEndpointNames: () => endpointNames,
isXiaomiDevice: (device) => {
return device.modelID !== 'lumi.router' && xiaomiManufacturerID.includes(device.manufacturerID) &&
(!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
},
isIkeaTradfriDevice: (device) => ikeaTradfriManufacturerID.includes(device.manufacturerID),
formatDate: (date, type) => formatDate(date, type),
equalsPartial,
getResponse,
capitalize,
parseJSON,
getExternalConvertersDefinitions,
validateFriendlyName,
loadModuleFromFile,
loadModuleFromText,
};
+412
View File
@@ -0,0 +1,412 @@
import equals from 'fast-deep-equal/es6';
import humanizeDuration from 'humanize-duration';
import data from './data';
import vm from 'vm';
import fs from 'fs';
import path from 'path';
import {detailedDiff} from 'deep-object-diff';
import objectAssignDeep from 'object-assign-deep';
// construct a local ISO8601 string (instead of UTC-based)
// Example:
// - ISO8601 (UTC) = 2019-03-01T15:32:45.941+0000
// - ISO8601 (local) = 2019-03-01T16:32:45.941+0100 (for timezone GMT+1)
function toLocalISOString(date: Date): string {
const tzOffset = -date.getTimezoneOffset();
const plusOrMinus = tzOffset >= 0 ? '+' : '-';
const pad = (num: number): string => {
const norm = Math.floor(Math.abs(num));
return (norm < 10 ? '0' : '') + norm;
};
return date.getFullYear() +
'-' + pad(date.getMonth() + 1) +
'-' + pad(date.getDate()) +
'T' + pad(date.getHours()) +
':' + pad(date.getMinutes()) +
':' + pad(date.getSeconds()) +
plusOrMinus + pad(tzOffset / 60) +
':' + pad(tzOffset % 60);
}
const endpointNames = [
'left', 'right', 'center', 'bottom_left', 'bottom_right', 'default',
'top_left', 'top_right', 'white', 'rgb', 'cct', 'system', 'top', 'bottom', 'center_left', 'center_right',
'ep1', 'ep2', 'row_1', 'row_2', 'row_3', 'row_4', 'relay', 'usb',
'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8',
'l9', 'l10', 'l11', 'l12', 'l13', 'l14', 'l15', 'l16',
'l17', 'l18', 'l19', 'l20', 'l21', 'l22', 'l23', 'l24',
'th1', 'th2', 'th3', 'th4', 'th5', 'th6', 'th7', 'th8', 'th9', 'th10',
'button_1', 'button_2', 'button_3', 'button_4', 'button_5',
'button_6', 'button_7', 'button_8', 'button_9', 'button_10',
'button_11', 'button_12', 'button_13', 'button_14', 'button_15',
'button_16', 'button_17', 'button_18', 'button_19', 'button_20',
'button_light', 'button_fan_high', 'button_fan_med', 'button_fan_low',
'heat', 'cool', 'water', 'meter', 'wifi', 'no_occupancy_since',
];
function capitalize(s: string): string {
return s[0].toUpperCase() + s.slice(1);
}
async function getZigbee2MQTTVersion(includeCommitHash=true): Promise<{commitHash: string, version: string}> {
const git = await import('git-last-commit');
const packageJSON = await import('../..' + '/package.json');
if (!includeCommitHash) {
return {version: packageJSON.version, commitHash: null};
}
return new Promise((resolve) => {
const version = packageJSON.version;
git.getLastCommit((err: Error, commit: {shortHash: string}) => {
let commitHash = null;
if (err) {
try {
commitHash = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', '.hash'), 'utf-8');
} catch (error) {
/* istanbul ignore next */
commitHash = 'unknown';
}
} else {
commitHash = commit.shortHash;
}
commitHash = commitHash.trim();
resolve({commitHash, version});
});
});
}
async function getDependencyVersion(depend: string): Promise<{version: string}> {
const packageJSON = await import(path.join(require.resolve(depend), '..', '..', 'package.json'));
const version = packageJSON.version;
return {version};
}
function formatDate(time: number, type: 'ISO_8601' | 'ISO_8601_local' | 'epoch' | 'relative'): string | number {
if (type === 'ISO_8601') return new Date(time).toISOString();
else if (type === 'ISO_8601_local') return toLocalISOString(new Date(time));
else if (type === 'epoch') return time;
else { // relative
return humanizeDuration(Date.now() - time, {language: 'en', largest: 2, round: true}) + ' ago';
}
}
function objectHasProperties(object: {[s: string]: unknown}, properties: string[]): boolean {
for (const property of properties) {
if (!object.hasOwnProperty(property)) {
return false;
}
}
return true;
}
function equalsPartial(object: KeyValue, expected: KeyValue): boolean {
for (const [key, value] of Object.entries(expected)) {
if (!equals(object[key], value)) {
return false;
}
}
return true;
}
function getObjectProperty(object: KeyValue, key: string, defaultValue: unknown): unknown {
return object && object.hasOwnProperty(key) ? object[key] : defaultValue;
}
function getResponse(request: KeyValue | string, data: KeyValue, error: string): MQTTResponse {
const response: MQTTResponse = {data, status: error ? 'error' : 'ok'};
if (error) response.error = error;
if (typeof request === 'object' && request.hasOwnProperty('transaction')) {
response.transaction = request.transaction;
}
return response;
}
function parseJSON(value: string, fallback: string): KeyValue | string {
try {
return JSON.parse(value);
} catch (e) {
return fallback;
}
}
function loadModuleFromText(moduleCode: string, name?: string): unknown {
const moduleFakePath = path.join(__dirname, '..', '..', 'data', 'extension', name || 'externally-loaded.js');
const sandbox = {
require: require,
module: {},
console,
setTimeout,
clearTimeout,
setInterval,
clearInterval,
setImmediate,
clearImmediate,
};
vm.runInNewContext(moduleCode, sandbox, moduleFakePath);
/* eslint-disable-line */ // @ts-ignore
return sandbox.module.exports;
}
function loadModuleFromFile(modulePath: string): unknown {
const moduleCode = fs.readFileSync(modulePath, {encoding: 'utf8'});
return loadModuleFromText(moduleCode);
}
function* getExternalConvertersDefinitions(settings: Settings): Generator<zhc.ExternalDefinition> {
const externalConverters = settings.external_converters;
for (const moduleName of externalConverters) {
let converter;
if (moduleName.endsWith('.js')) {
converter = loadModuleFromFile(data.joinPath(moduleName));
} else {
converter = require(moduleName);
}
if (Array.isArray(converter)) {
for (const item of converter) {
yield item;
}
} else {
yield converter;
}
}
}
function removeNullPropertiesFromObject(obj: KeyValue): void {
for (const key of Object.keys(obj)) {
const value = obj[key];
if (value == null) {
delete obj[key];
} else if (typeof value === 'object') {
removeNullPropertiesFromObject(value);
}
}
}
function toNetworkAddressHex(value: number): string {
const hex = value.toString(16);
return `0x${'0'.repeat(4 - hex.length)}${hex}`;
}
// eslint-disable-next-line
function toSnakeCase(value: string | KeyValue): any {
if (typeof value === 'object') {
value = {...value};
for (const key of Object.keys(value)) {
const keySnakeCase = toSnakeCase(key);
if (key !== keySnakeCase) {
value[keySnakeCase] = value[key];
delete value[key];
}
}
return value;
} else {
return value.replace(/\.?([A-Z])/g, (x, y) => '_' + y.toLowerCase()).replace(/^_/, '').replace('_i_d', '_id');
}
}
function charRange(start: string, stop: string): number[] {
const result = [];
for (let idx=start.charCodeAt(0), end=stop.charCodeAt(0); idx <=end; ++idx) {
result.push(idx);
}
return result;
}
const controlCharacters = [
...charRange('\u0000', '\u001F'),
...charRange('\u007f', '\u009F'),
...charRange('\ufdd0', '\ufdef'),
];
function containsControlCharacter(str: string): boolean {
for (let i = 0; i < str.length; i++) {
const ch = str.charCodeAt(i);
if (controlCharacters.includes(ch) || [0xFFFE, 0xFFFF].includes(ch & 0xFFFF)) {
return true;
}
}
return false;
}
function getAllFiles(path_: string): string[] {
const result = [];
for (let item of fs.readdirSync(path_)) {
item = path.join(path_, item);
if (fs.lstatSync(item).isFile()) {
result.push(item);
} else {
result.push(...getAllFiles(item));
}
}
return result;
}
function validateFriendlyName(name: string, throwFirstError=false): string[] {
const errors = [];
for (const endpointName of endpointNames) {
if (name.toLowerCase().endsWith('/' + endpointName)) {
errors.push(`friendly_name is not allowed to end with: '/${endpointName}'`);
}
}
if (name.length === 0) errors.push(`friendly_name must be at least 1 char long`);
if (name.endsWith('/') || name.startsWith('/')) errors.push(`friendly_name is not allowed to end or start with /`);
if (containsControlCharacter(name)) errors.push(`friendly_name is not allowed to contain control char`);
if (endpointNames.includes(name)) errors.push(`Following friendly_name are not allowed: '${endpointNames}'`);
if (name.match(/.*\/\d*$/)) errors.push(`Friendly name cannot end with a "/DIGIT" ('${name}')`);
if (name.includes('#') || name.includes('+')) {
errors.push(`MQTT wildcard (+ and #) not allowed in friendly_name ('${name}')`);
}
if (throwFirstError && errors.length) {
throw new Error(errors[0]);
}
return errors;
}
function sleep(seconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}
function sanitizeImageParameter(parameter: string): string {
const replaceByDash = [/\?/g, /&/g, /[^a-z\d\- _./:]/gi];
let sanitized = parameter;
replaceByDash.forEach((r) => sanitized = sanitized.replace(r, '-'));
return sanitized;
}
function isAvailabilityEnabledForEntity(entity: Device | Group, settings: Settings): boolean {
if (entity.isGroup()) {
return !entity.membersDevices().map((d) => isAvailabilityEnabledForEntity(d, settings)).includes(false);
}
if (entity.options.hasOwnProperty('availability')) {
return !!entity.options.availability;
}
// availability_timeout = deprecated
const enabledGlobal = settings.advanced.availability_timeout || settings.availability;
if (!enabledGlobal) return false;
if (entity.isDevice() && entity.options.disabled) return false;
const passlist = settings.advanced.availability_passlist.concat(settings.advanced.availability_whitelist);
if (passlist.length > 0) {
return passlist.includes(entity.name) || passlist.includes(entity.ieeeAddr);
}
const blocklist = settings.advanced.availability_blacklist.concat(settings.advanced.availability_blocklist);
return !blocklist.includes(entity.name) && !blocklist.includes(entity.ieeeAddr);
}
const entityIDRegex = new RegExp(`^(.+?)(?:/(${endpointNames.join('|')}|\\d+))?$`);
function parseEntityID(ID: string): {ID: string, endpoint: string} {
const match = ID.match(entityIDRegex);
return match && {ID: match[1], endpoint: match[2]};
}
function isEndpoint(obj: unknown): obj is zh.Endpoint {
return obj.constructor.name.toLowerCase() === 'endpoint';
}
function flatten<Type>(arr: Type[][]): Type[] {
return [].concat(...arr);
}
function arrayUnique<Type>(arr: Type[]): Type[] {
return [...new Set(arr)];
}
function isZHGroup(obj: unknown): obj is zh.Group {
return obj.constructor.name.toLowerCase() === 'group';
}
function availabilityPayload(state: 'online' | 'offline', settings: Settings): string {
return settings.advanced.legacy_availability_payload ? state : JSON.stringify({state});
}
const hours = (hours: number): number => 1000 * 60 * 60 * hours;
const minutes = (minutes: number): number => 1000 * 60 * minutes;
const seconds = (seconds: number): number => 1000 * seconds;
function publishLastSeen(data: eventdata.LastSeenChanged, settings: Settings, allowMessageEmitted: boolean,
publishEntityState: PublishEntityState): void {
/**
* Prevent 2 MQTT publishes when 1 message event is received;
* - In case reason == messageEmitted, receive.ts will only call this when it did not publish a
* message based on the received zigbee message. In this case allowMessageEmitted has to be true.
* - In case reason !== messageEmitted, controller.ts will call this based on the zigbee-herdsman
* lastSeenChanged event.
*/
const allow = data.reason !== 'messageEmitted' || (data.reason === 'messageEmitted' && allowMessageEmitted);
if (settings.advanced.last_seen && settings.advanced.last_seen !== 'disable' && allow) {
publishEntityState(data.device, {}, 'lastSeenChanged');
}
}
function filterProperties(filter: string[], data: KeyValue): void {
if (filter) {
for (const property of Object.keys(data)) {
if (filter.find((p) => property.match(`^${p}$`))) {
delete data[property];
}
}
}
}
function clone(obj: KeyValue): KeyValue {
return JSON.parse(JSON.stringify(obj));
}
function computeSettingsToChange(current: KeyValue, new_: KeyValue): KeyValue {
const diff: KeyValue = detailedDiff(current, new_);
// Remove any settings that are in the deleted.diff but not in the passed options
const cleanupDeleted = (options: KeyValue, deleted: KeyValue): void => {
for (const key of Object.keys(deleted)) {
if (!(key in options)) {
delete deleted[key];
} else if (!Array.isArray(options[key])) {
cleanupDeleted(options[key], deleted[key]);
}
}
};
cleanupDeleted(new_, diff.deleted);
// objectAssignDeep requires object prototype which is missing from detailedDiff, therefore clone
const newSettings = objectAssignDeep({}, clone(diff.added), clone(diff.updated), clone(diff.deleted));
// deep-object-diff converts arrays to objects, set original array back here
const convertBackArray = (before: KeyValue, after: KeyValue): void => {
for (const [key, afterValue] of Object.entries(after)) {
const beforeValue = before[key];
if (Array.isArray(beforeValue)) {
after[key] = beforeValue;
} else if (afterValue && typeof beforeValue === 'object') {
convertBackArray(beforeValue, afterValue);
}
}
};
convertBackArray(new_, newSettings);
return newSettings;
}
export default {
endpointNames, capitalize, getZigbee2MQTTVersion, getDependencyVersion, formatDate, objectHasProperties,
equalsPartial, getObjectProperty, getResponse, parseJSON, loadModuleFromText, loadModuleFromFile,
getExternalConvertersDefinitions, removeNullPropertiesFromObject, toNetworkAddressHex, toSnakeCase,
parseEntityID, isEndpoint, isZHGroup, hours, minutes, seconds, validateFriendlyName, sleep,
sanitizeImageParameter, isAvailabilityEnabledForEntity, publishLastSeen, availabilityPayload,
getAllFiles, filterProperties, flatten, arrayUnique, clone, computeSettingsToChange,
};
-36
View File
@@ -1,36 +0,0 @@
const yaml = require('js-yaml');
const fs = require('fs');
const equals = require('fast-deep-equal/es6');
function read(file) {
try {
return yaml.safeLoad(fs.readFileSync(file, 'utf8'));
} catch (error) {
if (error.name === 'YAMLException') {
error.file = file;
}
throw error;
}
}
function readIfExists(file, default_=null) {
return fs.existsSync(file) ? read(file) : default_;
}
function writeIfChanged(file, content) {
const before = readIfExists(file);
if (!equals(before, content)) {
fs.writeFileSync(file, yaml.safeDump(content));
}
}
function updateIfChanged(file, key, value) {
const content = read(file);
if (content[key] !== value) {
content[key] = value;
writeIfChanged(file, content);
}
}
module.exports = {read, readIfExists, writeIfChanged, updateIfChanged};
+36
View File
@@ -0,0 +1,36 @@
import yaml from 'js-yaml';
import fs from 'fs';
import equals from 'fast-deep-equal/es6';
function read(file: string): KeyValue {
try {
return yaml.load(fs.readFileSync(file, 'utf8'));
} catch (error) {
if (error.name === 'YAMLException') {
error.file = file;
}
throw error;
}
}
function readIfExists(file: string, default_?: KeyValue): KeyValue {
return fs.existsSync(file) ? read(file) : default_;
}
function writeIfChanged(file: string, content: KeyValue): void {
const before = readIfExists(file);
if (!equals(before, content)) {
fs.writeFileSync(file, yaml.dump(content));
}
}
function updateIfChanged(file: string, key: string, value: KeyValue): void {
const content = read(file);
if (content[key] !== value) {
content[key] = value;
writeIfChanged(file, content);
}
}
export default {read, readIfExists, updateIfChanged, writeIfChanged};

Some files were not shown because too many files have changed in this diff Show More