diff --git a/lib/controller.ts b/lib/controller.ts index cc57b3cfe2..f5e9132042 100644 --- a/lib/controller.ts +++ b/lib/controller.ts @@ -137,9 +137,8 @@ export class Controller { } // Start zigbee - let startResult; try { - startResult = await this.zigbee.start(); + await this.zigbee.start(); this.eventBus.onAdapterDisconnected(this, this.onZigbeeAdapterDisconnected); } catch (error) { logger.error('Failed to start zigbee'); @@ -149,15 +148,6 @@ export class Controller { return await this.exit(1); } - // Disable some legacy options on new network creation - if (startResult === 'reset') { - settings.set(['advanced', 'homeassistant_legacy_entity_attributes'], false); - settings.set(['advanced', 'legacy_api'], false); - settings.set(['advanced', 'legacy_availability_payload'], false); - settings.set(['device_options', 'legacy'], false); - await this.enableDisableExtension(false, 'BridgeLegacy'); - } - // Log zigbee clients on startup let deviceCount = 0; diff --git a/lib/extension/availability.ts b/lib/extension/availability.ts index f13552bd27..f0cf4f71ed 100644 --- a/lib/extension/availability.ts +++ b/lib/extension/availability.ts @@ -189,7 +189,7 @@ export default class Availability extends Extension { } const topic = `${entity.name}/availability`; - const payload = utils.availabilityPayload(available ? 'online' : 'offline', settings.get()); + const payload = JSON.stringify({state: available ? 'online' : 'offline'}); this.availabilityCache[entity.ID] = available; await this.mqtt.publish(topic, payload, {retain: true, qos: 1}); diff --git a/lib/extension/configure.ts b/lib/extension/configure.ts index 3068906340..cda7e74023 100644 --- a/lib/extension/configure.ts +++ b/lib/extension/configure.ts @@ -16,7 +16,6 @@ export default class Configure extends Extension { private configuring = new Set(); private attempts: {[s: string]: number} = {}; private topic = `${settings.get().mqtt.base_topic}/bridge/request/device/configure`; - private legacyTopic = `${settings.get().mqtt.base_topic}/bridge/configure`; @bind private async onReconfigure(data: eventdata.Reconfigure): Promise { // Disabling reporting unbinds some cluster which could be bound by configure, re-setup. @@ -29,20 +28,7 @@ export default class Configure extends Extension { } @bind private async onMQTTMessage(data: eventdata.MQTTMessage): Promise { - if (data.topic === this.legacyTopic) { - const device = this.zigbee.resolveEntity(data.message); - if (!device || !(device instanceof Device)) { - logger.error(`Device '${data.message}' does not exist`); - return; - } - - if (!device.definition || !device.definition.configure) { - logger.warning(`Skipping configure of '${device.name}', device does not require this.`); - return; - } - - await this.configure(device, 'mqtt_message', true); - } else if (data.topic === this.topic) { + if (data.topic === this.topic) { const message = utils.parseJSON(data.message, data.message); const ID = typeof message === 'object' && message.id !== undefined ? message.id : message; let error: string | undefined; diff --git a/lib/extension/homeassistant.ts b/lib/extension/homeassistant.ts index 6b7e48887e..1c05d2dd82 100644 --- a/lib/extension/homeassistant.ts +++ b/lib/extension/homeassistant.ts @@ -1641,7 +1641,7 @@ export default class HomeAssistant extends Extension { if (isDevice && entity.options.disabled) { // Mark disabled device always as unavailable payload.availability.forEach((a: KeyValue) => (a.value_template = '{{ "offline" }}')); - } else if (!settings.get().advanced.legacy_availability_payload) { + } else { payload.availability.forEach((a: KeyValue) => (a.value_template = '{{ value_json.state }}')); } } else { @@ -2017,7 +2017,6 @@ export default class HomeAssistant extends Extension { const discovery: DiscoveryEntry[] = []; const bridge = new Bridge(coordinatorIeeeAddress, coordinatorVersion, discovery); const baseTopic = `${settings.get().mqtt.base_topic}/${bridge.name}`; - const legacyAvailability = settings.get().advanced.legacy_availability_payload; discovery.push( // Binary sensors. @@ -2031,7 +2030,7 @@ export default class HomeAssistant extends Extension { entity_category: 'diagnostic', state_topic: true, state_topic_postfix: 'state', - value_template: !legacyAvailability ? '{{ value_json.state }}' : '{{ value }}', + value_template: '{{ value_json.state }}', payload_on: 'online', payload_off: 'offline', availability: false, diff --git a/lib/mqtt.ts b/lib/mqtt.ts index fc9f46ef8c..09f2ca1981 100644 --- a/lib/mqtt.ts +++ b/lib/mqtt.ts @@ -35,7 +35,7 @@ export default class MQTT { const options: mqtt.IClientOptions = { will: { topic: `${settings.get().mqtt.base_topic}/bridge/state`, - payload: Buffer.from(utils.availabilityPayload('offline', settings.get())), + payload: Buffer.from(JSON.stringify({state: 'offline'})), retain: settings.get().mqtt.force_disable_retain ? false : true, qos: 1, }, @@ -123,13 +123,13 @@ export default class MQTT { } @bind async publishStateOnline(): Promise { - await this.publish('bridge/state', utils.availabilityPayload('online', settings.get()), {retain: true, qos: 0}); + await this.publish('bridge/state', JSON.stringify({state: 'online'}), {retain: true, qos: 0}); } async disconnect(): Promise { clearTimeout(this.connectionTimer); clearTimeout(this.republishRetainedTimer); - await this.publish('bridge/state', utils.availabilityPayload('offline', settings.get()), {retain: true, qos: 0}); + await this.publish('bridge/state', JSON.stringify({state: 'offline'}), {retain: true, qos: 0}); this.eventBus.removeListeners(this); logger.info('Disconnecting from MQTT server'); this.client?.end(); diff --git a/lib/types/types.d.ts b/lib/types/types.d.ts index 1eefada854..eb629fb3a5 100644 --- a/lib/types/types.d.ts +++ b/lib/types/types.d.ts @@ -187,8 +187,6 @@ declare global { groups: {[s: string]: OptionalProps, 'devices'>}; device_options: KeyValue; advanced: { - legacy_api: boolean; - legacy_availability_payload: boolean; log_rotation: boolean; log_symlink_current: boolean; log_output: ('console' | 'file' | 'syslog')[]; diff --git a/lib/util/settings.ts b/lib/util/settings.ts index d3a2f2af40..97a53d2999 100644 --- a/lib/util/settings.ts +++ b/lib/util/settings.ts @@ -81,8 +81,6 @@ const defaults: RecursivePartial = { }, device_options: {}, advanced: { - legacy_api: true, - legacy_availability_payload: true, log_rotation: true, log_symlink_current: false, log_output: ['console', 'file'], diff --git a/lib/util/utils.ts b/lib/util/utils.ts index bb7e87f01d..5ae437451c 100644 --- a/lib/util/utils.ts +++ b/lib/util/utils.ts @@ -329,10 +329,6 @@ function isZHGroup(obj: unknown): obj is zh.Group { return obj?.constructor.name.toLowerCase() === 'group'; } -function availabilityPayload(state: 'online' | 'offline', settings: Settings): string { - return settings.advanced.legacy_availability_payload ? state : JSON.stringify({state}); -} - const hours = (hours: number): number => 1000 * 60 * 60 * hours; const minutes = (minutes: number): number => 1000 * 60 * minutes; const seconds = (seconds: number): number => 1000 * seconds; @@ -447,7 +443,6 @@ export default { sanitizeImageParameter, isAvailabilityEnabledForEntity, publishLastSeen, - availabilityPayload, getAllFiles, filterProperties, flatten, diff --git a/test/availability.test.js b/test/availability.test.js index 48e0b544ea..ff4ce5e8ab 100644 --- a/test/availability.test.js +++ b/test/availability.test.js @@ -68,11 +68,11 @@ describe('Availability', () => { }); it('Should publish availability on startup for device where it is enabled for', async () => { - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', 'online', {retain: true, qos: 1}, expect.any(Function)); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', 'online', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function)); expect(MQTT.publish).not.toHaveBeenCalledWith( 'zigbee2mqtt/bulb_color_2/availability', - 'online', + stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function), ); @@ -109,7 +109,7 @@ describe('Availability', () => { await setTimeAndAdvanceTimers(utils.minutes(7)); expect(devices.bulb_color.ping).toHaveBeenCalledTimes(1); expect(devices.bulb_color.ping).toHaveBeenNthCalledWith(1, true); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', 'offline', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function)); }); it('Shouldnt do anything for a device when availability: false is set for device', async () => { @@ -123,7 +123,7 @@ describe('Availability', () => { MQTT.publish.mockClear(); await setTimeAndAdvanceTimers(utils.hours(26)); expect(devices.remote.ping).toHaveBeenCalledTimes(0); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', 'offline', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function)); }); it('Should reset ping timer when device last seen changes for active device', async () => { @@ -133,7 +133,7 @@ describe('Availability', () => { expect(devices.bulb_color.ping).toHaveBeenCalledTimes(0); await zigbeeHerdsman.events.lastSeenChanged({device: devices.bulb_color}); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', 'offline', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function)); await setTimeAndAdvanceTimers(utils.minutes(7)); expect(devices.bulb_color.ping).toHaveBeenCalledTimes(0); @@ -165,7 +165,7 @@ describe('Availability', () => { expect(devices.remote.ping).toHaveBeenCalledTimes(0); await zigbeeHerdsman.events.lastSeenChanged({device: devices.remote}); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', 'offline', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function)); await setTimeAndAdvanceTimers(utils.hours(25)); expect(devices.remote.ping).toHaveBeenCalledTimes(0); @@ -178,12 +178,12 @@ describe('Availability', () => { MQTT.publish.mockClear(); await setTimeAndAdvanceTimers(utils.minutes(15)); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', 'offline', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function)); devices.bulb_color.lastSeen = Date.now(); await zigbeeHerdsman.events.lastSeenChanged({device: devices.bulb_color}); await flushPromises(); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', 'online', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function)); }); it('Should allow to change availability timeout via device options', async () => { @@ -299,13 +299,12 @@ describe('Availability', () => { await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', '', {retain: true, qos: 1}, expect.any(Function)); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', 'online', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function)); await setTimeAndAdvanceTimers(utils.hours(12)); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', 'offline', {retain: true, qos: 1}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function)); }); it('Should publish availability payload in JSON format', async () => { - settings.set(['advanced', 'legacy_availability_payload'], false); await resetExtension(); devices.remote.ping.mockClear(); MQTT.publish.mockClear(); @@ -326,7 +325,7 @@ describe('Availability', () => { expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/group_tradfri_remote/availability', - 'online', + stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function), ); @@ -334,7 +333,7 @@ describe('Availability', () => { await setTimeAndAdvanceTimers(utils.minutes(12)); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/group_tradfri_remote/availability', - 'offline', + stringify({state: 'offline'}), {retain: true, qos: 1}, expect.any(Function), ); @@ -344,7 +343,7 @@ describe('Availability', () => { await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/group_tradfri_remote/availability', - 'online', + stringify({state: 'online'}), {retain: true, qos: 1}, expect.any(Function), ); diff --git a/test/bridge.test.js b/test/bridge.test.js index 62acc1e3b0..8d3528c622 100644 --- a/test/bridge.test.js +++ b/test/bridge.test.js @@ -49,7 +49,6 @@ describe('Bridge', () => { beforeAll(async () => { jest.useFakeTimers(); mockRestart = jest.fn(); - settings.set(['advanced', 'legacy_api'], false); controller = new Controller(mockRestart, jest.fn()); await controller.start(); await flushPromises(); @@ -60,7 +59,6 @@ describe('Bridge', () => { MQTT.mock.reconnecting = false; data.writeDefaultConfiguration(); settings.reRead(); - settings.set(['advanced', 'legacy_api'], false); data.writeDefaultState(); logger.info.mockClear(); logger.warning.mockClear(); @@ -101,8 +99,6 @@ describe('Bridge', () => { elapsed: false, ext_pan_id: [221, 221, 221, 221, 221, 221, 221, 221], last_seen: 'disable', - legacy_api: false, - legacy_availability_payload: true, log_debug_namespace_ignore: '', log_debug_to_mqtt_frontend: false, log_directory: directory, diff --git a/test/configure.test.js b/test/configure.test.js index da7a0e2539..d5a700deb3 100644 --- a/test/configure.test.js +++ b/test/configure.test.js @@ -191,26 +191,6 @@ describe('Configure', () => { ); }); - it('Legacy api: Should allow to reconfigure manually', async () => { - mockClear(zigbeeHerdsman.devices.remote); - expectRemoteNotConfigured(); - await MQTT.events.message('zigbee2mqtt/bridge/configure', 'remote'); - await flushPromises(); - expectRemoteConfigured(); - }); - - it('Legacy api: Shouldnt manually reconfigure when device does not exist', async () => { - await MQTT.events.message('zigbee2mqtt/bridge/configure', 'remote_random_non_existing'); - await flushPromises(); - expect(logger.error).toHaveBeenCalledWith(`Device 'remote_random_non_existing' does not exist`); - }); - - it('Legacy api: Should skip reconfigure when device does not require this', async () => { - await MQTT.events.message('zigbee2mqtt/bridge/configure', '0x0017882104a44559'); - await flushPromises(); - expect(logger.warning).toHaveBeenCalledWith(`Skipping configure of 'TS0601_thermostat', device does not require this.`); - }); - it('Should not configure when interview not completed', async () => { const device = zigbeeHerdsman.devices.remote; delete device.meta.configured; diff --git a/test/controller.test.js b/test/controller.test.js index bc00b29a6a..939daf82d3 100644 --- a/test/controller.test.js +++ b/test/controller.test.js @@ -94,7 +94,7 @@ describe('Controller', () => { expect(logger.info).toHaveBeenCalledWith('0x0017880104e45518 (0x0017880104e45518): Not supported (EndDevice)'); expect(MQTT.connect).toHaveBeenCalledTimes(1); expect(MQTT.connect).toHaveBeenCalledWith('mqtt://localhost', { - will: {payload: Buffer.from('offline'), retain: true, topic: 'zigbee2mqtt/bridge/state', qos: 1}, + will: {payload: Buffer.from('{"state":"offline"}'), retain: true, topic: 'zigbee2mqtt/bridge/state', qos: 1}, }); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bulb', @@ -140,7 +140,7 @@ describe('Controller', () => { await flushPromises(); expect(MQTT.connect).toHaveBeenCalledTimes(1); const expected = { - will: {payload: Buffer.from('offline'), retain: true, topic: 'zigbee2mqtt/bridge/state', qos: 1}, + will: {payload: Buffer.from('{"state":"offline"}'), retain: true, topic: 'zigbee2mqtt/bridge/state', qos: 1}, keepalive: 30, ca: Buffer.from([99, 97]), key: Buffer.from([107, 101, 121]), @@ -895,7 +895,7 @@ describe('Controller', () => { await flushPromises(); expect(MQTT.connect).toHaveBeenCalledTimes(1); const expected = { - will: {payload: Buffer.from('offline'), retain: false, topic: 'zigbee2mqtt/bridge/state', qos: 1}, + will: {payload: Buffer.from('{"state":"offline"}'), retain: false, topic: 'zigbee2mqtt/bridge/state', qos: 1}, }; expect(MQTT.connect).toHaveBeenCalledWith('mqtt://localhost', expected); }); @@ -930,17 +930,6 @@ describe('Controller', () => { expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/fo', 'bar', {retain: false, qos: 0}, expect.any(Function)); }); - it('Should disable legacy options on new network start', async () => { - settings.set(['homeassistant'], true); - settings.reRead(); - expect(settings.get().homeassistant.legacy_entity_attributes).toBeTruthy(); - expect(settings.get().advanced.legacy_api).toBeTruthy(); - zigbeeHerdsman.start.mockReturnValueOnce('reset'); - await controller.start(); - expect(settings.get().homeassistant.legacy_entity_attributes).toBeFalsy(); - expect(settings.get().advanced.legacy_api).toBeFalsy(); - }); - it('Should publish last seen changes', async () => { settings.set(['advanced', 'last_seen'], 'epoch'); await controller.start(); diff --git a/test/frontend.test.js b/test/frontend.test.js index 69815dff12..2d70cfa1a7 100644 --- a/test/frontend.test.js +++ b/test/frontend.test.js @@ -246,7 +246,7 @@ describe('Frontend', () => { const allTopics = mockWSClient.implementation.send.mock.calls.map((m) => JSON.parse(m).topic); expect(allTopics).toContain('bridge/devices'); expect(allTopics).toContain('bridge/info'); - expect(mockWSClient.implementation.send).toHaveBeenCalledWith(stringify({topic: 'bridge/state', payload: 'online'})); + expect(mockWSClient.implementation.send).toHaveBeenCalledWith(stringify({topic: 'bridge/state', payload: {state: 'online'}})); expect(mockWSClient.implementation.send).toHaveBeenCalledWith(stringify({topic: 'remote', payload: {brightness: 255}})); // Message diff --git a/test/homeassistant.test.js b/test/homeassistant.test.js index f077a7c8af..220016c704 100644 --- a/test/homeassistant.test.js +++ b/test/homeassistant.test.js @@ -92,7 +92,7 @@ describe('HomeAssistant extension', () => { let payload; payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], brightness: true, brightness_scale: 254, command_topic: 'zigbee2mqtt/ha_discovery_group/set', @@ -137,7 +137,7 @@ describe('HomeAssistant extension', () => { ); payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], command_topic: 'zigbee2mqtt/ha_discovery_group/set', device: { identifiers: ['zigbee2mqtt_1221051039810110150109113116116_9'], @@ -183,7 +183,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], enabled_by_default: true, }; @@ -213,7 +213,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -242,7 +242,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -272,7 +272,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -303,7 +303,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -314,7 +314,7 @@ describe('HomeAssistant extension', () => { ); payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], command_topic: 'zigbee2mqtt/wall_switch_double/left/set', device: { identifiers: ['zigbee2mqtt_0x0017880104e45542'], @@ -343,7 +343,7 @@ describe('HomeAssistant extension', () => { ); payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], command_topic: 'zigbee2mqtt/wall_switch_double/right/set', device: { identifiers: ['zigbee2mqtt_0x0017880104e45542'], @@ -372,7 +372,7 @@ describe('HomeAssistant extension', () => { ); payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], brightness: true, brightness_scale: 254, supported_color_modes: ['color_temp'], @@ -428,7 +428,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }); const topic2 = 'homeassistant/device_automation/0x0017880104e45522/action_double/config'; const payload2 = stringify({ @@ -499,7 +499,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -528,7 +528,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -557,7 +557,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -616,7 +616,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'From Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], expire_after: 90, icon: 'mdi:test', }; @@ -645,7 +645,7 @@ describe('HomeAssistant extension', () => { via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, origin: origin, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], expire_after: 30, icon: 'mdi:test', object_id: 'weather_sensor_humidity', @@ -691,7 +691,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], enabled_by_default: true, }; @@ -721,7 +721,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -753,7 +753,7 @@ describe('HomeAssistant extension', () => { await flushPromises(); payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], command_topic: 'zigbee2mqtt/my_switch/set', device: { identifiers: ['zigbee2mqtt_0x0017880104e45541'], @@ -842,7 +842,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Hampton Bay', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -861,6 +861,7 @@ describe('HomeAssistant extension', () => { availability: [ { topic: 'zigbee2mqtt/bridge/state', + value_template: '{{ value_json.state }}', }, ], current_temperature_template: '{{ value_json.local_temperature }}', @@ -908,7 +909,7 @@ describe('HomeAssistant extension', () => { action_template: "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.running_state] }}", action_topic: 'zigbee2mqtt/bosch_radiator', - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], current_temperature_template: '{{ value_json.local_temperature }}', current_temperature_topic: 'zigbee2mqtt/bosch_radiator', device: { @@ -974,7 +975,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Keen Home', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -985,7 +986,7 @@ describe('HomeAssistant extension', () => { ); payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], command_topic: 'zigbee2mqtt/zigfred_plus/l6/set', device: { identifiers: ['zigbee2mqtt_0xf4ce368a38be56a1'], @@ -1047,7 +1048,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -1226,7 +1227,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -1395,7 +1396,7 @@ describe('HomeAssistant extension', () => { via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, availability_mode: 'all', - availability: [{topic: 'zigbee2mqtt/bridge/state'}, {topic: 'zigbee2mqtt/weather_sensor/availability'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}, {topic: 'zigbee2mqtt/weather_sensor/availability', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -1490,7 +1491,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -1541,7 +1542,7 @@ describe('HomeAssistant extension', () => { await flushPromises(); const payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], brightness: true, brightness_scale: 254, command_topic: 'zigbee2mqtt/ha_discovery_group_new/set', @@ -1627,7 +1628,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -1658,7 +1659,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'IKEA', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], device_class: 'update', entity_category: 'diagnostic', }; @@ -1992,7 +1993,7 @@ describe('HomeAssistant extension', () => { MQTT.publish.mockClear(); await MQTT.events.message( 'homeassistant/light/1221051039810110150109113116116_91231/light/config', - stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]}), + stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]}), ); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(1); @@ -2007,14 +2008,14 @@ describe('HomeAssistant extension', () => { MQTT.publish.mockClear(); await MQTT.events.message( 'homeassistant/light/1221051039810110150109113116116_9/light/config', - stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]}), + stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]}), ); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(0); // Existing group with old topic structure (1.20.0) -> clear MQTT.publish.mockClear(); - await MQTT.events.message('homeassistant/light/9/light/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]})); + await MQTT.events.message('homeassistant/light/9/light/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]})); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(1); expect(MQTT.publish).toHaveBeenCalledWith('homeassistant/light/9/light/config', '', {qos: 1, retain: true}, expect.any(Function)); @@ -2023,7 +2024,7 @@ describe('HomeAssistant extension', () => { MQTT.publish.mockClear(); await MQTT.events.message( 'homeassistant/light/1221051039810110150109113116116_9/switch/config', - stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]}), + stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]}), ); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(1); @@ -2036,7 +2037,7 @@ describe('HomeAssistant extension', () => { // Non-existing device -> clear MQTT.publish.mockClear(); - await MQTT.events.message('homeassistant/sensor/0x123/temperature/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]})); + await MQTT.events.message('homeassistant/sensor/0x123/temperature/config', stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]})); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(1); expect(MQTT.publish).toHaveBeenCalledWith('homeassistant/sensor/0x123/temperature/config', '', {qos: 1, retain: true}, expect.any(Function)); @@ -2045,7 +2046,7 @@ describe('HomeAssistant extension', () => { MQTT.publish.mockClear(); await MQTT.events.message( 'homeassistant/binary_sensor/0x000b57fffec6a5b2/update_available/config', - stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]}), + stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]}), ); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(0); @@ -2063,7 +2064,7 @@ describe('HomeAssistant extension', () => { MQTT.publish.mockClear(); await MQTT.events.message( 'homeassistant/sensor/0x000b57fffec6a5b2/update_available/config', - stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]}), + stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]}), ); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledTimes(1); @@ -2105,7 +2106,7 @@ describe('HomeAssistant extension', () => { await MQTT.events.message( 'homeassistant/sensor/0x000b57fffec6a5b2/update_available/config', - stringify({availability: [{topic: 'zigbee2mqtt/bridge/state'}]}), + stringify({availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}]}), ); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( @@ -2153,7 +2154,7 @@ describe('HomeAssistant extension', () => { manufacturer: 'Aqara', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2174,7 +2175,7 @@ describe('HomeAssistant extension', () => { await flushPromises(); const payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], brightness: true, brightness_scale: 254, command_topic: 'zigbee2mqtt/ha_discovery_group/set', @@ -2322,6 +2323,7 @@ describe('HomeAssistant extension', () => { availability: [ { topic: 'zigbee2mqtt/bridge/state', + value_template: '{{ value_json.state }}', }, ], device: { @@ -2381,7 +2383,7 @@ describe('HomeAssistant extension', () => { configuration_url: 'http://zigbee.mqtt/#/device/0x0017880104e45522/info', via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2427,7 +2429,7 @@ describe('HomeAssistant extension', () => { via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, origin: origin, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( `homeassistant/scene/0x000b57fffec6a5b4/scene_1/config`, @@ -2471,7 +2473,7 @@ describe('HomeAssistant extension', () => { via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae', }, origin: origin, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], }; expect(MQTT.publish).toHaveBeenCalledWith( `homeassistant/scene/1221051039810110150109113116116_9/scene_4/config`, @@ -2502,7 +2504,7 @@ describe('HomeAssistant extension', () => { hw_version: 'z-Stack 20190425', sw_version: z2m_version, }, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; @@ -2537,7 +2539,7 @@ describe('HomeAssistant extension', () => { device_class: 'connectivity', unique_id: 'bridge_0x00124b00120144ae_connection_state_zigbee2mqtt', state_topic: 'zigbee2mqtt/bridge/state', - value_template: '{{ value }}', + value_template: '{{ value_json.state }}', payload_on: 'online', payload_off: 'offline', origin: origin, @@ -2563,7 +2565,7 @@ describe('HomeAssistant extension', () => { payload_off: false, origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2583,7 +2585,7 @@ describe('HomeAssistant extension', () => { payload_press: '', origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2606,7 +2608,7 @@ describe('HomeAssistant extension', () => { options: settings.LOG_LEVELS, origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2627,7 +2629,7 @@ describe('HomeAssistant extension', () => { value_template: '{{ value_json.version }}', origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2648,7 +2650,7 @@ describe('HomeAssistant extension', () => { value_template: '{{ value_json.coordinator.meta.revision }}', origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2670,7 +2672,7 @@ describe('HomeAssistant extension', () => { json_attributes_template: '{{ value_json.data.value | tojson }}', origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2691,7 +2693,7 @@ describe('HomeAssistant extension', () => { value_template: '{{ iif(value_json.permit_join_timeout is defined, value_json.permit_join_timeout, None) }}', origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2714,7 +2716,7 @@ describe('HomeAssistant extension', () => { payload_off: 'false', origin: origin, device: devicePayload, - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], availability_mode: 'all', }; expect(MQTT.publish).toHaveBeenCalledWith( @@ -2750,7 +2752,7 @@ describe('HomeAssistant extension', () => { await zigbeeHerdsman.events.message(msg); await flushPromises(); const payload = { - availability: [{topic: 'zigbee2mqtt/bridge/state'}], + availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], command_topic: 'zigbee2mqtt/0x18fc26000000cafe/set/device_mode', device: { identifiers: ['zigbee2mqtt_0x18fc26000000cafe'],