From 49f8706738f26fa01dde960e75a428014c9f0f23 Mon Sep 17 00:00:00 2001 From: Nerivec <62446222+Nerivec@users.noreply.github.com> Date: Mon, 7 Oct 2024 21:03:16 +0200 Subject: [PATCH 1/6] fix: Improve permit join --- lib/controller.ts | 13 ----- lib/extension/bridge.ts | 37 ++++--------- lib/types/types.d.ts | 1 - lib/util/settings.ts | 1 - lib/zigbee.ts | 16 ++---- test/bridge.test.js | 107 ++++++++++-------------------------- test/controller.test.js | 19 ------- test/settings.test.js | 8 +-- test/stub/data.js | 1 - test/stub/zigbeeHerdsman.js | 3 +- 10 files changed, 49 insertions(+), 157 deletions(-) diff --git a/lib/controller.ts b/lib/controller.ts index 60dcde1733..e36ed832a0 100644 --- a/lib/controller.ts +++ b/lib/controller.ts @@ -167,19 +167,6 @@ export class Controller { logger.info(`Currently ${deviceCount} devices are joined.`); - // Enable zigbee join - try { - if (settings.get().permit_join) { - logger.warning('`permit_join` set to `true` in configuration.yaml.'); - logger.warning('Allowing new devices to join.'); - logger.warning('Set `permit_join` to `false` once you joined all devices.'); - } - - await this.zigbee.permitJoin(settings.get().permit_join); - } catch (error) { - logger.error(`Failed to set permit join to ${settings.get().permit_join} (${(error as Error).message})`); - } - // MQTT try { await this.mqtt.connect(); diff --git a/lib/extension/bridge.ts b/lib/extension/bridge.ts index d5d1549d30..69ff55963f 100644 --- a/lib/extension/bridge.ts +++ b/lib/extension/bridge.ts @@ -225,10 +225,6 @@ export default class Bridge extends Extension { if (restartRequired) this.restartRequired = true; // Apply some settings on-the-fly. - if (newSettings.permit_join != undefined) { - await this.zigbee.permitJoin(settings.get().permit_join); - } - if (newSettings.homeassistant != undefined) { await this.enableDisableExtension(!!settings.get().homeassistant, 'HomeAssistant'); } @@ -323,17 +319,15 @@ export default class Bridge extends Extension { } @bind async permitJoin(message: KeyValue | string): Promise { - if (typeof message === 'object' && message.value === undefined) { - throw new Error('Invalid payload'); - } - - let value: boolean | string; let time: number | undefined; let device: Device | undefined; if (typeof message === 'object') { - value = message.value; - time = message.time; + if (message.time === undefined) { + throw new Error('Invalid payload'); + } + + time = Number.parseInt(message.time, 10); if (message.device) { const resolved = this.zigbee.resolveEntity(message.device); @@ -345,25 +339,15 @@ export default class Bridge extends Extension { } } } else { - value = message; - } - - if (typeof value === 'string') { - value = value.toLowerCase() === 'true'; + time = Number.parseInt(message, 10); } - await this.zigbee.permitJoin(value, device, time); + await this.zigbee.permitJoin(time, device); - const response: {value: boolean; device?: string; time?: number} = {value}; + const response: {time: number; device?: string} = {time}; - if (typeof message === 'object') { - if (device) { - response.device = message.device; - } - - if (time != undefined) { - response.time = message.time; - } + if (device) { + response.device = device.name; } return utils.getResponse(message, response); @@ -679,7 +663,6 @@ export default class Bridge extends Extension { }, network: utils.toSnakeCaseObject(await this.zigbee.getNetworkParameters()), log_level: logger.getLevel(), - permit_join: this.zigbee.getPermitJoin(), permit_join_timeout: this.zigbee.getPermitJoinTimeout(), restart_required: this.restartRequired, config, diff --git a/lib/types/types.d.ts b/lib/types/types.d.ts index 7f943ccf45..f468c8a282 100644 --- a/lib/types/types.d.ts +++ b/lib/types/types.d.ts @@ -119,7 +119,6 @@ declare global { legacy_entity_attributes: boolean; legacy_triggers: boolean; }; - permit_join: boolean; availability?: { active: {timeout: number}; passive: {timeout: number}; diff --git a/lib/util/settings.ts b/lib/util/settings.ts index d0d10e976b..69d0172316 100644 --- a/lib/util/settings.ts +++ b/lib/util/settings.ts @@ -43,7 +43,6 @@ const ajvRestartRequiredGroupOptions = new Ajv({allErrors: true}) .addKeyword({keyword: 'requiresRestart', validate: (s: unknown) => !s}) .compile(schemaJson.definitions.group); const defaults: RecursivePartial = { - permit_join: false, external_converters: [], mqtt: { base_topic: 'zigbee2mqtt', diff --git a/lib/zigbee.ts b/lib/zigbee.ts index 5786cdc713..8a7e5e2b52 100644 --- a/lib/zigbee.ts +++ b/lib/zigbee.ts @@ -225,26 +225,18 @@ export default class Zigbee { logger.info('Stopped zigbee-herdsman'); } - getPermitJoin(): boolean { - return this.herdsman.getPermitJoin(); - } - - getPermitJoinTimeout(): number | undefined { + getPermitJoinTimeout(): number { return this.herdsman.getPermitJoinTimeout(); } - async permitJoin(permit: boolean, device?: Device, time?: number): Promise { - if (permit) { + async permitJoin(time: number, device?: Device): Promise { + if (time > 0) { logger.info(`Zigbee: allowing new devices to join${device ? ` via ${device.name}` : ''}.`); } else { logger.info('Zigbee: disabling joining new devices.'); } - if (device && permit) { - await this.herdsman.permitJoin(permit, device.zh, time); - } else { - await this.herdsman.permitJoin(permit, undefined, time); - } + await this.herdsman.permitJoin(time, device?.zh); } @bind private resolveDevice(ieeeAddr: string): Device | undefined { diff --git a/test/bridge.test.js b/test/bridge.test.js index 40feccbd8c..2218a7a78b 100644 --- a/test/bridge.test.js +++ b/test/bridge.test.js @@ -64,6 +64,7 @@ describe('Bridge', () => { logger.warning.mockClear(); logger.setTransportsEnabled(false); MQTT.publish.mockClear(); + zigbeeHerdsman.permitJoin.mockClear(); const device = zigbeeHerdsman.devices.bulb; device.interview.mockClear(); device.removeFromDatabase.mockClear(); @@ -203,14 +204,13 @@ describe('Bridge', () => { mqtt: {base_topic: 'zigbee2mqtt', force_disable_retain: false, include_device_information: false, server: 'mqtt://localhost'}, ota: {disable_automatic_update_check: false, update_check_interval: 1440}, passlist: [], - permit_join: true, serial: {disable_led: false, port: '/dev/dummy'}, }, config_schema: settings.schema, coordinator: {ieee_address: '0x00124b00120144ae', 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, + permit_join_timeout: 0, restart_required: false, version: version.version, zigbee_herdsman: zhVersion, @@ -2584,50 +2584,47 @@ describe('Bridge', () => { ); }); - it('Should allow permit join', async () => { - zigbeeHerdsman.permitJoin.mockClear(); - MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', 'true'); + it('Should allow permit join on all', async () => { + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time: 1})); await flushPromises(); expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(true, undefined, undefined); + expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(1, undefined); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/permit_join', - stringify({data: {value: true}, status: 'ok'}), + stringify({data: {time: 1}, status: 'ok'}), {retain: false, qos: 0}, expect.any(Function), ); + }); - zigbeeHerdsman.permitJoin.mockClear(); - MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: false})); + it('Should disallow permit join on all', async () => { + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time: 0})); await flushPromises(); expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(false, undefined, undefined); + expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(0, undefined); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/permit_join', - stringify({data: {value: false}, status: 'ok'}), + stringify({data: {time: 0}, status: 'ok'}), {retain: false, qos: 0}, expect.any(Function), ); + }); - zigbeeHerdsman.permitJoin.mockClear(); - MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: 'False'})); + it('Should allow permit join with number string (automatically on all)', async () => { + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', '1'); await flushPromises(); expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(false, undefined, undefined); + expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(1, undefined); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/permit_join', - stringify({data: {value: false}, status: 'ok'}), + stringify({data: {time: 1}, 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})); + it('Should not allow permit join with invalid payload', async () => { + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time_bla: false})); await flushPromises(); expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(0); expect(MQTT.publish).toHaveBeenCalledWith( @@ -2638,21 +2635,6 @@ describe('Bridge', () => { ); }); - it('Should allow permit join for certain time', async () => { - zigbeeHerdsman.permitJoin.mockClear(); - MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: false, time: 10})); - await flushPromises(); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(false, undefined, 10); - expect(MQTT.publish).toHaveBeenCalledWith( - 'zigbee2mqtt/bridge/response/permit_join', - stringify({data: {value: false, time: 10}, status: 'ok'}), - {retain: false, qos: 0}, - expect.any(Function), - ); - }); - it('Should republish bridge info when permit join changes', async () => { MQTT.publish.mockClear(); await zigbeeHerdsman.events.permitJoinChanged({permitted: false, timeout: 10}); @@ -2670,23 +2652,22 @@ describe('Bridge', () => { 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'})); + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time: 123, device: 'bulb'})); await flushPromises(); expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(true, device, undefined); + expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(123, device); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/permit_join', - stringify({data: {value: true, device: 'bulb'}, status: 'ok'}), + stringify({data: {time: 123, device: 'bulb'}, status: 'ok'}), {retain: false, qos: 0}, expect.any(Function), ); + }); - // Device does not exist - zigbeeHerdsman.permitJoin.mockClear(); + it('Should not allow permit join via non-existing device', async () => { MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: true, device: 'bulb_not_existing_woeeee'})); + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time: 123, device: 'bulb_not_existing_woeeee'})); await flushPromises(); expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(0); expect(MQTT.publish).toHaveBeenCalledWith( @@ -2699,11 +2680,11 @@ describe('Bridge', () => { it('Should put transaction in response when request is done with transaction', async () => { MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: false, transaction: 22})); + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time: 0, transaction: 22})); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/permit_join', - stringify({data: {value: false}, status: 'ok', transaction: 22}), + stringify({data: {time: 0}, status: 'ok', transaction: 22}), {retain: false, qos: 0}, expect.any(Function), ); @@ -2714,7 +2695,7 @@ describe('Bridge', () => { throw new Error('Failed to connect to adapter'); }); MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({value: false})); + MQTT.events.message('zigbee2mqtt/bridge/request/permit_join', stringify({time: 0})); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/permit_join', @@ -3560,7 +3541,6 @@ describe('Bridge', () => { const device = zigbeeHerdsman.devices.bulb; const endpoint = device.getEndpoint(1); endpoint.configureReporting.mockClear(); - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); MQTT.events.message( 'zigbee2mqtt/bridge/request/device/configure_reporting', @@ -3605,7 +3585,6 @@ describe('Bridge', () => { const device = zigbeeHerdsman.devices.bulb; const endpoint = device.getEndpoint(1); endpoint.configureReporting.mockClear(); - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); MQTT.events.message( 'zigbee2mqtt/bridge/request/device/configure_reporting', @@ -3632,7 +3611,6 @@ describe('Bridge', () => { const device = zigbeeHerdsman.devices.bulb; const endpoint = device.getEndpoint(1); endpoint.configureReporting.mockClear(); - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); MQTT.events.message( 'zigbee2mqtt/bridge/request/device/configure_reporting', @@ -3659,7 +3637,6 @@ describe('Bridge', () => { const device = zigbeeHerdsman.devices.bulb; const endpoint = device.getEndpoint(1); endpoint.configureReporting.mockClear(); - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); MQTT.events.message( 'zigbee2mqtt/bridge/request/device/configure_reporting', @@ -3709,7 +3686,6 @@ describe('Bridge', () => { }); it('Should allow to restart', async () => { - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); MQTT.events.message('zigbee2mqtt/bridge/request/restart', ''); await flushPromises(); @@ -3723,24 +3699,6 @@ describe('Bridge', () => { ); }); - it('Change options', async () => { - zigbeeHerdsman.permitJoin.mockClear(); - settings.apply({permit_join: false}); - MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/options', stringify({options: {permit_join: true}})); - await flushPromises(); - expect(settings.get().permit_join).toBe(true); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(true, undefined, undefined); - expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/info', expect.any(String), {retain: true, qos: 0}, expect.any(Function)); - expect(MQTT.publish).toHaveBeenCalledWith( - 'zigbee2mqtt/bridge/response/options', - stringify({data: {restart_required: false}, status: 'ok'}), - {retain: false, qos: 0}, - expect.any(Function), - ); - }); - it('Change options and apply - homeassistant', async () => { expect(controller.extensions.find((e) => e.constructor.name === 'HomeAssistant')).toBeUndefined(); MQTT.publish.mockClear(); @@ -3812,7 +3770,6 @@ describe('Bridge', () => { }); it('Change options restart required', async () => { - zigbeeHerdsman.permitJoin.mockClear(); settings.apply({serial: {port: '123'}}); MQTT.publish.mockClear(); MQTT.events.message('zigbee2mqtt/bridge/request/options', stringify({options: {serial: {port: '/dev/newport'}}})); @@ -3827,7 +3784,6 @@ describe('Bridge', () => { }); it('Change options array', async () => { - zigbeeHerdsman.permitJoin.mockClear(); expect(settings.get().advanced.ext_pan_id).toStrictEqual([221, 221, 221, 221, 221, 221, 221, 221]); MQTT.publish.mockClear(); MQTT.events.message( @@ -3845,7 +3801,6 @@ describe('Bridge', () => { }); it('Change options with null', async () => { - zigbeeHerdsman.permitJoin.mockClear(); expect(settings.get().serial).toStrictEqual({disable_led: false, port: '/dev/dummy'}); MQTT.publish.mockClear(); MQTT.events.message('zigbee2mqtt/bridge/request/options', stringify({options: {serial: {disable_led: false, port: null}}})); @@ -3860,7 +3815,6 @@ describe('Bridge', () => { }); it('Change options invalid payload', async () => { - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); MQTT.events.message('zigbee2mqtt/bridge/request/options', 'I am invalid'); await flushPromises(); @@ -3873,13 +3827,12 @@ describe('Bridge', () => { }); it('Change options not valid against schema', async () => { - zigbeeHerdsman.permitJoin.mockClear(); MQTT.publish.mockClear(); - MQTT.events.message('zigbee2mqtt/bridge/request/options', stringify({options: {permit_join: 'true'}})); + MQTT.events.message('zigbee2mqtt/bridge/request/options', stringify({options: {external_converters: 'true'}})); await flushPromises(); expect(MQTT.publish).toHaveBeenCalledWith( 'zigbee2mqtt/bridge/response/options', - stringify({data: {}, error: 'permit_join must be boolean', status: 'error'}), + stringify({data: {}, error: 'external_converters must be array', status: 'error'}), {retain: false, qos: 0}, expect.any(Function), ); diff --git a/test/controller.test.js b/test/controller.test.js index 939daf82d3..82c243f044 100644 --- a/test/controller.test.js +++ b/test/controller.test.js @@ -10,7 +10,6 @@ const stringify = require('json-stable-stringify-without-jsonify'); const flushPromises = require('./lib/flushPromises'); const tmp = require('tmp'); const mocksClear = [ - zigbeeHerdsman.permitJoin, MQTT.end, zigbeeHerdsman.stop, logger.debug, @@ -84,8 +83,6 @@ describe('Controller', () => { }); expect(zigbeeHerdsman.start).toHaveBeenCalledTimes(1); expect(zigbeeHerdsman.setTransmitPower).toHaveBeenCalledTimes(0); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(true, undefined, undefined); expect(logger.info).toHaveBeenCalledWith(`Currently ${Object.values(zigbeeHerdsman.devices).length - 1} devices are joined.`); expect(logger.info).toHaveBeenCalledWith( 'bulb (0x000b57fffec6a5b2): LED1545G12 - IKEA TRADFRI bulb E26/E27, white spectrum, globe, opal, 980 lm (Router)', @@ -105,15 +102,6 @@ describe('Controller', () => { expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255}), {retain: true, qos: 0}, expect.any(Function)); }); - it('Start controller when permit join fails', async () => { - zigbeeHerdsman.permitJoin.mockImplementationOnce(() => { - throw new Error('failed!'); - }); - await controller.start(); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(MQTT.connect).toHaveBeenCalledTimes(1); - }); - it('Start controller with specific MQTT settings', async () => { const ca = tmp.fileSync().name; fs.writeFileSync(ca, 'ca'); @@ -283,13 +271,6 @@ describe('Controller', () => { expect(mockExit).toHaveBeenCalledWith(1, false); }); - it('Start controller with permit join true', async () => { - settings.set(['permit_join'], false); - await controller.start(); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledTimes(1); - expect(zigbeeHerdsman.permitJoin).toHaveBeenCalledWith(false, undefined, undefined); - }); - it('Start controller and stop with restart', async () => { await controller.start(); await controller.stop(true); diff --git a/test/settings.test.js b/test/settings.test.js index bdd50b3d9b..1cdf9e3e32 100644 --- a/test/settings.test.js +++ b/test/settings.test.js @@ -13,7 +13,7 @@ const yaml = require('js-yaml'); const objectAssignDeep = require(`object-assign-deep`); const minimalConfig = { - permit_join: true, + external_converters: [], homeassistant: true, mqtt: {base_topic: 'zigbee2mqtt', server: 'localhost'}, }; @@ -55,12 +55,12 @@ describe('Settings', () => { }); it('Should return settings', () => { - write(configurationFile, {permit_join: true}); + write(configurationFile, {external_converters: ['abcd.js']}); const s = settings.get(); const expected = objectAssignDeep.noMutate({}, settings.testing.defaults); expected.devices = {}; expected.groups = {}; - expected.permit_join = true; + expected.external_converters = ['abcd.js']; expect(s).toStrictEqual(expected); }); @@ -964,7 +964,7 @@ describe('Settings', () => { }, }); settings.reRead(); - settings.apply({permit_join: false}); + settings.apply({external_converters: []}); expect(settings.get().device_options.homeassistant).toStrictEqual({temperature: null}); expect(settings.get().devices['0x1234567812345678'].homeassistant).toStrictEqual({humidity: null}); }); diff --git a/test/stub/data.js b/test/stub/data.js index 66a9f80e49..8e00f0d2eb 100644 --- a/test/stub/data.js +++ b/test/stub/data.js @@ -10,7 +10,6 @@ const stateFile = path.join(mockDir, 'state.json'); function writeDefaultConfiguration() { const config = { homeassistant: false, - permit_join: true, mqtt: { base_topic: 'zigbee2mqtt', server: 'mqtt://localhost', diff --git a/test/stub/zigbeeHerdsman.js b/test/stub/zigbeeHerdsman.js index 5cdfe3c563..75a12437ca 100644 --- a/test/stub/zigbeeHerdsman.js +++ b/test/stub/zigbeeHerdsman.js @@ -895,8 +895,7 @@ const mock = { getGroupByID: jest.fn().mockImplementation((groupID) => { return Object.values(groups).find((d) => d.groupID === groupID); }), - getPermitJoin: jest.fn().mockReturnValue(false), - getPermitJoinTimeout: jest.fn().mockReturnValue(undefined), + getPermitJoinTimeout: jest.fn().mockReturnValue(0), reset: jest.fn(), createGroup: jest.fn().mockImplementation((groupID) => { const group = new Group(groupID, []); From caccd0f08076f56832af15c1eeee7546f2888a8f Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Fri, 11 Oct 2024 22:20:49 +0200 Subject: [PATCH 2/6] Update Home Assistant permit join switch --- lib/extension/homeassistant.ts | 5 +++-- test/homeassistant.test.js | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/extension/homeassistant.ts b/lib/extension/homeassistant.ts index f0ea91e6df..fdc9bf94a8 100644 --- a/lib/extension/homeassistant.ts +++ b/lib/extension/homeassistant.ts @@ -2151,8 +2151,9 @@ export default class HomeAssistant extends Extension { value_template: '{{ value_json.permit_join | lower }}', command_topic: `${baseTopic}/request/permit_join`, state_on: 'true', - payload_on: '{"value": true, "time": 254}', - payload_off: 'false', + state_off: 'false', + payload_on: '{"time": 254}', + payload_off: '{"time": 0}', }, }, ); diff --git a/test/homeassistant.test.js b/test/homeassistant.test.js index 558524774e..68595125a5 100644 --- a/test/homeassistant.test.js +++ b/test/homeassistant.test.js @@ -2523,7 +2523,7 @@ describe('HomeAssistant extension', () => { expect(MQTT.publish).not.toHaveBeenCalledWith(topic, '', {retain: true, qos: 1}, expect.any(Function)); }); - it('Should discover bridge entities', async () => { + it('onlythis Should discover bridge entities', async () => { settings.set(['advanced', 'homeassistant_legacy_entity_attributes'], false); await resetExtension(); @@ -2719,8 +2719,9 @@ describe('HomeAssistant extension', () => { value_template: '{{ value_json.permit_join | lower }}', command_topic: 'zigbee2mqtt/bridge/request/permit_join', state_on: 'true', - payload_on: '{"value": true, "time": 254}', - payload_off: 'false', + state_off: 'false', + payload_on: '{"time": 254}', + payload_off: '{"time": 0}', origin: origin, device: devicePayload, availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}], From a9192387464a173450c12fb1acd8dfc947b72d39 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Fri, 11 Oct 2024 23:12:16 +0200 Subject: [PATCH 3/6] Remove `permit_join` from `settings.schema.json` --- lib/util/settings.schema.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/util/settings.schema.json b/lib/util/settings.schema.json index f52e6cbc4b..8b9a528c46 100644 --- a/lib/util/settings.schema.json +++ b/lib/util/settings.schema.json @@ -45,12 +45,6 @@ } ] }, - "permit_join": { - "type": "boolean", - "default": false, - "title": "Permit join", - "description": "Allow new devices to join (re-applied at restart)" - }, "availability": { "oneOf": [ { From 985f00ab956ce90e3ff6374216a0a8a3f87367c3 Mon Sep 17 00:00:00 2001 From: Nerivec <62446222+Nerivec@users.noreply.github.com> Date: Mon, 14 Oct 2024 23:20:35 +0200 Subject: [PATCH 4/6] Update zigbee-herdsman version to pre-release. --- package.json | 2 +- pnpm-lock.yaml | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 12170814e9..5a78dc8a46 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "winston-syslog": "^2.7.1", "winston-transport": "^4.8.0", "ws": "^8.18.0", - "zigbee-herdsman": "2.1.3", + "zigbee-herdsman": "3.0.0-pre.0", "zigbee-herdsman-converters": "20.28.0", "zigbee2mqtt-frontend": "0.7.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0d0bb94d2..ad60bcf14c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,11 +81,11 @@ importers: specifier: ^8.18.0 version: 8.18.0 zigbee-herdsman: - specifier: 2.1.3 - version: 2.1.3 + specifier: 3.0.0-pre.0 + version: 3.0.0-pre.0 zigbee-herdsman-converters: - specifier: 20.25.0 - version: 20.25.0 + specifier: 20.28.0 + version: 20.28.0 zigbee2mqtt-frontend: specifier: 0.7.4 version: 0.7.4 @@ -95,13 +95,13 @@ importers: version: 2.8.0 devDependencies: '@babel/core': - specifier: ^7.25.7 + specifier: ^7.25.8 version: 7.25.8 '@babel/plugin-proposal-decorators': specifier: ^7.25.7 version: 7.25.7(@babel/core@7.25.8) '@babel/preset-env': - specifier: ^7.25.7 + specifier: ^7.25.8 version: 7.25.8(@babel/core@7.25.8) '@babel/preset-typescript': specifier: ^7.25.7 @@ -131,7 +131,7 @@ importers: specifier: ^4.0.9 version: 4.0.9 '@types/node': - specifier: ^22.7.4 + specifier: ^22.7.5 version: 22.7.5 '@types/object-assign-deep': specifier: ^0.4.3 @@ -164,10 +164,10 @@ importers: specifier: ^0.2.3 version: 0.2.3 typescript: - specifier: ^5.6.2 + specifier: ^5.6.3 version: 5.6.3 typescript-eslint: - specifier: ^8.8.0 + specifier: ^8.8.1 version: 8.8.1(eslint@9.12.0)(typescript@5.6.3) packages: @@ -2800,12 +2800,15 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zigbee-herdsman-converters@20.25.0: - resolution: {integrity: sha512-iqCQmcdwrUGz00IhvtB36l3YN9sCWPhbx8D+lf9owyjpE5To7u2pOn4GA4g6QWQCU7BndCif8fXed1FWt9/nrg==} + zigbee-herdsman-converters@20.28.0: + resolution: {integrity: sha512-AMCuG4mlIR21JgShIyFnZsCimfITH2HpjQLS0vaAqIKmbYrG7sBF0MU/iznYc/8JqNq+Jav3BdV+BrE1M3GpEg==} zigbee-herdsman@2.1.3: resolution: {integrity: sha512-1LiSb3L2ZFzNOuGJHMWBFPRgPs1WVMS4CagtvYxEVUdifhVivp1vMNrCxBsbwNhDiNBh/Blk0pTR0szJttLzrA==} + zigbee-herdsman@3.0.0-pre.0: + resolution: {integrity: sha512-3mCSmdwu5eJb0DEJrTDSQPYEQAz1mOGAbqvXyEOjo6UOllo++GyzpmawTxWBH4FLWrbuKc9SefiVqQdC/4uZbQ==} + zigbee2mqtt-frontend@0.7.4: resolution: {integrity: sha512-skWNYxThSa6Ywn7aRB0ZvRKWifpqbku4+vUM5BbXiNaXYxCCbU0b3pN258Ahxt3NsLtYk2zBdYoQcXuBZxmJxw==} engines: {node: '>=18'} @@ -5939,7 +5942,7 @@ snapshots: yocto-queue@0.1.0: {} - zigbee-herdsman-converters@20.25.0: + zigbee-herdsman-converters@20.28.0: dependencies: axios: 1.7.7 buffer-crc32: 1.0.0 @@ -5947,6 +5950,7 @@ snapshots: iconv-lite: 0.6.3 semver: 7.6.3 tar-stream: 3.1.7 + uri-js: 4.4.1 zigbee-herdsman: 2.1.3 transitivePeerDependencies: - debug @@ -5965,4 +5969,17 @@ snapshots: transitivePeerDependencies: - supports-color + zigbee-herdsman@3.0.0-pre.0: + dependencies: + '@serialport/bindings-cpp': 12.0.1 + '@serialport/parser-delimiter': 12.0.0 + '@serialport/stream': 12.0.0 + bonjour-service: 1.2.1 + debounce: 2.1.1 + fast-deep-equal: 3.1.3 + mixin-deep: 2.0.1 + slip: 1.0.2 + transitivePeerDependencies: + - supports-color + zigbee2mqtt-frontend@0.7.4: {} From a97d002122384b2f7ecae1a13d803b2d91244289 Mon Sep 17 00:00:00 2001 From: Nerivec <62446222+Nerivec@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:30:24 +0200 Subject: [PATCH 5/6] Fix pnpm overrides --- package.json | 4 ++-- pnpm-lock.yaml | 21 ++++----------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 5a78dc8a46..b0e7e5454f 100644 --- a/package.json +++ b/package.json @@ -92,8 +92,8 @@ "typescript": "^5.6.3", "typescript-eslint": "^8.8.1" }, - "overrides": { - "zigbee-herdsman-converters": { + "pnpm": { + "overrides": { "zigbee-herdsman": "$zigbee-herdsman" } }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad60bcf14c..a7378bcb44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + zigbee-herdsman: 3.0.0-pre.0 + importers: .: @@ -2803,9 +2806,6 @@ packages: zigbee-herdsman-converters@20.28.0: resolution: {integrity: sha512-AMCuG4mlIR21JgShIyFnZsCimfITH2HpjQLS0vaAqIKmbYrG7sBF0MU/iznYc/8JqNq+Jav3BdV+BrE1M3GpEg==} - zigbee-herdsman@2.1.3: - resolution: {integrity: sha512-1LiSb3L2ZFzNOuGJHMWBFPRgPs1WVMS4CagtvYxEVUdifhVivp1vMNrCxBsbwNhDiNBh/Blk0pTR0szJttLzrA==} - zigbee-herdsman@3.0.0-pre.0: resolution: {integrity: sha512-3mCSmdwu5eJb0DEJrTDSQPYEQAz1mOGAbqvXyEOjo6UOllo++GyzpmawTxWBH4FLWrbuKc9SefiVqQdC/4uZbQ==} @@ -5951,24 +5951,11 @@ snapshots: semver: 7.6.3 tar-stream: 3.1.7 uri-js: 4.4.1 - zigbee-herdsman: 2.1.3 + zigbee-herdsman: 3.0.0-pre.0 transitivePeerDependencies: - debug - supports-color - zigbee-herdsman@2.1.3: - dependencies: - '@serialport/bindings-cpp': 12.0.1 - '@serialport/parser-delimiter': 12.0.0 - '@serialport/stream': 12.0.0 - bonjour-service: 1.2.1 - debounce: 2.1.1 - fast-deep-equal: 3.1.3 - mixin-deep: 2.0.1 - slip: 1.0.2 - transitivePeerDependencies: - - supports-color - zigbee-herdsman@3.0.0-pre.0: dependencies: '@serialport/bindings-cpp': 12.0.1 From 0c18022496940c4a47f1bc6123d91f1e0db0389d Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Tue, 15 Oct 2024 21:06:13 +0200 Subject: [PATCH 6/6] Update test/homeassistant.test.js --- test/homeassistant.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/homeassistant.test.js b/test/homeassistant.test.js index 68595125a5..23493d7f0a 100644 --- a/test/homeassistant.test.js +++ b/test/homeassistant.test.js @@ -2523,7 +2523,7 @@ describe('HomeAssistant extension', () => { expect(MQTT.publish).not.toHaveBeenCalledWith(topic, '', {retain: true, qos: 1}, expect.any(Function)); }); - it('onlythis Should discover bridge entities', async () => { + it('Should discover bridge entities', async () => { settings.set(['advanced', 'homeassistant_legacy_entity_attributes'], false); await resetExtension();