Compare commits

..
52 Commits
Author SHA1 Message Date
Koen Kanters 3a49c95786 chore(dev): release 2.7.2 (#30051) 2026-01-01 14:41:19 +01:00
Koen Kanters 0eba0c953d fix(ignore): update zigbee-herdsman-converters to 25.98.0 (#30417) 2026-01-01 13:23:35 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 4d6269e7e8 fix(ignore): bump zigbee2mqtt-windfront from 2.6.1 to 2.6.2 in the minor-patch group (#30412)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-31 19:56:27 +00:00
Koen Kanters 3727f078ec fix(ignore): update zigbee-herdsman-converters to 25.97.0 (#30396) 2025-12-30 14:29:46 +00:00
dependabot[bot] 93c9704fcd fix(ignore): bump @types/node from 24.10.2 to 24.10.4 in the minor-patch group (#30390) 2025-12-30 13:43:39 +01:00
Koen Kanters 2721b0ea78 fix(ignore): update zigbee-herdsman-converters to 25.96.0 (#30383) 2025-12-28 20:58:41 +00:00
Koen Kanters 4c48e9cfbc fix(ignore): update zigbee-herdsman-converters to 25.95.0 (#30371) 2025-12-27 20:42:04 +00:00
Koen Kanters 7cb5c58dc0 fix(ignore): update zigbee-herdsman-converters to 25.94.0 (#30355) 2025-12-26 14:37:38 +00:00
Koen Kanters c61f67f061 fix(ignore): update zigbee-herdsman-converters to 25.93.0 (#30331) 2025-12-23 20:58:54 +00:00
Nerivec 58d98c7263 fix: log dir tz format not working on some systems (#30324) 2025-12-23 17:45:04 +01:00
dependabot[bot]dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Nerivec
b10fa93700 fix(ignore): bump the minor-patch group with 2 updates (#30309)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nerivec <62446222+Nerivec@users.noreply.github.com>
2025-12-22 15:23:39 +00:00
Koen Kanters c28a024664 fix(ignore): update zigbee-herdsman-converters to 25.92.0 (#30300) 2025-12-21 21:28:27 +00:00
Nerivec 8549b37228 fix: Proper timezone in logs dir (#30297) 2025-12-21 20:44:05 +01:00
Koen Kanters 4c02e3da8f fix(ignore): update zigbee-herdsman-converters to 25.91.0 (#30279) 2025-12-19 21:02:06 +00:00
Koen Kanters ab0894715a fix(ignore): update zigbee-herdsman-converters to 25.90.0 (#30267) 2025-12-18 21:36:30 +00:00
Koen Kanters 1688a3b532 fix(ignore): update zigbee-herdsman to 8.0.1 (#30240) 2025-12-16 16:51:45 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 97694d2241 chore(deps): bump actions/cache from 4 to 5 (#30221)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-16 17:45:15 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> d6088c56db chore(deps): bump peter-evans/create-pull-request from 7 to 8 (#30222)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-16 17:45:06 +01:00
Koen Kanters b39b8d478e fix: Don't fail to start when removing old log directory fails (#30216) 2025-12-16 17:44:38 +01:00
Koen Kanters 01304cfc66 fix(ignore): update zigbee-herdsman-converters to 25.89.0 (#30215) 2025-12-14 20:40:29 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 1d15c2142f fix(ignore): bump the minor-patch group with 2 updates (#30207)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-14 16:40:27 +00:00
Koen Kanters 3818c50b8a fix(ignore): update zigbee-herdsman-converters to 25.88.0 (#30196) 2025-12-13 20:34:30 +00:00
Koen KantersandNerivec 7f5f6a5849 fix(ignore): update zigbee-herdsman to 8.0.0 and zigbee-herdsman-converters to 25.87.0 (#30186)
Co-authored-by: Nerivec <62446222+Nerivec@users.noreply.github.com>
2025-12-13 20:40:09 +01:00
Nerivec 0025ef87c5 fix: Biome floating promises detection (#30137) 2025-12-13 20:38:03 +01:00
Koen Kanters 3460f157df fix(ignore): update zigbee-herdsman-converters to 25.86.0 (#30143) 2025-12-10 21:14:41 +00:00
Koen Kanters ecb0af4057 fix(ignore): update zigbee-herdsman to 7.0.6 (#30142) 2025-12-10 21:11:13 +00:00
Koen Kanters 5db6ae0a19 fix(ignore): update zigbee-herdsman-converters to 25.85.0 (#30120) 2025-12-09 20:15:54 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ad3c09036b fix(ignore): bump the minor-patch group across 1 directory with 4 updates (#30117)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-09 20:33:03 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 0c89629526 chore(deps): bump alpine from 3.22 to 3.23 in /docker (#30094)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-09 20:04:22 +01:00
Koen Kanters 4574ffc71a fix(ignore): update zigbee-herdsman to 7.0.5 (#30116) 2025-12-09 18:46:55 +00:00
Koen Kanters 1707f3abf3 chore: merge master to dev 2025-12-07 21:26:17 +01:00
Koen Kanters 8916fb7b50 chore: lint issueBot 2025-12-07 21:25:58 +01:00
Koen Kanters 6e70ef24d0 chore: merge master to dev 2025-12-07 21:22:54 +01:00
Koen Kanters 8a3c4bd59f chore: issueBot: handle duplicates 2025-12-07 21:22:34 +01:00
Koen Kanters c18d1329c8 fix(ignore): update zigbee-herdsman-converters to 25.84.0 (#30081) 2025-12-07 19:56:11 +00:00
Yuxin Wang ed1e7b333f fix: Remove extra > in onboarding(#30065) 2025-12-07 20:22:04 +01:00
github-actions[bot] 95c38810a8 chore: promote to dev 2025-12-06 20:39:43 +00:00
Koen Kanters b70701f8b8 chore: fix changelog generator undefined whitelabel vendor/description 2025-12-06 21:23:09 +01:00
Koen Kanters 6d30fa156c chore(dev): release 2.7.1 (#29926) 2025-12-06 21:14:47 +01:00
Koen Kanters 9b6035387b fix(ignore): update zigbee-herdsman-converters to 25.83.1 (#30050) 2025-12-06 20:06:52 +00:00
burmistrzakandKoen Kanters 9ca85dfac8 fix: Home Assistant: Translate boolean to state topic for current_humidity_topic (#30014)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2025-12-06 20:46:27 +01:00
Koen Kanters 334fa2a60d fix(ignore): update zigbee-herdsman to 7.0.4 (#30041) 2025-12-06 13:22:31 +00:00
Koen Kanters a7f1345a91 fix(ignore): update zigbee-herdsman-converters to 25.83.0 (#30011) 2025-12-04 20:54:41 +00:00
Koen Kanters bae9bb8812 fix(ignore): update zigbee-herdsman to 7.0.3 (#30008) 2025-12-04 20:02:17 +00:00
Koen Kanters 740edd8b58 fix(ignore): update zigbee-herdsman-converters to 25.82.0 (#29990) 2025-12-03 19:29:19 +00:00
Koen Kanters 267fee3414 Revert "chore: retry 'Docker build and push' on failure"
This reverts commit 91f4b76970.
2025-12-03 20:10:50 +01:00
burmistrzak fa99c6dcca fix: Home Assistant: Accept multiple access levels for current_humidity source property (#29936) 2025-12-03 19:34:35 +01:00
Koen Kanters 91f4b76970 chore: retry 'Docker build and push' on failure 2025-12-02 21:57:12 +01:00
Koen Kanters fd4282b98d fix(ignore): update zigbee-herdsman-converters to 25.81.0 (#29959) 2025-12-02 20:48:36 +00:00
Koen Kanters 403bd4a725 fix(ignore): update zigbee-herdsman to 7.0.2 (#29956) 2025-12-02 20:16:21 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ce27ff3cbf fix(ignore): bump finalhandler from 2.1.0 to 2.1.1 in the minor-patch group (#29920)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-02 21:00:30 +01:00
github-actions[bot] 5f474e03b8 chore: promote to dev 2025-12-01 20:35:56 +00:00
23 changed files with 796 additions and 252 deletions
+2 -2
View File
@@ -42,7 +42,7 @@ jobs:
ref: master
- name: Restore cache commit-user-lookup.json
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: z2m/scripts/commit-user-lookup.json
key: commit-user-lookup-dummy
@@ -67,7 +67,7 @@ jobs:
env:
GH_TOKEN: ${{secrets.GH_TOKEN}}
- name: Save cache commit-user-lookup.json
uses: actions/cache/save@v4
uses: actions/cache/save@v5
if: always()
with:
path: z2m/scripts/commit-user-lookup.json
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
- run: |
pnpm install ${{ github.event.client_payload.package }}@${{ github.event.client_payload.version }} --save-exact
pnpm install --no-frozen-lockfile
- uses: peter-evans/create-pull-request@v7
- uses: peter-evans/create-pull-request@v8
id: cpr
with:
commit-message: 'fix(ignore): update ${{ github.event.client_payload.package }} to ${{ github.event.client_payload.version }}'
+1 -1
View File
@@ -1,3 +1,3 @@
{
".": "2.7.0"
".": "2.7.2"
}
+50
View File
@@ -1,5 +1,55 @@
# Changelog
## [2.7.2](https://github.com/Koenkk/zigbee2mqtt/compare/2.7.1...2.7.2) (2026-01-01)
### Bug Fixes
* Biome floating promises detection ([#30137](https://github.com/Koenkk/zigbee2mqtt/issues/30137)) ([0025ef8](https://github.com/Koenkk/zigbee2mqtt/commit/0025ef87c502970b94e1b720516d42631e21323c))
* Don't fail to start when removing old log directory fails ([#30216](https://github.com/Koenkk/zigbee2mqtt/issues/30216)) ([b39b8d4](https://github.com/Koenkk/zigbee2mqtt/commit/b39b8d478e99c5a5ee5a3a610547168b3724ca91))
* **ignore:** bump @types/node from 24.10.2 to 24.10.4 in the minor-patch group ([#30390](https://github.com/Koenkk/zigbee2mqtt/issues/30390)) ([93c9704](https://github.com/Koenkk/zigbee2mqtt/commit/93c9704fcd5552e234dd03a7ae1cddc11403622b))
* **ignore:** bump the minor-patch group across 1 directory with 4 updates ([#30117](https://github.com/Koenkk/zigbee2mqtt/issues/30117)) ([ad3c090](https://github.com/Koenkk/zigbee2mqtt/commit/ad3c09036b804eb108238036f22776d83ea371b2))
* **ignore:** bump the minor-patch group with 2 updates ([#30207](https://github.com/Koenkk/zigbee2mqtt/issues/30207)) ([1d15c21](https://github.com/Koenkk/zigbee2mqtt/commit/1d15c2142fefb9c7ce96c947e5ac7ddc6101439f))
* **ignore:** bump the minor-patch group with 2 updates ([#30309](https://github.com/Koenkk/zigbee2mqtt/issues/30309)) ([b10fa93](https://github.com/Koenkk/zigbee2mqtt/commit/b10fa93700febe84634040dbdeb4857258cd2882))
* **ignore:** bump zigbee2mqtt-windfront from 2.6.1 to 2.6.2 in the minor-patch group ([#30412](https://github.com/Koenkk/zigbee2mqtt/issues/30412)) ([4d6269e](https://github.com/Koenkk/zigbee2mqtt/commit/4d6269e7e89af52df0b2576925abade2f6b60e09))
* **ignore:** update zigbee-herdsman to 7.0.5 ([#30116](https://github.com/Koenkk/zigbee2mqtt/issues/30116)) ([4574ffc](https://github.com/Koenkk/zigbee2mqtt/commit/4574ffc71a799846c6a04121c3b5908f968ff0be))
* **ignore:** update zigbee-herdsman to 7.0.6 ([#30142](https://github.com/Koenkk/zigbee2mqtt/issues/30142)) ([ecb0af4](https://github.com/Koenkk/zigbee2mqtt/commit/ecb0af40575ebaadf887685c50cd1a9968cc1c68))
* **ignore:** update zigbee-herdsman to 8.0.0 and zigbee-herdsman-converters to 25.87.0 ([#30186](https://github.com/Koenkk/zigbee2mqtt/issues/30186)) ([7f5f6a5](https://github.com/Koenkk/zigbee2mqtt/commit/7f5f6a5849d940a6e5288865edf7999c41af12e2))
* **ignore:** update zigbee-herdsman to 8.0.1 ([#30240](https://github.com/Koenkk/zigbee2mqtt/issues/30240)) ([1688a3b](https://github.com/Koenkk/zigbee2mqtt/commit/1688a3b5323a8774ad2c36775fdb99f48057f72a))
* **ignore:** update zigbee-herdsman-converters to 25.84.0 ([#30081](https://github.com/Koenkk/zigbee2mqtt/issues/30081)) ([c18d132](https://github.com/Koenkk/zigbee2mqtt/commit/c18d1329c801ce48cf5277c00682ad2f9098f383))
* **ignore:** update zigbee-herdsman-converters to 25.85.0 ([#30120](https://github.com/Koenkk/zigbee2mqtt/issues/30120)) ([5db6ae0](https://github.com/Koenkk/zigbee2mqtt/commit/5db6ae0a197a180abc5e497aebe6e59fcb9b6b3c))
* **ignore:** update zigbee-herdsman-converters to 25.86.0 ([#30143](https://github.com/Koenkk/zigbee2mqtt/issues/30143)) ([3460f15](https://github.com/Koenkk/zigbee2mqtt/commit/3460f157df84d10f8de87a37d6b0b0b243de6874))
* **ignore:** update zigbee-herdsman-converters to 25.88.0 ([#30196](https://github.com/Koenkk/zigbee2mqtt/issues/30196)) ([3818c50](https://github.com/Koenkk/zigbee2mqtt/commit/3818c50b8ae516e56ad07e8fce3c451f35e1b678))
* **ignore:** update zigbee-herdsman-converters to 25.89.0 ([#30215](https://github.com/Koenkk/zigbee2mqtt/issues/30215)) ([01304cf](https://github.com/Koenkk/zigbee2mqtt/commit/01304cfc6604b86acf181dc3f07688f56ecbe8a1))
* **ignore:** update zigbee-herdsman-converters to 25.90.0 ([#30267](https://github.com/Koenkk/zigbee2mqtt/issues/30267)) ([ab08947](https://github.com/Koenkk/zigbee2mqtt/commit/ab0894715a002bd5c14d8af45a67e5e546889590))
* **ignore:** update zigbee-herdsman-converters to 25.91.0 ([#30279](https://github.com/Koenkk/zigbee2mqtt/issues/30279)) ([4c02e3d](https://github.com/Koenkk/zigbee2mqtt/commit/4c02e3da8f66cafbdcde89303bb1aea6eaf73bcd))
* **ignore:** update zigbee-herdsman-converters to 25.92.0 ([#30300](https://github.com/Koenkk/zigbee2mqtt/issues/30300)) ([c28a024](https://github.com/Koenkk/zigbee2mqtt/commit/c28a024664989fe8a044babe3cdf43403b0ee2b5))
* **ignore:** update zigbee-herdsman-converters to 25.93.0 ([#30331](https://github.com/Koenkk/zigbee2mqtt/issues/30331)) ([c61f67f](https://github.com/Koenkk/zigbee2mqtt/commit/c61f67f061d2766e99c5cb9c99c02b172832271c))
* **ignore:** update zigbee-herdsman-converters to 25.94.0 ([#30355](https://github.com/Koenkk/zigbee2mqtt/issues/30355)) ([7cb5c58](https://github.com/Koenkk/zigbee2mqtt/commit/7cb5c58dc028f86c59935b64a738444950ef8e12))
* **ignore:** update zigbee-herdsman-converters to 25.95.0 ([#30371](https://github.com/Koenkk/zigbee2mqtt/issues/30371)) ([4c48e9c](https://github.com/Koenkk/zigbee2mqtt/commit/4c48e9cfbcedb9cd6aedee9f694db2993038eaee))
* **ignore:** update zigbee-herdsman-converters to 25.96.0 ([#30383](https://github.com/Koenkk/zigbee2mqtt/issues/30383)) ([2721b0e](https://github.com/Koenkk/zigbee2mqtt/commit/2721b0ea78f4e86e6fe3b5f4831c5787a28585a8))
* **ignore:** update zigbee-herdsman-converters to 25.97.0 ([#30396](https://github.com/Koenkk/zigbee2mqtt/issues/30396)) ([3727f07](https://github.com/Koenkk/zigbee2mqtt/commit/3727f078ecde73a5c444c42909f36b4a0f35d8c3))
* **ignore:** update zigbee-herdsman-converters to 25.98.0 ([#30417](https://github.com/Koenkk/zigbee2mqtt/issues/30417)) ([0eba0c9](https://github.com/Koenkk/zigbee2mqtt/commit/0eba0c953d7543b2850a9b9672ffbc3d87840fb3))
* log dir tz format not working on some systems ([#30324](https://github.com/Koenkk/zigbee2mqtt/issues/30324)) ([58d98c7](https://github.com/Koenkk/zigbee2mqtt/commit/58d98c7263dbe687eb677199eb760799ecff8e8f))
* Proper timezone in logs dir ([#30297](https://github.com/Koenkk/zigbee2mqtt/issues/30297)) ([8549b37](https://github.com/Koenkk/zigbee2mqtt/commit/8549b372283da8b55804c4049c7341294ced1538))
* Remove extra `>` in onboarding([#30065](https://github.com/Koenkk/zigbee2mqtt/issues/30065)) ([ed1e7b3](https://github.com/Koenkk/zigbee2mqtt/commit/ed1e7b333f481a4b3a37b021f2058331b86ebd84))
## [2.7.1](https://github.com/Koenkk/zigbee2mqtt/compare/2.7.0...2.7.1) (2025-12-06)
### Bug Fixes
* Home Assistant: Accept multiple access levels for `current_humidity` source property ([#29936](https://github.com/Koenkk/zigbee2mqtt/issues/29936)) ([fa99c6d](https://github.com/Koenkk/zigbee2mqtt/commit/fa99c6dcca97d2c8c90136249293dea3d42e0998))
* Home Assistant: Translate boolean to state topic for `current_humidity_topic` ([#30014](https://github.com/Koenkk/zigbee2mqtt/issues/30014)) ([9ca85df](https://github.com/Koenkk/zigbee2mqtt/commit/9ca85dfac8b0f0421ad0622dfdbe36c8766d22b4))
* **ignore:** bump finalhandler from 2.1.0 to 2.1.1 in the minor-patch group ([#29920](https://github.com/Koenkk/zigbee2mqtt/issues/29920)) ([ce27ff3](https://github.com/Koenkk/zigbee2mqtt/commit/ce27ff3cbfac204579b38d034e71733e4e4bb18f))
* **ignore:** update zigbee-herdsman to 7.0.2 ([#29956](https://github.com/Koenkk/zigbee2mqtt/issues/29956)) ([403bd4a](https://github.com/Koenkk/zigbee2mqtt/commit/403bd4a72541bf7342de246b033c5090b186df32))
* **ignore:** update zigbee-herdsman to 7.0.3 ([#30008](https://github.com/Koenkk/zigbee2mqtt/issues/30008)) ([bae9bb8](https://github.com/Koenkk/zigbee2mqtt/commit/bae9bb8812c81e46d4068b4284e0f9957821f88a))
* **ignore:** update zigbee-herdsman to 7.0.4 ([#30041](https://github.com/Koenkk/zigbee2mqtt/issues/30041)) ([334fa2a](https://github.com/Koenkk/zigbee2mqtt/commit/334fa2a60d04c66749978b8b8f4b9b5af6c7c7eb))
* **ignore:** update zigbee-herdsman-converters to 25.81.0 ([#29959](https://github.com/Koenkk/zigbee2mqtt/issues/29959)) ([fd4282b](https://github.com/Koenkk/zigbee2mqtt/commit/fd4282b98d9630f9a98e82f627c12c5920d810b4))
* **ignore:** update zigbee-herdsman-converters to 25.82.0 ([#29990](https://github.com/Koenkk/zigbee2mqtt/issues/29990)) ([740edd8](https://github.com/Koenkk/zigbee2mqtt/commit/740edd8b58b7d72b7a2a5247f7f6ac8ee99ff0fa))
* **ignore:** update zigbee-herdsman-converters to 25.83.0 ([#30011](https://github.com/Koenkk/zigbee2mqtt/issues/30011)) ([a7f1345](https://github.com/Koenkk/zigbee2mqtt/commit/a7f1345a9164f6c83cb81688c33511b14646fab8))
* **ignore:** update zigbee-herdsman-converters to 25.83.1 ([#30050](https://github.com/Koenkk/zigbee2mqtt/issues/30050)) ([9b60353](https://github.com/Koenkk/zigbee2mqtt/commit/9b6035387be6f285fab455f7845baa75f3f722be))
## [2.7.0](https://github.com/Koenkk/zigbee2mqtt/compare/2.6.3...2.7.0) (2025-12-01)
+7 -2
View File
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
@@ -12,7 +12,7 @@
"bracketSpacing": false
},
"files": {
"includes": ["**", "!package.json"]
"includes": ["**", "!package.json", "!!**/dist", "!!**/coverage"]
},
"linter": {
"includes": ["**"],
@@ -72,6 +72,11 @@
"suspicious": {
"noConstEnum": "off",
"useAwait": "error"
},
"nursery": {
"useExhaustiveSwitchCases": "error",
"noFloatingPromises": "error",
"noMisusedPromises": "error"
}
}
},
+1 -1
View File
@@ -1,6 +1,6 @@
ARG TARGETPLATFORM
FROM alpine:3.22 AS base
FROM alpine:3.23 AS base
ENV NODE_ENV=production
WORKDIR /app
+2 -2
View File
@@ -174,11 +174,11 @@ async function handleQuit() {
if (require.main === module || require.main.filename.endsWith(`${path.sep}cli.js`)) {
if (process.argv.length === 3 && process.argv[2] === "writehash") {
writeHash();
void writeHash();
} else {
process.on("SIGINT", handleQuit);
process.on("SIGTERM", handleQuit);
start();
void start();
}
} else {
process.on("SIGINT", handleQuit);
+8 -7
View File
@@ -99,7 +99,11 @@ export class Controller {
// Start zigbee
try {
await this.zigbee.start();
this.eventBus.onAdapterDisconnected(this, this.onZigbeeAdapterDisconnected);
this.eventBus.onAdapterDisconnected(this, async () => {
logger.error("Adapter disconnected, stopping");
await this.stop(false, 2);
});
} catch (error) {
logger.error("Failed to start zigbee-herdsman");
logger.error(
@@ -157,7 +161,9 @@ export class Controller {
}
}
this.eventBus.onLastSeenChanged(this, (data) => utils.publishLastSeen(data, settings.get(), false, this.publishEntityState));
this.eventBus.onLastSeenChanged(this, (data) => {
utils.publishLastSeen(data, settings.get(), false, this.publishEntityState).catch(() => {});
});
logger.info("Zigbee2MQTT started!");
@@ -317,11 +323,6 @@ export class Controller {
return await this.exitCallback(code, restart);
}
@bind async onZigbeeAdapterDisconnected(): Promise<void> {
logger.error("Adapter disconnected, stopping");
await this.stop(false, 2);
}
@bind async publishEntityState(entity: Group | Device, payload: KeyValue, stateChangeReason?: StateChangeReason): Promise<void> {
let message: Zigbee2MQTTAPI["{friendlyName}"] = {...payload};
+1 -1
View File
@@ -61,7 +61,7 @@ export default class EventBus {
public emitAdapterDisconnected(): void {
this.emitter.emit("adapterDisconnected");
}
public onAdapterDisconnected(key: ListenerKey, callback: () => void): void {
public onAdapterDisconnected(key: ListenerKey, callback: () => Promise<void>): void {
this.on("adapterDisconnected", callback, key);
}
+5 -1
View File
@@ -752,7 +752,7 @@ export class HomeAssistant extends Extension {
discoveryEntries.push(discoveryEntry);
}
const currentHumidity = allExposes?.filter(isNumericExpose).find((e) => e.name === "humidity" && e.access === ACCESS_STATE);
const currentHumidity = allExposes?.filter(isNumericExpose).find((e) => e.name === "humidity" && e.access & ACCESS_STATE);
if (currentHumidity) {
discoveryEntry.discovery_payload.current_humidity_template = `{{ value_json.${currentHumidity.property} }}`;
discoveryEntry.discovery_payload.current_humidity_topic = true;
@@ -1681,6 +1681,10 @@ export class HomeAssistant extends Extension {
payload.action_topic = stateTopic;
}
if (payload.current_humidity_topic) {
payload.current_humidity_topic = stateTopic;
}
// Override configuration with user settings.
if (entity.options.homeassistant != null) {
const add = (obj: KeyValue, ignoreName: boolean): void => {
+23 -18
View File
@@ -9,27 +9,25 @@ import * as settings from "./settings";
const NAMESPACE_SEPARATOR = ":";
class Logger {
// @ts-expect-error initalized in `init`
private level: settings.LogLevel;
// @ts-expect-error initalized in `init`
private output: string[];
// @ts-expect-error initalized in `init`
private directory: string;
// @ts-expect-error initalized in `init`
private logger: winston.Logger;
// @ts-expect-error initalized in `init`
private fileTransport: winston.transports.FileTransportInstance;
private level!: settings.LogLevel;
private output!: string[];
private directory!: string;
private logger!: winston.Logger;
private fileTransport: winston.transports.FileTransportInstance | undefined;
private debugNamespaceIgnoreRegex?: RegExp;
// @ts-expect-error initalized in `init`
private namespacedLevels: Record<string, settings.LogLevel>;
// @ts-expect-error initalized in `init`
private cachedNamespacedLevels: Record<string, settings.LogLevel>;
private namespacedLevels!: Record<string, settings.LogLevel>;
private cachedNamespacedLevels!: Record<string, settings.LogLevel>;
public init(): void {
// What transports to enable
this.output = settings.get().advanced.log_output;
// Directory to log to
const timestamp = new Date().toISOString().slice(0, 19).replace("T", ".").replace(/:/g, "-");
const date = new Date();
// offset UTC by current timezone, ISO keeps "Z" (UTC) which is then wrong but we strip it
const timestamp = new Date(date.getTime() - date.getTimezoneOffset() * 60000)
.toISOString()
.slice(0, 19)
.replace("T", ".")
.replaceAll(":", "-");
this.directory = settings.get().advanced.log_directory.replace("%TIMESTAMP%", timestamp);
const logFilename = settings.get().advanced.log_file.replace("%TIMESTAMP%", timestamp);
this.level = settings.get().advanced.log_level;
@@ -240,7 +238,11 @@ class Logger {
for (const dir of directories) {
this.debug(`Removing old log directory '${dir.path}'`);
rimrafSync(dir.path);
try {
rimrafSync(dir.path);
} catch (e) {
this.error(`Failed to remove old log directory '${dir.path}': ${e}`);
}
}
}
}
@@ -262,7 +264,10 @@ class Logger {
// @ts-expect-error workaround
this.fileTransport.on("open", () => this.fileTransport._dest.on("finish", resolve));
}
this.fileTransport.end();
if (this.fileTransport) {
this.fileTransport.end();
}
});
}
}
+1 -1
View File
@@ -146,7 +146,7 @@ function generateHtmlForm(currentSettings: RecursivePartial<Settings>, devices:
id="serial_rtscts"
name="serial_rtscts"
${currentSettings.serial?.rtscts ? "checked" : ""}
${process.env.ZIGBEE2MQTT_CONFIG_SERIAL_RTSCTS ? "disabled" : ""}>
${process.env.ZIGBEE2MQTT_CONFIG_SERIAL_RTSCTS ? "disabled" : ""}
style="margin-bottom: 1rem;">
<small>Can be ignored for networked coordinators (TCP).</small>
</fieldset>
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "zigbee2mqtt",
"version": "2.7.0",
"version": "2.7.2",
"description": "Zigbee to MQTT bridge using Zigbee-herdsman",
"main": "index.js",
"types": "dist/types/api.d.ts",
@@ -47,8 +47,8 @@
"debounce": "^3.0.0",
"express-static-gzip": "^3.0.0",
"fast-deep-equal": "^3.1.3",
"finalhandler": "^2.1.0",
"humanize-duration": "^3.33.1",
"finalhandler": "^2.1.1",
"humanize-duration": "^3.33.2",
"js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"jszip": "^3.10.1",
@@ -58,23 +58,23 @@
"semver": "^7.7.3",
"source-map-support": "^0.5.21",
"throttleit": "^2.1.0",
"winston": "^3.18.3",
"winston": "^3.19.0",
"winston-syslog": "^2.7.1",
"winston-transport": "^4.9.0",
"ws": "^8.18.1",
"zigbee-herdsman": "7.0.1",
"zigbee-herdsman-converters": "25.80.0",
"zigbee-herdsman": "8.0.1",
"zigbee-herdsman-converters": "25.98.0",
"zigbee2mqtt-frontend": "0.9.21",
"zigbee2mqtt-windfront": "2.4.2"
"zigbee2mqtt-windfront": "2.6.2"
},
"devDependencies": {
"@biomejs/biome": "^2.3.8",
"@biomejs/biome": "^2.3.10",
"@types/finalhandler": "^1.2.3",
"@types/humanize-duration": "^3.27.4",
"@types/js-yaml": "^4.0.9",
"@types/node": "^24.10.1",
"@types/node": "^24.10.4",
"@types/object-assign-deep": "^0.4.3",
"@types/readable-stream": "4.0.22",
"@types/readable-stream": "4.0.23",
"@types/serve-static": "^2.2.0",
"@types/ws": "8.18.1",
"@vitest/coverage-v8": "^3.1.1",
+138 -132
View File
@@ -5,7 +5,7 @@ settings:
excludeLinksFromLockfile: false
overrides:
zigbee-herdsman: 7.0.1
zigbee-herdsman: 8.0.1
importers:
@@ -27,11 +27,11 @@ importers:
specifier: ^3.1.3
version: 3.1.3
finalhandler:
specifier: ^2.1.0
version: 2.1.0
specifier: ^2.1.1
version: 2.1.1
humanize-duration:
specifier: ^3.33.1
version: 3.33.1
specifier: ^3.33.2
version: 3.33.2
js-yaml:
specifier: ^4.1.0
version: 4.1.1
@@ -60,11 +60,11 @@ importers:
specifier: ^2.1.0
version: 2.1.0
winston:
specifier: ^3.18.3
version: 3.18.3
specifier: ^3.19.0
version: 3.19.0
winston-syslog:
specifier: ^2.7.1
version: 2.7.1(winston@3.18.3)
version: 2.7.1(winston@3.19.0)
winston-transport:
specifier: ^4.9.0
version: 4.9.0
@@ -72,21 +72,21 @@ importers:
specifier: ^8.18.1
version: 8.18.3
zigbee-herdsman:
specifier: 7.0.1
version: 7.0.1
specifier: 8.0.1
version: 8.0.1
zigbee-herdsman-converters:
specifier: 25.80.0
version: 25.80.0
specifier: 25.98.0
version: 25.98.0
zigbee2mqtt-frontend:
specifier: 0.9.21
version: 0.9.21
zigbee2mqtt-windfront:
specifier: 2.4.2
version: 2.4.2
specifier: 2.6.2
version: 2.6.2
devDependencies:
'@biomejs/biome':
specifier: ^2.3.8
version: 2.3.8
specifier: ^2.3.10
version: 2.3.10
'@types/finalhandler':
specifier: ^1.2.3
version: 1.2.4
@@ -97,14 +97,14 @@ importers:
specifier: ^4.0.9
version: 4.0.9
'@types/node':
specifier: ^24.10.1
version: 24.10.1
specifier: ^24.10.4
version: 24.10.4
'@types/object-assign-deep':
specifier: ^0.4.3
version: 0.4.3
'@types/readable-stream':
specifier: 4.0.22
version: 4.0.22
specifier: 4.0.23
version: 4.0.23
'@types/serve-static':
specifier: ^2.2.0
version: 2.2.0
@@ -113,7 +113,7 @@ importers:
version: 8.18.1
'@vitest/coverage-v8':
specifier: ^3.1.1
version: 3.2.4(vitest@3.2.4(@types/node@24.10.1))
version: 3.2.4(vitest@3.2.4(@types/node@24.10.4))
tmp:
specifier: ^0.2.5
version: 0.2.5
@@ -122,7 +122,7 @@ importers:
version: 5.9.3
vitest:
specifier: ^3.1.1
version: 3.2.4(@types/node@24.10.1)
version: 3.2.4(@types/node@24.10.4)
optionalDependencies:
unix-dgram:
specifier: ^2.0.7
@@ -159,55 +159,55 @@ packages:
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
'@biomejs/biome@2.3.8':
resolution: {integrity: sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA==}
'@biomejs/biome@2.3.10':
resolution: {integrity: sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ==}
engines: {node: '>=14.21.3'}
hasBin: true
'@biomejs/cli-darwin-arm64@2.3.8':
resolution: {integrity: sha512-HM4Zg9CGQ3txTPflxD19n8MFPrmUAjaC7PQdLkugeeC0cQ+PiVrd7i09gaBS/11QKsTDBJhVg85CEIK9f50Qww==}
'@biomejs/cli-darwin-arm64@2.3.10':
resolution: {integrity: sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [darwin]
'@biomejs/cli-darwin-x64@2.3.8':
resolution: {integrity: sha512-lUDQ03D7y/qEao7RgdjWVGCu+BLYadhKTm40HkpJIi6kn8LSv5PAwRlew/DmwP4YZ9ke9XXoTIQDO1vAnbRZlA==}
'@biomejs/cli-darwin-x64@2.3.10':
resolution: {integrity: sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [darwin]
'@biomejs/cli-linux-arm64-musl@2.3.8':
resolution: {integrity: sha512-PShR4mM0sjksUMyxbyPNMxoKFPVF48fU8Qe8Sfx6w6F42verbwRLbz+QiKNiDPRJwUoMG1nPM50OBL3aOnTevA==}
'@biomejs/cli-linux-arm64-musl@2.3.10':
resolution: {integrity: sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
'@biomejs/cli-linux-arm64@2.3.8':
resolution: {integrity: sha512-Uo1OJnIkJgSgF+USx970fsM/drtPcQ39I+JO+Fjsaa9ZdCN1oysQmy6oAGbyESlouz+rzEckLTF6DS7cWse95g==}
'@biomejs/cli-linux-arm64@2.3.10':
resolution: {integrity: sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
'@biomejs/cli-linux-x64-musl@2.3.8':
resolution: {integrity: sha512-YGLkqU91r1276uwSjiUD/xaVikdxgV1QpsicT0bIA1TaieM6E5ibMZeSyjQ/izBn4tKQthUSsVZacmoJfa3pDA==}
'@biomejs/cli-linux-x64-musl@2.3.10':
resolution: {integrity: sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
'@biomejs/cli-linux-x64@2.3.8':
resolution: {integrity: sha512-QDPMD5bQz6qOVb3kiBui0zKZXASLo0NIQ9JVJio5RveBEFgDgsvJFUvZIbMbUZT3T00M/1wdzwWXk4GIh0KaAw==}
'@biomejs/cli-linux-x64@2.3.10':
resolution: {integrity: sha512-wwAkWD1MR95u+J4LkWP74/vGz+tRrIQvr8kfMMJY8KOQ8+HMVleREOcPYsQX82S7uueco60L58Wc6M1I9WA9Dw==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
'@biomejs/cli-win32-arm64@2.3.8':
resolution: {integrity: sha512-H4IoCHvL1fXKDrTALeTKMiE7GGWFAraDwBYFquE/L/5r1927Te0mYIGseXi4F+lrrwhSWbSGt5qPFswNoBaCxg==}
'@biomejs/cli-win32-arm64@2.3.10':
resolution: {integrity: sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [win32]
'@biomejs/cli-win32-x64@2.3.8':
resolution: {integrity: sha512-RguzimPoZWtBapfKhKjcWXBVI91tiSprqdBYu7tWhgN8pKRZhw24rFeNZTNf6UiBfjCYCi9eFQs/JzJZIhuK4w==}
'@biomejs/cli-win32-x64@2.3.10':
resolution: {integrity: sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [win32]
@@ -557,14 +557,14 @@ packages:
'@types/js-yaml@4.0.9':
resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==}
'@types/node@24.10.1':
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
'@types/node@24.10.4':
resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==}
'@types/object-assign-deep@0.4.3':
resolution: {integrity: sha512-d9Gxaj5j1hzrxJ61EFEg13B4g4FgrT/DYtcDWFXPehR8DF2SUZbVMFtZIs8exkVRiqrqBpdTc/lUUZjncsPpMw==}
'@types/readable-stream@4.0.22':
resolution: {integrity: sha512-/FFhJpfCLAPwAcN3mFycNUa77ddnr8jTgF5VmSNetaemWB2cIlfCA9t0YTM3JAT0wOcv8D4tjPo7pkDhK3EJIg==}
'@types/readable-stream@4.0.23':
resolution: {integrity: sha512-wwXrtQvbMHxCbBgjHaMGEmImFTQxxpfMOR/ZoQnXxB1woqkUbdLGFDgauo00Py9IudiaqSeiBiulSV9i6XIPig==}
'@types/serve-static@2.2.0':
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
@@ -695,23 +695,23 @@ packages:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-convert@3.1.2:
resolution: {integrity: sha512-UNqkvCDXstVck3kdowtOTWROIJQwafjOfXSmddoDrXo4cewMKmusCeF22Q24zvjR8nwWib/3S/dfyzPItPEiJg==}
color-convert@3.1.3:
resolution: {integrity: sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==}
engines: {node: '>=14.6'}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
color-name@2.0.2:
resolution: {integrity: sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==}
color-name@2.1.0:
resolution: {integrity: sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==}
engines: {node: '>=12.20'}
color-string@2.1.2:
resolution: {integrity: sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA==}
color-string@2.1.4:
resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==}
engines: {node: '>=18'}
color@5.0.2:
resolution: {integrity: sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA==}
color@5.0.3:
resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==}
engines: {node: '>=18'}
commist@3.2.0:
@@ -847,9 +847,9 @@ packages:
file-uri-to-path@1.0.0:
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
finalhandler@2.1.0:
resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
engines: {node: '>= 0.8'}
finalhandler@2.1.1:
resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==}
engines: {node: '>= 18.0.0'}
fn.name@1.1.0:
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
@@ -893,11 +893,11 @@ packages:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
humanize-duration@3.33.1:
resolution: {integrity: sha512-hwzSCymnRdFx9YdRkQQ0OYequXiVAV6ZGQA2uzocwB0F4309Ke6pO8dg0P8LHhRQJyVjGteRTAA/zNfEcpXn8A==}
humanize-duration@3.33.2:
resolution: {integrity: sha512-K7Ny/ULO1hDm2nnhvAY+SJV1skxFb61fd073SG1IWJl+D44ULrruCuTyjHKjBVVcSuTlnY99DKtgEG39CM5QOQ==}
iconv-lite@0.7.0:
resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
iconv-lite@0.7.1:
resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==}
engines: {node: '>=0.10.0'}
ieee754@1.2.1:
@@ -1229,6 +1229,10 @@ packages:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
statuses@2.0.2:
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
engines: {node: '>= 0.8'}
std-env@3.9.0:
resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
@@ -1427,8 +1431,8 @@ packages:
resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==}
engines: {node: '>= 12.0.0'}
winston@3.18.3:
resolution: {integrity: sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww==}
winston@3.19.0:
resolution: {integrity: sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==}
engines: {node: '>= 12.0.0'}
worker-factory@7.0.45:
@@ -1463,23 +1467,23 @@ packages:
utf-8-validate:
optional: true
zigbee-herdsman-converters@25.80.0:
resolution: {integrity: sha512-dJSN/Uo3MkGeSB11Afh1BwIRi64+ig5dxOElGUH7Ac1jbDMLSTx8WSTA52d8VcpXUneM4P5pagPlb/7WjFXMKg==}
zigbee-herdsman-converters@25.98.0:
resolution: {integrity: sha512-GBLmtRnxAvWRxb6fnAGjq3OmZq1mnO3XfH5HgL5apy1iirTzvshVkPdZ3YwNbK2KYRNrmQEtYjugDNMj5IOopw==}
engines: {node: '>=20.15.0'}
zigbee-herdsman@7.0.1:
resolution: {integrity: sha512-XHfngXqc0G9cUN/YXivbhdNKX2NapxQ38F+ZWboF0VGJ6ZkiMNpGTO9Wnq6DpveBKHpcYJFlMbenDF5IxEW4qQ==}
zigbee-herdsman@8.0.1:
resolution: {integrity: sha512-avIIufN1QNAvFWw9U1IzqvstbpEznk8PLAJwCF7BgXhtKEsTUAujB3JzKc7mnhgVTyQRmVytoEDD7UpUuurjSw==}
zigbee-on-host@0.2.2:
resolution: {integrity: sha512-GixjVXTWDaLAN2650vuafv+KUY0JbwsCg5n8dsarFvCREkQw1B5DbQjbMs2Gz1+aRto2QtKfU7tkdDEa5JtIUg==}
zigbee-on-host@0.2.4:
resolution: {integrity: sha512-NIG6CWp+Yfn7PjqEIRvenHqpwT1U7rSkyimnFOUIFpnmxQOJKrmcwWDfn6WjbU/YIYYWSQPlj+g13icu1xwlyg==}
engines: {node: ^20.19.0 || >=22.12.0}
zigbee2mqtt-frontend@0.9.21:
resolution: {integrity: sha512-ClHYlG7g0v/tnIsD6kycNCi1ZEKIbQuU7lGJR3WqYcDmuqEMVcHDGbRiRwYRQcZGMxkqCf7guxNsXiKnC10+kg==}
engines: {node: '>=20.11'}
zigbee2mqtt-windfront@2.4.2:
resolution: {integrity: sha512-Tp77ZQ0yaQzeLOpgfWnkcKrMddjwnWwFHQxmtssbTVHvJUFpTQgB2Pbezj6ji5Wlr1xa8m8/J6S5dQms1TpQOg==}
zigbee2mqtt-windfront@2.6.2:
resolution: {integrity: sha512-WymwIUskBJo+71DBn9bHenqCw5bEk5HZ5YucjrPGp6Ju4cYyDaQHFAKEOHR0gQRWy/1m0Inl+Rcl5JpINmMkzw==}
engines: {node: '>=22.12.0'}
snapshots:
@@ -1506,39 +1510,39 @@ snapshots:
'@bcoe/v8-coverage@1.0.2': {}
'@biomejs/biome@2.3.8':
'@biomejs/biome@2.3.10':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 2.3.8
'@biomejs/cli-darwin-x64': 2.3.8
'@biomejs/cli-linux-arm64': 2.3.8
'@biomejs/cli-linux-arm64-musl': 2.3.8
'@biomejs/cli-linux-x64': 2.3.8
'@biomejs/cli-linux-x64-musl': 2.3.8
'@biomejs/cli-win32-arm64': 2.3.8
'@biomejs/cli-win32-x64': 2.3.8
'@biomejs/cli-darwin-arm64': 2.3.10
'@biomejs/cli-darwin-x64': 2.3.10
'@biomejs/cli-linux-arm64': 2.3.10
'@biomejs/cli-linux-arm64-musl': 2.3.10
'@biomejs/cli-linux-x64': 2.3.10
'@biomejs/cli-linux-x64-musl': 2.3.10
'@biomejs/cli-win32-arm64': 2.3.10
'@biomejs/cli-win32-x64': 2.3.10
'@biomejs/cli-darwin-arm64@2.3.8':
'@biomejs/cli-darwin-arm64@2.3.10':
optional: true
'@biomejs/cli-darwin-x64@2.3.8':
'@biomejs/cli-darwin-x64@2.3.10':
optional: true
'@biomejs/cli-linux-arm64-musl@2.3.8':
'@biomejs/cli-linux-arm64-musl@2.3.10':
optional: true
'@biomejs/cli-linux-arm64@2.3.8':
'@biomejs/cli-linux-arm64@2.3.10':
optional: true
'@biomejs/cli-linux-x64-musl@2.3.8':
'@biomejs/cli-linux-x64-musl@2.3.10':
optional: true
'@biomejs/cli-linux-x64@2.3.8':
'@biomejs/cli-linux-x64@2.3.10':
optional: true
'@biomejs/cli-win32-arm64@2.3.8':
'@biomejs/cli-win32-arm64@2.3.10':
optional: true
'@biomejs/cli-win32-x64@2.3.8':
'@biomejs/cli-win32-x64@2.3.10':
optional: true
'@colors/colors@1.6.0': {}
@@ -1752,7 +1756,7 @@ snapshots:
'@so-ric/colorspace@1.1.6':
dependencies:
color: 5.0.2
color: 5.0.3
text-hex: 1.0.0
'@types/chai@5.2.2':
@@ -1765,7 +1769,7 @@ snapshots:
'@types/finalhandler@1.2.4':
dependencies:
'@types/node': 24.10.1
'@types/node': 24.10.4
'@types/http-errors@2.0.5': {}
@@ -1773,28 +1777,28 @@ snapshots:
'@types/js-yaml@4.0.9': {}
'@types/node@24.10.1':
'@types/node@24.10.4':
dependencies:
undici-types: 7.16.0
'@types/object-assign-deep@0.4.3': {}
'@types/readable-stream@4.0.22':
'@types/readable-stream@4.0.23':
dependencies:
'@types/node': 24.10.1
'@types/node': 24.10.4
'@types/serve-static@2.2.0':
dependencies:
'@types/http-errors': 2.0.5
'@types/node': 24.10.1
'@types/node': 24.10.4
'@types/triple-beam@1.3.5': {}
'@types/ws@8.18.1':
dependencies:
'@types/node': 24.10.1
'@types/node': 24.10.4
'@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@24.10.1))':
'@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@24.10.4))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2
@@ -1809,7 +1813,7 @@ snapshots:
std-env: 3.9.0
test-exclude: 7.0.1
tinyrainbow: 2.0.0
vitest: 3.2.4(@types/node@24.10.1)
vitest: 3.2.4(@types/node@24.10.4)
transitivePeerDependencies:
- supports-color
@@ -1821,13 +1825,13 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
'@vitest/mocker@3.2.4(vite@6.3.5(@types/node@24.10.1))':
'@vitest/mocker@3.2.4(vite@6.3.5(@types/node@24.10.4))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
vite: 6.3.5(@types/node@24.10.1)
vite: 6.3.5(@types/node@24.10.4)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -1901,7 +1905,7 @@ snapshots:
bl@6.1.3:
dependencies:
'@types/readable-stream': 4.0.22
'@types/readable-stream': 4.0.23
buffer: 6.0.3
inherits: 2.0.4
readable-stream: 4.7.0
@@ -1945,22 +1949,22 @@ snapshots:
dependencies:
color-name: 1.1.4
color-convert@3.1.2:
color-convert@3.1.3:
dependencies:
color-name: 2.0.2
color-name: 2.1.0
color-name@1.1.4: {}
color-name@2.0.2: {}
color-name@2.1.0: {}
color-string@2.1.2:
color-string@2.1.4:
dependencies:
color-name: 2.0.2
color-name: 2.1.0
color@5.0.2:
color@5.0.3:
dependencies:
color-convert: 3.1.2
color-string: 2.1.2
color-convert: 3.1.3
color-string: 2.1.4
commist@3.2.0: {}
@@ -2083,14 +2087,14 @@ snapshots:
file-uri-to-path@1.0.0:
optional: true
finalhandler@2.1.0:
finalhandler@2.1.1:
dependencies:
debug: 4.4.0
debug: 4.4.3
encodeurl: 2.0.0
escape-html: 1.0.3
on-finished: 2.4.1
parseurl: 1.3.3
statuses: 2.0.1
statuses: 2.0.2
transitivePeerDependencies:
- supports-color
@@ -2137,9 +2141,9 @@ snapshots:
statuses: 2.0.1
toidentifier: 1.0.1
humanize-duration@3.33.1: {}
humanize-duration@3.33.2: {}
iconv-lite@0.7.0:
iconv-lite@0.7.1:
dependencies:
safer-buffer: 2.1.2
@@ -2270,7 +2274,7 @@ snapshots:
mqtt@5.14.1:
dependencies:
'@types/readable-stream': 4.0.22
'@types/readable-stream': 4.0.23
'@types/ws': 8.18.1
commist: 3.2.0
concat-stream: 2.0.0
@@ -2443,7 +2447,7 @@ snapshots:
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.1
statuses: 2.0.2
transitivePeerDependencies:
- supports-color
@@ -2496,6 +2500,8 @@ snapshots:
statuses@2.0.1: {}
statuses@2.0.2: {}
std-env@3.9.0: {}
string-width@4.2.3:
@@ -2589,13 +2595,13 @@ snapshots:
util-deprecate@1.0.2: {}
vite-node@3.2.4(@types/node@24.10.1):
vite-node@3.2.4(@types/node@24.10.4):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 6.3.5(@types/node@24.10.1)
vite: 6.3.5(@types/node@24.10.4)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -2610,7 +2616,7 @@ snapshots:
- tsx
- yaml
vite@6.3.5(@types/node@24.10.1):
vite@6.3.5(@types/node@24.10.4):
dependencies:
esbuild: 0.25.5
fdir: 6.4.6(picomatch@4.0.2)
@@ -2619,14 +2625,14 @@ snapshots:
rollup: 4.44.0
tinyglobby: 0.2.14
optionalDependencies:
'@types/node': 24.10.1
'@types/node': 24.10.4
fsevents: 2.3.3
vitest@3.2.4(@types/node@24.10.1):
vitest@3.2.4(@types/node@24.10.4):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@24.10.1))
'@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@24.10.4))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -2644,11 +2650,11 @@ snapshots:
tinyglobby: 0.2.14
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 6.3.5(@types/node@24.10.1)
vite-node: 3.2.4(@types/node@24.10.1)
vite: 6.3.5(@types/node@24.10.4)
vite-node: 3.2.4(@types/node@24.10.4)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 24.10.1
'@types/node': 24.10.4
transitivePeerDependencies:
- jiti
- less
@@ -2672,11 +2678,11 @@ snapshots:
siginfo: 2.0.0
stackback: 0.0.2
winston-syslog@2.7.1(winston@3.18.3):
winston-syslog@2.7.1(winston@3.19.0):
dependencies:
glossy: 0.1.7
triple-beam: 1.4.1
winston: 3.18.3
winston: 3.19.0
winston-transport: 4.9.0
optionalDependencies:
unix-dgram: 2.0.6
@@ -2687,7 +2693,7 @@ snapshots:
readable-stream: 3.6.2
triple-beam: 1.4.1
winston@3.18.3:
winston@3.19.0:
dependencies:
'@colors/colors': 1.6.0
'@dabh/diagnostics': 2.0.8
@@ -2742,15 +2748,15 @@ snapshots:
ws@8.18.3: {}
zigbee-herdsman-converters@25.80.0:
zigbee-herdsman-converters@25.98.0:
dependencies:
iconv-lite: 0.7.0
iconv-lite: 0.7.1
semver: 7.7.3
zigbee-herdsman: 7.0.1
zigbee-herdsman: 8.0.1
transitivePeerDependencies:
- supports-color
zigbee-herdsman@7.0.1:
zigbee-herdsman@8.0.1:
dependencies:
'@date-fns/tz': 1.4.1
'@serialport/bindings-cpp': 13.0.1
@@ -2761,12 +2767,12 @@ snapshots:
fast-deep-equal: 3.1.3
mixin-deep: 2.0.1
slip: 1.0.2
zigbee-on-host: 0.2.2
zigbee-on-host: 0.2.4
transitivePeerDependencies:
- supports-color
zigbee-on-host@0.2.2: {}
zigbee-on-host@0.2.4: {}
zigbee2mqtt-frontend@0.9.21: {}
zigbee2mqtt-windfront@2.4.2: {}
zigbee2mqtt-windfront@2.6.2: {}
+7 -1
View File
@@ -59,7 +59,13 @@ if (fs.existsSync(commitUserFile)) {
}
const definitions = definitionIndex.default.map((d) => zhc.prepareDefinition(d));
const whiteLabels = definitions.filter((d) => d.whiteLabel).flatMap((d) => d.whiteLabel);
const whiteLabels = definitions
.filter((d) => d.whiteLabel)
.flatMap((d) =>
d.whiteLabel.map((wl) => {
return {model: wl.model, vendor: wl.vendor ?? d.vendor, description: wl.description ?? d.description};
}),
);
const capitalizeFirstChar = (str) => str.charAt(0).toUpperCase() + str.slice(1);
for (const changelog of changelogs) {
+37
View File
@@ -1,5 +1,40 @@
import {execSync} from "node:child_process";
async function checkDuplicateIssue(github, context, name) {
// Search for existing issues with the same `name`
const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:issue -is:pr "${name}" label:"new device support","external converter"`;
try {
const searchResults = await github.rest.search.issuesAndPullRequests({q: searchQuery, per_page: 100});
// Filter out the current issue and return the first duplicate found
const existingIssues = searchResults.data.items.filter((item) => item.number !== context.payload.issue.number).map((i) => `#${i.number}`);
if (existingIssues.length > 0) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
body: `👋 Hi there! This issue appears to be a duplicate of ${existingIssues.join(", ")}
This issue will be closed. Please follow the existing issue for updates.`,
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
state: "closed",
});
return true;
}
} catch (error) {
console.error(`Error searching for duplicate issues with ${name}:`, error);
}
return false;
}
export async function newDeviceSupport(github, _core, context, zhcDir) {
const issue = context.payload.issue;
// Hide previous bot comments
@@ -27,6 +62,7 @@ export async function newDeviceSupport(github, _core, context, zhcDir) {
console.log("Found tuyaManufacturerNames", tuyaManufacturerNames);
if (tuyaManufacturerNames.length > 0) {
for (const [fullName, partialName] of tuyaManufacturerNames) {
if (await checkDuplicateIssue(github, context, fullName)) return;
const fullMatch = (() => {
try {
return execSync(`grep -r --include="*.ts" "${fullName}" "${zhcDir}"`, {encoding: "utf8"});
@@ -93,6 +129,7 @@ Let us know if it works so we can support this device out-of-the-box!`,
if (zigbeeModels.length > 0) {
for (const zigbeeModel of zigbeeModels) {
if (await checkDuplicateIssue(github, context, fullName)) return;
const fullMatch = (() => {
try {
return execSync(`grep -r --include="*.ts" '"${zigbeeModel}"' "${zhcDir}"`, {encoding: "utf8"});
+1 -1
View File
@@ -91,4 +91,4 @@ if (processArgs.length !== 1) {
const eraser = new ZStackNvMemEraser(processArgs[0]);
eraser.start();
void eraser.start();
+1
View File
@@ -164,6 +164,7 @@ describe("Extension: Bridge", () => {
"0x0017880104a44559": {friendly_name: "J1_cover"},
"0x0017880104e43559": {friendly_name: "U202DST600ZB"},
"0x0017880104e44559": {friendly_name: "3157100_thermostat"},
"0x18fc2600000d7ae3": {friendly_name: "bosch_rm230z"},
"0x0017880104e45517": {friendly_name: "remote", retain: true},
"0x0017880104e45520": {friendly_name: "button", retain: false},
"0x0017880104e45521": {
+45
View File
@@ -1197,6 +1197,51 @@ describe("Extension: HomeAssistant", () => {
overrideSpy.mockRestore();
});
it("Should discover Bosch BTH-RM230Z with a current_humidity attribute", () => {
const payload = {
action_template:
"{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.running_state] }}",
action_topic: "zigbee2mqtt/bosch_rm230z",
availability: [{topic: "zigbee2mqtt/bridge/state", value_template: "{{ value_json.state }}"}],
current_humidity_template: "{{ value_json.humidity }}",
current_humidity_topic: "zigbee2mqtt/bosch_rm230z",
current_temperature_template: "{{ value_json.local_temperature }}",
current_temperature_topic: "zigbee2mqtt/bosch_rm230z",
default_entity_id: "climate.bosch_rm230z",
device: {
identifiers: ["zigbee2mqtt_0x18fc2600000d7ae3"],
manufacturer: "Bosch",
model: "Room thermostat II 230V",
model_id: "BTH-RM230Z",
name: "bosch_rm230z",
via_device: "zigbee2mqtt_bridge_0x00124b00120144ae",
},
max_temp: "30",
min_temp: "5",
mode_command_topic: "zigbee2mqtt/bosch_rm230z/set/system_mode",
mode_state_template: "{{ value_json.system_mode }}",
mode_state_topic: "zigbee2mqtt/bosch_rm230z",
modes: ["off", "heat", "cool"],
name: null,
object_id: "bosch_rm230z",
origin,
temp_step: 0.5,
temperature_high_command_topic: "zigbee2mqtt/bosch_rm230z/set/occupied_cooling_setpoint",
temperature_high_state_template: "{{ value_json.occupied_cooling_setpoint }}",
temperature_high_state_topic: "zigbee2mqtt/bosch_rm230z",
temperature_low_command_topic: "zigbee2mqtt/bosch_rm230z/set/occupied_heating_setpoint",
temperature_low_state_template: "{{ value_json.occupied_heating_setpoint }}",
temperature_low_state_topic: "zigbee2mqtt/bosch_rm230z",
temperature_unit: "C",
unique_id: "0x18fc2600000d7ae3_climate_zigbee2mqtt",
};
expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/climate/0x18fc2600000d7ae3/climate/config", stringify(payload), {
qos: 1,
retain: true,
});
});
it("Should discover devices with cover_position", () => {
let payload;
+411 -71
View File
@@ -73,7 +73,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness: "200"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({brightness: 200, state: "ON"});
@@ -119,7 +124,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness_percent: "92"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 235, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 235, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({state: "ON", brightness: 235});
@@ -132,7 +142,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness: 230}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 230, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 230, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({state: "ON", brightness: 230});
@@ -145,7 +160,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color_temp: "222"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColorTemp", {colortemp: 222, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 222, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color_mode: "color_temp", color_temp: 222});
@@ -158,7 +178,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color_temp_percent: 100}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColorTemp", {colortemp: 500, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 500, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color_mode: "color_temp", color_temp: 500});
@@ -223,7 +248,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/0x0017882194e45543/set", stringify({state_l2: "ON", brightness_l2: 50}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith("zigbee2mqtt/QS-Zigbee-D02-TRIAC-2C-LN", stringify({brightness_l2: 50, state_l2: "ON"}), {
retain: false,
qos: 0,
@@ -284,7 +314,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color: {x: 100, y: 50}}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 6553500, colory: 3276750, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 6553500, colory: 3276750, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color_mode: "xy", color: {x: 100, y: 50}});
@@ -298,7 +333,12 @@ describe("Extension: Publish", () => {
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command).toHaveBeenCalledWith("genOnOff", "on", {}, {});
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 6553500, colory: 3276750, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 6553500, colory: 3276750, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
"zigbee2mqtt/bulb_color",
@@ -313,8 +353,18 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color: {x: 100, y: 50}, brightness: 20}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 6553500, colory: 3276750, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 6553500, colory: 3276750, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
"zigbee2mqtt/bulb_color",
@@ -329,8 +379,18 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color: {x: 100, y: 50}, brightness: 20, state: "ON"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 6553500, colory: 3276750, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 6553500, colory: 3276750, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
"zigbee2mqtt/bulb_color",
@@ -345,7 +405,13 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color: {x: 100, y: 50}, brightness: 20, state: "OFF"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command).toHaveBeenNthCalledWith(1, "lightingColorCtrl", "moveToColor", {colorx: 6553500, colory: 3276750, transtime: 0}, {});
expect(endpoint.command).toHaveBeenNthCalledWith(
1,
"lightingColorCtrl",
"moveToColor",
{colorx: 6553500, colory: 3276750, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenNthCalledWith(2, "genOnOff", "off", {}, {});
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
@@ -361,7 +427,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color: {r: 100, g: 200, b: 10}}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 17806, colory: 43155, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 17806, colory: 43155, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color: {x: 0.2717, y: 0.6585}, color_mode: "xy"});
@@ -373,7 +444,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({color: {rgb: "100,200,10"}}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 17806, colory: 43155, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 17806, colory: 43155, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color: {x: 0.2717, y: 0.6585}, color_mode: "xy"});
@@ -385,7 +461,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON", brightness: "50"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({state: "ON", brightness: 50});
@@ -410,7 +491,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_1/set", stringify({brightness_percent: 50}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 128, transtime: 0}, {});
expect(group.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 128, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2); // 'zigbee2mqtt/bulb_color' + below
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual("zigbee2mqtt/group_1");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[1][1])).toStrictEqual({state: "ON", brightness: 128});
@@ -449,7 +535,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_1/set", stringify({state: "ON", brightness: 50}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {});
expect(group.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2); // 'zigbee2mqtt/bulb_color' + below
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual("zigbee2mqtt/group_1");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[1][1])).toStrictEqual({state: "ON", brightness: 50});
@@ -475,7 +566,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_1/set", stringify({color: {x: 0.37, y: 0.28}}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 24248, colory: 18350, transtime: 0}, {});
expect(group.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 24248, colory: 18350, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2); // 'zigbee2mqtt/bulb_color' + below
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual("zigbee2mqtt/group_1");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[1][1])).toStrictEqual({color: {x: 0.37, y: 0.28}, color_mode: "xy"});
@@ -488,7 +584,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_1/set", stringify({color_temp: 100}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColorTemp", {colortemp: 100, transtime: 0}, {});
expect(group.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 100, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2); // 'zigbee2mqtt/bulb_color' + below
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual("zigbee2mqtt/group_1");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[1][1])).toStrictEqual({color_temp: 100, color_mode: "color_temp"});
@@ -515,7 +616,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness: "200"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(0);
});
@@ -526,7 +632,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness: "200"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({state: "ON"});
});
@@ -681,7 +792,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set/color", "#64C80A");
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 17806, colory: 43155, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"lightingColorCtrl",
"moveToColor",
{colorx: 17806, colory: 43155, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color: {x: 0.2717, y: 0.6585}, color_mode: "xy"});
@@ -798,7 +914,12 @@ describe("Extension: Publish", () => {
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[0]).toEqual(["genOnOff", "on", {}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["lightingColorCtrl", "moveToColor", {colorx: 45940, colory: 19595, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"lightingColorCtrl",
"moveToColor",
{colorx: 45940, colory: 19595, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should also use on/off cluster when controlling group with switch", async () => {
@@ -809,7 +930,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/switch_group/set", stringify({state: "ON", brightness: 100}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(2);
expect(group.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 100, transtime: 0}, {});
expect(group.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 100, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(group.command).toHaveBeenCalledWith("genOnOff", "on", {}, {});
expect(mockMQTTPublishAsync).toHaveBeenCalledWith("zigbee2mqtt/switch_group", stringify({state: "ON", brightness: 100}), {
retain: false,
@@ -835,7 +961,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_1/set", stringify({brightness: 100}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 100, transtime: 200}, {});
expect(group.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 100, transtime: 200, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2); // zigbee2mqtt/bulb_color + below
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual("zigbee2mqtt/group_1");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[1][1])).toStrictEqual({state: "ON", brightness: 100});
@@ -850,7 +981,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 200}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 200, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should use transition from device_options on brightness command", async () => {
@@ -861,7 +997,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 200}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 200, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should turn bulb on with correct brightness when device is turned off twice and brightness is reported", async () => {
@@ -909,10 +1050,34 @@ describe("Extension: Publish", () => {
});
expect(endpoint.command).toHaveBeenCalledTimes(4);
expect(endpoint.command).toHaveBeenNthCalledWith(1, "genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 0}, {});
expect(endpoint.command).toHaveBeenNthCalledWith(2, "genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 0}, {});
expect(endpoint.command).toHaveBeenNthCalledWith(3, "genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 0}, {});
expect(endpoint.command).toHaveBeenNthCalledWith(4, "genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 0}, {});
expect(endpoint.command).toHaveBeenNthCalledWith(
1,
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenNthCalledWith(
2,
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenNthCalledWith(
3,
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenNthCalledWith(
4,
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
});
it("Should turn bulb on with full brightness when transition is used and no brightness is known", async () => {
@@ -929,8 +1094,18 @@ describe("Extension: Publish", () => {
qos: 0,
});
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 5}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 254, transtime: 5}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 5, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 254, transtime: 5, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Transition parameter should not influence brightness on state ON", async () => {
@@ -944,9 +1119,19 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON", transition: 1}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(3);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[1]).toEqual(["genOnOff", "on", {}, {}]);
expect(endpoint.command.mock.calls[2]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 10}, {}]);
expect(endpoint.command.mock.calls[2]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 10, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should use transition when color temp", async () => {
@@ -957,7 +1142,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["lightingColorCtrl", "moveToColorTemp", {colortemp: 200, transtime: 200}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 200, transtime: 200, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should use transition only once when setting brightness and color temperature for TRADFRI", async () => {
@@ -967,8 +1157,18 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["lightingColorCtrl", "moveToColorTemp", {colortemp: 200, transtime: 200}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[1]).toEqual([
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 200, transtime: 200, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should use transition only once when setting brightness and color temperature for group which contains TRADFRI", async () => {
@@ -976,8 +1176,18 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_with_tradfri/set", stringify({state: "ON", transition: 60, brightness: 20, color_temp: 400}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(2);
expect(group.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 0}, {}]);
expect(group.command.mock.calls[1]).toEqual(["lightingColorCtrl", "moveToColorTemp", {colortemp: 400, transtime: 600}, {}]);
expect(group.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(group.command.mock.calls[1]).toEqual([
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 400, transtime: 600, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Message transition should overrule options transition", async () => {
@@ -988,7 +1198,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 100}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 100, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should set state with brightness before color", async () => {
@@ -998,8 +1213,18 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 100, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["lightingColorCtrl", "moveToColor", {colorx: 45940, colory: 19595, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 100, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[1]).toEqual([
"lightingColorCtrl",
"moveToColor",
{colorx: 45940, colory: 19595, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should turn device off when brightness 0 is send", async () => {
@@ -1012,9 +1237,24 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(3);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[2]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[2]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(3);
expect(mockMQTTPublishAsync.mock.calls[0]).toEqual([
"zigbee2mqtt/bulb_color",
@@ -1043,9 +1283,24 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(3);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[2]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[2]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 50, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(3);
expect(mockMQTTPublishAsync.mock.calls[0]).toEqual([
"zigbee2mqtt/bulb_color",
@@ -1074,7 +1329,7 @@ describe("Extension: Publish", () => {
expect(endpoint.command.mock.calls[0]).toEqual([
"lightingColorCtrl",
"enhancedMoveToHueAndSaturation",
{enhancehue: 45510, saturation: 127, transtime: 0},
{enhancehue: 45510, saturation: 127, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
@@ -1129,7 +1384,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 254, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 254, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should turn device on with on/off with transition when transition 0 is provided", async () => {
@@ -1139,7 +1399,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 254, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 254, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Should turn device off with onOff on off with transition", async () => {
@@ -1149,7 +1414,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 10}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 10, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({state: "OFF"});
@@ -1168,7 +1438,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "OFF", transition: 3}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0]).toEqual([
"zigbee2mqtt/bulb_color",
@@ -1197,7 +1472,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON", transition: 3}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(3);
expect(mockMQTTPublishAsync.mock.calls[2]).toEqual([
"zigbee2mqtt/bulb_color",
@@ -1219,7 +1499,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "OFF", transition: 3}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 0, transtime: 30}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 0, transtime: 30, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0]).toEqual([
"zigbee2mqtt/bulb_color",
@@ -1231,7 +1516,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 200, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2);
expect(mockMQTTPublishAsync.mock.calls[1]).toEqual([
"zigbee2mqtt/bulb_color",
@@ -1264,7 +1554,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["lightingColorCtrl", "moveToColorTemp", {colortemp: 100, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 100, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({state: "ON", color_temp: 100, color_mode: "color_temp"});
@@ -1281,7 +1576,12 @@ describe("Extension: Publish", () => {
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[0]).toEqual(["genOnOff", "on", {}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["lightingColorCtrl", "moveToColorTemp", {colortemp: 100, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"lightingColorCtrl",
"moveToColorTemp",
{colortemp: 100, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
"zigbee2mqtt/bulb_color",
@@ -1300,7 +1600,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify(payload));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command.mock.calls[0]).toEqual(["lightingColorCtrl", "moveToColor", {colorx: 26869, colory: 16384, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[0]).toEqual([
"lightingColorCtrl",
"moveToColor",
{colorx: 26869, colory: 16384, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/bulb_color");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({color: {x: 0.41, y: 0.25}, state: "ON", color_mode: "xy"});
@@ -1363,7 +1668,7 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness_move: -40}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "move", {movemode: 1, rate: 40}, {});
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "move", {movemode: 1, rate: 40, optionsMask: 0, optionsOverride: 0}, {});
});
it("Should publish brightness_move down to zigbee devices", async () => {
@@ -1371,7 +1676,7 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({brightness_move: 30}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "move", {movemode: 0, rate: 30}, {});
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "move", {movemode: 0, rate: 30, optionsMask: 0, optionsOverride: 0}, {});
});
it("HS2WD-E burglar warning", async () => {
@@ -1442,7 +1747,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/roller_shutter/set", stringify({state: "OPEN"}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 255, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 255, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
expect(mockMQTTPublishAsync.mock.calls[0][0]).toStrictEqual("zigbee2mqtt/roller_shutter");
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[0][1])).toStrictEqual({position: 100});
@@ -1476,7 +1786,12 @@ describe("Extension: Publish", () => {
await vi.runOnlyPendingTimersAsync();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[0]).toEqual(["genOnOff", "on", {}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(mockMQTTPublishAsync).toHaveBeenCalledWith("zigbee2mqtt/GL-S-007ZS", stringify({state: "ON", brightness: 20}), {
qos: 0,
retain: false,
@@ -1509,8 +1824,18 @@ describe("Extension: Publish", () => {
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith("genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 10}, {});
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
);
expect(endpoint.command).toHaveBeenCalledWith(
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 20, transtime: 10, optionsMask: 0, optionsOverride: 0},
{},
);
});
it("Should restore brightness when its turned off without transition and is turned on with", async () => {
@@ -1527,7 +1852,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON", brightness: 123}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 123, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 123, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "OFF"}));
await flushPromises();
@@ -1537,7 +1867,12 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/bulb_color/set", stringify({state: "ON", transition: 1.0}));
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(4);
expect(endpoint.command.mock.calls[3]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 123, transtime: 10}, {}]);
expect(endpoint.command.mock.calls[3]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 123, transtime: 10, optionsMask: 0, optionsOverride: 0},
{},
]);
});
it("Shouldnt use moveToLevelWithOnOff on turn on when no transition has been used as some devices do not turn on in that case", async () => {
@@ -1556,7 +1891,12 @@ describe("Extension: Publish", () => {
expect(endpoint.command).toHaveBeenCalledTimes(4);
expect(endpoint.command.mock.calls[0]).toEqual(["genOnOff", "on", {}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 150, transtime: 0}, {}]);
expect(endpoint.command.mock.calls[1]).toEqual([
"genLevelCtrl",
"moveToLevelWithOnOff",
{level: 150, transtime: 0, optionsMask: 0, optionsOverride: 0},
{},
]);
expect(endpoint.command.mock.calls[2]).toEqual(["genOnOff", "off", {}, {}]);
expect(endpoint.command.mock.calls[3]).toEqual(["genOnOff", "on", {}, {}]);
@@ -1601,7 +1941,7 @@ describe("Extension: Publish", () => {
await mockMQTTEvents.message("zigbee2mqtt/group_tradfri_remote/set", stringify({scene_recall: 1}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("genScenes", "recall", {groupid: 15071, sceneid: 1}, {});
expect(group.command).toHaveBeenCalledWith("genScenes", "recall", {groupid: 15071, sceneid: 1, transitionTime: 0xffff}, {});
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(8);
expect(mockMQTTPublishAsync).toHaveBeenNthCalledWith(
1,
+27
View File
@@ -12,6 +12,14 @@ import Transport from "winston-transport";
import logger from "../lib/util/logger";
import * as settings from "../lib/util/settings";
vi.mock("rimraf", async (importOriginal) => {
const actual = await importOriginal<typeof import("rimraf")>();
return {
...actual,
rimrafSync: vi.fn(actual.rimrafSync),
};
});
describe("Logger", () => {
let consoleWriteSpy: MockInstance;
const dir = tmp.dirSync();
@@ -43,6 +51,7 @@ describe("Logger", () => {
it("Create log directory", () => {
const dirs = fs.readdirSync(dir.name);
expect(dirs.length).toBe(1);
expect(dirs[0]).toMatch(/^[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]{2}-[0-9]{2}-[0-9]{2}$/);
});
it("Should cleanup (default setting)", () => {
@@ -59,6 +68,24 @@ describe("Logger", () => {
expect(fs.readdirSync(dir.name).length).toBe(10);
});
it("Should handle cleanup error", () => {
for (const d of fs.readdirSync(dir.name)) {
rimrafSync(path.join(dir.name, d));
}
for (let i = 0; i < 20; i++) {
fs.mkdirSync(path.join(dir.name, `log_${i}`));
}
vi.mocked(rimrafSync).mockImplementationOnce(() => {
throw new Error("EACCES: permission denied");
});
const errorSpy = vi.spyOn(logger, "error");
logger.init();
expect(errorSpy).toHaveBeenCalledWith(expect.stringMatching(/Failed to remove old log directory '.*': Error: EACCES: permission denied/));
});
it("Should cleanup (15 folders setting)", () => {
for (const d of fs.readdirSync(dir.name)) {
rimrafSync(path.join(dir.name, d));
+3
View File
@@ -26,6 +26,9 @@ export const DEFAULT_CONFIGURATION = {
"0x18fc2600000d7ae2": {
friendly_name: "bosch_radiator",
},
"0x18fc2600000d7ae3": {
friendly_name: "bosch_rm230z",
},
"0x000b57fffec6a5b2": {
retain: true,
friendly_name: "bulb",
+14
View File
@@ -1137,6 +1137,20 @@ export const devices = {
"DC Source",
"FanBee1",
),
BTH_RM230Z: new Device(
"Router",
"0x18fc2600000d7ae3",
35902,
4617,
[new Endpoint(1, [0, 3, 513, 516, 1029, 2821], [10, 25], "0x18fc2600000d7ae3")],
InterviewState.Successful,
"Mains (single phase)",
"RBSH-RTH0-ZB-EU",
undefined,
undefined,
undefined,
CUSTOM_CLUSTER_BTHRA,
),
};
export const mockController = {