mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-07-03 18:41:39 +00:00
Allow to specify endpoint when adding device to group. (#1515)
* uu * Update
This commit is contained in:
+30
-20
@@ -1,6 +1,7 @@
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
const data = require('../util/data');
|
||||
const utils = require('../util/utils');
|
||||
const fs = require('fs');
|
||||
const diff = require('deep-diff');
|
||||
|
||||
@@ -44,7 +45,7 @@ class Groups {
|
||||
const groupID = diff.path[0];
|
||||
|
||||
if (diff.kind === 'N') {
|
||||
diff.rhs.forEach((ieeeAddr) => this.updateDeviceGroup(ieeeAddr, 'add', groupID));
|
||||
diff.rhs.forEach((ID) => this.updateDeviceGroup(ID, 'add', groupID));
|
||||
} else if (diff.kind === 'A') {
|
||||
if (diff.item.lhs) {
|
||||
this.updateDeviceGroup(diff.item.lhs, 'remove', groupID);
|
||||
@@ -52,7 +53,7 @@ class Groups {
|
||||
this.updateDeviceGroup(diff.item.rhs, 'add', groupID);
|
||||
}
|
||||
} else if (diff.kind === 'D') {
|
||||
diff.lhs.forEach((ieeeAddr) => this.updateDeviceGroup(ieeeAddr, 'remove', groupID));
|
||||
diff.lhs.forEach((ID) => this.updateDeviceGroup(ID, 'remove', groupID));
|
||||
} else if (diff.kind === 'E') {
|
||||
this.updateDeviceGroup(diff.rhs, 'add', groupID);
|
||||
this.updateDeviceGroup(diff.lhs, 'remove', groupID);
|
||||
@@ -61,9 +62,28 @@ class Groups {
|
||||
}
|
||||
}
|
||||
|
||||
getGroupsOfDevice(ieeeAddr) {
|
||||
parseID(ID) {
|
||||
let entityID = ID;
|
||||
let endpointID = null;
|
||||
const postfix = utils.getPostfixes().find((p) => entityID.endsWith(`/${p}`));
|
||||
if (postfix) {
|
||||
// Found a postfix, retrieve the endpoint which correspodns to the postfix
|
||||
entityID = entityID.substring(0, entityID.length - (postfix.length + 1));
|
||||
const endpoint = utils.getEndpointByEntityID(this.zigbee, entityID, postfix);
|
||||
|
||||
if (!endpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
endpointID = endpoint.epId;
|
||||
}
|
||||
|
||||
return {endpointID, entityID};
|
||||
}
|
||||
|
||||
getGroupsOfDevice(entityID) {
|
||||
return Object.keys(settings.getGroups()).filter((groupID) => {
|
||||
return settings.getGroup(groupID).devices.includes(ieeeAddr);
|
||||
return settings.getGroup(groupID).devices.includes(entityID);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -113,7 +133,7 @@ class Groups {
|
||||
return {friendly_name: topic, type};
|
||||
}
|
||||
|
||||
updateDeviceGroup(ieeeAddr, cmd, groupID) {
|
||||
updateDeviceGroup(ID, cmd, groupID) {
|
||||
let payload = null;
|
||||
const orignalCmd = cmd;
|
||||
if (cmd === 'add') {
|
||||
@@ -127,6 +147,9 @@ class Groups {
|
||||
cmd = 'removeAll';
|
||||
}
|
||||
|
||||
const {entityID, endpointID} = this.parseID(ID);
|
||||
const ieeeAddr = settings.resolveEntity(entityID).ID;
|
||||
|
||||
const cb = (error, rsp) => {
|
||||
if (error) {
|
||||
logger.error(`Failed to ${cmd} ${ieeeAddr} from ${groupID}`);
|
||||
@@ -176,7 +199,7 @@ class Groups {
|
||||
|
||||
this.zigbee.publish(
|
||||
ieeeAddr, 'device', 'genGroups', cmd, 'functional',
|
||||
payload, null, null, cb,
|
||||
payload, null, endpointID, cb,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -194,21 +217,8 @@ class Groups {
|
||||
return;
|
||||
}
|
||||
|
||||
if (groupID === 99) {
|
||||
logger.error('Group 99 is reserved, please use a different groupID');
|
||||
return;
|
||||
}
|
||||
|
||||
// Map message to ieeeAddr and check if device exist.
|
||||
message = message.toString();
|
||||
const ieeeAddr = settings.getIeeeAddrByFriendlyName(message) || message;
|
||||
if (!this.zigbee.getDevice(ieeeAddr)) {
|
||||
logger.error(`Failed to find device '${message}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send command to the device.
|
||||
this.updateDeviceGroup(ieeeAddr, topic.type, groupID);
|
||||
this.updateDeviceGroup(message.toString(), topic.type, groupID.toString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const Groups = require('../lib/extension/groups');
|
||||
const settings = require('../lib/util/settings');
|
||||
|
||||
let groupExtension = null;
|
||||
let zigbee = null;
|
||||
@@ -175,4 +176,82 @@ describe('Groups', () => {
|
||||
{groupid: '2', groupname: ''}, null, null, expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('Apply group updates add with postfix', async () => {
|
||||
zigbee.publish.mockClear();
|
||||
zigbee.getDevice = () => ({modelId: 'lumi.ctrl_neutral2'});
|
||||
zigbee.getEndpoint = (entityID, ep) => ({epId: ep});
|
||||
const from = {};
|
||||
const to = {'1': ['0x12345689/right']};
|
||||
groupExtension.apply(from, to);
|
||||
expect(zigbee.publish).toHaveBeenCalledTimes(1);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'add', 'functional',
|
||||
{groupid: '1', groupname: ''}, null, 3, expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('Apply group updates add and remove with postfix', async () => {
|
||||
zigbee.publish.mockClear();
|
||||
zigbee.getDevice = () => ({modelId: 'lumi.ctrl_neutral2'});
|
||||
zigbee.getEndpoint = (entityID, ep) => ({epId: ep});
|
||||
const from = {'1': ['0x12345689/right']};
|
||||
const to = {'1': ['0x12345689'], '2': ['0x12345689/left']};
|
||||
groupExtension.apply(from, to);
|
||||
expect(zigbee.publish).toHaveBeenCalledTimes(3);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'add', 'functional',
|
||||
{groupid: '2', groupname: ''}, null, 2, expect.any(Function)
|
||||
);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'remove', 'functional',
|
||||
{groupid: '1'}, null, 3, expect.any(Function)
|
||||
);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'add', 'functional',
|
||||
{groupid: '1', groupname: ''}, null, null, expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('Add to group via MQTT', async () => {
|
||||
zigbee.publish.mockClear();
|
||||
zigbee.getDevice = () => ({modelId: 'lumi.ctrl_neutral2'});
|
||||
zigbee.getEndpoint = (entityID, ep) => ({epId: ep});
|
||||
jest.spyOn(settings, 'getGroupIDByFriendlyName').mockReturnValue(1);
|
||||
jest.spyOn(settings, 'getIeeeAddrByFriendlyName').mockReturnValue('0x12345689');
|
||||
groupExtension.onMQTTMessage('zigbee2mqtt/bridge/group/my_group/add', 'my_switch');
|
||||
expect(zigbee.publish).toHaveBeenCalledTimes(1);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'add', 'functional',
|
||||
{groupid: '1', groupname: ''}, null, null, expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('Add to group via MQTT with postfix', async () => {
|
||||
zigbee.publish.mockClear();
|
||||
zigbee.getDevice = () => ({modelId: 'lumi.ctrl_neutral2'});
|
||||
zigbee.getEndpoint = (entityID, ep) => ({epId: ep});
|
||||
jest.spyOn(settings, 'getGroupIDByFriendlyName').mockReturnValue(1);
|
||||
jest.spyOn(settings, 'getIeeeAddrByFriendlyName').mockReturnValue('0x12345689');
|
||||
groupExtension.onMQTTMessage('zigbee2mqtt/bridge/group/my_group/add', 'my_switch/right');
|
||||
expect(zigbee.publish).toHaveBeenCalledTimes(1);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'add', 'functional',
|
||||
{groupid: '1', groupname: ''}, null, 3, expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('Remove from group via MQTT with postfix', async () => {
|
||||
zigbee.publish.mockClear();
|
||||
zigbee.getDevice = () => ({modelId: 'lumi.ctrl_neutral2'});
|
||||
zigbee.getEndpoint = (entityID, ep) => ({epId: ep});
|
||||
jest.spyOn(settings, 'getGroupIDByFriendlyName').mockReturnValue(1);
|
||||
jest.spyOn(settings, 'getIeeeAddrByFriendlyName').mockReturnValue('0x12345689');
|
||||
groupExtension.onMQTTMessage('zigbee2mqtt/bridge/group/my_group/remove', 'my_switch/left');
|
||||
expect(zigbee.publish).toHaveBeenCalledTimes(1);
|
||||
expect(zigbee.publish).toHaveBeenCalledWith(
|
||||
'0x12345689', 'device', 'genGroups', 'remove', 'functional',
|
||||
{groupid: '1'}, null, 2, expect.any(Function)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user