diff --git a/lib/controller.js b/lib/controller.js index f537c72d..b7d835dc 100644 --- a/lib/controller.js +++ b/lib/controller.js @@ -52,6 +52,7 @@ class Controller { // Initialize extensions. const args = [this.zigbee, this.mqtt, this.state, this.publishEntityState, this.eventBus]; this.extensions = [ + new ExtensionBridge(...args, this.enableDisableExtension), new ExtensionPublish(...args), new ExtensionReceive(...args), new ExtensionDeviceGroupMembership(...args), @@ -64,10 +65,6 @@ class Controller { new ExtensionReport(...args), ]; - if (settings.get().experimental.new_api) { - this.extensions.push(new ExtensionBridge(...args, this.enableDisableExtension)); - } - if (settings.get().frontend) { this.extensions.push(new ExtensionFrontend(...args)); } diff --git a/lib/extension/bind.js b/lib/extension/bind.js index 9b114fd9..5225d391 100644 --- a/lib/extension/bind.js +++ b/lib/extension/bind.js @@ -28,7 +28,7 @@ class Bind extends Extension { type = topic.split('/')[0]; sourceKey = topic.replace(`${type}/`, ''); targetKey = message; - } else if (settings.get().experimental.new_api && topic.match(topicRegex)) { + } else if (topic.match(topicRegex)) { type = topic.endsWith('unbind') ? 'unbind' : 'bind'; message = JSON.parse(message); sourceKey = message.from; diff --git a/lib/extension/homeassistant.js b/lib/extension/homeassistant.js index 8ac02da7..6270527b 100644 --- a/lib/extension/homeassistant.js +++ b/lib/extension/homeassistant.js @@ -86,7 +86,6 @@ class HomeAssistant extends Extension { this.mapping = {}; this.discoveredTriggers = {}; this.legacyApi = settings.get().advanced.legacy_api; - this.newApi = settings.get().experimental.new_api; if (!settings.get().advanced.cache_state) { logger.warn('In order for HomeAssistant integration to work properly set `cache_state: true'); @@ -535,7 +534,7 @@ class HomeAssistant extends Extension { }, { property: 'update', - condition: supportsOTA && this.newApi, + condition: supportsOTA, value: {state: 'idle'}, }, { @@ -595,13 +594,10 @@ class HomeAssistant extends Extension { let configs = this.mapping[resolvedEntity.definition.model].slice(); if (resolvedEntity.definition.hasOwnProperty('ota')) { + configs.push(cfg.sensor_update_state); if (this.legacyApi) { configs.push(cfg.binary_sensor_update_available); } - - if (this.newApi) { - configs.push(cfg.sensor_update_state); - } } if (resolvedEntity.settings.hasOwnProperty('legacy') && !resolvedEntity.settings.legacy) { diff --git a/lib/extension/networkMap.js b/lib/extension/networkMap.js index af31ede7..e1d8f057 100644 --- a/lib/extension/networkMap.js +++ b/lib/extension/networkMap.js @@ -42,7 +42,7 @@ class NetworkMap extends Extension { } } - if (settings.get().experimental.new_api && topic === this.topic) { + if (topic === this.topic) { try { message = utils.parseJSON(message, message); const type = typeof message === 'object' ? message.type : message; diff --git a/lib/extension/otaUpdate.js b/lib/extension/otaUpdate.js index 9ee7b4dd..e6f3ec02 100644 --- a/lib/extension/otaUpdate.js +++ b/lib/extension/otaUpdate.js @@ -90,20 +90,15 @@ class OTAUpdate extends Extension { } getEntityPublishPayload(state, progress=null, remaining=null) { - const payload = {}; + const payload = {update: {state}}; + if (progress !== null) payload.update.progress = progress; + if (remaining !== null) payload.update.remaining = Math.round(remaining); /* istanbul ignore else */ if (this.legacyApi) { payload.update_available = state === 'available'; } - /* istanbul ignore else */ - if (settings.get().experimental.new_api) { - payload.update = {state}; - if (progress !== null) payload.update.progress = progress; - if (remaining !== null) payload.update.remaining = Math.round(remaining); - } - return payload; } diff --git a/lib/util/settings.js b/lib/util/settings.js index be6d752c..f7308e48 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -50,7 +50,6 @@ const defaults = { experimental: { // json or attribute or attribute_and_json output: 'json', - new_api: false, }, advanced: { legacy_api: true, diff --git a/lib/util/utils.js b/lib/util/utils.js index 75e7f233..fe9211be 100644 --- a/lib/util/utils.js +++ b/lib/util/utils.js @@ -174,6 +174,7 @@ function* getExternalConvertersDefinitions(settings) { function toSnakeCase(value) { if (typeof value === 'object') { + value = {...value}; for (const key of Object.keys(value)) { const keySnakeCase = toSnakeCase(key); if (key !== keySnakeCase) { diff --git a/test/availability.test.js b/test/availability.test.js index bcb6534e..eed8add2 100644 --- a/test/availability.test.js +++ b/test/availability.test.js @@ -28,7 +28,6 @@ describe('Availability', () => { data.writeEmptyState(); jest.useFakeTimers(); settings.set(['advanced', 'availability_timeout'], 10); - settings.set(['experimental', 'new_api'], true); controller = new Controller(); mocksClear.forEach((m) => m.mockClear()); await controller.start(); diff --git a/test/bind.test.js b/test/bind.test.js index 99b9a230..a383b34b 100644 --- a/test/bind.test.js +++ b/test/bind.test.js @@ -25,7 +25,6 @@ describe('Bind', () => { data.writeDefaultConfiguration(); settings._reRead(); data.writeEmptyState(); - settings.set(['experimental', 'new_api'], true); controller = new Controller(); await controller.start(); await flushPromises(); diff --git a/test/bridge.test.js b/test/bridge.test.js index 71ec12c6..6d026601 100644 --- a/test/bridge.test.js +++ b/test/bridge.test.js @@ -23,7 +23,6 @@ describe('Bridge', () => { data.writeDefaultConfiguration(); settings._reRead(); settings.set(['advanced', 'legacy_api'], false); - settings.set(['experimental', 'new_api'], true); data.writeDefaultState(); logger.info.mockClear(); logger.warn.mockClear(); @@ -42,7 +41,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, "adapter_delay": 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", "force_disable_retain": false, }, "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, "adapter_delay": 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": { "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", "force_disable_retain": false, }, "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) ); diff --git a/test/frontend.test.js b/test/frontend.test.js index 26e2120b..ea5b9dab 100644 --- a/test/frontend.test.js +++ b/test/frontend.test.js @@ -75,7 +75,6 @@ describe('Frontend', () => { data.writeDefaultConfiguration(); data.writeDefaultState(); settings._reRead(); - settings.set(['experimental'], {new_api: true}); settings.set(['frontend'], {port: 8081, host: "127.0.0.1"}); settings.set(['homeassistant'], true); zigbeeHerdsman.devices.bulb.linkquality = 10; diff --git a/test/group.test.js b/test/group.test.js index ed5cefa2..593debc6 100644 --- a/test/group.test.js +++ b/test/group.test.js @@ -20,7 +20,6 @@ describe('Groups', () => { beforeEach(() => { data.writeEmptyState(); - settings.set(['experimental', 'new_api'], true); controller = new Controller(); Object.values(zigbeeHerdsman.groups).forEach((g) => g.members = []); data.writeDefaultConfiguration(); diff --git a/test/homeassistant.test.js b/test/homeassistant.test.js index f047773e..a8acb923 100644 --- a/test/homeassistant.test.js +++ b/test/homeassistant.test.js @@ -779,8 +779,6 @@ describe('HomeAssistant extension', () => { MQTT.publish.mockClear(); await zigbeeHerdsman.events.deviceLeave(payload); await flushPromises(); - // 1 publish is from device_removed - expect(MQTT.publish).toHaveBeenCalledTimes(1); }); it('Should send all status when home assistant comes online (default topic)', async () => { @@ -797,13 +795,13 @@ describe('HomeAssistant extension', () => { await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bulb', - stringify({"state":"ON","brightness":50,"color_temp":370,"linkquality":99,"update_available":false}), + stringify({"state":"ON","brightness":50,"color_temp":370,"linkquality":99,"update":{"state":"idle"},"update_available":false}), { retain: true, qos: 0 }, expect.any(Function) ); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/remote', - stringify({"brightness":255,"update_available":false}), + stringify({"brightness":255,"update_available":false,"update":{"state":"idle"}}), { retain: true, qos: 0 }, expect.any(Function) ); @@ -823,13 +821,13 @@ describe('HomeAssistant extension', () => { await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bulb', - stringify({"state":"ON","brightness":50,"color_temp":370,"linkquality":99,"update_available":false}), + stringify({"state":"ON","brightness":50,"color_temp":370,"linkquality":99,"update_available":false,"update":{"state":"idle"}}), { retain: true, qos: 0 }, expect.any(Function) ); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/remote', - stringify({"brightness":255,"update_available":false}), + stringify({"brightness":255,"update_available":false,"update":{"state":"idle"}}), { retain: true, qos: 0 }, expect.any(Function) ); @@ -948,7 +946,6 @@ describe('HomeAssistant extension', () => { }); it('Should refresh discovery when device is renamed', async () => { - settings.set(['experimental', 'new_api'], true); controller = new Controller(false); await controller.start(); await flushPromises(); @@ -1014,7 +1011,6 @@ describe('HomeAssistant extension', () => { }); it('Shouldnt refresh discovery when device is renamed and homeassistant_rename is false', async () => { - settings.set(['experimental', 'new_api'], true); controller = new Controller(false); await controller.start(); await flushPromises(); diff --git a/test/networkMap.test.js b/test/networkMap.test.js index df30dc26..4a5b9340 100644 --- a/test/networkMap.test.js +++ b/test/networkMap.test.js @@ -31,7 +31,6 @@ describe('Networkmap', () => { data.writeEmptyState(); fs.copyFileSync(path.join(__dirname, 'assets', 'mock-external-converter.js'), path.join(data.mockDir, 'mock-external-converter.js')); settings.set(['external_converters'], ['mock-external-converter.js']); - settings.set(['experimental', 'new_api'], true); controller = new Controller(); await controller.start(); mocksClear.forEach((m) => m.mockClear()); diff --git a/test/otaUpdate.test.js b/test/otaUpdate.test.js index b270a6bb..5d54d30b 100644 --- a/test/otaUpdate.test.js +++ b/test/otaUpdate.test.js @@ -19,7 +19,6 @@ describe('OTA update', () => { beforeEach(async () => { data.writeDefaultConfiguration(); settings._reRead(); - settings.set(['experimental', 'new_api'], true); data.writeEmptyState(); controller = new Controller(); await controller.start();