mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-29 07:08:56 +00:00
* Update zigbee-herdsman and zigbee-shepherd-converters. * Force Aqara S2 Lock endvices (#1764) * Start on zigbee-herdsman controller refactor. * More updates. * Cleanup zapp. * updates. * Propagate adapter disconnected event. * Updates. * Initial refactor to zigbee-herdsman. * Refactor deviceReceive to zigbee-herdsman. * Rename * Refactor deviceConfigure. * Finish bridge config. * Refactor availability. * Active homeassistant extension and more refactors. * Refactor groups. * Enable soft reset. * Activate group membership * Start on tests. * Enable reporting. * Add more controller tests. * Add more tests * Fix linting error. * Data en deviceReceive tests. * Move to zigbee-herdsman-converters. * More device publish tests. * Cleanup dependencies. * Bring device publish coverage to 100. * Bring home assistant test coverage to 100. * Device configure tests. * Attempt to fix tests. * Another attempt. * Another one. * Another one. * Another. * Add wait. * Longer wait. * Debug. * Update dependencies. * Another. * Begin on availability tests. * Improve availability tests. * Complete deviceAvailability tests. * Device bind tests. * More tests. * Begin networkmap refactors. * start on networkmap tests. * Network map tests. * Add utils tests. * Logger tests. * Settings and logger tests. * Ignore some stuff for coverage and add todos. * Add remaining missing tests. * Enforce 100% test coverage. * Start on groups test and refactor entityPublish to resolveEntity * Remove joinPathStorage, not used anymore as group information is stored into zigbee-herdsman database. * Fix linting issues. * Improve tests. * Add groups. * fix group membership. * Group: log names. * Convert MQTT message to string by default. * Fix group name. * Updates. * Revert configuration.yaml. * Add new line. * Fixes. * Updates. * Fix tests. * Ignore soft reset extension.
79 lines
3.3 KiB
JavaScript
79 lines
3.3 KiB
JavaScript
const settings = require('../util/settings');
|
|
const logger = require('../util/logger');
|
|
const assert = require('assert');
|
|
const topicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/(bind|unbind)/.+$`);
|
|
|
|
const clusters = ['genScenes', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl'];
|
|
|
|
class DeviceBind {
|
|
constructor(zigbee, mqtt, state, publishEntityState) {
|
|
this.zigbee = zigbee;
|
|
this.mqtt = mqtt;
|
|
this.state = state;
|
|
this.publishEntityState = publishEntityState;
|
|
}
|
|
|
|
onMQTTConnected() {
|
|
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/bind/+`);
|
|
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/bind/+/+`);
|
|
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/unbind/+`);
|
|
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/unbind/+/+`);
|
|
}
|
|
|
|
async onMQTTMessage(topic, message) {
|
|
if (!topic.match(topicRegex)) {
|
|
return null;
|
|
}
|
|
|
|
// Parse topic, retrieve type (bind or unbind) and source
|
|
topic = topic.replace(`${settings.get().mqtt.base_topic}/bridge/`, '');
|
|
const type = topic.split('/')[0];
|
|
const sourceKey = topic.replace(`${type}/`, '');
|
|
const targetKey = message;
|
|
|
|
// Find source; can only be a device and target
|
|
const source = await this.zigbee.resolveEntity(sourceKey);
|
|
assert(source != null && source.type === 'device', 'Source undefined or not a device');
|
|
const target = await this.zigbee.resolveEntity(targetKey);
|
|
assert(target != null, 'Target is unknown');
|
|
|
|
const sourceName = source.settings.friendlyName;
|
|
const targetName = target.settings.friendlyName;
|
|
|
|
// Find which clusters are supported by both the source and target.
|
|
// Groups are assumed to support all clusters.
|
|
for (const cluster of clusters) {
|
|
const targetValid = target.type === 'group' ||
|
|
target.device.type === 'Coordinator' || target.endpoint.supportsInputCluster(cluster);
|
|
|
|
if (source.endpoint.supportsOutputCluster(cluster) && targetValid) {
|
|
logger.debug(`${type}ing cluster '${cluster}' from '${sourceName}' to '${targetName}'`);
|
|
try {
|
|
const bindTarget = target.type === 'group' ? target.group : target.endpoint;
|
|
if (type === 'bind') {
|
|
await source.endpoint.bind(cluster, bindTarget);
|
|
} else {
|
|
await source.endpoint.unbind(cluster, bindTarget);
|
|
}
|
|
|
|
logger.info(
|
|
`Successfully ${type === 'bind' ? 'bound' : 'unbound'} cluster '${cluster}' from ` +
|
|
`'${sourceName}' to '${targetName}'`
|
|
);
|
|
this.mqtt.log(
|
|
`device_${type}`,
|
|
{from: sourceName, to: targetName, cluster}
|
|
);
|
|
} catch (error) {
|
|
logger.error(
|
|
`Failed to ${type} cluster '${cluster}' from '${sourceName}' to ` +
|
|
`'${targetName}' (${error})`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = DeviceBind;
|