This commit is contained in:
Koen Kanters 2019-11-03 14:54:03 +01:00
parent 4265fe05c6
commit afbfdda0d7
3 changed files with 48 additions and 10 deletions

View File

@ -22,6 +22,7 @@ class BridgeConfig extends BaseExtension {
this.groups = this.groups.bind(this);
this.rename = this.rename.bind(this);
this.remove = this.remove.bind(this);
this.forceRemove = this.forceRemove.bind(this);
this.ban = this.ban.bind(this);
this.deviceOptions = this.deviceOptions.bind(this);
this.addGroup = this.addGroup.bind(this);
@ -40,6 +41,7 @@ class BridgeConfig extends BaseExtension {
'devices/get': this.devices,
'rename': this.rename,
'remove': this.remove,
'force_remove': this.forceRemove,
'ban': this.ban,
'device_options': this.deviceOptions,
'add_group': this.addGroup,
@ -214,16 +216,25 @@ class BridgeConfig extends BaseExtension {
logger.info(`Removed group '${name}'`);
}
async forceRemove(topic, message) {
await this.removeForceRemoveOrBan('force_remove', message);
}
async remove(topic, message) {
await this.removeOrBan(false, message);
await this.removeForceRemoveOrBan('remove', message);
}
async ban(topic, message) {
await this.removeOrBan(true, message);
await this.removeForceRemoveOrBan('ban', message);
}
async removeOrBan(ban, message) {
async removeForceRemoveOrBan(action, message) {
const entity = this.zigbee.resolveEntity(message.trim());
const lookup = {
ban: ['banned', 'Banning', 'ban'],
force_remove: ['force_removed', 'Force removing', 'force remove'],
remove: ['removed', 'Removing', 'remove'],
};
const cleanup = () => {
// Remove from configuration.yaml
@ -232,20 +243,24 @@ class BridgeConfig extends BaseExtension {
// Remove from state
this.state.remove(entity.settings.ID);
logger.info(`Successfully ${ban ? 'banned' : 'removed'} ${entity.settings.friendlyName}`);
this.mqtt.log(ban ? 'device_banned' : 'device_removed', message);
logger.info(`Successfully ${lookup[action][0]} ${entity.settings.friendlyName}`);
this.mqtt.log(`device_${lookup[action][0]}`, message);
};
// Remove from zigbee network.
try {
logger.info(`Removing '${entity.settings.friendlyName}'`);
await entity.device.removeFromNetwork();
logger.info(`${lookup[action][1]} '${entity.settings.friendlyName}'`);
if (action === 'force_remove') {
await entity.device.removeFromDatabase();
} else {
await entity.device.removeFromNetwork();
}
cleanup();
} catch (error) {
logger.error(`Failed to ${ban ? 'ban' : 'remove'} ${entity.settings.friendlyName} (${error})`);
logger.error(`Failed to ${lookup[action][2]} ${entity.settings.friendlyName} (${error})`);
}
if (ban) {
if (action === 'ban') {
settings.banDevice(entity.settings.ID);
}
}

View File

@ -247,6 +247,28 @@ describe('Bridge config', () => {
expect(settings.get().ban.length).toBe(0);
});
it('Should allow to force remove device', async () => {
controller.state.state = {'0x000b57fffec6a5b3': {brightness: 100}};
const device = zigbeeHerdsman.devices.bulb_color;
device.removeFromDatabase.mockClear();
expect(settings.get().ban.length).toBe(0);
await flushPromises();
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/config/force_remove', 'bulb_color');
await flushPromises();
expect(device.removeFromDatabase).toHaveBeenCalledTimes(1);
expect(controller.state[device.ieeeAddr]).toBeUndefined();
expect(settings.getDevice('bulb_color')).toBeNull();
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/log',
JSON.stringify({type: 'device_force_removed', message: 'bulb_color'}),
{qos: 0, retain: false},
expect.any(Function)
);
expect(controller.state.state).toStrictEqual({});
expect(settings.get().ban.length).toBe(0);
});
it('Should allow to ban device', async () => {
const device = zigbeeHerdsman.devices.bulb_color;
device.removeFromNetwork.mockClear();

View File

@ -77,6 +77,7 @@ class Device {
this.meta = {};
this.ping = jest.fn();
this.removeFromNetwork = jest.fn();
this.removeFromDatabase = jest.fn();
this.save = jest.fn();
this.manufacturerName = manufacturerName;
this.lastSeen = 1000;