fix: Only republish changed scenes to Home Assistant when changed (#20248)

This commit is contained in:
Der Mundschenk & Compagnie
2023-12-17 09:21:59 +01:00
committed by GitHub
parent 2c5d3e14f7
commit e0f50218d7
2 changed files with 42 additions and 7 deletions
+3 -1
View File
@@ -1615,6 +1615,7 @@ export default class HomeAssistant extends Extension {
@bind async onScenesChanged(): Promise<void> {
// Re-trigger MQTT discovery of all devices and groups, similar to bridge.ts
const entities = [...this.zigbee.devices(), ...this.zigbee.groups()];
const clearedEntities = new Set<Device|Group>();
// First, clear existing scene discovery topics
entities.forEach((entity) => {
@@ -1622,6 +1623,7 @@ export default class HomeAssistant extends Extension {
this.discovered[this.getDiscoverKey(entity)]?.topics.forEach((topic) => {
if (topic.startsWith('scene')) {
this.mqtt.publish(topic, null, {retain: true, qos: 1}, this.discoveryTopic, false, false);
clearedEntities.add(entity);
}
});
});
@@ -1633,7 +1635,7 @@ export default class HomeAssistant extends Extension {
// Re-discover all entities (including their new scenes).
logger.debug(`Re-discovering entities with their scenes.`);
entities.forEach((entity) => {
clearedEntities.forEach((entity) => {
this.discover(entity, true);
});
}
+39 -6
View File
@@ -2160,21 +2160,27 @@ describe('HomeAssistant extension', () => {
});
it('Should rediscover scenes when a scene is changed', async () => {
const device = controller.zigbee.resolveEntity(zigbeeHerdsman.devices.bulb_color_2);
MQTT.publish.mockClear();
controller.eventBus.emitScenesChanged();
await flushPromises();
// Discovery messages for scenes have been purged.
expect(MQTT.publish).toHaveBeenCalledWith(
`homeassistant/scene/${device.ID}/scene_1/config`,
`homeassistant/scene/0x000b57fffec6a5b4/scene_1/config`,
null,
{retain: true, qos: 1},
expect.any(Function),
);
expect(MQTT.publish).toHaveBeenCalledWith(
`homeassistant/scene/1221051039810110150109113116116_9/scene_4/config`,
null,
{retain: true, qos: 1},
expect.any(Function),
);
jest.runOnlyPendingTimers();
await flushPromises();
const payload = {
let payload = {
'name': 'Chill scene',
'command_topic': 'zigbee2mqtt/bulb_color_2/set',
'payload_on': '{ "scene_recall": 1 }',
@@ -2192,13 +2198,40 @@ describe('HomeAssistant extension', () => {
'origin': origin,
'availability': [ { 'topic': 'zigbee2mqtt/bridge/state' } ]
}
expect(MQTT.publish).toHaveBeenCalledWith(
`homeassistant/scene/${device.ID}/scene_1/config`,
`homeassistant/scene/0x000b57fffec6a5b4/scene_1/config`,
stringify(payload),
{retain: true, qos: 1},
expect.any(Function),
);
payload = {
'name': 'Scene 4',
'command_topic': 'zigbee2mqtt/ha_discovery_group/set',
'payload_on': '{ "scene_recall": 4 }',
'json_attributes_topic':'zigbee2mqtt/ha_discovery_group',
'object_id': 'ha_discovery_group_4_scene_4',
'unique_id': '9_scene_4_zigbee2mqtt',
'device': {
'identifiers': [ 'zigbee2mqtt_1221051039810110150109113116116_9' ],
'name': 'ha_discovery_group',
'sw_version': 'Zigbee2MQTT 1.34.0-dev',
'model': 'Group',
'manufacturer': 'Zigbee2MQTT',
'via_device': 'zigbee2mqtt_bridge_0x00124b00120144ae'
},
'origin': origin,
'availability': [ { 'topic': 'zigbee2mqtt/bridge/state' } ]
}
expect(MQTT.publish).toHaveBeenCalledWith(
`homeassistant/scene/1221051039810110150109113116116_9/scene_4/config`,
stringify(payload),
{retain: true, qos: 1},
expect.any(Function),
);
// Only discovery entries for entities with scenes need to be republished.
expect(MQTT.publish).toHaveBeenCalledTimes( 16 );
});
it('Should not clear bridge entities unnecessarily', async () => {