diff --git a/lib/controller.js b/lib/controller.js index eefa97428..50648916e 100644 --- a/lib/controller.js +++ b/lib/controller.js @@ -32,7 +32,7 @@ class Controller { this.zigbee = new Zigbee(); this.mqtt = new MQTT(); this.stateCache = {}; - this.configuredReport = []; + this.configured = []; this.handleZigbeeMessage = this.handleZigbeeMessage.bind(this); this.handleMQTTMessage = this.handleMQTTMessage.bind(this); } @@ -140,11 +140,11 @@ class Controller { } configureDevice(device) { - // Configure reporting for this device. const ieeeAddr = device.ieeeAddr; - if (ieeeAddr && device.modelId && !this.configuredReport.includes(ieeeAddr)) { + if (ieeeAddr && device.modelId && !this.configured.includes(ieeeAddr)) { const mappedModel = zigbeeShepherdConverters.findByZigbeeModel(device.modelId); + // Call configure function of device. if (mappedModel && mappedModel.configure) { mappedModel.configure(ieeeAddr, this.zigbee.shepherd, this.zigbee.getCoordinator(), (ok, msg) => { if (ok) { @@ -155,7 +155,12 @@ class Controller { }); } - this.configuredReport.push(ieeeAddr); + // Setup an OnAfIncomingMsg handler if needed. + if (mappedModel && mappedModel.onAfIncomingMsg) { + mappedModel.onAfIncomingMsg.forEach((ep) => this.zigbee.registerOnAfIncomingMsg(ieeeAddr, ep)); + } + + this.configured.push(ieeeAddr); } } @@ -237,18 +242,32 @@ class Controller { } // After this point we cant handle message withoud cid anymore. - if (!message.data.cid) { + if (!message.data || (!message.data.cid && !message.data.cmdId)) { return; } // Find a conveter for this message. const cid = message.data.cid; - const converters = mappedModel.fromZigbee.filter((c) => c.cid === cid && c.type === message.type); + const cmdId = message.data.cmdId; + const converters = mappedModel.fromZigbee.filter((c) => { + if (cid) { + return c.cid === cid && c.type === message.type; + } else if (cmdId) { + return c.cmd === cmdId; + } + + return false; + }); if (!converters.length) { - logger.warn( - `No converter available for '${mappedModel.model}' with cid '${cid}' and type '${message.type}'` - ); + if (cid) { + logger.warn( + `No converter available for '${mappedModel.model}' with cid '${cid}' and type '${message.type}'` + ); + } else if (cmdId) { + logger.warn(`No converter available for '${mappedModel.model}' with cmd '${cmdId}'`); + } + logger.warn(`Please see: https://github.com/Koenkk/zigbee2mqtt/wiki/How-to-support-new-devices.`); return; } diff --git a/lib/zigbee.js b/lib/zigbee.js index 677a98080..d71213298 100644 --- a/lib/zigbee.js +++ b/lib/zigbee.js @@ -3,6 +3,7 @@ const logger = require('./util/logger'); const settings = require('./util/settings'); const data = require('./util/data'); const debug = require('debug')('zigbee2mqtt:zigbee'); +const zclPacket = require('zcl-packet'); const advancedSettings = settings.get().advanced; @@ -154,6 +155,21 @@ class Zigbee { device.read(cid, attr, callback); } + registerOnAfIncomingMsg(ieeeAddr, ep) { + const device = this._findDevice(ieeeAddr, ep); + device.onAfIncomingMsg = (message) => { + // Parse the message + zclPacket.parse(message.data, message.clusterid, (error, zclData) => { + const message = { + endpoints: [device], + data: zclData, + }; + + this.handleMessage(message); + }); + }; + } + _findDevice(deviceID, ep) { // Find device in zigbee-shepherd let device = this.getDevice(deviceID); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index e6b2be306..308b70bc0 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2810,9 +2810,12 @@ } }, "zigbee-shepherd-converters": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/zigbee-shepherd-converters/-/zigbee-shepherd-converters-1.0.3.tgz", - "integrity": "sha512-/VMKNW4h1c8VhjRpoQ4F2yjdd5Wj5eWt6bFqNIuwgFQwynfeZOYdgHRytLyaIRMQfJaVX9uGsthY4zpF+PG07A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/zigbee-shepherd-converters/-/zigbee-shepherd-converters-2.0.0.tgz", + "integrity": "sha512-GtQKwU0AD7os51bPdFLcunGvSt7c2kxrwEf+szGInGFwA5hibVgoXvLhFA0t8C8bRlxqy2FcXQDblS6i8LogiA==", + "requires": { + "debounce": "1.1.0" + }, "dependencies": { "acorn": { "version": "5.5.3", @@ -3055,6 +3058,11 @@ "which": "1.3.0" } }, + "debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.1.0.tgz", + "integrity": "sha512-ZQVKfRVlwRfD150ndzEK8M90ABT+Y/JQKs4Y7U4MXdpuoUkkrr4DwKbVux3YjylA5bUMUj0Nc3pMxPJX6N2QQQ==" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",