diff --git a/lib/controller.js b/lib/controller.js index f289aa3c4..7e7eb9c7a 100644 --- a/lib/controller.js +++ b/lib/controller.js @@ -46,9 +46,15 @@ class Controller { new ExtensionBridgeConfig(this.zigbee, this.mqtt, this.state, this.publishEntityState), new ExtensionGroups(this.zigbee, this.mqtt, this.state, this.publishEntityState), new ExtensionDeviceBind(this.zigbee, this.mqtt, this.state, this.publishEntityState), - new ExtensionDeviceReport(this.zigbee, this.mqtt, this.state, this.publishEntityState), + ]; + if (settings.get().advanced.report) { + this.extensions.push(new ExtensionDeviceReport( + this.zigbee, this.mqtt, this.state, this.publishEntityState + )); + } + if (settings.get().homeassistant) { this.extensions.push(new ExtensionHomeAssistant( this.zigbee, this.mqtt, this.state, this.publishEntityState diff --git a/lib/extension/deviceBind.js b/lib/extension/deviceBind.js index 914407933..b0d027035 100644 --- a/lib/extension/deviceBind.js +++ b/lib/extension/deviceBind.js @@ -120,6 +120,8 @@ class DeviceBind { }); }); }); + + return true; } } diff --git a/lib/extension/deviceReport.js b/lib/extension/deviceReport.js index 6428c0b52..1a37f3c89 100644 --- a/lib/extension/deviceReport.js +++ b/lib/extension/deviceReport.js @@ -1,4 +1,5 @@ const zigbeeShepherdConverters = require('zigbee-shepherd-converters'); +const logger = require('../util/logger'); const candidates = { 'genOnOff': { @@ -30,15 +31,31 @@ class DeviceReport { this.publishEntityState = publishEntityState; } - setupReporting(endpoint) { + setupReporting(mappedDevice, device) { + let epId = null; + + // Check if this device uses a different epId. + if (mappedDevice.hasOwnProperty('ep')) { + const eps = mappedDevice.ep(device); + epId = eps[''] || null; + } + + const endpoint = this.zigbee.getEndpoint(device.ieeeAddr, epId); + + if (!endpoint) { + logger.error(`Failed to setup reporting for ${device.ieeeAddr}, endpoint not found`); + return; + } + + logger.debug(`Setting up reporting for ${device.ieeeAddr}`); + Object.values(endpoint.clusters).filter((c) => c).forEach((c) => { const cluster = c.attrs.cid; if (candidates[cluster]) { const candidate = candidates[cluster]; const attributeNames = candidate.attrs.filter((a) => c.attrs.hasOwnProperty(a)); - const attributes = []; - attributeNames.forEach((attribute) => { - attributes.push({ + const attributes = attributeNames.map((attribute) => { + return { attr: attribute, min: candidate.hasOwnProperty('reportIntervalMin')? candidate.reportIntervalMin:reportInterval.min, @@ -46,9 +63,12 @@ class DeviceReport { candidate.reportIntervalMax:reportInterval.max, change: candidate.hasOwnProperty('reportableChange')? candidate.reportableChange:reportableChange, - }); + }; }); - this.zigbee.report(endpoint, cluster, attributes); + + if (attributes.length > 0) { + this.zigbee.report(endpoint, cluster, attributes); + } } }); } @@ -57,33 +77,20 @@ class DeviceReport { this.zigbee.getAllClients().forEach((device) => { const mappedDevice = zigbeeShepherdConverters.findByZigbeeModel(device.modelId); - if (mappedDevice && mappedDevice.report) { - const endpoint = (typeof(mappedDevice.report)=='number') - ? this.zigbee.getEndpoint(device.ieeeAddr, mappedDevice.report) - : this.zigbee.getEndpoint(device.ieeeAddr); - this.setupReporting(endpoint); + if (mappedDevice) { + this.setupReporting(mappedDevice, device); } }); } onZigbeeMessage(message, device, mappedDevice) { - // Handle messages of type endDeviceAnnce. + // Handle messages of type endDeviceAnnce and devIncoming. // This message is typically send when a device comes online after being powered off // Ikea TRADFRI tend to forget their reporting after powered off. // Re-setup reporting. // https://github.com/Koenkk/zigbee2mqtt/issues/966 - // The mappedDevice.report property is now used as boolean - // the property might contain more information about how to - // configure reporting. For instance the endpointIds to use. - if (device && mappedDevice - && (message.type=='endDeviceAnnce' || message.type=='devIncoming') - && mappedDevice.report) { - const endpoint = (typeof(mappedDevice.report)=='number') - ? this.zigbee.getEndpoint(device.ieeeAddr, mappedDevice.report) - : this.zigbee.getEndpoint(device.ieeeAddr); - if (endpoint) { - this.setupReporting(endpoint); - } + if (device && mappedDevice && ['endDeviceAnnce', 'devIncoming'].includes(message.type)) { + this.setupReporting(mappedDevice, device); } } } diff --git a/lib/util/settings.js b/lib/util/settings.js index 6976d2726..2157febb3 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -59,6 +59,11 @@ const defaults = { * Changing this will require you to repair your devices. */ network_key: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13], + + /** + * Enables reporting feature + */ + report: false, }, }; diff --git a/lib/zigbee.js b/lib/zigbee.js index b0085e18b..aff2d6c18 100644 --- a/lib/zigbee.js +++ b/lib/zigbee.js @@ -317,20 +317,18 @@ class Zigbee { * change the minimum amount of change before sending a report */ report(ep, cluster, attributes) { - const cfgArr = []; - for (let i=0; i { const attrId = zclId.attr(cluster, attribute.attr).value; const dataType = zclId.attrType(cluster, attribute.attr).value; - cfgArr.push({ + return { direction: 0, attrId, dataType, minRepIntval: attribute.min, maxRepIntval: attribute.max, repChange: attribute.change, - }); - } + }; + }); const log=`for ${ep.device.ieeeAddr} - ${cluster} - ${attributes.length}`;