diff --git a/lib/extension/bridgeConfig.js b/lib/extension/bridgeConfig.js index c16a8a08..c2f2fd45 100644 --- a/lib/extension/bridgeConfig.js +++ b/lib/extension/bridgeConfig.js @@ -22,6 +22,7 @@ class BridgeConfig extends BaseExtension { this.devices = this.devices.bind(this); this.groups = this.groups.bind(this); this.rename = this.rename.bind(this); + this.renameLast = this.renameLast.bind(this); this.remove = this.remove.bind(this); this.forceRemove = this.forceRemove.bind(this); this.ban = this.ban.bind(this); @@ -31,6 +32,8 @@ class BridgeConfig extends BaseExtension { this.whitelist = this.whitelist.bind(this); this.touchlinkFactoryReset = this.touchlinkFactoryReset.bind(this); + this.lastJoinedDeviceName = null; + // Set supported options this.supportedOptions = { 'permit_join': this.permitJoin, @@ -42,6 +45,7 @@ class BridgeConfig extends BaseExtension { 'groups': this.groups, 'devices/get': this.devices, 'rename': this.rename, + 'rename_last': this.renameLast, 'remove': this.remove, 'force_remove': this.forceRemove, 'ban': this.ban, @@ -197,12 +201,25 @@ class BridgeConfig extends BaseExtension { return; } + this._renameInternal(json.old, json.new); + } + + renameLast(topic, message) { + if (!this.lastJoinedDeviceName) { + logger.error(`Cannot rename last joined device, no device has joined during this session`); + return; + } + + this._renameInternal(this.lastJoinedDeviceName, message); + } + + _renameInternal(from, to) { try { - settings.changeFriendlyName(json.old, json.new); - logger.info(`Successfully renamed - ${json.old} to ${json.new} `); - this.mqtt.log('device_renamed', {from: json.old, to: json.new}); + settings.changeFriendlyName(from, to); + logger.info(`Successfully renamed - ${from} to ${to} `); + this.mqtt.log('device_renamed', {from, to}); } catch (error) { - logger.error(`Failed to rename - ${json.old} to ${json.new}`); + logger.error(`Failed to rename - ${from} to ${to}`); } } @@ -333,6 +350,12 @@ class BridgeConfig extends BaseExtension { await this.mqtt.publish(topic, JSON.stringify(payload), {retain: true, qos: 0}); } + onZigbeeEvent(type, data, mappedDevice, settingsDevice) { + if (type === 'deviceJoined') { + this.lastJoinedDeviceName = settingsDevice.friendlyName; + } + } + async touchlinkFactoryReset() { logger.info('Starting touchlink factory reset...'); const result = await this.zigbee.touchlinkFactoryReset(); diff --git a/test/bridgeConfig.test.js b/test/bridgeConfig.test.js index 800b0705..40938d32 100644 --- a/test/bridgeConfig.test.js +++ b/test/bridgeConfig.test.js @@ -203,6 +203,33 @@ describe('Bridge config', () => { expect(settings.getDevice('bulb_color2')).toStrictEqual(bulb_color2); }); + it('Should allow to rename last joined device', async () => { + const device = zigbeeHerdsman.devices.bulb; + const payload = {device}; + await zigbeeHerdsman.events.deviceJoined(payload); + await flushPromises(); + expect(settings.getDevice('0x000b57fffec6a5b2').friendlyName).toStrictEqual('bulb'); + MQTT.events.message('zigbee2mqtt/bridge/config/rename_last', 'bulb_new_name'); + await flushPromises(); + expect(settings.getDevice('0x000b57fffec6a5b2').friendlyName).toStrictEqual('bulb_new_name'); + expect(MQTT.publish).toHaveBeenCalledWith( + 'zigbee2mqtt/bridge/log', + JSON.stringify({type: 'device_renamed', message: {from: 'bulb', to: 'bulb_new_name'}}), + {qos: 0, retain: false}, + expect.any(Function) + ); + }); + + it('Shouldnt rename when no device has been joined', async () => { + controller = new Controller(); + await controller.start(); + await flushPromises(); + expect(settings.getDevice('0x000b57fffec6a5b2').friendlyName).toStrictEqual('bulb'); + MQTT.events.message('zigbee2mqtt/bridge/config/rename_last', 'bulb_new_name'); + await flushPromises(); + expect(settings.getDevice('0x000b57fffec6a5b2').friendlyName).toStrictEqual('bulb'); + }); + it('Should allow to add groups', async () => { zigbeeHerdsman.createGroup.mockClear(); MQTT.events.message('zigbee2mqtt/bridge/config/add_group', 'new_group');