Skip to content

Commit 7242889

Browse files
authored
fix: Fix group with only multi endpoints devices not being controllable (#25156)
1 parent 39c007d commit 7242889

File tree

6 files changed

+125
-22
lines changed

6 files changed

+125
-22
lines changed

lib/extension/publish.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ export default class Publish extends Extension {
202202
/* istanbul ignore next */
203203
// Match any key if the toZigbee converter defines no key.
204204
const converter = converters.find(
205-
(c) => (!c.key || c.key.includes(key)) && (!c.endpoints || (endpointName && c.endpoints.includes(endpointName))),
205+
(c) =>
206+
(!c.key || c.key.includes(key)) && (re instanceof Group || !c.endpoints || (endpointName && c.endpoints.includes(endpointName))),
206207
);
207208

208209
if (parsedTopic.type === 'set' && converter && usedConverters[endpointOrGroupID].includes(converter)) {

test/extensions/availability.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ returnDevices.push(
2525
devices.ZNCZ02LM.ieeeAddr,
2626
devices.GLEDOPTO_2ID.ieeeAddr,
2727
devices.QBKG03LM.ieeeAddr,
28+
devices.hue_twilight.ieeeAddr,
2829
);
2930

3031
describe('Extension: Availability', () => {

test/extensions/bridge.test.ts

+79-19
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ describe('Extension: Bridge', () => {
8585
const zhVersion = await utils.getDependencyVersion('zigbee-herdsman');
8686
const zhcVersion = await utils.getDependencyVersion('zigbee-herdsman-converters');
8787
const directory = settings.get().advanced.log_directory;
88-
// console.log(mockMQTT.publish.mock.calls.find((c) => c[0] === 'zigbee2mqtt/bridge/info')[1])
88+
// console.log(mockMQTT.publishAsync.mock.calls.find((c) => c[0] === 'zigbee2mqtt/bridge/info')![1]);
8989
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
9090
'zigbee2mqtt/bridge/info',
9191
stringify({
@@ -118,36 +118,78 @@ describe('Extension: Bridge', () => {
118118
blocklist: [],
119119
device_options: {},
120120
devices: {
121-
'0x000b57fffec6a5b2': {description: 'this is my bulb', friendly_name: 'bulb', retain: true},
121+
'0x000b57cdfec6a5b3': {friendly_name: 'hue_twilight'},
122+
'0x000b57fffec6a5b2': {
123+
description: 'this is my bulb',
124+
friendly_name: 'bulb',
125+
retain: true,
126+
},
122127
'0x000b57fffec6a5b3': {friendly_name: 'bulb_color', retain: false},
123-
'0x000b57fffec6a5b4': {friendly_name: 'bulb_color_2', retain: false},
128+
'0x000b57fffec6a5b4': {
129+
friendly_name: 'bulb_color_2',
130+
retain: false,
131+
},
124132
'0x000b57fffec6a5b7': {friendly_name: 'bulb_2', retain: false},
125133
'0x0017880104a44559': {friendly_name: 'J1_cover'},
126134
'0x0017880104e43559': {friendly_name: 'U202DST600ZB'},
127135
'0x0017880104e44559': {friendly_name: '3157100_thermostat'},
128136
'0x0017880104e45517': {friendly_name: 'remote', retain: true},
129137
'0x0017880104e45520': {friendly_name: 'button', retain: false},
130-
'0x0017880104e45521': {friendly_name: 'button_double_key', retain: false},
131-
'0x0017880104e45522': {friendly_name: 'weather_sensor', qos: 1, retain: false},
132-
'0x0017880104e45523': {friendly_name: 'occupancy_sensor', retain: false},
138+
'0x0017880104e45521': {
139+
friendly_name: 'button_double_key',
140+
retain: false,
141+
},
142+
'0x0017880104e45522': {
143+
friendly_name: 'weather_sensor',
144+
qos: 1,
145+
retain: false,
146+
},
147+
'0x0017880104e45523': {
148+
friendly_name: 'occupancy_sensor',
149+
retain: false,
150+
},
133151
'0x0017880104e45524': {friendly_name: 'power_plug', retain: false},
134152
'0x0017880104e45526': {friendly_name: 'GL-S-007ZS'},
135-
'0x0017880104e45529': {friendly_name: 'unsupported2', retain: false},
136-
'0x0017880104e45530': {friendly_name: 'button_double_key_interviewing', retain: false},
153+
'0x0017880104e45529': {
154+
friendly_name: 'unsupported2',
155+
retain: false,
156+
},
157+
'0x0017880104e45530': {
158+
friendly_name: 'button_double_key_interviewing',
159+
retain: false,
160+
},
137161
'0x0017880104e45540': {friendly_name: 'ikea_onoff'},
138162
'0x0017880104e45541': {friendly_name: 'wall_switch', retain: false},
139-
'0x0017880104e45542': {friendly_name: 'wall_switch_double', retain: false},
140-
'0x0017880104e45543': {friendly_name: 'led_controller_1', retain: false},
141-
'0x0017880104e45544': {friendly_name: 'led_controller_2', retain: false},
142-
'0x0017880104e45545': {friendly_name: 'dimmer_wall_switch', retain: false},
163+
'0x0017880104e45542': {
164+
friendly_name: 'wall_switch_double',
165+
retain: false,
166+
},
167+
'0x0017880104e45543': {
168+
friendly_name: 'led_controller_1',
169+
retain: false,
170+
},
171+
'0x0017880104e45544': {
172+
friendly_name: 'led_controller_2',
173+
retain: false,
174+
},
175+
'0x0017880104e45545': {
176+
friendly_name: 'dimmer_wall_switch',
177+
retain: false,
178+
},
143179
'0x0017880104e45547': {friendly_name: 'curtain', retain: false},
144180
'0x0017880104e45548': {friendly_name: 'fan', retain: false},
145181
'0x0017880104e45549': {friendly_name: 'siren', retain: false},
146182
'0x0017880104e45550': {friendly_name: 'thermostat', retain: false},
147183
'0x0017880104e45551': {friendly_name: 'smart vent', retain: false},
148184
'0x0017880104e45552': {friendly_name: 'j1', retain: false},
149-
'0x0017880104e45553': {friendly_name: 'bulb_enddevice', retain: false},
150-
'0x0017880104e45559': {friendly_name: 'cc2530_router', retain: false},
185+
'0x0017880104e45553': {
186+
friendly_name: 'bulb_enddevice',
187+
retain: false,
188+
},
189+
'0x0017880104e45559': {
190+
friendly_name: 'cc2530_router',
191+
retain: false,
192+
},
151193
'0x0017880104e45560': {friendly_name: 'livolo', retain: false},
152194
'0x0017880104e45561': {friendly_name: 'temperature_sensor'},
153195
'0x0017880104e45562': {friendly_name: 'heating_actuator'},
@@ -160,7 +202,10 @@ describe('Extension: Bridge', () => {
160202
'0x90fd9ffffe4b64aa': {friendly_name: 'SP600_OLD'},
161203
'0x90fd9ffffe4b64ab': {friendly_name: 'SP600_NEW'},
162204
'0x90fd9ffffe4b64ac': {friendly_name: 'MKS-CM-W5'},
163-
'0x90fd9ffffe4b64ae': {friendly_name: 'tradfri_remote', retain: false},
205+
'0x90fd9ffffe4b64ae': {
206+
friendly_name: 'tradfri_remote',
207+
retain: false,
208+
},
164209
'0x90fd9ffffe4b64af': {friendly_name: 'roller_shutter'},
165210
'0x90fd9ffffe4b64ax': {friendly_name: 'ZNLDP12LM'},
166211
'0xf4ce368a38be56a1': {
@@ -187,6 +232,7 @@ describe('Extension: Bridge', () => {
187232
12: {friendly_name: 'thermostat_group', retain: false},
188233
14: {friendly_name: 'switch_group', retain: false},
189234
15071: {friendly_name: 'group_tradfri_remote', retain: false},
235+
19: {friendly_name: 'hue_twilight_group'},
190236
2: {friendly_name: 'group_2', retain: false},
191237
21: {friendly_name: 'gledopto_group'},
192238
9: {friendly_name: 'ha_discovery_group'},
@@ -195,8 +241,16 @@ describe('Extension: Bridge', () => {
195241
map_options: {
196242
graphviz: {
197243
colors: {
198-
fill: {coordinator: '#e04e5d', enddevice: '#fff8ce', router: '#4ea3e0'},
199-
font: {coordinator: '#ffffff', enddevice: '#000000', router: '#ffffff'},
244+
fill: {
245+
coordinator: '#e04e5d',
246+
enddevice: '#fff8ce',
247+
router: '#4ea3e0',
248+
},
249+
font: {
250+
coordinator: '#ffffff',
251+
enddevice: '#000000',
252+
router: '#ffffff',
253+
},
200254
line: {active: '#009900', inactive: '#994444'},
201255
},
202256
},
@@ -209,10 +263,10 @@ describe('Extension: Bridge', () => {
209263
server: 'mqtt://localhost',
210264
},
211265
ota: {
266+
default_maximum_data_size: 50,
212267
disable_automatic_update_check: false,
213-
update_check_interval: 1440,
214268
image_block_response_delay: 250,
215-
default_maximum_data_size: 50,
269+
update_check_interval: 1440,
216270
},
217271
passlist: [],
218272
serial: {disable_led: false, port: '/dev/dummy'},
@@ -2174,6 +2228,12 @@ describe('Extension: Bridge', () => {
21742228
],
21752229
scenes: [{id: 4, name: 'Scene 4'}],
21762230
},
2231+
{
2232+
friendly_name: 'hue_twilight_group',
2233+
id: 19,
2234+
members: [{endpoint: 11, ieee_address: '0x000b57cdfec6a5b3'}],
2235+
scenes: [],
2236+
},
21772237
]),
21782238
{retain: true, qos: 0},
21792239
);

test/extensions/publish.test.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,19 @@ describe('Extension: Publish', () => {
429429
);
430430
});
431431

432+
it('Should publish messages to group with just 1 Hue Twilight in int (convers have an `endpoint` on it)', async () => {
433+
// https://github.com/Koenkk/zigbee2mqtt/issues/24792
434+
const group = groups.hue_twilight_group;
435+
await mockMQTTEvents.message('zigbee2mqtt/hue_twilight_group/set', stringify({state: 'ON'}));
436+
await flushPromises();
437+
console.log(mockLogger.warning.mock.calls);
438+
expect(group.command).toHaveBeenCalledTimes(1);
439+
expect(group.command).toHaveBeenCalledWith('genOnOff', 'on', {}, {});
440+
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(2);
441+
expect(mockMQTT.publishAsync.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/hue_twilight_group');
442+
expect(JSON.parse(mockMQTT.publishAsync.mock.calls[1][1])).toStrictEqual({state: 'ON'});
443+
});
444+
432445
it('Should publish messages to groups with on and brightness', async () => {
433446
const group = groups.group_1;
434447
group.members.push(devices.bulb_color.getEndpoint(1)!);
@@ -483,10 +496,10 @@ describe('Extension: Publish', () => {
483496

484497
it('Should create and publish to group which is in configuration.yaml but not in zigbee-herdsman', async () => {
485498
settings.addGroup('group_12312', '12312');
486-
expect(Object.values(groups).length).toBe(10);
499+
expect(Object.values(groups).length).toBe(11);
487500
await mockMQTTEvents.message('zigbee2mqtt/group_12312/set', stringify({state: 'ON'}));
488501
await flushPromises();
489-
expect(Object.values(groups).length).toBe(11);
502+
expect(Object.values(groups).length).toBe(12);
490503
// group contains no device
491504
// @ts-expect-error runtime mock
492505
expect(groups.group_12312.command).toHaveBeenCalledTimes(0);

test/mocks/data.ts

+6
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ export function writeDefaultConfiguration(config: unknown = undefined): void {
201201
'0x0017880104e45562': {
202202
friendly_name: 'heating_actuator',
203203
},
204+
'0x000b57cdfec6a5b3': {
205+
friendly_name: 'hue_twilight',
206+
},
204207
},
205208
groups: {
206209
1: {
@@ -233,6 +236,9 @@ export function writeDefaultConfiguration(config: unknown = undefined): void {
233236
9: {
234237
friendly_name: 'ha_discovery_group',
235238
},
239+
19: {
240+
friendly_name: 'hue_twilight_group',
241+
},
236242
},
237243
};
238244

test/mocks/zigbeeHerdsman.ts

+22
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,26 @@ const bulb_2 = new Device(
383383
'Mains (single phase)',
384384
'TRADFRI bulb E27 WS opal 980lm',
385385
);
386+
const hue_twilight = new Device(
387+
'Router',
388+
'0x000b57cdfec6a5b3',
389+
40399,
390+
4107,
391+
[
392+
new Endpoint(1, [0, 3, 4, 5, 6, 8, 768, 2821, 4096], [5, 25, 32, 4096], '0x000b57cdfec6a5b3', [], {
393+
lightingColorCtrl: {colorCapabilities: 254},
394+
}),
395+
new Endpoint(11, [0, 3, 4, 5, 6, 8, 768, 2821, 4096], [5, 25, 32, 4096], '0x000b57cdfec6a5b3', [], {
396+
lightingColorCtrl: {colorCapabilities: 254},
397+
}),
398+
new Endpoint(12, [0, 3, 4, 5, 6, 8, 768, 2821, 4096], [5, 25, 32, 4096], '0x000b57cdfec6a5b3', [], {
399+
lightingColorCtrl: {colorCapabilities: 254},
400+
}),
401+
],
402+
true,
403+
'Mains (single phase)',
404+
'LGT003',
405+
);
386406
const TS0601_thermostat = new Device(
387407
'EndDevice',
388408
'0x0017882104a44559',
@@ -488,6 +508,7 @@ export const groups = {
488508
gledopto_group: new Group(21, [GLEDOPTO_2ID.endpoints[3]]),
489509
default_bind_group: new Group(901, []),
490510
ha_discovery_group: new Group(9, [bulb_color_2.endpoints[0], bulb_2.endpoints[0], QBKG03LM.endpoints[2]]),
511+
hue_twilight_group: new Group(19, [hue_twilight.endpoints[1]]),
491512
};
492513

493514
const groupMembersBackup = Object.fromEntries(Object.entries(groups).map((v) => [v[0], [...v[1].members]]));
@@ -545,6 +566,7 @@ export const devices = {
545566
),
546567
bulb_color: bulb_color,
547568
bulb_2: bulb_2,
569+
hue_twilight,
548570
bulb_color_2: bulb_color_2,
549571
remote: new Device(
550572
'EndDevice',

0 commit comments

Comments
 (0)