From 9f1b8cf2141f4b889de7cadb16d02ab49e377cad Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 1 Mar 2020 15:55:20 +0100 Subject: [PATCH] Allow to disable homeassistant legacy triggers. #3033 --- lib/extension/deviceReceive.js | 2 +- lib/extension/homeassistant.js | 7 ++- lib/util/settings.js | 7 +++ test/homeassistant.test.js | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/lib/extension/deviceReceive.js b/lib/extension/deviceReceive.js index 5186013148..dafe0bc5ec 100755 --- a/lib/extension/deviceReceive.js +++ b/lib/extension/deviceReceive.js @@ -145,7 +145,7 @@ class DeviceReceive extends BaseExtension { } else { this.publishEntityState(data.device.ieeeAddr, payload); - if (settings.get().homeassistant) { + if (settings.get().homeassistant && settings.get().advanced.homeassistant_legacy_triggers) { /** * Publish an empty value for click and action payload, in this way Home Assistant * can use Home Assistant entities in automations. diff --git a/lib/extension/homeassistant.js b/lib/extension/homeassistant.js index 5cd9daef00..08a5ac8efb 100644 --- a/lib/extension/homeassistant.js +++ b/lib/extension/homeassistant.js @@ -1364,10 +1364,15 @@ class HomeAssistant extends BaseExtension { } getConfigs(mappedModel) { - const configs = mapping[mappedModel.model].slice(); + let configs = mapping[mappedModel.model].slice(); if (mappedModel.hasOwnProperty('ota')) { configs.push(cfg.binary_sensor_update_available); } + + if (!settings.get().advanced.homeassistant_legacy_triggers) { + configs = configs.filter((c) => c !== cfg.sensor_action && c !== cfg.sensor_click); + } + return configs; } diff --git a/lib/util/settings.js b/lib/util/settings.js index abd4dca197..55499b7e86 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -104,6 +104,13 @@ const defaults = { */ homeassistant_status_topic: 'hass/status', + /** + * Home Assistant legacy triggers, when enabled: + * - Zigbee2mqt will send an empty 'action' or 'click' after one has been send + * - A 'sensor_action' and 'sensor_click' will be discoverd + */ + homeassistant_legacy_triggers: true, + /** * Configurable timestampFormat * https://github.com/Koenkk/zigbee2mqtt/commit/44db557a0c83f419d66755d14e460cd78bd6204e diff --git a/test/homeassistant.test.js b/test/homeassistant.test.js index 1669047cfe..c59089d463 100644 --- a/test/homeassistant.test.js +++ b/test/homeassistant.test.js @@ -724,6 +724,12 @@ describe('HomeAssistant extension', () => { controller = new Controller(false); await controller.start(); await flushPromises(); + + const discovered = MQTT.publish.mock.calls.filter((c) => c[0].includes('0x0017880104e45520')).map((c) => c[0]); + expect(discovered.length).toBe(4); + expect(discovered).toContain('homeassistant/sensor/0x0017880104e45520/click/config'); + expect(discovered).toContain('homeassistant/sensor/0x0017880104e45520/action/config'); + MQTT.publish.mockClear(); const device = zigbeeHerdsman.devices.WXKG11LM; @@ -762,6 +768,20 @@ describe('HomeAssistant extension', () => { expect.any(Function), ); + expect(MQTT.publish).toHaveBeenCalledWith( + 'zigbee2mqtt/button', + JSON.stringify({click: "single", linkquality: 10}), + { retain: false, qos: 0 }, + expect.any(Function), + ); + + expect(MQTT.publish).toHaveBeenCalledWith( + 'zigbee2mqtt/button', + JSON.stringify({linkquality: 10, click: ""}), + { retain: false, qos: 0 }, + expect.any(Function), + ); + // Should only discover it once MQTT.publish.mockClear(); await zigbeeHerdsman.events.message(payload); @@ -780,4 +800,63 @@ describe('HomeAssistant extension', () => { expect.any(Function), ); }); + + it('Should disable Home Assistant legacy triggers', async () => { + settings.set(['advanced', 'homeassistant_legacy_triggers'], false); + controller = new Controller(false); + await controller.start(); + await flushPromises(); + + const discovered = MQTT.publish.mock.calls.filter((c) => c[0].includes('0x0017880104e45520')).map((c) => c[0]); + expect(discovered.length).toBe(2); + expect(discovered).not.toContain('homeassistant/sensor/0x0017880104e45520/click/config'); + expect(discovered).not.toContain('homeassistant/sensor/0x0017880104e45520/action/config'); + + MQTT.publish.mockClear(); + + const device = zigbeeHerdsman.devices.WXKG11LM; + const payload = {data: {onOff: 1}, cluster: 'genOnOff', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10}; + await zigbeeHerdsman.events.message(payload); + await flushPromises(); + + const discoverPayload = { + "automation_type":"trigger", + "type":"click", + "subtype":"single", + "payload":"single", + "topic":"zigbee2mqtt/button/click", + "device":{ + "identifiers":[ + "zigbee2mqtt_0x0017880104e45520" + ], + "name":"button", + "sw_version": this.version, + "model":"Aqara wireless switch (WXKG11LM)", + "manufacturer":"Xiaomi" + } + }; + + expect(MQTT.publish).toHaveBeenCalledWith( + 'homeassistant/device_automation/0x0017880104e45520/click_single/config', + JSON.stringify(discoverPayload), + { retain: true, qos: 0 }, + expect.any(Function), + ); + + expect(MQTT.publish).toHaveBeenCalledWith( + 'zigbee2mqtt/button/click', + 'single', + { retain: false, qos: 0 }, + expect.any(Function), + ); + + expect(MQTT.publish).toHaveBeenCalledWith( + 'zigbee2mqtt/button', + JSON.stringify({click: "single", linkquality: 10}), + { retain: false, qos: 0 }, + expect.any(Function), + ); + + expect(MQTT.publish).toHaveBeenCalledTimes(3); + }); });