Allow to specify endpoint when adding device to group. (#1515)

* uu

* Update
This commit is contained in:
Koen Kanters
2019-05-29 20:11:40 +02:00
committed by GitHub
parent 82ed260d47
commit c29bfe1455
2 changed files with 109 additions and 20 deletions
+30 -20
View File
@@ -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;
}
+79
View File
@@ -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)
);
});
});