Fix optimistic group behavior whenever a device is shared between groups (#2134)

This commit is contained in:
Gabe Cook 2019-10-14 11:04:04 -05:00 committed by Koen Kanters
parent 4abafa9527
commit 09b7fe699e
2 changed files with 44 additions and 17 deletions

View File

@ -90,21 +90,7 @@ class Groups extends BaseExtension {
if (entity.type === 'device') {
for (const zigbeeGroup of zigbeeGroups) {
if (zigbeeGroup.hasMember(entity.endpoint)) {
let shouldGroupChange = true;
if (payload.state && payload.state === 'OFF') {
for (const member of zigbeeGroup.members) {
const device = member.getDevice();
if (this.state.exists(device.ieeeAddr)) {
const state = this.state.get(device.ieeeAddr);
if (state.state && state.state === 'ON') {
shouldGroupChange = false;
}
}
}
}
if (shouldGroupChange) {
if (!payload || payload.state !== 'OFF' || this.allMembersOff(zigbeeGroup)) {
await this.publishEntityState(zigbeeGroup.groupID, payload, reason);
}
}
@ -115,7 +101,9 @@ class Groups extends BaseExtension {
await this.publishEntityState(member.getDevice().ieeeAddr, payload, reason);
for (const zigbeeGroup of zigbeeGroups) {
if (zigbeeGroup.hasMember(member)) {
groupIDsToPublish.add(zigbeeGroup.groupID);
if (!payload || payload.state !== 'OFF' || this.allMembersOff(zigbeeGroup)) {
groupIDsToPublish.add(zigbeeGroup.groupID);
}
}
}
}
@ -127,6 +115,19 @@ class Groups extends BaseExtension {
}
}
allMembersOff(zigbeeGroup) {
for (const member of zigbeeGroup.members) {
const device = member.getDevice();
if (this.state.exists(device.ieeeAddr)) {
const state = this.state.get(device.ieeeAddr);
if (state && state.state === 'ON') {
return false;
}
}
}
return true;
}
async onMQTTMessage(topic, message) {
let type;
let group;

View File

@ -316,7 +316,7 @@ describe('Groups', () => {
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_2", '{"state":"ON"}', {"retain": false, qos: 0}, expect.any(Function));
});
it('Should not publish state change off if any lights within are still on', async () => {
it('Should not publish state change off if any lights within are still on when changed via device', async () => {
const device_1 = zigbeeHerdsman.devices.bulb_color;
const device_2 = zigbeeHerdsman.devices.bulb;
const endpoint_1 = device_1.getEndpoint(1);
@ -340,6 +340,32 @@ describe('Groups', () => {
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", '{"state":"OFF"}', {"retain": false, qos: 0}, expect.any(Function));
});
it('Should not publish state change off if any lights within are still on when changed via shared group', async () => {
const device_1 = zigbeeHerdsman.devices.bulb_color;
const device_2 = zigbeeHerdsman.devices.bulb;
const endpoint_1 = device_1.getEndpoint(1);
const endpoint_2 = device_2.getEndpoint(1);
const group = zigbeeHerdsman.groups.group_1;
group.members.push(endpoint_1);
group.members.push(endpoint_2);
settings.set(['groups'], {
'1': {friendly_name: 'group_1', devices: [device_1.ieeeAddr, device_2.ieeeAddr], retain: false},
'2': {friendly_name: 'group_2', retain: false, devices: [device_1.ieeeAddr]},
});
await controller.start();
await flushPromises();
await MQTT.events.message('zigbee2mqtt/group_1/set', JSON.stringify({state: 'ON'}));
await flushPromises();
MQTT.publish.mockClear();
await MQTT.events.message('zigbee2mqtt/group_2/set', JSON.stringify({state: 'OFF'}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_2", '{"state":"OFF"}', {"retain": false, qos: 0}, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", '{"state":"OFF"}', {"retain": false, qos: 0}, expect.any(Function));
});
it('Should publish state change off if all lights within turn off', async () => {
const device_1 = zigbeeHerdsman.devices.bulb_color;
const device_2 = zigbeeHerdsman.devices.bulb;