mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-27 21:20:03 +00:00
Improve device bind robustness. https://github.com/Koenkk/zigbee2mqtt/issues/176
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
const utils = require('../util/utils');
|
||||
const zigbeeShepherdConverters = require('zigbee-shepherd-converters');
|
||||
|
||||
const postfixes = utils.getPostfixes();
|
||||
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/(bind|unbind)/.+$`);
|
||||
@@ -56,20 +55,6 @@ class DeviceBind {
|
||||
return {type, ...this.getIDAndPostfix(topic)};
|
||||
}
|
||||
|
||||
getEp(ID, postfix) {
|
||||
let source = null;
|
||||
if (postfix) {
|
||||
const device = this.zigbee.getDevice(ID);
|
||||
const mappedDevice = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
|
||||
const epID = mappedDevice.ep(device)[postfix];
|
||||
source = this.zigbee.getEndpoint(ID, epID);
|
||||
} else {
|
||||
source = this.zigbee.getEndpoint(ID);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
onMQTTMessage(topic, message) {
|
||||
topic = this.parseTopic(topic);
|
||||
|
||||
@@ -79,28 +64,21 @@ class DeviceBind {
|
||||
|
||||
// Find source; can only be a device.
|
||||
const sourceEntity = settings.resolveEntity(topic.ID);
|
||||
const source = this.getEp(sourceEntity.ID, topic.postfix);
|
||||
if (!source) {
|
||||
logger.error(`Failed to find device '${sourceEntity.ID}'`);
|
||||
return false;
|
||||
}
|
||||
const source = utils.getEndpointByEntityID(this.zigbee, topic.ID, topic.postfix);
|
||||
|
||||
// Find target; can be a device or group.
|
||||
const targetEntityIDPostfix= this.getIDAndPostfix(message.toString());
|
||||
const targetEntity = settings.resolveEntity(targetEntityIDPostfix.ID);
|
||||
let target = null;
|
||||
|
||||
if (targetEntity.type === 'device') {
|
||||
target = this.getEp(targetEntity.ID, targetEntityIDPostfix.postfix);
|
||||
|
||||
if (!target) {
|
||||
logger.error(`Failed to find target device '${targetEntity.ID}'`);
|
||||
return false;
|
||||
}
|
||||
target = utils.getEndpointByEntityID(this.zigbee, targetEntity.ID, targetEntityIDPostfix.postfix);
|
||||
} else if (targetEntity.type === 'group') {
|
||||
target = targetEntity.ID;
|
||||
}
|
||||
|
||||
if (!source || !target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find which clusters are supported by both the source and target.
|
||||
// Groups are assumed to support all clusters (as we don't know which devices are in)
|
||||
let supported = [];
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
const zigbeeShepherdConverters = require('zigbee-shepherd-converters');
|
||||
const logger = require('../util/logger');
|
||||
|
||||
// Xiaomi uses 4151 and 4447 (lumi.plug) as manufacturer ID.
|
||||
const xiaomiManufacturerID = [4151, 4447];
|
||||
const ikeaTradfriManufacturerID = [4476];
|
||||
@@ -29,6 +32,41 @@ const postfixes = [
|
||||
'top_left', 'top_right', 'white', 'rgb', 'system', 'top', 'bottom',
|
||||
];
|
||||
|
||||
function getEndpointByEntityID(zigbee, entityID, epName) {
|
||||
const device = zigbee.getDevice(entityID);
|
||||
if (!device) {
|
||||
logger.error(`Failed to find device with entity ID '${entityID}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
const mappedDevice = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
|
||||
if (!mappedDevice) {
|
||||
logger.error(`Device with model ID ${device.modelId} is not supported`);
|
||||
return;
|
||||
}
|
||||
|
||||
let epID = null;
|
||||
if (epName) {
|
||||
if (!mappedDevice.ep) {
|
||||
logger.error(`Device ${mappedDevice.model} doesn't define eps`);
|
||||
return;
|
||||
}
|
||||
|
||||
epID = mappedDevice.ep(device)[epName];
|
||||
if (!epID) {
|
||||
logger.error(`Device ${mappedDevice.model} doesn't have ep named '${epName}'`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const endpoint = zigbee.getEndpoint(entityID, epID);
|
||||
if (!endpoint) {
|
||||
logger.error(`Failed to retrieve for entity ID ${entityID} and endpoint ID ${epID}`);
|
||||
}
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
millisecondsToSeconds: (milliseconds) => milliseconds / 1000,
|
||||
secondsToMilliseconds: (seconds) => seconds * 1000,
|
||||
@@ -37,4 +75,5 @@ module.exports = {
|
||||
isNumeric: (string) => /^\d+$/.test(string),
|
||||
toLocalISOString: (dDate) => toLocalISOString(dDate),
|
||||
getPostfixes: () => postfixes,
|
||||
getEndpointByEntityID,
|
||||
};
|
||||
|
||||
@@ -52,8 +52,12 @@ const zigbee = {
|
||||
getDevice: (ID) => {
|
||||
if (ID === 'switch_ep2') {
|
||||
return {modelId: 'lumi.sensor_86sw2.es1'};
|
||||
} else if (ID == 'switch_ep3') {
|
||||
} else if (ID === 'switch_ep3') {
|
||||
return {modelId: 'DNCKAT_S003'};
|
||||
} else if (ID === 'bulb') {
|
||||
return {modelId: 'TRADFRI bulb E27 WS opal 980lm'};
|
||||
} else if (ID === 'remote') {
|
||||
return {modelId: 'TRADFRI remote control'};
|
||||
}
|
||||
|
||||
throw new Error(`No mock for ${ID}`);
|
||||
|
||||
Reference in New Issue
Block a user