Compare commits

...
145 Commits
Author SHA1 Message Date
Koen Kanters 9ed84e130f 1.16.0 2020-11-01 12:58:35 +01:00
Koen Kanters 47cd482461 Undev 2020-11-01 12:58:31 +01:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
4fb8d4820f Update zigbee-herdsman-converters to 12.0.224 (#4833)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-11-01 11:05:20 +01:00
Koen Kanters a09bb3bc00 Home Assistant: support multiendpoint for enum sensor 2020-11-01 11:02:35 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 4d3e6eb11f Update zigbee-herdsman to 0.13.26 (#4834)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-11-01 10:52:41 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 606f7f44cc Update dependencies (#4830)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-11-01 10:35:22 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 1933b0f29d Update zigbee2mqtt-frontend to 0.2.68 (#4828)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-11-01 07:21:51 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 98d49a77ed Update zigbee2mqtt-frontend to 0.2.67 (#4826)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-31 21:21:06 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 7cead8cb68 Update zigbee2mqtt-frontend to 0.2.66 (#4825)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-31 18:35:18 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 487cc20129 Update zigbee2mqtt-frontend to 0.2.65 (#4823)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-31 14:39:36 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 09ae27503e Update zigbee2mqtt-frontend to 0.2.64 (#4822)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-31 10:20:35 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
e1b5a105dd Update zigbee-herdsman-converters to 12.0.223 (#4820)
* Update zigbee-herdsman-converters to 12.0.223

* Update homeassistant.js

* Update bridge.test.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-30 23:39:26 +01:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
79275f9a4c Update zigbee-herdsman-converters to 12.0.222 (#4816)
* Update zigbee-herdsman-converters to 12.0.222

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-29 21:43:47 +01:00
Koen Kanters aac7cb1ff6 Fix brightness or state not read when reading state and brightness. https://github.com/Koenkk/zigbee2mqtt/issues/4803 2020-10-29 18:03:16 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> d78610eecf Update zigbee2mqtt-frontend to 0.2.63 (#4810)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-29 13:41:04 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 6880dd786f Update zigbee2mqtt-frontend to 0.2.62 (#4808)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-29 10:14:02 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> a62f8e17ca Update zigbee2mqtt-frontend to 0.2.61 (#4788)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-29 07:43:38 +08:00
Emil FlachandEmil Flach 084fccc53d Partial fix for #4571, changed current_heating_setpoint for occupied_heating_setpoint (#4784)
Co-authored-by: Emil Flach <emil.flach@skopei.com>
2020-10-28 17:54:31 +01:00
Drzony 5d643bac8e Home Assistant fixes for Saswell TRV (#4800)
* Home Assistant fixes for Saswell TRV

* fixup! Home Assistant fixes for Saswell TRV
2020-10-28 17:49:44 +01:00
Hacker-CB 82f3d7d9bb update.sh: add checking if data-backup exists (#4793) 2020-10-28 10:45:49 +01:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
697955997a Update zigbee-herdsman-converters to 12.0.221 (#4796)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-27 21:57:35 +01:00
Koen Kanters 9a53399a8c Changes for zigbee-herdsman-converters 12.0.221 2020-10-27 21:50:55 +01:00
Koen Kanters b2049b449b Home Assistant discovery: use availability instead of availability_topic. https://github.com/Koenkk/zigbee2mqtt/issues/775 2020-10-27 21:49:44 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> a2992ab144 Update zigbee2mqtt-frontend to 0.2.50 (#4787)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-27 05:52:29 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
21fcfb0b17 Update zigbee-herdsman-converters to 12.0.220 (#4782)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-26 17:34:46 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> e449b772cc Update zigbee-herdsman to 0.13.24 (#4781)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-26 17:31:28 +01:00
Koen Kanters 922f828696 Allow binary exposes not in lookup. 2020-10-26 17:25:41 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> fee631080e Update zigbee2mqtt-frontend to 0.2.48 (#4777)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-26 07:25:59 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 22681be3c7 Update dependencies (#4766)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-25 09:58:46 +01:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 7b0498aab0 Update zigbee2mqtt-frontend to 0.2.45 (#4770)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-25 16:25:37 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> c9e030bb19 Update zigbee2mqtt-frontend to 0.2.43 (#4768)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-25 13:20:12 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> c702badd98 Update zigbee2mqtt-frontend to 0.2.40 (#4767)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-25 10:54:01 +08:00
Koen Kanters 63044421fd Get linkquality from herdsman instead of mesage. https://github.com/Koenkk/zigbee2mqtt/issues/4758 2020-10-24 17:15:46 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 8895c14f42 Update zigbee-herdsman to 0.13.23 (#4762)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-24 17:13:26 +02:00
Koen Kanters ddbf936102 Mark ZIGBEE2MQTT_CONFIG as deprecated. https://github.com/Koenkk/zigbee2mqtt/issues/4697 2020-10-24 16:20:48 +02:00
Koen Kanters 70a72dd32a Ignore yaml configuration files in data. https://github.com/Koenkk/zigbee2mqtt/issues/4697 2020-10-24 15:58:49 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
b13d18fa9a Update zigbee-herdsman-converters to 12.0.219 (#4745)
* Update zigbee-herdsman-converters to 12.0.219

* Update homeassistant.js

* Update bridge.test.js

* Update package.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-24 14:35:21 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> fcf10680f4 Update zigbee-herdsman to 0.13.21 (#4761)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-24 14:29:57 +02:00
Jan bd91b704b7 Added manual mode for GS361A-H04 (#4755) 2020-10-24 09:58:45 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> bd149af508 Update zigbee-herdsman to 0.13.20 (#4753)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-23 19:26:00 +02:00
mr G1K aa9ba03228 adapter zigate (#4737) 2020-10-23 19:13:33 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 3cbe7e3f39 Update zigbee2mqtt-frontend to 0.2.39 (#4749)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-23 08:21:04 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 040f612cd5 Update zigbee-herdsman to 0.13.19 (#4740)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-22 16:11:52 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 851aef3b2d Update zigbee2mqtt-frontend to 0.2.36 (#4732)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-21 08:54:18 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
6e74cb571f Update zigbee-herdsman-converters to 12.0.217 (#4728)
* Update zigbee-herdsman-converters to 12.0.217

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-20 20:10:30 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 466e9636a5 Update zigbee2mqtt-frontend to 0.2.35 (#4724)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-20 08:16:24 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
099aa26c6f Update zigbee-herdsman-converters to 12.0.216 (#4723)
* Update zigbee-herdsman-converters to 12.0.216

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-19 19:06:49 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
d73aea8ede Update zigbee-herdsman-converters to 12.0.215 (#4721)
* Update zigbee-herdsman-converters to 12.0.215

* Update homeassistant.js

* Update publish.js

* Update bridge.test.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-19 16:48:09 +02:00
Koen Kanters 5134f0b689 Fix 0x0000000000000000 in networkmap. 2020-10-19 16:38:53 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> b9662ed866 Update zigbee2mqtt-frontend to 0.2.33 (#4715)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-19 09:33:36 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 3de953aa2b Update zigbee2mqtt-frontend to 0.2.32 (#4714)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-19 08:13:59 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
09fbed6c75 Update zigbee-herdsman-converters to 12.0.214 (#4713)
* Update zigbee-herdsman-converters to 12.0.214

* Update bridge.test.js

* Update homeassistant.js

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-18 21:51:32 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> a9106924c7 Update dependencies (#4702)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-18 17:11:00 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
9ac660bc22 Update zigbee-herdsman-converters to 12.0.213 (#4696)
* Update zigbee-herdsman-converters to 12.0.213

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-17 16:58:27 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 87cabc29d4 Update zigbee-herdsman to 0.13.18 (#4695)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-17 16:32:01 +02:00
Utyf a5c9fb2940 Add unit_of_measurement for DIYRuZ_Geiger. (#4689) 2020-10-17 16:17:36 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 6837cfa2fc Update zigbee-herdsman-converters to 12.0.212 (#4685)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-16 18:40:46 +02:00
949a16eba0 Support JAVIS lock and TS0601 roller blind motor (#4652)
* Added support for Zemismart garage opener, Larkey dimmer & curtain switch

* support JAVIS lock

* support roller blind motor

* fix test coverage

* fix coding style

* update JAVIS lock name

* Update homeassistant.js

Co-authored-by: ChinhND <dinhchinh@gmail.com>
Co-authored-by: unknown <dungnguyen98nd@gmail.com>
Co-authored-by: TheEnd98 <49032426+TheEnd98@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-16 18:20:53 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 61e449430b Update zigbee-herdsman to 0.13.17 (#4684)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-16 17:33:13 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 9e4e8acdb0 Update zigbee-herdsman to 0.13.16 (#4675)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-15 19:22:22 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
84e725d5ce Update zigbee-herdsman-converters to 12.0.211 (#4667)
* Update zigbee-herdsman-converters to 12.0.211

* Update publish.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-14 22:18:51 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
8319cdbd61 Update zigbee-herdsman-converters to 12.0.210 (#4659)
* Update zigbee-herdsman-converters to 12.0.210

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-14 08:59:14 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 467be5410c Update zigbee2mqtt-frontend to 0.2.31 (#4658)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-14 06:29:33 +08:00
Marco MassarottoandKoen Kanters e63a2ac7f6 Allow redefine autodiscovery type (#4647)
* allow to redefine entity type and id in homeassistant autodiscovery

* Update homeassistant.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-13 20:33:48 +02:00
insipiensandKoen Kanters 24188a3eea add saswell TRV (#4644)
* add saswell TRV

* Update homeassistant.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-12 17:30:36 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
c2f28d4ed6 Update zigbee-herdsman-converters to 12.0.209 (#4646)
* Update zigbee-herdsman-converters to 12.0.209

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-12 17:22:53 +02:00
Koen Kanters fa5ac2902f Update dumpHomeAssistantMapping.js 2020-10-12 17:20:27 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> ebdf4bb2e2 Update zigbee2mqtt-frontend to 0.2.29 (#4645)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-12 07:13:33 +08:00
Koen Kanters 73bc34f419 Fix frontend not loading after update. #4266 2020-10-11 16:17:52 +02:00
Koen Kanters 9098bb1e06 Add missing test 2020-10-11 15:12:07 +02:00
Koen Kanters 8202a10837 Permit joining on specific device. https://github.com/Koenkk/zigbee2mqtt/issues/3281 2020-10-11 15:05:21 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2aa652f6e9 Update dependencies (#4636)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-11 14:01:41 +02:00
Koen Kanters 983340f44c Fix BHT-002-GCLZB HA discovery. https://github.com/Koenkk/zigbee2mqtt/pull/4537#issuecomment-706562247 2020-10-11 13:43:11 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> d9b9b05494 Update zigbee-herdsman-converters to 12.0.208 (#4633)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-10 16:54:28 +02:00
Koen Kanters 723e3a3964 Fix optimistic group state not published on startup. https://github.com/Koenkk/zigbee2mqtt/issues/3461 2020-10-10 16:41:02 +02:00
timstanley1985 ad0905607b Fix typo is ota logs (#4628) 2020-10-10 16:00:10 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
e836984e5e Update zigbee-herdsman-converters to 12.0.207 (#4627)
* Update zigbee-herdsman-converters to 12.0.207

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-10 01:25:53 +02:00
Koen Kanters e92a852349 Don't setup reporting for TS0115. https://github.com/Koenkk/zigbee2mqtt/issues/4621 2020-10-09 23:51:48 +02:00
Koen Kanters eecd15ebfa Don't republish identical optimistic group states. #3461 (#4623)
* Don't republish identical optimistic state for groups. #3461

* Fixes
2020-10-09 23:29:34 +02:00
John DoeandKoen Kanters da91158f94 rePublish device state on rename (#4620)
* Republish device state on rename

* Update bridge.js

* Update bridge.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-09 22:59:10 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
9dc34c421f Update zigbee-herdsman-converters to 12.0.205 (#4625)
* Update zigbee-herdsman-converters to 12.0.205

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-09 22:53:07 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 759751629d Update zigbee-herdsman to 0.13.15 (#4624)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-09 22:44:46 +02:00
Koen Kanters 24d8e5f113 Expose linkquality sensor for all devices. https://github.com/Koenkk/zigbee-herdsman-converters/pull/1638 2020-10-09 21:57:54 +02:00
Koen Kanters 9d29bcc566 Fix switches/plugs not controllable in group. https://github.com/Koenkk/zigbee2mqtt/issues/4558 2020-10-09 21:40:33 +02:00
Koen Kanters e2e51fc32c Revert "Does linux/386 work now?"
This reverts commit 75ca6f3970.
2020-10-09 18:21:50 +02:00
Koen Kanters 75ca6f3970 Does linux/386 work now? 2020-10-09 18:19:59 +02:00
Koen Kanters 33985bc976 Fix buildx command 2020-10-09 18:15:14 +02:00
Koen Kanters 17545a6f72 Fix ci.yml 2020-10-09 18:12:38 +02:00
Koen Kanters e36ca7f8f8 Merge branch 'master' into dev 2020-10-09 18:09:50 +02:00
Koen Kanters ed8b4e567b Migrate to docker setup QEMU/Buildx 2020-10-09 18:09:40 +02:00
Koen Kanters c1a1b91a25 Fix docker build 2020-10-09 15:20:05 +02:00
Koen Kanters 330927d4b7 Merge branch 'master' into dev 2020-10-09 14:25:22 +02:00
Koen Kanters 40ab11bc49 Revert "Use buildx 0.4.2"
This reverts commit a571949f49.
2020-10-09 14:25:11 +02:00
Koen Kanters f618926d09 Merge branch 'master' into dev 2020-10-09 14:21:35 +02:00
Koen Kanters 0e30a73a19 Drop linux/i386 image (causes build errors) 2020-10-09 14:21:26 +02:00
Koen Kanters fb7b8ba867 Merge branch 'master' into dev 2020-10-09 14:18:14 +02:00
Koen Kanters 6fa4807a5a linux/386 -> linux/i386 2020-10-09 14:18:00 +02:00
Koen Kanters 456fb4014c Merge branch 'master' into dev 2020-10-09 14:10:44 +02:00
Koen Kanters a571949f49 Use buildx 0.4.2 2020-10-09 14:01:35 +02:00
Koen Kanters ddf3b57ec5 Use 12-alpine3.12 as base Docker image 2020-10-09 13:55:36 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 5ec3ef5be6 Update zigbee2mqtt-frontend to 0.2.27 (#4619)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-09 18:43:01 +08:00
Koen Kanters 61e650e7b5 Don't add stale to "breaking change" issues. https://github.com/Koenkk/zigbee2mqtt/pull/4572 2020-10-08 22:21:00 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
8cae206c64 Update zigbee-herdsman-converters to 12.0.204 (#4605)
* Update zigbee-herdsman-converters to 12.0.204

* Update homeassistant.js

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-08 22:08:18 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> e9c96e7a24 Update zigbee-herdsman to 0.13.14 (#4606)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-08 22:00:50 +02:00
434981b567 [ImgBot] Optimize images (#4602)
*Total -- 451.91kb -> 199.42kb (55.87%)

/images/logo_large.png -- 243.86kb -> 81.11kb (66.74%)
/images/logo_bee_only.png -- 89.06kb -> 29.77kb (66.57%)
/images/logo.png -- 3.62kb -> 2.28kb (36.82%)
/images/architecture.png -- 102.93kb -> 75.96kb (26.21%)
/images/logo_vector.svg -- 12.44kb -> 10.30kb (17.19%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>

Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-08 20:35:42 +02:00
Hacker-CB dcaaef286d Fix for HEIMAN Smart socket HS2SK (NXP version) haElectricalMeasurement. (#4596)
Device does not support reporting. Need to poll.
2020-10-08 19:43:18 +02:00
Marco MassarottoandKoen Kanters bc7a436241 allow to redefine homeassistant autodiscovery entity "type" and "object_id" (#4593)
* Add link for creating frontend issues. #4568

* allow to redefine entity type and object_id in homeassistant autodiscovery

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-08 19:38:25 +02:00
Koen Kanters 667bc42bee Merge branch 'master' into dev 2020-10-08 19:36:29 +02:00
Koen Kanters 9257cd82b3 Fix optimistic for groups. https://github.com/Koenkk/zigbee2mqtt/pull/4572 2020-10-08 17:59:39 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 6989f303b8 Update zigbee2mqtt-frontend to 0.2.26 (#4592)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-08 06:26:30 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
ebca056ad9 Update zigbee-herdsman-converters to 12.0.203 (#4583)
* Update zigbee-herdsman-converters to 12.0.203

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-07 17:37:03 +02:00
Koen Kanters 172773a7f2 Sort in dumpHomeAssistantMapping.js 2020-10-07 17:34:48 +02:00
Koen Kanters 3a1f697d93 Don't log when including logger.js 2020-10-07 17:15:46 +02:00
Koen Kanters 8f40d18c0a Fix last seen unknown when opening frontend. #4266 2020-10-07 17:05:46 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> a132094be4 Update zigbee2mqtt-frontend to 0.2.24 (#4578)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-07 08:27:32 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
ba57e352b7 Update zigbee-herdsman-converters to 12.0.202 (#4576)
* Update zigbee-herdsman-converters to 12.0.202

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-06 22:10:40 +02:00
Koen Kanters 5d1975d60c Add optimistic option. https://github.com/Koenkk/zigbee2mqtt/issues/4524 (#4572) 2020-10-06 21:50:07 +02:00
Koen Kanters a982acc1ca Fix tests after https://github.com/Koenkk/zigbee2mqtt/pull/4510 2020-10-06 21:42:05 +02:00
Hacker-CB c045b90d2b Add tz.tuya_thermostat_away_mode (fix for https://github.com/Koenkk/z… (#4510)
* Add tz.tuya_thermostat_away_mode (fix for https://github.com/Koenkk/zigbee2mqtt/pull/4491)

* Added /* istanbul ignore else */
2020-10-06 21:37:15 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
34e82118a1 Update zigbee-herdsman-converters to 12.0.201 (#4575)
* Update zigbee-herdsman-converters to 12.0.201

* Update homeassistant.js

* Update utils.js

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-06 20:40:20 +02:00
Koen Kanters e90182642d Republish groups on device remove. https://github.com/nurikk/z2m-frontend/issues/31 2020-10-06 19:28:32 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 6ca8982237 Update zigbee-herdsman to 0.13.13 (#4573)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-06 16:33:20 +02:00
Koen Kanters e30b2576b7 Add link for creating frontend issues. #4568 2020-10-06 12:49:56 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
20c643552c Update zigbee-herdsman-converters to 12.0.200 (#4566)
* Update zigbee-herdsman-converters to 12.0.200

* Update homeassistant.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-05 19:36:32 +02:00
Nick RandellandKoen Kanters d5a3bf5d93 Added SmartPlug51AU (#4562)
* Added SmartPlug51AU

* Updated to fix conflicts

* Update homeassistant.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-05 19:22:46 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> cb0cf20e46 Update zigbee-herdsman-converters to 12.0.199 (#4563)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-05 17:47:44 +02:00
Koen Kanters a2a7cebd07 Fix tests 2020-10-05 17:43:57 +02:00
Koen Kanters 2fb3cb62f6 Fix touchlink factory reset failing with ''BUFFER' not available' error. #4543 2020-10-05 16:21:20 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> a7f931b8e3 Update dependencies (#4553)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-05 11:38:00 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> aea803bec7 Update zigbee2mqtt-frontend to 0.2.23 (#4560)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-05 06:41:06 +08:00
John Doe 628ca0daa1 Remove mqtt password from bridge/info (#4556) 2020-10-04 20:42:38 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 75ec7c3e05 Update zigbee2mqtt-frontend to 0.2.22 (#4554)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-04 11:17:39 +08:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
57b5529cd1 Update zigbee-herdsman-converters to 12.0.198 (#4551)
* Update zigbee-herdsman-converters to 12.0.198

* Update homeassistant.js

* Update publish.test.js

* Update publish.test.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-04 00:32:43 +02:00
insipiensandKoen Kanters 9df1ea4359 Moes room thermostat (#4537)
* Add Moes Room Thermostat entry

* Added entry for Moes Room thermostat

* Revert "Added entry for Moes Room thermostat"

This reverts commit 697c530023.

* Correct layout

* remove duplicate

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-03 23:33:31 +02:00
Koen Kanters 2a08127e13 Fix tests 2020-10-03 23:24:08 +02:00
Koen Kanters 0c36b7894b Fix json escaped raw networkmap. https://github.com/Koenkk/zigbee2mqtt/issues/3281 2020-10-03 22:47:20 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 43f085b069 Update zigbee2mqtt-frontend to 0.2.21 (#4539)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-03 08:19:46 +08:00
Koen Kanters 14c96a1045 Exposes for switch. https://github.com/Koenkk/zigbee2mqtt/issues/4466 2020-10-02 17:26:08 +02:00
github-actions[bot]github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Koen Kanters
145f1e862d Update zigbee-herdsman-converters to 12.0.197 (#4534)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2020-10-02 17:25:25 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> b5dc732a91 Update zigbee-herdsman to 0.13.12 (#4535)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-02 17:24:24 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 30449565ac Update zigbee2mqtt-frontend to 0.2.20 (#4525)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-02 15:28:43 +08:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2117e79324 Update zigbee2mqtt-frontend to 0.2.18 (#4522)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-02 10:44:02 +08:00
Koen Kanters 50226d2c84 Exposes for lights. #4466 (#4516)
* Add dumpHomeAssistantMapping

* Add exposes for lights. https://github.com/Koenkk/zigbee2mqtt/issues/4466

* Updates

* Updates
2020-10-01 18:33:59 +02:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> c75c89c388 Update zigbee-herdsman-converters to 12.0.196 (#4517)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2020-10-01 18:14:43 +02:00
Koen Kanters 4c2ce0d5eb Promote to dev 2020-10-01 16:49:55 +02:00
43 changed files with 3188 additions and 5724 deletions
+4 -1
View File
@@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Frontend issues
url: https://github.com/nurikk/z2m-frontend/issues
about: Issues related to the frontend.
- name: Home Assistant addon issues
url: https://github.com/danielwelch/hassio-zigbee2mqtt/issues
about: Issues related to the Home Assistant addon.
@@ -8,4 +11,4 @@ contact_links:
about: Frequently asked questions.
- name: Support Chat
url: https://discord.gg/NyseBeK
about: Chat for feedback, questions and troubleshooting.
about: Chat for feedback, questions and troubleshooting.
+14 -11
View File
@@ -31,20 +31,23 @@ jobs:
- name: Docker login
if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push'
run: echo ${{ secrets.DOCKER_KEY }} | docker login -u koenkk --password-stdin
- name: Docker setup
- name: Docker setup - QEMU
if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push'
run: |
sudo wget -O /usr/local/bin/buildx https://github.com/docker/buildx/releases/download/v0.3.1/buildx-v0.3.1.linux-amd64
sudo chmod a+x /usr/local/bin/buildx
docker run --rm --privileged hypriot/qemu-register:v2.7.0
buildx create --use
buildx ls
uses: docker/setup-qemu-action@v1
with:
platforms: all
- name: Docker setup - Buildx
if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push'
id: buildx
uses: docker/setup-buildx-action@v1
with:
version: latest
- name: Docker build dev
if: github.ref == 'refs/heads/dev' && github.event_name == 'push'
run: |
buildx build \
docker buildx build \
--build-arg COMMIT=$(git rev-parse --short HEAD) \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386 \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7 \
-f docker/Dockerfile \
--push \
-t koenkk/zigbee2mqtt:latest-dev \
@@ -53,9 +56,9 @@ jobs:
if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'push'
run: |
TAG="$(git describe --tags)"
buildx build \
docker buildx build \
--build-arg COMMIT=$(git rev-parse --short HEAD) \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386 \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7 \
-f docker/Dockerfile \
--push \
-t koenkk/zigbee2mqtt:latest -t "koenkk/zigbee2mqtt:$TAG" \
+1
View File
@@ -16,3 +16,4 @@ jobs:
days-before-stale: 30
days-before-close: 7
operations-per-run: 500
exempt-issue-labels: 'breaking change'
+4 -1
View File
@@ -70,4 +70,7 @@ data/database.db.backup
data/extension
# MacOS indexing file
.DS_Store
.DS_Store
# Ignore config
data/*.yaml
+2 -2
View File
@@ -1,4 +1,4 @@
FROM node:12-alpine as base
FROM node:12-alpine3.12 as base
WORKDIR /app
RUN apk add --no-cache tzdata eudev
@@ -10,7 +10,7 @@ FROM base as dependencies
COPY npm-shrinkwrap.json ./
RUN apk add --no-cache --virtual .buildtools make gcc g++ python linux-headers git && \
RUN apk add --no-cache --virtual .buildtools make gcc g++ python3 linux-headers git && \
npm ci --production && \
apk del .buildtools
Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 76 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 81 KiB

+1 -146
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

+7
View File
@@ -104,6 +104,7 @@ class Controller {
async start() {
this.state.start();
logger.logOutput();
const info = await utils.getZigbee2mqttVersion();
logger.info(`Starting Zigbee2MQTT version ${info.version} (commit #${info.commitHash})`);
@@ -313,11 +314,17 @@ class Controller {
attributes.forEach((a) => messagePayload.device[a] = resolvedEntity.device[a]);
}
// Add lastseen
const lastSeen = settings.get().advanced.last_seen;
if (isDevice && lastSeen !== 'disable' && resolvedEntity.device.lastSeen) {
messagePayload.last_seen = utils.formatDate(resolvedEntity.device.lastSeen, lastSeen);
}
// Add device linkquality.
if (resolvedEntity.type === 'device' && resolvedEntity.device.linkquality !== undefined) {
messagePayload.linkquality = resolvedEntity.device.linkquality;
}
// filter mqtt message attributes
if (resolvedEntity.settings.filtered_attributes) {
resolvedEntity.settings.filtered_attributes.forEach((a) => delete messagePayload[a]);
+1 -3
View File
@@ -140,13 +140,11 @@ class Availability extends Extension {
async onReconnect(device) {
const resolvedEntity = this.zigbee.resolveEntity(device);
if (resolvedEntity && resolvedEntity.definition) {
const used = [];
try {
for (const key of ['state', 'brightness', 'color', 'color_temp']) {
const converter = resolvedEntity.definition.toZigbee.find((tz) => tz.key.includes(key));
if (converter && !used.includes(converter)) {
if (converter) {
await converter.convertGet(device.endpoints[0], key, {});
used.push(converter);
}
}
} catch (error) {
+45 -18
View File
@@ -92,13 +92,9 @@ class Bridge extends Extension {
friendly_name: resolvedEntity.settings.friendlyName, status: data.status, ieee_address: ieeeAddress,
};
if (data.status === 'successful') {
payload.supported = !!resolvedEntity.definition;
payload.definition = resolvedEntity.definition ? {
model: resolvedEntity.definition.model,
vendor: resolvedEntity.definition.vendor,
description: resolvedEntity.definition.description,
supports: resolvedEntity.definition.supports,
} : null;
const definition = resolvedEntity.definition;
payload.supported = !!definition;
payload.definition = this.getDefinitionPayload(definition);
}
} else if (type === 'deviceAnnounce') {
payload = {
@@ -164,10 +160,29 @@ class Bridge extends Extension {
}
async permitJoin(message) {
const value = this.getValue(message);
await this.zigbee.permitJoin(value);
if (typeof message === 'object' && !message.hasOwnProperty('value')) {
throw new Error('Invalid payload');
}
let value;
let resolvedEntity;
if (typeof message === 'object') {
value = message.value;
if (message.device) {
resolvedEntity = this.zigbee.resolveEntity(message.device);
if (!resolvedEntity || resolvedEntity.type !== 'device') {
throw new Error(`Device '${message.device}' does not exist`);
}
}
} else {
value = message;
}
await this.zigbee.permitJoin(value, resolvedEntity);
await this.publishInfo();
return utils.getResponse(message, {value: value}, null);
return utils.getResponse(
message, resolvedEntity ? {value: value, device: message.device} : {value: value}, null,
);
}
configLastSeen(message) {
@@ -331,6 +346,9 @@ class Bridge extends Extension {
this.eventBus.emit(`groupRenamed`, {group: entity.group, homeAssisantRename});
}
// Repulish entity state
this.publishEntityState(to, {});
return utils.getResponse(
message,
{from: entity.settings.friendlyName, to, homeassistant_rename: homeAssisantRename},
@@ -396,6 +414,7 @@ class Bridge extends Extension {
logger.info(`Successfully removed ${entity.type} '${entity.settings.friendlyName}'${blockForceLog}`);
if (entity.type === 'device') {
this.publishGroups();
this.publishDevices();
return utils.getResponse(message, {id: ID, block, force}, null);
} else {
@@ -420,6 +439,7 @@ class Bridge extends Extension {
async publishInfo() {
const config = objectAssignDeep.noMutate({}, settings.get());
delete config.advanced.network_key;
delete config.mqtt.password;
const payload = {
version: this.zigbee2mqttVersion.version,
commit: this.zigbee2mqttVersion.commitHash,
@@ -437,13 +457,6 @@ class Bridge extends Extension {
const devices = this.zigbee.getDevices().map((device) => {
const definition = zigbeeHerdsmanConverters.findByDevice(device);
const resolved = this.zigbee.resolveEntity(device);
const definitionPayload = definition ? {
model: definition.model,
vendor: definition.vendor,
description: definition.description,
supports: definition.supports,
} : null;
const endpoints = {};
for (const endpoint of device.endpoints) {
const data = {
@@ -477,7 +490,7 @@ class Bridge extends Extension {
network_address: device.networkAddress,
supported: !!definition,
friendly_name: resolved.name,
definition: definitionPayload,
definition: this.getDefinitionPayload(definition),
power_source: device.powerSource,
software_build_id: device.softwareBuildID,
date_code: device.dateCode,
@@ -507,6 +520,20 @@ class Bridge extends Extension {
await this.mqtt.publish('bridge/groups', stringify(groups), {retain: true, qos: 0});
}
getDefinitionPayload(definition) {
if (definition) {
return {
model: definition.model,
vendor: definition.vendor,
description: definition.description,
[definition.hasOwnProperty('exposes') ? 'exposes' : 'supports']:
definition.hasOwnProperty('exposes') ? definition.exposes : definition.supports,
};
} else {
return null;
}
}
}
module.exports = Bridge;
+17 -3
View File
@@ -33,7 +33,13 @@ class Frontend extends Extension {
if (this.development) {
this.proxy = httpProxy.createProxyServer({ws: true});
} else {
this.fileServer = serveStatic(frontend.getPath());
/* istanbul ignore next */
const options = {setHeaders: (res, path) => {
if (path.endsWith('index.html')) {
res.setHeader('Cache-Control', 'no-store');
}
}};
this.fileServer = serveStatic(frontend.getPath(), options);
}
this.wss = new WebSocket.Server({noServer: true});
@@ -92,10 +98,18 @@ class Frontend extends Extension {
}
for (const device of this.zigbee.getClients()) {
let payload = {};
const resolvedEntity = this.zigbee.resolveEntity(device);
if (this.state.exists(device.ieeeAddr)) {
const resolvedEntity = this.zigbee.resolveEntity(device);
ws.send(stringify({topic: resolvedEntity.name, payload: this.state.get(device.ieeeAddr)}));
payload = {...payload, ...this.state.get(device.ieeeAddr)};
}
const lastSeen = settings.get().advanced.last_seen;
if (lastSeen !== 'disable') {
payload.last_seen = utils.formatDate(resolvedEntity.device.lastSeen, lastSeen);
}
ws.send(stringify({topic: resolvedEntity.name, payload}));
}
}
+5 -1
View File
@@ -4,6 +4,7 @@ const Extension = require('./extension');
const utils = require('../util/utils');
const postfixes = utils.getEndpointNames();
const stringify = require('json-stable-stringify-without-jsonify');
const equals = require('fast-deep-equal/es6');
const topicRegex =
new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/group/members/(remove|add|remove_all)$`);
@@ -15,6 +16,7 @@ class Groups extends Extension {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.onStateChange = this.onStateChange.bind(this);
this.legacyApi = settings.get().advanced.legacy_api;
this.lastOptimisticState = {};
}
onMQTTConnected() {
@@ -119,8 +121,10 @@ class Groups extends Extension {
if (resolvedEntity.type === 'device') {
for (const zigbeeGroup of zigbeeGroups) {
if (zigbeeGroup.hasMember(resolvedEntity.endpoint)) {
if (zigbeeGroup.hasMember(resolvedEntity.endpoint) &&
!equals(this.lastOptimisticState[zigbeeGroup.groupID], payload)) {
if (!payload || payload.state !== 'OFF' || this.areAllMembersOff(zigbeeGroup)) {
this.lastOptimisticState[zigbeeGroup.groupID] = payload;
await this.publishEntityState(zigbeeGroup.groupID, payload, reason);
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -452,7 +452,7 @@ class BridgeLegacy extends Extension {
'bridge/log',
stringify({type: `touchlink`, message: 'reset_started', meta: {status: 'started'}}),
);
const result = await this.zigbee.touchlinkFactoryReset();
const result = await this.zigbee.touchlinkFactoryResetFirst();
if (result) {
logger.info('Successfully factory reset device through Touchlink');
+10 -2
View File
@@ -48,7 +48,8 @@ class NetworkMap extends Extension {
this.supportedFormats.hasOwnProperty(message)) {
const includeRoutes = topic === this.legacyTopicRoutes;
const topology = await this.networkScan(includeRoutes);
const converted = this.supportedFormats[message](topology);
let converted = this.supportedFormats[message](topology);
converted = message === 'raw' ? stringify(converted) : converted;
this.mqtt.publish(`bridge/networkmap/${message}`, converted, {});
}
}
@@ -78,7 +79,7 @@ class NetworkMap extends Extension {
}
raw(topology) {
return stringify(topology);
return topology;
}
graphviz(topology) {
@@ -274,6 +275,13 @@ class NetworkMap extends Extension {
continue;
}
// Some Xiaomi devices return 0x00 as the neighbor ieeeAddr (obviously not correct).
// Determine the correct ieeeAddr based on the networkAddress.
const neighborDevice = this.zigbee.getDeviceByNetworkAddress(neighbor.networkAddress);
if (neighbor.ieeeAddr === '0x0000000000000000' && neighborDevice) {
neighbor.ieeeAddr = neighborDevice.ieeeAddr;
}
const link = {
source: {ieeeAddr: neighbor.ieeeAddr, networkAddress: neighbor.networkAddress},
target: {ieeeAddr: device.ieeeAddr, networkAddress: device.networkAddress},
+1 -1
View File
@@ -203,7 +203,7 @@ class OTAUpdate extends Extension {
const meta = {status: `update_in_progress`, device: resolvedEntity.name};
this.mqtt.publish(
'bridge/log',
stringify({type: `ota_update`, msg, meta}),
stringify({type: `ota_update`, message: msg, meta}),
);
}
+9 -5
View File
@@ -13,7 +13,7 @@ const stateValues = ['on', 'off', 'toggle', 'open', 'close', 'stop', 'lock', 'un
const groupConverters = [
zigbeeHerdsmanConverters.toZigbeeConverters.light_onoff_brightness,
zigbeeHerdsmanConverters.toZigbeeConverters.light_color_colortemp,
zigbeeHerdsmanConverters.toZigbeeConverters.light_alert,
zigbeeHerdsmanConverters.toZigbeeConverters.effect,
zigbeeHerdsmanConverters.toZigbeeConverters.ignore_transition,
zigbeeHerdsmanConverters.toZigbeeConverters.cover_position_tilt,
zigbeeHerdsmanConverters.toZigbeeConverters.thermostat_occupied_heating_setpoint,
@@ -197,8 +197,9 @@ class EntityPublish extends Extension {
if (!usedConverters.hasOwnProperty(endpointOrGroupID)) usedConverters[endpointOrGroupID] = [];
const converter = converters.find((c) => c.key.includes(key));
if (usedConverters[endpointOrGroupID].includes(converter)) {
// Use a converter only once (e.g. light_onoff_brightness converters can convert state and brightness)
if (topic.type === 'set' && usedConverters[endpointOrGroupID].includes(converter)) {
// Use a converter for set only once
// (e.g. light_onoff_brightness converters can convert state and brightness)
continue;
}
@@ -223,7 +224,10 @@ class EntityPublish extends Extension {
if (topic.type === 'set' && converter.convertSet) {
logger.debug(`Publishing '${topic.type}' '${key}' to '${resolvedEntity.name}'`);
const result = await converter.convertSet(actualTarget, key, value, meta);
if (result && result.state) {
const isGroup = actualTarget.constructor.name == 'Group';
// Optimistic behaviour of groups and devices is different.
const publishOptimistic = isGroup || (!options.hasOwnProperty('optimistic') || options.optimistic);
if (result && result.state && publishOptimistic) {
const msg = result.state;
if (endpointName) {
@@ -238,7 +242,7 @@ class EntityPublish extends Extension {
this.publishEntityState(resolvedEntity.settings.ID, msg);
}
if (result && result.membersState) {
if (result && result.membersState && publishOptimistic) {
for (const [ieeeAddr, state] of Object.entries(result.membersState)) {
this.publishEntityState(ieeeAddr, state);
}
-5
View File
@@ -136,11 +136,6 @@ class Receive extends Extension {
// - If NO payload is returned do nothing. This is for non-standard behaviour
// for e.g. click switches where we need to count number of clicks and detect long presses.
const publish = (payload) => {
// Add device linkquality.
if (data.hasOwnProperty('linkquality')) {
payload.linkquality = data.linkquality;
}
if (settings.get().advanced.elapsed) {
const now = Date.now();
if (this.elapsed[data.device.ieeeAddr]) {
+1
View File
@@ -16,6 +16,7 @@ const devicesNotSupportingReporting = [
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'BASICZBR3'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'ZM-CSW032-D'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'TS0001'),
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'TS0115'),
];
const reportKey = 1;
+15 -12
View File
@@ -115,24 +115,27 @@ function cleanup() {
}
}
// Print to user what logging is enabled
function logOutput() {
if (output.includes('file')) {
if (output.includes('console')) {
logger.info(`Logging to console and directory: '${directory}' filename: ${logFilename}`);
} else {
logger.info(`Logging to directory: '${directory}' filename: ${logFilename}`);
}
logger.cleanup();
} else if (output.includes('console')) {
logger.info(`Logging to console only'`);
}
}
logger.cleanup = cleanup;
logger.logOutput = logOutput;
logger.getLevel = () => transportsToUse[0].level;
logger.setLevel = (level) => {
transportsToUse.forEach((transport) => transport.level = level);
};
// Print to user what logging is enabled
if (output.includes('file')) {
if (output.includes('console')) {
logger.info(`Logging to console and directory: '${directory}' filename: ${logFilename}`);
} else {
logger.info(`Logging to directory: '${directory}' filename: ${logFilename}`);
}
logger.cleanup();
} else if (output.includes('console')) {
logger.info(`Logging to console only'`);
}
// winston.config.syslog.levels doesnt have warn, but is required for syslog.
/* istanbul ignore next */
logger.warn = (message) => logger.warning(message);
+2 -1
View File
@@ -1,5 +1,6 @@
const data = require('./data');
const utils = require('./utils');
// DEPRECATED ZIGBEE2MQTT_CONFIG: https://github.com/Koenkk/zigbee2mqtt/issues/4697
const file = process.env.ZIGBEE2MQTT_CONFIG || data.joinPath('configuration.yaml');
const objectAssignDeep = require(`object-assign-deep`);
const path = require('path');
@@ -160,7 +161,7 @@ const schema = {
properties: {
port: {type: ['string', 'null']},
disable_led: {type: 'boolean'},
adapter: {type: 'string', enum: ['deconz', 'zstack']},
adapter: {type: 'string', enum: ['deconz', 'zstack', 'zigate']},
},
},
blocklist: {type: 'array', items: {type: 'string'}},
+1
View File
@@ -38,6 +38,7 @@ const endpointNames = [
'button_11', 'button_12', 'button_13', 'button_14', 'button_15',
'button_16', 'button_17', 'button_18', 'button_19', 'button_20',
'button_light', 'button_fan_high', 'button_fan_med', 'button_fan_low',
'heat', 'cool',
];
function capitalize(s) {
+7 -3
View File
@@ -116,12 +116,16 @@ class Zigbee extends events.EventEmitter {
logger.info('zigbee-herdsman stopped');
}
async permitJoin(permit) {
async permitJoin(permit, resolvedEntity) {
permit ?
logger.info('Zigbee: allowing new devices to join.') :
logger.info(`Zigbee: allowing new devices to join${resolvedEntity ? ` via ${resolvedEntity.name}` : ''}.`) :
logger.info('Zigbee: disabling joining new devices.');
await this.herdsman.permitJoin(permit);
if (resolvedEntity && permit) {
await this.herdsman.permitJoin(permit, resolvedEntity.device);
} else {
await this.herdsman.permitJoin(permit);
}
}
async getPermitJoin() {
+2368 -3595
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "zigbee2mqtt",
"version": "1.15.0",
"version": "1.16.0",
"description": "Zigbee to MQTT bridge using Zigbee-herdsman",
"main": "index.js",
"repository": {
@@ -52,9 +52,9 @@
"winston": "^3.3.3",
"winston-syslog": "^2.4.4",
"ws": "^7.3.1",
"zigbee-herdsman": "0.13.11",
"zigbee-herdsman-converters": "12.0.194",
"zigbee2mqtt-frontend": "0.2.17"
"zigbee-herdsman": "0.13.26",
"zigbee-herdsman-converters": "12.0.224",
"zigbee2mqtt-frontend": "0.2.68"
},
"devDependencies": {
"eslint": "*",
+35
View File
@@ -0,0 +1,35 @@
const HomeAssistant = require('../lib/extension/homeassistant');
const stringify = require('json-stable-stringify-without-jsonify');
const homeassistant = new HomeAssistant(null, null, null, null, {on: () => {}});
const mapping = Object.entries(homeassistant._getMapping());
mapping.sort((a, b) => {
if (a[0] > b[0]) {
return -1;
}
if (b[0] > a[0]) {
return 1;
}
return 0;
});
for (const map of mapping) {
map[1].sort((a, b) => {
return JSON.stringify(a).localeCompare(JSON.stringify(b));
});
const toDelete = [];
for (const entry of map[1]) {
if (entry.type === 'light') {
if (entry.discovery_payload.brightness === false) delete entry.discovery_payload.brightness;
if (entry.discovery_payload.color_temp === false) delete entry.discovery_payload.color_temp;
if (entry.discovery_payload.xy === false) delete entry.discovery_payload.xy;
if (entry.discovery_payload.hs === false) delete entry.discovery_payload.hs;
} else if (entry.object_id === 'linkquality') {
toDelete.push(entry);
}
}
toDelete.forEach((d) => map[1].splice(map[1].indexOf(d), 1));
console.log(`${map[0]} - ${stringify(map[1])}`);
}
+6 -6
View File
@@ -81,7 +81,7 @@ describe('Availability', () => {
});
it('Should publish availabilty online and query state on reconnect', async () => {
const device = zigbeeHerdsman.devices.bulb_color;
const device = zigbeeHerdsman.devices.E11_G13;
const endpoint = device.getEndpoint(1);
device.ping.mockImplementationOnce(() => {throw new Error('failed')});
jest.advanceTimersByTime(11 * 1000);
@@ -90,16 +90,15 @@ describe('Availability', () => {
jest.advanceTimersByTime(11 * 1000);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bulb_color/availability',
'zigbee2mqtt/bulb_enddevice/availability',
'online',
{ retain: true, qos: 0 },
expect.any(Function)
);
expect(endpoint.read).toHaveBeenCalledTimes(3);
expect(endpoint.read).toHaveBeenCalledTimes(2);
expect(endpoint.read).toHaveBeenCalledWith('genLevelCtrl', ['currentLevel']);
expect(endpoint.read).toHaveBeenCalledWith('genOnOff', ['onOff']);
expect(endpoint.read).toHaveBeenCalledWith('lightingColorCtrl', ['currentX', 'currentY', 'colorTemperature']);
});
it('Should fail gracefully when quering state after reconnect fails', async () => {
@@ -173,10 +172,11 @@ describe('Availability', () => {
endpoint.read.mockClear();
await zigbeeHerdsman.events.deviceAnnounce({device});
await flushPromises();
expect(endpoint.read).toHaveBeenCalledTimes(3);
expect(endpoint.read).toHaveBeenCalledTimes(4);
expect(endpoint.read).toHaveBeenCalledWith('genLevelCtrl', ['currentLevel']);
expect(endpoint.read).toHaveBeenCalledWith('genOnOff', ['onOff']);
expect(endpoint.read).toHaveBeenCalledWith('lightingColorCtrl', ['currentX', 'currentY', 'colorTemperature']);
expect(endpoint.read).toHaveBeenCalledWith('lightingColorCtrl', ['currentX', 'currentY']);
expect(endpoint.read).toHaveBeenCalledWith('lightingColorCtrl', ['colorTemperature']);
});
it('Should not retrieve the state when device is turned on/off within availability timeout on deviceJoined', async () => {
+53 -9
View File
@@ -7,12 +7,13 @@ const Controller = require('../lib/controller');
const flushPromises = () => new Promise(setImmediate);
const stringify = require('json-stable-stringify-without-jsonify');
const {coordinator, bulb, unsupported, WXKG11LM, remote} = zigbeeHerdsman.devices;
const {coordinator, bulb, unsupported, WXKG11LM, remote, ZNCZ02LM} = zigbeeHerdsman.devices;
zigbeeHerdsman.returnDevices.push(coordinator.ieeeAddr);
zigbeeHerdsman.returnDevices.push(bulb.ieeeAddr);
zigbeeHerdsman.returnDevices.push(unsupported.ieeeAddr);
zigbeeHerdsman.returnDevices.push(WXKG11LM.ieeeAddr);
zigbeeHerdsman.returnDevices.push(remote.ieeeAddr);
zigbeeHerdsman.returnDevices.push(ZNCZ02LM.ieeeAddr);
describe('Bridge', () => {
let controller;
@@ -41,7 +42,7 @@ describe('Bridge', () => {
const directory = settings.get().advanced.log_directory;
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/info',
stringify({"commit":version.commitHash,"config":{"advanced":{"adapter_concurrent":null,"availability_blacklist":[],"availability_blocklist":[],"availability_passlist":[],"availability_timeout":0,"availability_whitelist":[],"cache_state":true,"cache_state_persistent":true,"cache_state_send_on_startup":true,"channel":11,"elapsed":false,"ext_pan_id":[221,221,221,221,221,221,221,221],"homeassistant_discovery_topic":"homeassistant","homeassistant_legacy_triggers":true,"homeassistant_status_topic":"hass/status","last_seen":"disable","legacy_api":false,"log_directory":directory,"log_file":"log.txt","log_level":"info","log_output":["console","file"],"log_rotation":true,"log_syslog":{},"pan_id":6754,"report":false,"soft_reset_timeout":0,"timestamp_format":"YYYY-MM-DD HH:mm:ss"},"ban":[],"blocklist":[],"device_options":{},"devices":{"0x000b57fffec6a5b2":{"friendly_name":"bulb","retain":true},"0x000b57fffec6a5b3":{"friendly_name":"bulb_color","retain":false},"0x000b57fffec6a5b4":{"friendly_name":"bulb_color_2","retain":false},"0x000b57fffec6a5b7":{"friendly_name":"bulb_2","retain":false},"0x0017880104a44559":{"friendly_name":"J1_cover"},"0x0017880104e43559":{"friendly_name":"U202DST600ZB"},"0x0017880104e44559":{"friendly_name":"3157100_thermostat"},"0x0017880104e45517":{"friendly_name":"remote","retain":true},"0x0017880104e45518":{"friendly_name":"0x0017880104e45518"},"0x0017880104e45520":{"friendly_name":"button","retain":false},"0x0017880104e45521":{"friendly_name":"button_double_key","retain":false},"0x0017880104e45522":{"friendly_name":"weather_sensor","qos":1,"retain":false},"0x0017880104e45523":{"friendly_name":"occupancy_sensor","retain":false},"0x0017880104e45524":{"friendly_name":"power_plug","retain":false},"0x0017880104e45526":{"friendly_name":"GL-S-007ZS"},"0x0017880104e45529":{"friendly_name":"unsupported2","retain":false},"0x0017880104e45530":{"friendly_name":"button_double_key_interviewing","retain":false},"0x0017880104e45540":{"friendly_name":"ikea_onoff"},"0x0017880104e45541":{"friendly_name":"wall_switch","retain":false},"0x0017880104e45542":{"friendly_name":"wall_switch_double","retain":false},"0x0017880104e45543":{"friendly_name":"led_controller_1","retain":false},"0x0017880104e45544":{"friendly_name":"led_controller_2","retain":false},"0x0017880104e45545":{"friendly_name":"dimmer_wall_switch","retain":false},"0x0017880104e45547":{"friendly_name":"curtain","retain":false},"0x0017880104e45548":{"friendly_name":"fan","retain":false},"0x0017880104e45549":{"friendly_name":"siren","retain":false},"0x0017880104e45550":{"friendly_name":"thermostat","retain":false},"0x0017880104e45551":{"friendly_name":"smart vent","retain":false},"0x0017880104e45552":{"friendly_name":"j1","retain":false},"0x0017880104e45553":{"friendly_name":"bulb_enddevice","retain":false},"0x0017880104e45559":{"friendly_name":"cc2530_router","retain":false},"0x0017880104e45560":{"friendly_name":"livolo","retain":false},"0x0017882104a44559":{"friendly_name":"TS0601_thermostat"},"0x90fd9ffffe4b64aa":{"friendly_name":"SP600_OLD"},"0x90fd9ffffe4b64ab":{"friendly_name":"SP600_NEW"},"0x90fd9ffffe4b64ac":{"friendly_name":"MKS-CM-W5"},"0x90fd9ffffe4b64ae":{"friendly_name":"tradfri_remote","retain":false},"0x90fd9ffffe4b64af":{"friendly_name":"roller_shutter"},"0x90fd9ffffe4b64ax":{"friendly_name":"ZNLDP12LM"}},"experimental":{"new_api":true,"output":"json"},"external_converters":[],"groups":{"1":{"friendly_name":"group_1","retain":false},"11":{"devices":["bulb_2"],"friendly_name":"group_with_tradfri","retain":false},"12":{"devices":["TS0601_thermostat"],"friendly_name":"thermostat_group","retain":false},"15071":{"devices":["bulb_color_2","bulb_2"],"friendly_name":"group_tradfri_remote","retain":false},"2":{"friendly_name":"group_2","retain":false}},"homeassistant":false,"map_options":{"graphviz":{"colors":{"fill":{"coordinator":"#e04e5d","enddevice":"#fff8ce","router":"#4ea3e0"},"font":{"coordinator":"#ffffff","enddevice":"#000000","router":"#ffffff"},"line":{"active":"#009900","inactive":"#994444"}}}},"mqtt":{"base_topic":"zigbee2mqtt","include_device_information":false,"server":"mqtt://localhost"},"passlist":[],"permit_join":true,"serial":{"disable_led":false,"port":"/dev/dummy"},"whitelist":[]},"coordinator":{"meta":{"revision":20190425,"version":1},"type":"z-Stack"},"log_level":"info","network":{"channel":15,"extended_pan_id":[0,11,22],"pan_id":5674},"permit_join":false,"version":version.version}),
stringify({"commit":version.commitHash,"config":{"advanced":{"adapter_concurrent":null,"availability_blacklist":[],"availability_blocklist":[],"availability_passlist":[],"availability_timeout":0,"availability_whitelist":[],"cache_state":true,"cache_state_persistent":true,"cache_state_send_on_startup":true,"channel":11,"elapsed":false,"ext_pan_id":[221,221,221,221,221,221,221,221],"homeassistant_discovery_topic":"homeassistant","homeassistant_legacy_triggers":true,"homeassistant_status_topic":"hass/status","last_seen":"disable","legacy_api":false,"log_directory":directory,"log_file":"log.txt","log_level":"info","log_output":["console","file"],"log_rotation":true,"log_syslog":{},"pan_id":6754,"report":false,"soft_reset_timeout":0,"timestamp_format":"YYYY-MM-DD HH:mm:ss"},"ban":[],"blocklist":[],"device_options":{},"devices":{"0x000b57fffec6a5b2":{"friendly_name":"bulb","retain":true},"0x000b57fffec6a5b3":{"friendly_name":"bulb_color","retain":false},"0x000b57fffec6a5b4":{"friendly_name":"bulb_color_2","retain":false},"0x000b57fffec6a5b7":{"friendly_name":"bulb_2","retain":false},"0x0017880104a44559":{"friendly_name":"J1_cover"},"0x0017880104e43559":{"friendly_name":"U202DST600ZB"},"0x0017880104e44559":{"friendly_name":"3157100_thermostat"},"0x0017880104e45517":{"friendly_name":"remote","retain":true},"0x0017880104e45518":{"friendly_name":"0x0017880104e45518"},"0x0017880104e45520":{"friendly_name":"button","retain":false},"0x0017880104e45521":{"friendly_name":"button_double_key","retain":false},"0x0017880104e45522":{"friendly_name":"weather_sensor","qos":1,"retain":false},"0x0017880104e45523":{"friendly_name":"occupancy_sensor","retain":false},"0x0017880104e45524":{"friendly_name":"power_plug","retain":false},"0x0017880104e45526":{"friendly_name":"GL-S-007ZS"},"0x0017880104e45529":{"friendly_name":"unsupported2","retain":false},"0x0017880104e45530":{"friendly_name":"button_double_key_interviewing","retain":false},"0x0017880104e45540":{"friendly_name":"ikea_onoff"},"0x0017880104e45541":{"friendly_name":"wall_switch","retain":false},"0x0017880104e45542":{"friendly_name":"wall_switch_double","retain":false},"0x0017880104e45543":{"friendly_name":"led_controller_1","retain":false},"0x0017880104e45544":{"friendly_name":"led_controller_2","retain":false},"0x0017880104e45545":{"friendly_name":"dimmer_wall_switch","retain":false},"0x0017880104e45547":{"friendly_name":"curtain","retain":false},"0x0017880104e45548":{"friendly_name":"fan","retain":false},"0x0017880104e45549":{"friendly_name":"siren","retain":false},"0x0017880104e45550":{"friendly_name":"thermostat","retain":false},"0x0017880104e45551":{"friendly_name":"smart vent","retain":false},"0x0017880104e45552":{"friendly_name":"j1","retain":false},"0x0017880104e45553":{"friendly_name":"bulb_enddevice","retain":false},"0x0017880104e45559":{"friendly_name":"cc2530_router","retain":false},"0x0017880104e45560":{"friendly_name":"livolo","retain":false},"0x0017882104a44559":{"friendly_name":"TS0601_thermostat"},"0x90fd9ffffe4b64aa":{"friendly_name":"SP600_OLD"},"0x90fd9ffffe4b64ab":{"friendly_name":"SP600_NEW"},"0x90fd9ffffe4b64ac":{"friendly_name":"MKS-CM-W5"},"0x90fd9ffffe4b64ae":{"friendly_name":"tradfri_remote","retain":false},"0x90fd9ffffe4b64af":{"friendly_name":"roller_shutter"},"0x90fd9ffffe4b64ax":{"friendly_name":"ZNLDP12LM"}},"experimental":{"new_api":true,"output":"json"},"external_converters":[],"groups":{"1":{"friendly_name":"group_1","retain":false},"11":{"devices":["bulb_2"],"friendly_name":"group_with_tradfri","retain":false},"14":{"devices":["power_plug"],"friendly_name":"switch_group","retain":false},"12":{"devices":["TS0601_thermostat"],"friendly_name":"thermostat_group","retain":false},"15071":{"devices":["bulb_color_2","bulb_2"],"friendly_name":"group_tradfri_remote","retain":false},"2":{"friendly_name":"group_2","retain":false}},"homeassistant":false,"map_options":{"graphviz":{"colors":{"fill":{"coordinator":"#e04e5d","enddevice":"#fff8ce","router":"#4ea3e0"},"font":{"coordinator":"#ffffff","enddevice":"#000000","router":"#ffffff"},"line":{"active":"#009900","inactive":"#994444"}}}},"mqtt":{"base_topic":"zigbee2mqtt","include_device_information":false,"server":"mqtt://localhost"},"passlist":[],"permit_join":true,"serial":{"disable_led":false,"port":"/dev/dummy"},"whitelist":[]},"coordinator":{"meta":{"revision":20190425,"version":1},"type":"z-Stack"},"log_level":"info","network":{"channel":15,"extended_pan_id":[0,11,22],"pan_id":5674},"permit_join":false,"version":version.version}),
{ retain: true, qos: 0 },
expect.any(Function)
);
@@ -50,9 +51,9 @@ describe('Bridge', () => {
it('Should publish devices on startup', async () => {
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/devices',
stringify([{"date_code":null,"definition":null,"endpoints":{"1":{"bindings":[],"clusters":{"input":[],"output":[]}}},"friendly_name":"Coordinator","ieee_address":"0x00124b00120144ae","interview_completed":false,"interviewing":false,"network_address":0,"power_source":null,"software_build_id":null,"supported":false,"type":"Coordinator"},{"date_code":null,"definition":{"description":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white","model":"LED1545G12","supports":"on/off, brightness, color temperature","vendor":"IKEA"},"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic","genScenes","genOnOff","genLevelCtrl","lightingColorCtrl"],"output":["genScenes","genOta"]}}},"friendly_name":"bulb","ieee_address":"0x000b57fffec6a5b2","interview_completed":true,"interviewing":false,"network_address":40369,"power_source":"Mains (single phase)","software_build_id":null,"supported":true,"type":"Router"},{"date_code":null,"definition":{"description":"Hue dimmer switch","model":"324131092621","supports":"on/off, brightness, up/down/hold/release, click count","vendor":"Philips"},"endpoints":{"1":{"bindings":[{"cluster":"genLevelCtrl","target":{"endpoint":1,"ieee_address":"0x000b57fffec6a5b3","type":"endpoint"}},{"cluster":"genOnOff","target":{"id":1,"type":"group"}}],"clusters":{"input":["genBasic"],"output":["genBasic","genOnOff","genLevelCtrl","genScenes"]}},"2":{"bindings":[],"clusters":{"input":["genBasic"],"output":["genOta","genOnOff"]}}},"friendly_name":"remote","ieee_address":"0x0017880104e45517","interview_completed":true,"interviewing":false,"network_address":6535,"power_source":"Battery","software_build_id":null,"supported":true,"type":"EndDevice"},{"date_code":null,"definition":null,"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic"],"output":["genBasic","genOnOff","genLevelCtrl","genScenes"]}}},"friendly_name":"0x0017880104e45518","ieee_address":"0x0017880104e45518","interview_completed":true,"interviewing":false,"network_address":6536,"power_source":"Battery","software_build_id":null,"supported":false,"type":"EndDevice"},{"date_code":null,"definition":{"description":"Aqara wireless switch","model":"WXKG11LM","supports":"single, double click (and triple, quadruple, hold, release depending on model)","vendor":"Xiaomi"},"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic"],"output":["genBasic","genOnOff","genLevelCtrl","genScenes"]}}},"friendly_name":"button","ieee_address":"0x0017880104e45520","interview_completed":true,"interviewing":false,"network_address":6537,"power_source":"Battery","software_build_id":null,"supported":true,"type":"EndDevice"}]),
{ retain: true, qos: 0 },
expect.any(Function)
stringify([{"date_code":null,"definition":null,"endpoints":{"1":{"bindings":[],"clusters":{"input":[],"output":[]}}},"friendly_name":"Coordinator","ieee_address":"0x00124b00120144ae","interview_completed":false,"interviewing":false,"network_address":0,"power_source":null,"software_build_id":null,"supported":false,"type":"Coordinator"},{"date_code":null,"definition":{"description":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white","exposes":[{"features":[{"access":"rw","name":"state","property":"state","type":"binary","value_off":"OFF","value_on":"ON","value_toggle":"TOGGLE"},{"access":"rw","name":"brightness","property":"brightness","type":"numeric","value_max":254,"value_min":0},{"access":"rw","name":"color_temp","property":"color_temp","type":"numeric","unit":"mired","value_max":500,"value_min":150}],"type":"light"},{"access":"w","name":"effect","property":"effect","type":"enum","values":["blink","breathe","okay","channel_change","finish_effect","stop_effect"]},{"access":"r","name":"linkquality","property":"linkquality","type":"numeric","unit":"lqi"}],"model":"LED1545G12","vendor":"IKEA"},"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic","genScenes","genOnOff","genLevelCtrl","lightingColorCtrl"],"output":["genScenes","genOta"]}}},"friendly_name":"bulb","ieee_address":"0x000b57fffec6a5b2","interview_completed":true,"interviewing":false,"network_address":40369,"power_source":"Mains (single phase)","software_build_id":null,"supported":true,"type":"Router"},{"date_code":null,"definition":{"description":"Hue dimmer switch","exposes":[{"access":"r","name":"battery","property":"battery","type":"numeric","unit":"%"},{"access":"r","name":"action","property":"action","type":"enum","values":["on-press","on-hold","on-release","up-press","up-hold","up-release","down-press","down-hold","down-release","off-press","off-hold","off-release"]},{"access":"r","name":"linkquality","property":"linkquality","type":"numeric","unit":"lqi"}],"model":"324131092621","vendor":"Philips"},"endpoints":{"1":{"bindings":[{"cluster":"genLevelCtrl","target":{"endpoint":1,"ieee_address":"0x000b57fffec6a5b3","type":"endpoint"}},{"cluster":"genOnOff","target":{"id":1,"type":"group"}}],"clusters":{"input":["genBasic"],"output":["genBasic","genOnOff","genLevelCtrl","genScenes"]}},"2":{"bindings":[],"clusters":{"input":["genBasic"],"output":["genOta","genOnOff"]}}},"friendly_name":"remote","ieee_address":"0x0017880104e45517","interview_completed":true,"interviewing":false,"network_address":6535,"power_source":"Battery","software_build_id":null,"supported":true,"type":"EndDevice"},{"date_code":null,"definition":null,"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic"],"output":["genBasic","genOnOff","genLevelCtrl","genScenes"]}}},"friendly_name":"0x0017880104e45518","ieee_address":"0x0017880104e45518","interview_completed":true,"interviewing":false,"network_address":6536,"power_source":"Battery","software_build_id":null,"supported":false,"type":"EndDevice"},{"date_code":null,"definition":{"description":"Aqara wireless switch","exposes":[{"access":"r","name":"battery","property":"battery","type":"numeric","unit":"%"},{"access":"r","name":"action","property":"action","type":"enum","values":["single","double","tripple","quadruple","hold","release"]},{"access":"r","name":"linkquality","property":"linkquality","type":"numeric","unit":"lqi"}],"model":"WXKG11LM","vendor":"Xiaomi"},"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic"],"output":["genBasic","genOnOff","genLevelCtrl","genScenes"]}}},"friendly_name":"button","ieee_address":"0x0017880104e45520","interview_completed":true,"interviewing":false,"network_address":6537,"power_source":"Battery","software_build_id":null,"supported":true,"type":"EndDevice"},{"date_code":null,"definition":{"description":"Mi power plug ZigBee","exposes":[{"features":[{"access":"rw","name":"state","property":"state","type":"binary","value_off":"OFF","value_on":"ON","value_toggle":"TOGGLE"}],"type":"switch"},{"access":"r","name":"power","property":"power","type":"numeric","unit":"W"},{"access":"r","name":"energy","property":"energy","type":"numeric","unit":"kWh"},{"access":"r","name":"temperature","property":"temperature","type":"numeric","unit":"°C"},{"access":"r","name":"linkquality","property":"linkquality","type":"numeric","unit":"lqi"}],"model":"ZNCZ02LM","vendor":"Xiaomi"},"endpoints":{"1":{"bindings":[],"clusters":{"input":["genBasic"],"output":[]}}},"friendly_name":"power_plug","ieee_address":"0x0017880104e45524","interview_completed":true,"interviewing":false,"network_address":6540,"power_source":"Mains (single phase)","software_build_id":null,"supported":true,"type":"Router"}]),
{ retain: true, qos: 0 },
expect.any(Function)
);
});
@@ -86,7 +87,7 @@ describe('Bridge', () => {
logger.setTransportsEnabled(true);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/groups',
stringify([{"friendly_name":"group_1","id":1,"members":[]},{"friendly_name":"group_tradfri_remote","id":15071,"members":[]},{"friendly_name":99,"id":99,"members":[]},{"friendly_name":"group_with_tradfri","id":11,"members":[]},{"friendly_name":"thermostat_group","id":12,"members":[]},{"friendly_name":"group_2","id":2,"members":[]}]),
stringify([{"friendly_name":"group_1","id":1,"members":[]},{"friendly_name":"group_tradfri_remote","id":15071,"members":[]},{"friendly_name":99,"id":99,"members":[]},{"friendly_name":"group_with_tradfri","id":11,"members":[]},{"friendly_name":"thermostat_group","id":12,"members":[]},{"friendly_name":"switch_group","id":14,"members":[{"endpoint":1,"ieee_address":"0x0017880104e45524"}]},{"friendly_name":"group_2","id":2,"members":[]}]),
{ retain: true, qos: 0 },
expect.any(Function)
);
@@ -158,7 +159,7 @@ describe('Bridge', () => {
expect(MQTT.publish).toHaveBeenCalledTimes(4);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/event',
stringify({"type":"device_interview","data":{"friendly_name":"bulb","status":"successful","ieee_address":"0x000b57fffec6a5b2","supported":true,"definition":{"model":"LED1545G12","vendor":"IKEA","description":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white","supports":"on/off, brightness, color temperature"}}}),
stringify({"data":{"definition":{"description":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white","exposes":[{"features":[{"access":"rw","name":"state","property":"state","type":"binary","value_off":"OFF","value_on":"ON","value_toggle":"TOGGLE"},{"access":"rw","name":"brightness","property":"brightness","type":"numeric","value_max":254,"value_min":0},{"access":"rw","name":"color_temp","property":"color_temp","type":"numeric","unit":"mired","value_max":500,"value_min":150}],"type":"light"},{"access":"w","name":"effect","property":"effect","type":"enum","values":["blink","breathe","okay","channel_change","finish_effect","stop_effect"]},{"access":"r","name":"linkquality","property":"linkquality","type":"numeric","unit":"lqi"}],"model":"LED1545G12","vendor":"IKEA"},"friendly_name":"bulb","ieee_address":"0x000b57fffec6a5b2","status":"successful","supported":true},"type":"device_interview"}),
{ retain: false, qos: 0 },
expect.any(Function)
);
@@ -221,6 +222,46 @@ describe('Bridge', () => {
stringify({"data":{"value":false},"status":"ok"}),
{retain: false, qos: 0}, expect.any(Function)
);
// Invalid payload
zigbeeHerdsman.permitJoin.mockClear();
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({"value_bla": false}));
await flushPromises();
expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(0);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/permit_join',
stringify({"data":{},"status":"error","error":"Invalid payload"}),
{retain: false, qos: 0}, expect.any(Function)
);
});
it('Should allow permit join via device', async () => {
const device = zigbeeHerdsman.devices.bulb;
zigbeeHerdsman.permitJoin.mockClear();
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: true, device: 'bulb'}));
await flushPromises();
expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1);
expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(true, device);
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/info', expect.any(String), { retain: true, qos: 0 }, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/permit_join',
stringify({"data":{"value":true,"device":"bulb"},"status":"ok"}),
{retain: false, qos: 0}, expect.any(Function)
);
// Device does not exist
zigbeeHerdsman.permitJoin.mockClear();
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: true, device: 'bulb_not_existing_woeeee'}));
await flushPromises();
expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(0);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/permit_join',
stringify({"data":{},"status":"error","error":"Device 'bulb_not_existing_woeeee' does not exist"}),
{retain: false, qos: 0}, expect.any(Function)
);
});
it('Should put transaction in response when request is done with transaction', async () => {
@@ -248,10 +289,10 @@ describe('Bridge', () => {
it('Should put error in response when format is incorrect', async () => {
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({"value_not_good": false}));
MQTT.events.message('zigbee2mqtt/bridge/request/config/last_seen', stringify({"value_not_good": false}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/permit_join',
'zigbee2mqtt/bridge/response/config/last_seen',
stringify({"data":{},"status":"error","error": "No value given"}),
{retain: false, qos: 0}, expect.any(Function)
);
@@ -294,6 +335,8 @@ describe('Bridge', () => {
{retain: false, qos: 0}, expect.any(Function)
);
expect(settings.get().blocklist).toStrictEqual([]);
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/devices', expect.any(String), expect.any(Object), expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/groups', expect.any(String), expect.any(Object), expect.any(Function));
});
it('Should allow to remove device by object ID', async () => {
@@ -407,6 +450,7 @@ describe('Bridge', () => {
expect(settings.getDevice('bulb_new_name')).toStrictEqual({"ID": "0x000b57fffec6a5b2", "friendly_name": "bulb_new_name", "friendlyName": "bulb_new_name", "retain": true});
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb', '', {retain: true, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/devices', expect.any(String), expect.any(Object), expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name', stringify({"brightness":50,"color_temp":370,"linkquality":99,"state":"ON"}), expect.any(Object), expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/device/rename',
stringify({"data":{"from":"bulb","to":"bulb_new_name","homeassistant_rename":false},"status":"ok"}),
+11 -2
View File
@@ -122,9 +122,10 @@ describe('Frontend', () => {
};
mockWS.implementation.clients.push(mockWSClient.implementation);
await mockWS.events.connection(mockWSClient.implementation);
expect(mockWSClient.implementation.send).toHaveBeenCalledTimes(9);
expect(mockWSClient.implementation.send).toHaveBeenCalledTimes(48);
expect(JSON.parse(mockWSClient.implementation.send.mock.calls[0])).toStrictEqual({topic: 'bridge/state', payload: 'online'});
expect(JSON.parse(mockWSClient.implementation.send.mock.calls[8])).toStrictEqual({topic:"remote", payload:{brightness:255, update:{state: "idle"}, update_available: false}});
expect(JSON.parse(mockWSClient.implementation.send.mock.calls[12])).toStrictEqual({topic:"remote", payload:{brightness:255, update:{state: "idle"}, update_available: false}});
// Message
MQTT.publish.mockClear();
@@ -152,6 +153,14 @@ describe('Frontend', () => {
mockWSClient.implementation.readyState = 'close';
mockWSClient.events.message(stringify({topic: 'bulb_color/set', payload: {state: 'ON'}}))
expect(mockWSClient.implementation.send).toHaveBeenCalledTimes(0);
// Send last seen on connect
mockWSClient.implementation.send.mockClear();
mockWSClient.implementation.readyState = 'open';
settings.set(['advanced'], {last_seen: 'ISO_8601'});
mockWS.implementation.clients.push(mockWSClient.implementation);
await mockWS.events.connection(mockWSClient.implementation);
expect(JSON.parse(mockWSClient.implementation.send.mock.calls[12])).toStrictEqual({topic:"remote", payload:{brightness:255, last_seen: "1970-01-01T00:00:01.000Z", update:{state: "idle"}, update_available: false}});
});
it('onReques/onUpgrade', async () => {
+23 -2
View File
@@ -7,6 +7,9 @@ zigbeeHerdsman.returnDevices.push('0x00124b00120144ae');
zigbeeHerdsman.returnDevices.push('0x000b57fffec6a5b3');
zigbeeHerdsman.returnDevices.push('0x000b57fffec6a5b2');
zigbeeHerdsman.returnDevices.push('0x0017880104e45542');
zigbeeHerdsman.returnDevices.push('0x000b57fffec6a5b4');
zigbeeHerdsman.returnDevices.push('0x000b57fffec6a5b7');
const MQTT = require('./stub/mqtt');
const Controller = require('../lib/controller');
const flushPromises = () => new Promise(setImmediate);
@@ -293,10 +296,28 @@ describe('Groups', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", stringify({"state":"ON","linkquality":10}), {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_1", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
});
it('Should not republish identical optimistic group states', async () => {
const device1 = zigbeeHerdsman.devices.bulb_2;
const device2 = zigbeeHerdsman.devices.bulb_color_2;
const group = zigbeeHerdsman.groups.group_tradfri_remote;
await controller.start();
await flushPromises();
MQTT.publish.mockClear();
await zigbeeHerdsman.events.message({data: {onOff: 1}, cluster: 'genOnOff', device: device1, endpoint: device1.getEndpoint(1), type: 'attributeReport', linkquality: 10});
await zigbeeHerdsman.events.message({data: {onOff: 1}, cluster: 'genOnOff', device: device2, endpoint: device2.getEndpoint(1), type: 'attributeReport', linkquality: 10});
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(4);
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_tradfri_remote", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_2", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color_2", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_with_tradfri", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
});
it('Should publish state change of all members when a group changes its state', async () => {
const device = zigbeeHerdsman.devices.bulb_color;
const endpoint = device.getEndpoint(1);
@@ -346,7 +367,7 @@ describe('Groups', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", stringify({"state":"ON","linkquality":10}), {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", stringify({"state":"ON"}), {"retain": false, qos: 0}, expect.any(Function));
});
it('Should publish state change of another group with shared device when a group changes its state', async () => {
+89 -36
View File
@@ -26,8 +26,8 @@ describe('HomeAssistant extension', () => {
const missing = [];
const ha = new HomeAssistant(null, null, null, null, {on: () => {}});
require('zigbee-herdsman-converters').devices.forEach((d) => {
if (!ha._getMapping()[d.model]) {
require('zigbee-herdsman-converters').definitions.forEach((d) => {
if (!d.hasOwnProperty('exposes') && !ha._getMapping()[d.model]) {
missing.push(d.model);
}
});
@@ -77,7 +77,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -102,7 +102,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -127,7 +127,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -152,7 +152,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -177,7 +177,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -218,7 +218,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -243,7 +243,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -268,7 +268,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -324,7 +324,7 @@ describe('HomeAssistant extension', () => {
'model': 'custom model',
'manufacturer': 'From Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
'expire_after': 90,
'icon': 'mdi:test',
};
@@ -350,7 +350,7 @@ describe('HomeAssistant extension', () => {
'model': 'custom model',
'manufacturer': 'Not from Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
'expire_after': 30,
'icon': 'mdi:test',
};
@@ -363,6 +363,58 @@ describe('HomeAssistant extension', () => {
);
});
it('Should discover devices with overriden user configuration affecting type and object_id', async () => {
settings.set(['devices', '0x0017880104e45541'], {
friendly_name: 'my_switch',
homeassistant: {
switch: {
type: 'light',
object_id: 'light'
},
light: {
type: 'this should be ignored',
name: 'my_light_name_override'
}
},
})
controller = new Controller(false);
await controller.start();
let payload;
await flushPromises();
payload = {
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/my_switch/availability'}],
"command_topic": "zigbee2mqtt/my_switch/set",
"device": {
"identifiers": [
"zigbee2mqtt_0x0017880104e45541"
],
"manufacturer": "Xiaomi",
"model": "Aqara single key wired wall switch without neutral wire. Doesn't work as a router and doesn't support power meter (QBKG04LM)",
"name": "my_switch",
"sw_version": this.version
},
"json_attributes_topic": "zigbee2mqtt/my_switch",
"name": "my_light_name_override",
"payload_off": "OFF",
"payload_on": "ON",
"state_topic": "zigbee2mqtt/my_switch",
"unique_id": "0x0017880104e45541_light_zigbee2mqtt",
"value_template": "{{ value_json.state }}"
}
expect(MQTT.publish).toHaveBeenCalledWith(
'homeassistant/light/0x0017880104e45541/light/config',
stringify(payload),
{ retain: true, qos: 0 },
expect.any(Function),
);
});
it('Shouldnt discover devices when homeassistant null is set in device options', async () => {
settings.set(['devices', '0x0017880104e45522'], {
homeassistant: null,
@@ -415,7 +467,7 @@ describe('HomeAssistant extension', () => {
"model":"Universal wink enabled white ceiling fan premier remote control (99432)",
"manufacturer":"Hampton Bay"
},
"availability_topic":"zigbee2mqtt/bridge/state"
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/fan/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -436,7 +488,10 @@ describe('HomeAssistant extension', () => {
payload = {
"action_template":"{% set values = {'idle':'off','heat':'heating','cool':'cooling','fan only':'fan'} %}{{ values[value_json.running_state] }}",
"action_topic":"zigbee2mqtt/TS0601_thermostat",
"availability_topic":"zigbee2mqtt/bridge/state",
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/TS0601_thermostat/availability'}],
"away_mode_command_topic":"zigbee2mqtt/TS0601_thermostat/set/away_mode",
"away_mode_state_template":"{{ value_json.away_mode }}",
"away_mode_state_topic":"zigbee2mqtt/TS0601_thermostat",
"current_temperature_template":"{{ value_json.local_temperature }}",
"current_temperature_topic":"zigbee2mqtt/TS0601_thermostat",
"device":{
@@ -452,7 +507,6 @@ describe('HomeAssistant extension', () => {
"hold_modes":[
"schedule",
"manual",
"away",
"boost",
"complex",
"comfort",
@@ -510,7 +564,7 @@ describe('HomeAssistant extension', () => {
model: 'Smart vent (SV01)',
manufacturer: 'Keen Home'
},
availability_topic: 'zigbee2mqtt/bridge/state'
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/smart vent/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -544,7 +598,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -609,7 +663,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -737,7 +791,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/weather_sensor/availability',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -824,7 +878,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor_renamed/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -895,7 +949,7 @@ describe('HomeAssistant extension', () => {
'model': 'Aqara temperature, humidity and pressure sensor (WSDCGQ11LM)',
'manufacturer': 'Xiaomi',
},
'availability_topic': 'zigbee2mqtt/bridge/state',
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor_renamed/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -927,7 +981,7 @@ describe('HomeAssistant extension', () => {
"model":"TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white (LED1545G12)",
"manufacturer":"IKEA"
},
"availability_topic":"zigbee2mqtt/bridge/state"
'availability': [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/bulb/availability'}],
};
expect(MQTT.publish).toHaveBeenCalledWith(
@@ -1019,21 +1073,21 @@ describe('HomeAssistant extension', () => {
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/button',
stringify({action: "single", linkquality: 10, click: "single"}),
stringify({action: "single", click: "single"}),
{ retain: false, qos: 0 },
expect.any(Function),
);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/button',
stringify({linkquality: 10, action: ""}),
stringify({action: ""}),
{ retain: false, qos: 0 },
expect.any(Function),
);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/button',
stringify({linkquality: 10, click: ""}),
stringify({click: ""}),
{ retain: false, qos: 0 },
expect.any(Function),
);
@@ -1160,7 +1214,7 @@ describe('HomeAssistant extension', () => {
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/button',
stringify({action: "single", linkquality: 10}),
stringify({action: "single"}),
{ retain: false, qos: 0 },
expect.any(Function),
);
@@ -1206,10 +1260,10 @@ describe('HomeAssistant extension', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(4);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({action: 'single', linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({action: 'single'});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
expect(MQTT.publish.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/button');
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({action: '', linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({action: ''});
expect(MQTT.publish.mock.calls[1][2]).toStrictEqual({"qos": 0, "retain": false});
expect(MQTT.publish.mock.calls[2][0]).toStrictEqual('homeassistant/device_automation/0x0017880104e45520/action_single/config');
expect(MQTT.publish.mock.calls[3][0]).toStrictEqual('zigbee2mqtt/button/action');
@@ -1246,26 +1300,26 @@ describe('HomeAssistant extension', () => {
// Non-existing device -> clear
MQTT.publish.mockClear();
await MQTT.events.message('homeassistant/sensor/0x123/temperature/config', stringify({availability_topic: 'zigbee2mqtt/0x123/availability'}));
await MQTT.events.message('homeassistant/sensor/0x123/temperature/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/0x123/availability'}]}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith('homeassistant/sensor/0x123/temperature/config', null, {qos: 0, retain: true}, expect.any(Function));
// Existing device -> don't clear
MQTT.publish.mockClear();
await MQTT.events.message('homeassistant/binary_sensor/0x000b57fffec6a5b2/update_available/config', stringify({availability_topic: 'zigbee2mqtt/0x000b57fffec6a5b2/availability'}));
await MQTT.events.message('homeassistant/binary_sensor/0x000b57fffec6a5b2/update_available/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/0x000b57fffec6a5b2/availability'}]}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(0);
// Non-existing device of different instance -> don't clear
MQTT.publish.mockClear();
await MQTT.events.message('homeassistant/sensor/0x123/temperature/config', stringify({availability_topic: 'zigbee2mqtt_different/0x123/availability'}));
await MQTT.events.message('homeassistant/sensor/0x123/temperature/config', stringify({availability: [{topic: 'zigbee2mqtt_different/bridge/state'}, {topic: 'zigbee2mqtt_different/0x123/availability'}]}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(0);
// Existing device but non-existing config -> don't clear
MQTT.publish.mockClear();
await MQTT.events.message('homeassistant/sensor/0x000b57fffec6a5b2/update_available/config', stringify({availability_topic: 'zigbee2mqtt/0x000b57fffec6a5b2/availability'}));
await MQTT.events.message('homeassistant/sensor/0x000b57fffec6a5b2/update_available/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/0x000b57fffec6a5b2/availability'}]}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith('homeassistant/sensor/0x000b57fffec6a5b2/update_available/config', null, {qos: 0, retain: true}, expect.any(Function));
@@ -1282,11 +1336,10 @@ describe('HomeAssistant extension', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(0);
// Not-existing device, device automation -> don't clear
// Device automation of different instance -> don't clear
MQTT.publish.mockClear();
await MQTT.events.message('homeassistant/device_automation/0x000b57fffec6a5b2_not_existing/action_button_3_single/config', stringify({topic: 'zigbee2mqtt/0x000b57fffec6a5b2_not_existing/availability'}));
await MQTT.events.message('homeassistant/device_automation/0x000b57fffec6a5b2_not_existing/action_button_3_single/config', stringify({topic: 'zigbee2mqtt_different/0x000b57fffec6a5b2_not_existing/availability'}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith('homeassistant/device_automation/0x000b57fffec6a5b2_not_existing/action_button_3_single/config', null, {qos: 0, retain: true}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledTimes(0);
});
});
+7 -7
View File
@@ -188,7 +188,7 @@ describe('Bridge legacy', () => {
await flushPromises();
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/bridge/log');
const payload = JSON.parse(MQTT.publish.mock.calls[0][1]);
expect(payload).toStrictEqual({"message": [{"ID": 1, "friendly_name": "group_1", "retain": false, 'devices': [], optimistic: true}, {"ID": 2, "friendly_name": "group_2", "retain": false, "devices": [], optimistic: true}, {"ID": 11, "friendly_name": "group_with_tradfri", "retain": false, "devices": ['bulb_2'], optimistic: true}, {"ID": 12, "friendly_name": "thermostat_group", "retain": false, "devices": ['TS0601_thermostat'], optimistic: true}, {"ID": 15071, "friendly_name": "group_tradfri_remote", "retain": false, "devices": ['bulb_color_2', 'bulb_2'], optimistic: true}], "type": "groups"});
expect(payload).toStrictEqual({"message":[{"ID":1,"devices":[],"friendly_name":"group_1","optimistic":true,"retain":false},{"ID":2,"devices":[],"friendly_name":"group_2","optimistic":true,"retain":false},{"ID":11,"devices":["bulb_2"],"friendly_name":"group_with_tradfri","optimistic":true,"retain":false},{"ID":12,"devices":["TS0601_thermostat"],"friendly_name":"thermostat_group","optimistic":true,"retain":false},{"ID":14,"devices":["power_plug"],"friendly_name":"switch_group","optimistic":true,"retain":false},{"ID":15071,"devices":["bulb_color_2","bulb_2"],"friendly_name":"group_tradfri_remote","optimistic":true,"retain":false}],"type":"groups"});
});
it('Should allow rename devices', async () => {
@@ -457,22 +457,22 @@ describe('Bridge legacy', () => {
});
it('Should allow to touchlink factory reset (OK)', async () => {
zigbeeHerdsman.touchlinkFactoryReset.mockClear();
zigbeeHerdsman.touchlinkFactoryResetFirst.mockClear();
zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(true);
zigbeeHerdsman.touchlinkFactoryResetFirst.mockReturnValueOnce(true);
MQTT.events.message('zigbee2mqtt/bridge/config/touchlink/factory_reset', '');
await flushPromises();
expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledTimes(1);
expect(zigbeeHerdsman.touchlinkFactoryResetFirst).toHaveBeenCalledTimes(1);
expect(logger.info).toHaveBeenCalledWith('Successfully factory reset device through Touchlink');
});
it('Should allow to touchlink factory reset (FAILS)', async () => {
zigbeeHerdsman.touchlinkFactoryReset.mockClear();
zigbeeHerdsman.touchlinkFactoryResetFirst.mockClear();
zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(false);
zigbeeHerdsman.touchlinkFactoryResetFirst.mockReturnValueOnce(false);
MQTT.events.message('zigbee2mqtt/bridge/config/touchlink/factory_reset', '');
await flushPromises();
expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledTimes(1);
expect(zigbeeHerdsman.touchlinkFactoryResetFirst).toHaveBeenCalledTimes(1);
expect(logger.warn).toHaveBeenCalledWith('Failed to factory reset device through Touchlink');
});
});
+9
View File
@@ -24,12 +24,14 @@ describe('Logger', () => {
it('Create log directory', () => {
const logger = require('../lib/util/logger.js');
logger.logOutput();
const dirs = fs.readdirSync(dir.name);
expect(dirs.length).toBe(1);
});
it('Should cleanup', () => {
const logger = require('../lib/util/logger.js');
logger.logOutput();
for (const d of fs.readdirSync(dir.name)) {
rimraf.sync(path.join(dir.name, d));
@@ -46,6 +48,7 @@ describe('Logger', () => {
it('Should not cleanup when there is no timestamp set', () => {
const logger = require('../lib/util/logger.js');
logger.logOutput();
for (let i = 30; i < 40; i++) {
fs.mkdirSync(path.join(dir.name, `log_${i}`));
}
@@ -58,12 +61,14 @@ describe('Logger', () => {
it('Set and get log level', () => {
const logger = require('../lib/util/logger.js');
logger.logOutput();
logger.setLevel('debug');
expect(logger.getLevel()).toBe('debug');
});
it('Logger should be console and file by default', () => {
const logger = require('../lib/util/logger.js');
logger.logOutput();
const pipes = logger._readableState.pipes;
expect(pipes.length).toBe(2);
expect(pipes[0].constructor.name).toBe('Console');
@@ -75,6 +80,7 @@ describe('Logger', () => {
it('Logger can be file only', () => {
settings.set(['advanced', 'log_output'], ['file']);
const logger = require('../lib/util/logger.js');
logger.logOutput();
const pipes = logger._readableState.pipes;
expect(pipes.length).toBe(2);
expect(pipes[0].constructor.name).toBe('Console');
@@ -86,6 +92,7 @@ describe('Logger', () => {
it('Logger can be console only', () => {
settings.set(['advanced', 'log_output'], ['console']);
const logger = require('../lib/util/logger.js');
logger.logOutput();
const pipes = logger._readableState.pipes;
expect(pipes.constructor.name).toBe('Console');
expect(pipes.silent).toBe(false);
@@ -94,6 +101,7 @@ describe('Logger', () => {
it('Logger can be nothing', () => {
settings.set(['advanced', 'log_output'], []);
const logger = require('../lib/util/logger.js');
logger.logOutput();
const pipes = logger._readableState.pipes;
expect(pipes.constructor.name).toBe('Console');
expect(pipes.silent).toBe(true);
@@ -102,6 +110,7 @@ describe('Logger', () => {
it('Should allow to disable log rotation', () => {
settings.set(['advanced', 'log_rotation'], false);
const logger = require('../lib/util/logger.js');
logger.logOutput();
const pipes = logger._readableState.pipes;
expect(pipes[1].constructor.name).toBe('File');
expect(pipes[1].maxFiles).toBeNull();
+1 -2
View File
@@ -70,7 +70,7 @@ describe('Networkmap', () => {
bulb_color.routingTable = () => {return {table: []}};
CC2530_ROUTER.lqi = () => {return {neighbors: [
{ieeeAddr: WXKG02LM.ieeeAddr, networkAddress: WXKG02LM.networkAddress, relationship: 1, depth: 2, linkquality: 130},
{ieeeAddr: '0x0000000000000000', networkAddress: WXKG02LM.networkAddress, relationship: 1, depth: 2, linkquality: 130},
{ieeeAddr: bulb_color.ieeeAddr, networkAddress: bulb_color.networkAddress, relationship: 4, depth: 2, linkquality: 130},
]}};
CC2530_ROUTER.routingTable = () => {return {table: []}};
@@ -295,7 +295,6 @@ describe('Networkmap', () => {
};
const actual = JSON.parse(call[1]);
actual.data.value = JSON.parse(actual.data.value);
expect(actual).toStrictEqual(expected);
});
+54 -13
View File
@@ -282,10 +282,10 @@ describe('Publish', () => {
await MQTT.events.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: 16764, colory: 40979, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 17721, colory: 43148, transtime: 0}, {});
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/bulb_color');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({color_temp: 162, color: {x: 0.2558, y: 0.6253}});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({color_temp: 157, color: {x: 0.2704, y: 0.6584}});
});
it('Should publish messages to zigbee devices with color rgb', async () => {
@@ -294,10 +294,10 @@ describe('Publish', () => {
await MQTT.events.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: 16764, colory: 40979, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 17721, colory: 43148, transtime: 0}, {});
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/bulb_color');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({color_temp: 162, color: {x: 0.2558, y: 0.6253}});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({color_temp: 157, color: {x: 0.2704, y: 0.6584}});
});
it('Should publish messages to zigbee devices with color rgb', async () => {
@@ -388,14 +388,25 @@ describe('Publish', () => {
it('Should create and publish to group which is in configuration.yaml but not in zigbee-herdsman', async () => {
delete zigbeeHerdsman.groups.group_2;
expect(Object.values(zigbeeHerdsman.groups).length).toBe(5);
expect(Object.values(zigbeeHerdsman.groups).length).toBe(6);
await MQTT.events.message('zigbee2mqtt/group_2/set', stringify({state: 'ON'}));
await flushPromises();
expect(Object.values(zigbeeHerdsman.groups).length).toBe(6);
expect(Object.values(zigbeeHerdsman.groups).length).toBe(7);
expect(zigbeeHerdsman.groups.group_2.command).toHaveBeenCalledTimes(1);
expect(zigbeeHerdsman.groups.group_2.command).toHaveBeenCalledWith("genOnOff", "on", {}, {});
});
it('Shouldnt publish new state when optimistic = false', async () => {
const device = zigbeeHerdsman.devices.bulb_color;
const endpoint = device.getEndpoint(1);
settings.set(['devices', device.ieeeAddr, 'optimistic'], false);
await MQTT.events.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(MQTT.publish).toHaveBeenCalledTimes(0);
});
it('Should handle non-valid topics', async () => {
await MQTT.events.message('zigbee2mqtt1/bulb_color/set', stringify({state: 'ON'}));
await flushPromises();
@@ -429,10 +440,11 @@ describe('Publish', () => {
it('Should handle get', async () => {
const device = zigbeeHerdsman.devices.bulb_color;
const endpoint = device.getEndpoint(1);
await MQTT.events.message('zigbee2mqtt/bulb_color/get', stringify({state: ''}));
await MQTT.events.message('zigbee2mqtt/bulb_color/get', stringify({state: '', brightness: ''}));
await flushPromises();
expect(endpoint.read).toHaveBeenCalledTimes(1);
expect(endpoint.read).toHaveBeenCalledTimes(2);
expect(endpoint.read).toHaveBeenCalledWith('genOnOff', ['onOff']);
expect(endpoint.read).toHaveBeenCalledWith('genLevelCtrl', ['currentLevel']);
});
it('Should handle get with multiple endpoints', async () => {
@@ -524,10 +536,10 @@ describe('Publish', () => {
await MQTT.events.message('zigbee2mqtt/bulb_color/set/color', '#64C80A');
await flushPromises();
expect(endpoint.command).toHaveBeenCalledTimes(1);
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 16764, colory: 40979, transtime: 0}, {});
expect(endpoint.command).toHaveBeenCalledWith("lightingColorCtrl", "moveToColor", {colorx: 17721, colory: 43148, transtime: 0}, {});
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/bulb_color');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({color_temp: 162, color: {x: 0.2558, y: 0.6253}});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({color_temp: 157, color: {x: 0.2704, y: 0.6584}});
});
it('Should parse set with ieeeAddr topic', async () => {
@@ -651,7 +663,36 @@ describe('Publish', () => {
expect(endpoint.command.mock.calls[1]).toEqual(["lightingColorCtrl", "moveToColor", {"colorx": 45940, "colory": 19595, "transtime": 0}, {}]);
expect(endpoint.read).toHaveBeenCalledTimes(2);
expect(endpoint.read.mock.calls[0]).toEqual(["genOnOff", ["onOff"]]);
expect(endpoint.read.mock.calls[1]).toEqual(["lightingColorCtrl", ["currentX", "currentY", "colorTemperature"]]);
expect(endpoint.read.mock.calls[1]).toEqual(["lightingColorCtrl", ["currentX", "currentY"]]);
});
it('Should also use on/off cluster when controlling group with switch', async () => {
const group = zigbeeHerdsman.groups.group_with_switch;
MQTT.publish.mockClear();
group.command.mockClear();
await MQTT.events.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("genOnOff", "on", {}, {});
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/switch_group',
stringify({state: 'ON', brightness: 100}),
{retain: false, qos: 0}, expect.any(Function)
);
MQTT.publish.mockClear();
group.command.mockClear();
await MQTT.events.message('zigbee2mqtt/switch_group/set', stringify({state: 'OFF', brightness: 100}));
await flushPromises();
expect(group.command).toHaveBeenCalledTimes(1);
expect(group.command).toHaveBeenCalledWith("genOnOff", "off", {}, {});
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/switch_group',
stringify({state: 'OFF', brightness: 100}),
{retain: false, qos: 0}, expect.any(Function)
);
});
it('Should use transition when brightness with group', async () => {
@@ -925,7 +966,7 @@ describe('Publish', () => {
await zigbeeHerdsman.events.message({data: {currentLevel: 1}, cluster: 'genLevelCtrl', device, endpoint, type: 'attributeReport', linkquality: 10});
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(MQTT.publish.mock.calls[1]).toEqual(["zigbee2mqtt/bulb_color", stringify({state: 'OFF', brightness: 1, linkquality: 10}), {"qos": 0, "retain": false}, expect.any(Function)]);
expect(MQTT.publish.mock.calls[1]).toEqual(["zigbee2mqtt/bulb_color", stringify({state: 'OFF', brightness: 1}), {"qos": 0, "retain": false}, expect.any(Function)]);
// Turn on again
await MQTT.events.message('zigbee2mqtt/bulb_color/set', stringify({state: 'ON', transition: 3}));
@@ -933,7 +974,7 @@ describe('Publish', () => {
expect(endpoint.command).toHaveBeenCalledTimes(2);
expect(endpoint.command.mock.calls[1]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 200, transtime: 30}, {}]);
expect(MQTT.publish).toHaveBeenCalledTimes(3);
expect(MQTT.publish.mock.calls[2]).toEqual(["zigbee2mqtt/bulb_color", stringify({state: 'ON', brightness: 200, linkquality: 10}), {"qos": 0, "retain": false}, expect.any(Function)]);
expect(MQTT.publish.mock.calls[2]).toEqual(["zigbee2mqtt/bulb_color", stringify({state: 'ON', brightness: 200}), {"qos": 0, "retain": false}, expect.any(Function)]);
});
it('When device is turned off with transition and turned on WITHOUT transition it should restore the brightness', async () => {
+42 -30
View File
@@ -20,10 +20,12 @@ describe('Receive', () => {
controller = new Controller();
await controller.start();
mocksClear.forEach((m) => m.mockClear());
delete zigbeeHerdsman.devices.WXKG11LM.linkquality;
});
it('Should handle a zigbee message', async () => {
const device = zigbeeHerdsman.devices.WXKG11LM;
device.linkquality = 10;
const data = {onOff: 1}
const payload = {data, cluster: 'genOnOff', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10};
await zigbeeHerdsman.events.message(payload);
@@ -40,7 +42,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button_double_key');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({click: 'left', action: 'single_left', linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({click: 'left', action: 'single_left'});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -52,7 +54,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button_double_key');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({click: 'right', action: 'single_right', linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({click: 'right', action: 'single_right'});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -64,7 +66,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -0.85, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -0.85});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": false});
});
@@ -75,7 +77,7 @@ describe('Receive', () => {
await zigbeeHerdsman.events.message({data: {currentPositionLiftPercentage: 90, currentPositionTiltPercentage: 80}, cluster: 'closuresWindowCovering', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10});
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/J1_cover', stringify({position: 10, tilt: 20, linkquality: 10}), {retain: false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/J1_cover', stringify({position: 10, tilt: 20}), {retain: false, qos: 0}, expect.any(Function));
// Inverted
MQTT.publish.mockClear();
@@ -83,7 +85,7 @@ describe('Receive', () => {
await zigbeeHerdsman.events.message({data: {currentPositionLiftPercentage: 90, currentPositionTiltPercentage: 80}, cluster: 'closuresWindowCovering', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10});
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/J1_cover', stringify({position: 90, tilt: 80, linkquality: 10}), {retain: false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/J1_cover', stringify({position: 90, tilt: 80}), {retain: false, qos: 0}, expect.any(Function));
});
it('Should allow to disable the legacy integration', async () => {
@@ -94,7 +96,7 @@ describe('Receive', () => {
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/button', stringify({action: 'single', linkquality: 10}), {retain: false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/button', stringify({action: 'single'}), {retain: false, qos: 0}, expect.any(Function));
});
it('Should debounce messages', async () => {
@@ -117,7 +119,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: 0.08, humidity: 0.01, pressure: 2, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: 0.08, humidity: 0.01, pressure: 2});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": false});
});
@@ -143,7 +145,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: 0.08, humidity: 0.01, pressure: 2, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: 0.08, humidity: 0.01, pressure: 2});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": true});
});
@@ -163,11 +165,11 @@ describe('Receive', () => {
await flushPromises();
jest.advanceTimersByTime(50);
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: 0.08, pressure: 2, linkquality: 13});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: 0.08, pressure: 2});
jest.runAllTimers();
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({temperature: 0.07, pressure: 2, humidity: 0.03, linkquality: 13});
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({temperature: 0.07, pressure: 2, humidity: 0.03});
});
it('Shouldnt republish old state', async () => {
@@ -181,7 +183,7 @@ describe('Receive', () => {
jest.runAllTimers();
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({state: 'ON'});
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({state: 'ON', linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({state: 'ON'});
});
it('Should handle a zigbee message with 1 precision', async () => {
@@ -193,7 +195,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -0.8, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -0.8});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": false});
});
@@ -206,7 +208,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -1, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -1});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": false});
});
@@ -219,7 +221,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -0.8, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -0.8});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": false});
});
@@ -233,7 +235,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/weather_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -1, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({temperature: -1});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 1, "retain": false});
});
@@ -246,14 +248,14 @@ describe('Receive', () => {
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({"battery":91,"voltage":2985,"temperature":23.5,"humidity":46.08,"pressure":915.5,"linkquality":10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({"battery":91,"voltage":2985,"temperature":23.5,"humidity":46.08,"pressure":915.5});
MQTT.publish.mockClear();
payload = {data: {"16":9354,"20":-1,"measuredValue":915}, cluster: 'msPressureMeasurement', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10};
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({"battery":91,"voltage":2985,"temperature":23.5,"humidity":46.08,"pressure":935.4,"linkquality":10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({"battery":91,"voltage":2985,"temperature":23.5,"humidity":46.08,"pressure":935.4});
});
it('Should handle a zigbee message with voltage 3010', async () => {
@@ -264,7 +266,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button_double_key');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 100, voltage: 3010, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 100, voltage: 3010});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -276,7 +278,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button_double_key');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 35, voltage: 2850, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 35, voltage: 2850});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -288,7 +290,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button_double_key');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 14, voltage: 2650, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 14, voltage: 2650});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -300,7 +302,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button_double_key');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 0, voltage: 2000, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({battery: 0, voltage: 2000});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -312,7 +314,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/occupancy_sensor');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({'battery': 100, 'illuminance': 381, "illuminance_lux": 381, 'voltage': 3045, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({'battery': 100, 'illuminance': 381, "illuminance_lux": 381, 'voltage': 3045});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -372,7 +374,7 @@ describe('Receive', () => {
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/weather_sensor',
stringify({temperature: -0.85, linkquality: 10}),
stringify({temperature: -0.85}),
{"qos": 1, "retain": false},
expect.any(Function),
)
@@ -384,10 +386,20 @@ describe('Receive', () => {
const payload = {data, cluster: 'genOnOff', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 20};
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/power_plug');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({'state': 'ON', linkquality: 20});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/power_plug',
stringify({state: 'ON'}),
{ retain: false, qos: 0 },
expect.any(Function)
);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/switch_group',
stringify({'state': 'ON'}),
{ retain: false, qos: 0 },
expect.any(Function)
);
});
it('Should not handle messages from coordinator', async () => {
@@ -430,7 +442,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/ikea_onoff');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({'click': 'brightness_stop', action: 'brightness_stop', linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({'click': 'brightness_stop', action: 'brightness_stop'});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
@@ -477,7 +489,7 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/SP600_NEW');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({energy: 0.66, power: 49.6, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({energy: 0.66, power: 49.6});
MQTT.publish.mockClear();
const SP600_OLD = zigbeeHerdsman.devices.SP600_OLD;
@@ -485,6 +497,6 @@ describe('Receive', () => {
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(1);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/SP600_OLD');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({energy: 6.648, power: 496, linkquality: 10});
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({energy: 6.648, power: 496});
});
});
+5
View File
@@ -186,6 +186,11 @@ function writeDefaultConfiguration() {
friendly_name: 'thermostat_group',
retain: false,
devices: ['TS0601_thermostat'],
},
'14': {
friendly_name: 'switch_group',
retain: false,
devices: ['power_plug'],
}
},
external_converters: [],
+1
View File
@@ -17,6 +17,7 @@ const mock = {
error: jest.fn().mockImplementation((msg) => callTransports('error', msg)),
debug: jest.fn().mockImplementation((msg) => callTransports('debug', msg)),
cleanup: jest.fn(),
logOutput: jest.fn(),
add: (transport) => transports.push(transport),
setLevel: (newLevel) => {level = newLevel},
getLevel: () => level,
+4 -3
View File
@@ -139,7 +139,7 @@ const devices = {
'WXKG02LM': new Device('EndDevice', '0x0017880104e45521', 6538,4151, [new Endpoint(1, [0], []), new Endpoint(2, [0], [])], true, "Battery", "lumi.sensor_86sw2.es1"),
'WSDCGQ11LM': new Device('EndDevice', '0x0017880104e45522', 6539,4151, [new Endpoint(1, [0], [])], true, "Battery", "lumi.weather"),
'RTCGQ11LM': new Device('EndDevice', '0x0017880104e45523', 6540,4151, [new Endpoint(1, [0], [])], true, "Battery", "lumi.sensor_motion.aq2"),
'ZNCZ02LM': new Device('Router', '0x0017880104e45524', 6540,4151, [new Endpoint(1, [0], [])], true, "Mains (single phase)", "lumi.plug"),
'ZNCZ02LM': new Device('Router', '0x0017880104e45524', 6540,4151, [new Endpoint(1, [0], [], '0x0017880104e45524')], true, "Mains (single phase)", "lumi.plug"),
'E1743': new Device('Router', '0x0017880104e45540', 6540,4476, [new Endpoint(1, [0], [])], true, "Mains (single phase)", 'TRADFRI on/off switch'),
'QBKG04LM': new Device('Router', '0x0017880104e45541', 6549,4151, [new Endpoint(1, [0], [25]), new Endpoint(2, [0, 6], [])], true, "Mains (single phase)", 'lumi.ctrl_neutral1'),
'QBKG03LM':new Device('Router', '0x0017880104e45542', 6540,4151, [new Endpoint(1, [0], [], '0x0017880104e45542'), new Endpoint(2, [0, 6], [], '0x0017880104e45542'), new Endpoint(3, [0, 6], [], '0x0017880104e45542')], true, "Mains (single phase)", 'lumi.ctrl_neutral2'),
@@ -175,7 +175,8 @@ const groups = {
'group_tradfri_remote': new Group(15071, [bulb_color_2.endpoints[0], bulb_2.endpoints[0]]),
'group/with/slashes': new Group(99, []),
'group_with_tradfri': new Group(11, [bulb_2.endpoints[0]]),
'thermostat_group': new Group(12, [TS0601_thermostat.endpoints[0]])
'thermostat_group': new Group(12, [TS0601_thermostat.endpoints[0]]),
'group_with_switch': new Group(14, [devices.ZNCZ02LM.endpoints[0]]),
}
const mock = {
@@ -203,7 +204,7 @@ const mock = {
return Object.values(devices).filter((d) => returnDevices.length === 0 || returnDevices.includes(d.ieeeAddr)).find((d) => d.ieeeAddr === ieeeAddr);
}),
getDeviceByNetworkAddress: jest.fn().mockImplementation((networkAddress) => {
return Object.values(devices).filter((d) => returnDevices.length === 0 || returnDevices.includes(d.networkAddress)).find((d) => d.networkAddress === networkAddress);
return Object.values(devices).filter((d) => returnDevices.length === 0 || returnDevices.includes(d.ieeeAddr)).find((d) => d.networkAddress === networkAddress);
}),
getGroups: jest.fn().mockImplementation((query) => {
return Object.values(groups);
+7
View File
@@ -1,5 +1,12 @@
#!/bin/bash -e
if [ -d data-backup ]; then
echo "ERROR: Backup directory exists. May be previous restoring was failed?"
echo "1. Save 'data-backup' and 'data' dirs to safe location to make possibility to restore config later."
echo "2. Manually delete 'data-backup' dir and try again."
exit 1
fi
echo "Stopping Zigbee2MQTT..."
sudo systemctl stop zigbee2mqtt