Skip to content

Commit

Permalink
Prepare for read commands. #518
Browse files Browse the repository at this point in the history
  • Loading branch information
Koenkk committed Nov 5, 2018
1 parent f379bc0 commit 9119e54
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 404 deletions.
4 changes: 2 additions & 2 deletions lib/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const settings = require('./util/settings');
const ExtensionNetworkMap = require('./extension/networkMap');
const ExtensionSoftReset = require('./extension/softReset');
const ExtensionRouterPollXiaomi = require('./extension/routerPollXiaomi');
const ExtensionDeviceCommand = require('./extension/deviceCommand');
const ExtensionDevicePublish = require('./extension/devicePublish');
const zigbeeShepherdConverters = require('zigbee-shepherd-converters');
const homeassistant = require('./homeassistant');
const objectAssignDeep = require('object-assign-deep');
Expand Down Expand Up @@ -92,7 +92,7 @@ class Controller {

// Initialize extensions.
this.extensions = [
new ExtensionDeviceCommand(this.zigbee, this.mqtt, this.state, this.mqttPublishDeviceState),
new ExtensionDevicePublish(this.zigbee, this.mqtt, this.state, this.mqttPublishDeviceState),
new ExtensionNetworkMap(this.zigbee, this.mqtt, this.state, this.mqttPublishDeviceState),
new ExtensionSoftReset(this.zigbee, this.mqtt, this.state, this.mqttPublishDeviceState),
new ExtensionRouterPollXiaomi(this.zigbee, this.mqtt, this.state, this.mqttPublishDeviceState),
Expand Down
50 changes: 12 additions & 38 deletions lib/extension/deviceCommand.js → lib/extension/devicePublish.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ const logger = require('../util/logger');

const setTopic = new RegExp(`${settings.get().mqtt.base_topic}/[\\w\\s\\d.-]+/set`, 'g');
const setWithPrefixTopic = new RegExp(`${settings.get().mqtt.base_topic}/[\\w\\s\\d.-]+/[\\w\\s\\d.-]+/set`, 'g');
const getTopic = new RegExp(`${settings.get().mqtt.base_topic}/[\\w\\s\\d.-]+/get`, 'g');
const getWithPrefixTopic = new RegExp(`${settings.get().mqtt.base_topic}/[\\w\\s\\d.-]+/[\\w\\s\\d.-]+/get`, 'g');

class DeviceCommand {
class DevicePublish {
constructor(zigbee, mqtt, state, mqttPublishDeviceState) {
this.zigbee = zigbee;
this.mqtt = mqtt;
Expand All @@ -28,14 +30,17 @@ class DeviceCommand {
// Subscribe to topics.
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/+/set`);
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/+/+/set`);
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/+/get`);
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/+/+/get`);
}

stop() {
this.queue.stop();
}

handleMQTTMessage(topic, message) {
if (!topic.match(setTopic) && !topic.match(setWithPrefixTopic)) {
if (!topic.match(setTopic) && !topic.match(setWithPrefixTopic) &&
!topic.match(getTopic) && !topic.match(getWithPrefixTopic)) {
// Can't handle this message
return false;
}
Expand All @@ -44,6 +49,7 @@ class DeviceCommand {
const hasPrefix = topic.match(setWithPrefixTopic);
const deviceKey = topic.split('/').slice(hasPrefix ? -3 : -2)[0]; // Could be friendlyName or ieeeAddr
const prefix = hasPrefix ? topic.split('/').slice(-2)[0] : '';
const type = (topic.match(getTopic) || topic.match(getWithPrefixTopic)) ? 'get' : 'set';

// Map friendlyName to ieeeAddr if possible.
const ieeeAddr = settings.getIeeAddrByFriendlyName(deviceKey) || deviceKey;
Expand Down Expand Up @@ -84,7 +90,7 @@ class DeviceCommand {
}

// Converter didn't return a result, skip
const converted = converter.convert(json[key], json);
const converted = converter.convert(json[key], json, type);
if (!converted) {
return;
}
Expand All @@ -95,11 +101,11 @@ class DeviceCommand {
ieeeAddr,
converted.cid,
converted.cmd,
converted.cmdType,
converted.zclData,
converted.cfg,
endpoint,
converted.type,
(error) => {
(error, rsp) => {
// Devices do not report when they go off, this ensures state (on/off) is always in sync.
if (!error && (key.startsWith('state') || key === 'brightness')) {
const msg = {};
Expand All @@ -115,39 +121,7 @@ class DeviceCommand {
});

return true;

// TODO
// Is this still needed??????
/**
* After publishing a command to a zigbee device we want to monitor the changed attribute(s) so that
* everything stays in sync.
*/
// published.forEach((p) => {
// let counter = 0;
// let secondsToMonitor = 1;

// // In case of a transition we need to monitor for the whole transition time.
// if (p.message.zclData.hasOwnProperty('transtime')) {
// // Note that: transtime 10 = 0.1 seconds, 100 = 1 seconds, etc.
// secondsToMonitor = (p.message.zclData.transtime / 10) + 1;
// }

// const timer = setInterval(() => {
// counter++;

// // Doing a 'read' will result in the device sending a zigbee message with the
// //current attribute value.
// // which will be handled by this.handleZigbeeMessage.
// p.converter.attr.forEach((attribute) => {
// this.zigbee.read(deviceID, p.message.cid, attribute, ep, () => null);
// });

// if (counter >= secondsToMonitor) {
// clearTimeout(timer);
// }
// }, 1000);
// });
}
}

module.exports = DeviceCommand;
module.exports = DevicePublish;
34 changes: 13 additions & 21 deletions lib/zigbee.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,46 +186,38 @@ class Zigbee {
return this.shepherd.find(device.ieeeAddr, 1);
}

publish(deviceID, cid, cmd, zclData, cfg, ep, type, callback) {
const device = this._findDevice(deviceID, ep);
publish(ieeAddr, cid, cmd, cmdType, zclData, cfg, ep, callback) {
const device = this._findDevice(ieeAddr, ep);
if (!device) {
logger.error(`Zigbee cannot publish message to device because '${deviceID}' not known by zigbee-shepherd`);
logger.error(`Zigbee cannot publish message to device because '${ieeAddr}' not known by zigbee-shepherd`);
return;
}

logger.info(
`Zigbee publish to '${deviceID}', ${cid} - ${cmd} - ` +
`Zigbee publish to '${ieeAddr}', ${cid} - ${cmd} - ` +
`${JSON.stringify(zclData)} - ${JSON.stringify(cfg)} - ${ep}`
);

const callback_ = (error) => {
const callback_ = (error, rsp) => {
if (error) {
logger.error(
`Zigbee publish to '${deviceID}', ${cid} - ${cmd} - ${JSON.stringify(zclData)} ` +
`Zigbee publish to '${ieeAddr}', ${cid} - ${cmd} - ${JSON.stringify(zclData)} ` +
`- ${JSON.stringify(cfg)} - ${ep} ` +
`failed with error ${error}`);
}

callback(error);
callback(error, rsp);

// TODO: Send read reponse back to MQTT.
};

if (type === 'functional') {
if (cmdType === 'functional') {
device.functional(cid, cmd, zclData, cfg, callback_);
} else if (type === 'foundation') {
device.foundation(cid, cmd, [zclData], cfg, callback_);
} else if (cmdType === 'foundation') {
device.foundation(cid, cmd, zclData, cfg, callback_);
} else {
logger.error(`Unknown zigbee publish type ${type}`);
}
}

read(deviceID, cid, attr, ep, callback) {
const device = this._findDevice(deviceID, ep);
if (!device) {
logger.error(`Zigbee cannot read attribute from device because '${deviceID}' not known by zigbee-shepherd`);
return;
logger.error(`Unknown zigbee publish cmdType ${cmdType}`);
}

device.read(cid, attr, callback);
}

networkScan(callback) {
Expand Down
Loading

0 comments on commit 9119e54

Please sign in to comment.