mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-09-14 17:05:51 +00:00
fix: Fix group with only multi endpoints devices not being controllable (#25156)
This commit is contained in:
@@ -202,7 +202,8 @@ export default class Publish extends Extension {
|
||||
/* istanbul ignore next */
|
||||
// Match any key if the toZigbee converter defines no key.
|
||||
const converter = converters.find(
|
||||
(c) => (!c.key || c.key.includes(key)) && (!c.endpoints || (endpointName && c.endpoints.includes(endpointName))),
|
||||
(c) =>
|
||||
(!c.key || c.key.includes(key)) && (re instanceof Group || !c.endpoints || (endpointName && c.endpoints.includes(endpointName))),
|
||||
);
|
||||
|
||||
if (parsedTopic.type === 'set' && converter && usedConverters[endpointOrGroupID].includes(converter)) {
|
||||
|
||||
@@ -25,6 +25,7 @@ returnDevices.push(
|
||||
devices.ZNCZ02LM.ieeeAddr,
|
||||
devices.GLEDOPTO_2ID.ieeeAddr,
|
||||
devices.QBKG03LM.ieeeAddr,
|
||||
devices.hue_twilight.ieeeAddr,
|
||||
);
|
||||
|
||||
describe('Extension: Availability', () => {
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('Extension: Bridge', () => {
|
||||
const zhVersion = await utils.getDependencyVersion('zigbee-herdsman');
|
||||
const zhcVersion = await utils.getDependencyVersion('zigbee-herdsman-converters');
|
||||
const directory = settings.get().advanced.log_directory;
|
||||
// console.log(mockMQTT.publish.mock.calls.find((c) => c[0] === 'zigbee2mqtt/bridge/info')[1])
|
||||
// console.log(mockMQTT.publishAsync.mock.calls.find((c) => c[0] === 'zigbee2mqtt/bridge/info')![1]);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/info',
|
||||
stringify({
|
||||
@@ -118,36 +118,78 @@ describe('Extension: Bridge', () => {
|
||||
blocklist: [],
|
||||
device_options: {},
|
||||
devices: {
|
||||
'0x000b57fffec6a5b2': {description: 'this is my bulb', friendly_name: 'bulb', retain: true},
|
||||
'0x000b57cdfec6a5b3': {friendly_name: 'hue_twilight'},
|
||||
'0x000b57fffec6a5b2': {
|
||||
description: 'this is my bulb',
|
||||
friendly_name: 'bulb',
|
||||
retain: true,
|
||||
},
|
||||
'0x000b57fffec6a5b3': {friendly_name: 'bulb_color', retain: false},
|
||||
'0x000b57fffec6a5b4': {friendly_name: 'bulb_color_2', retain: false},
|
||||
'0x000b57fffec6a5b4': {
|
||||
friendly_name: 'bulb_color_2',
|
||||
retain: false,
|
||||
},
|
||||
'0x000b57fffec6a5b7': {friendly_name: 'bulb_2', retain: false},
|
||||
'0x0017880104a44559': {friendly_name: 'J1_cover'},
|
||||
'0x0017880104e43559': {friendly_name: 'U202DST600ZB'},
|
||||
'0x0017880104e44559': {friendly_name: '3157100_thermostat'},
|
||||
'0x0017880104e45517': {friendly_name: 'remote', retain: true},
|
||||
'0x0017880104e45520': {friendly_name: 'button', retain: false},
|
||||
'0x0017880104e45521': {friendly_name: 'button_double_key', retain: false},
|
||||
'0x0017880104e45522': {friendly_name: 'weather_sensor', qos: 1, retain: false},
|
||||
'0x0017880104e45523': {friendly_name: 'occupancy_sensor', retain: false},
|
||||
'0x0017880104e45521': {
|
||||
friendly_name: 'button_double_key',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45522': {
|
||||
friendly_name: 'weather_sensor',
|
||||
qos: 1,
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45523': {
|
||||
friendly_name: 'occupancy_sensor',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45524': {friendly_name: 'power_plug', retain: false},
|
||||
'0x0017880104e45526': {friendly_name: 'GL-S-007ZS'},
|
||||
'0x0017880104e45529': {friendly_name: 'unsupported2', retain: false},
|
||||
'0x0017880104e45530': {friendly_name: 'button_double_key_interviewing', retain: false},
|
||||
'0x0017880104e45529': {
|
||||
friendly_name: 'unsupported2',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45530': {
|
||||
friendly_name: 'button_double_key_interviewing',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45540': {friendly_name: 'ikea_onoff'},
|
||||
'0x0017880104e45541': {friendly_name: 'wall_switch', retain: false},
|
||||
'0x0017880104e45542': {friendly_name: 'wall_switch_double', retain: false},
|
||||
'0x0017880104e45543': {friendly_name: 'led_controller_1', retain: false},
|
||||
'0x0017880104e45544': {friendly_name: 'led_controller_2', retain: false},
|
||||
'0x0017880104e45545': {friendly_name: 'dimmer_wall_switch', retain: false},
|
||||
'0x0017880104e45542': {
|
||||
friendly_name: 'wall_switch_double',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45543': {
|
||||
friendly_name: 'led_controller_1',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45544': {
|
||||
friendly_name: 'led_controller_2',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45545': {
|
||||
friendly_name: 'dimmer_wall_switch',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45547': {friendly_name: 'curtain', retain: false},
|
||||
'0x0017880104e45548': {friendly_name: 'fan', retain: false},
|
||||
'0x0017880104e45549': {friendly_name: 'siren', retain: false},
|
||||
'0x0017880104e45550': {friendly_name: 'thermostat', retain: false},
|
||||
'0x0017880104e45551': {friendly_name: 'smart vent', retain: false},
|
||||
'0x0017880104e45552': {friendly_name: 'j1', retain: false},
|
||||
'0x0017880104e45553': {friendly_name: 'bulb_enddevice', retain: false},
|
||||
'0x0017880104e45559': {friendly_name: 'cc2530_router', retain: false},
|
||||
'0x0017880104e45553': {
|
||||
friendly_name: 'bulb_enddevice',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45559': {
|
||||
friendly_name: 'cc2530_router',
|
||||
retain: false,
|
||||
},
|
||||
'0x0017880104e45560': {friendly_name: 'livolo', retain: false},
|
||||
'0x0017880104e45561': {friendly_name: 'temperature_sensor'},
|
||||
'0x0017880104e45562': {friendly_name: 'heating_actuator'},
|
||||
@@ -160,7 +202,10 @@ describe('Extension: Bridge', () => {
|
||||
'0x90fd9ffffe4b64aa': {friendly_name: 'SP600_OLD'},
|
||||
'0x90fd9ffffe4b64ab': {friendly_name: 'SP600_NEW'},
|
||||
'0x90fd9ffffe4b64ac': {friendly_name: 'MKS-CM-W5'},
|
||||
'0x90fd9ffffe4b64ae': {friendly_name: 'tradfri_remote', retain: false},
|
||||
'0x90fd9ffffe4b64ae': {
|
||||
friendly_name: 'tradfri_remote',
|
||||
retain: false,
|
||||
},
|
||||
'0x90fd9ffffe4b64af': {friendly_name: 'roller_shutter'},
|
||||
'0x90fd9ffffe4b64ax': {friendly_name: 'ZNLDP12LM'},
|
||||
'0xf4ce368a38be56a1': {
|
||||
@@ -187,6 +232,7 @@ describe('Extension: Bridge', () => {
|
||||
12: {friendly_name: 'thermostat_group', retain: false},
|
||||
14: {friendly_name: 'switch_group', retain: false},
|
||||
15071: {friendly_name: 'group_tradfri_remote', retain: false},
|
||||
19: {friendly_name: 'hue_twilight_group'},
|
||||
2: {friendly_name: 'group_2', retain: false},
|
||||
21: {friendly_name: 'gledopto_group'},
|
||||
9: {friendly_name: 'ha_discovery_group'},
|
||||
@@ -195,8 +241,16 @@ describe('Extension: Bridge', () => {
|
||||
map_options: {
|
||||
graphviz: {
|
||||
colors: {
|
||||
fill: {coordinator: '#e04e5d', enddevice: '#fff8ce', router: '#4ea3e0'},
|
||||
font: {coordinator: '#ffffff', enddevice: '#000000', router: '#ffffff'},
|
||||
fill: {
|
||||
coordinator: '#e04e5d',
|
||||
enddevice: '#fff8ce',
|
||||
router: '#4ea3e0',
|
||||
},
|
||||
font: {
|
||||
coordinator: '#ffffff',
|
||||
enddevice: '#000000',
|
||||
router: '#ffffff',
|
||||
},
|
||||
line: {active: '#009900', inactive: '#994444'},
|
||||
},
|
||||
},
|
||||
@@ -209,10 +263,10 @@ describe('Extension: Bridge', () => {
|
||||
server: 'mqtt://localhost',
|
||||
},
|
||||
ota: {
|
||||
disable_automatic_update_check: false,
|
||||
update_check_interval: 1440,
|
||||
image_block_response_delay: 250,
|
||||
default_maximum_data_size: 50,
|
||||
disable_automatic_update_check: false,
|
||||
image_block_response_delay: 250,
|
||||
update_check_interval: 1440,
|
||||
},
|
||||
passlist: [],
|
||||
serial: {disable_led: false, port: '/dev/dummy'},
|
||||
@@ -2174,6 +2228,12 @@ describe('Extension: Bridge', () => {
|
||||
],
|
||||
scenes: [{id: 4, name: 'Scene 4'}],
|
||||
},
|
||||
{
|
||||
friendly_name: 'hue_twilight_group',
|
||||
id: 19,
|
||||
members: [{endpoint: 11, ieee_address: '0x000b57cdfec6a5b3'}],
|
||||
scenes: [],
|
||||
},
|
||||
]),
|
||||
{retain: true, qos: 0},
|
||||
);
|
||||
|
||||
@@ -429,6 +429,19 @@ describe('Extension: Publish', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('Should publish messages to group with just 1 Hue Twilight in int (convers have an `endpoint` on it)', async () => {
|
||||
// https://github.com/Koenkk/zigbee2mqtt/issues/24792
|
||||
const group = groups.hue_twilight_group;
|
||||
await mockMQTTEvents.message('zigbee2mqtt/hue_twilight_group/set', stringify({state: 'ON'}));
|
||||
await flushPromises();
|
||||
console.log(mockLogger.warning.mock.calls);
|
||||
expect(group.command).toHaveBeenCalledTimes(1);
|
||||
expect(group.command).toHaveBeenCalledWith('genOnOff', 'on', {}, {});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(2);
|
||||
expect(mockMQTT.publishAsync.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/hue_twilight_group');
|
||||
expect(JSON.parse(mockMQTT.publishAsync.mock.calls[1][1])).toStrictEqual({state: 'ON'});
|
||||
});
|
||||
|
||||
it('Should publish messages to groups with on and brightness', async () => {
|
||||
const group = groups.group_1;
|
||||
group.members.push(devices.bulb_color.getEndpoint(1)!);
|
||||
@@ -483,10 +496,10 @@ describe('Extension: Publish', () => {
|
||||
|
||||
it('Should create and publish to group which is in configuration.yaml but not in zigbee-herdsman', async () => {
|
||||
settings.addGroup('group_12312', '12312');
|
||||
expect(Object.values(groups).length).toBe(10);
|
||||
expect(Object.values(groups).length).toBe(11);
|
||||
await mockMQTTEvents.message('zigbee2mqtt/group_12312/set', stringify({state: 'ON'}));
|
||||
await flushPromises();
|
||||
expect(Object.values(groups).length).toBe(11);
|
||||
expect(Object.values(groups).length).toBe(12);
|
||||
// group contains no device
|
||||
// @ts-expect-error runtime mock
|
||||
expect(groups.group_12312.command).toHaveBeenCalledTimes(0);
|
||||
|
||||
@@ -201,6 +201,9 @@ export function writeDefaultConfiguration(config: unknown = undefined): void {
|
||||
'0x0017880104e45562': {
|
||||
friendly_name: 'heating_actuator',
|
||||
},
|
||||
'0x000b57cdfec6a5b3': {
|
||||
friendly_name: 'hue_twilight',
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
1: {
|
||||
@@ -233,6 +236,9 @@ export function writeDefaultConfiguration(config: unknown = undefined): void {
|
||||
9: {
|
||||
friendly_name: 'ha_discovery_group',
|
||||
},
|
||||
19: {
|
||||
friendly_name: 'hue_twilight_group',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -383,6 +383,26 @@ const bulb_2 = new Device(
|
||||
'Mains (single phase)',
|
||||
'TRADFRI bulb E27 WS opal 980lm',
|
||||
);
|
||||
const hue_twilight = new Device(
|
||||
'Router',
|
||||
'0x000b57cdfec6a5b3',
|
||||
40399,
|
||||
4107,
|
||||
[
|
||||
new Endpoint(1, [0, 3, 4, 5, 6, 8, 768, 2821, 4096], [5, 25, 32, 4096], '0x000b57cdfec6a5b3', [], {
|
||||
lightingColorCtrl: {colorCapabilities: 254},
|
||||
}),
|
||||
new Endpoint(11, [0, 3, 4, 5, 6, 8, 768, 2821, 4096], [5, 25, 32, 4096], '0x000b57cdfec6a5b3', [], {
|
||||
lightingColorCtrl: {colorCapabilities: 254},
|
||||
}),
|
||||
new Endpoint(12, [0, 3, 4, 5, 6, 8, 768, 2821, 4096], [5, 25, 32, 4096], '0x000b57cdfec6a5b3', [], {
|
||||
lightingColorCtrl: {colorCapabilities: 254},
|
||||
}),
|
||||
],
|
||||
true,
|
||||
'Mains (single phase)',
|
||||
'LGT003',
|
||||
);
|
||||
const TS0601_thermostat = new Device(
|
||||
'EndDevice',
|
||||
'0x0017882104a44559',
|
||||
@@ -488,6 +508,7 @@ export const groups = {
|
||||
gledopto_group: new Group(21, [GLEDOPTO_2ID.endpoints[3]]),
|
||||
default_bind_group: new Group(901, []),
|
||||
ha_discovery_group: new Group(9, [bulb_color_2.endpoints[0], bulb_2.endpoints[0], QBKG03LM.endpoints[2]]),
|
||||
hue_twilight_group: new Group(19, [hue_twilight.endpoints[1]]),
|
||||
};
|
||||
|
||||
const groupMembersBackup = Object.fromEntries(Object.entries(groups).map((v) => [v[0], [...v[1].members]]));
|
||||
@@ -545,6 +566,7 @@ export const devices = {
|
||||
),
|
||||
bulb_color: bulb_color,
|
||||
bulb_2: bulb_2,
|
||||
hue_twilight,
|
||||
bulb_color_2: bulb_color_2,
|
||||
remote: new Device(
|
||||
'EndDevice',
|
||||
|
||||
Reference in New Issue
Block a user