Skip to content

Commit

Permalink
apply app settings + disconnect devices + refactored registration wor…
Browse files Browse the repository at this point in the history
…kflow
  • Loading branch information
harriedegroot committed Jan 28, 2019
1 parent ee4ec87 commit af4dfb8
Show file tree
Hide file tree
Showing 13 changed files with 473 additions and 143 deletions.
31 changes: 31 additions & 0 deletions DeviceManager.js
Expand Up @@ -237,6 +237,37 @@ class DeviceManager {
return capabillities ? capabillities[capabilityId] : undefined;
}

computeChanges(devices) {
let changes = {
enabled: [],
disabled: [],
untouched: []
};
if (devices) {
for (let id in devices) {
if (devices.hasOwnProperty(id)) {
const enabled = devices[id] !== false;
if (enabled !== this.isDeviceEnabled(id)) {
if (enabled) {
if (this.devices) {
Log.debug("Enabled device: " + (this.devices[id] || {}).name);
}
changes.enabled.push(id);
} else {
if (this.devices) {
Log.debug("Disabled device: " + (this.devices[id] || {}).name);
}
changes.disabled.push(id);
}
} else {
changes.untouched.push(id);
}
}
}
}
return changes;
}

setEnabledDevices(devices) {
this._enabledDevices = devices;
}
Expand Down
4 changes: 4 additions & 0 deletions MessageHandler.js
Expand Up @@ -101,6 +101,10 @@ class MessageHandler {
}
}
}

destroy() {
// TODO: implement
}
}

module.exports = MessageHandler;
9 changes: 7 additions & 2 deletions TODO
@@ -1,5 +1,8 @@
=== TODO ===
- Try to combine the old topic format with the Homie Convention (&Ditch the old topic format?)
- Fix on/off button
- Disable settings running button (show loader) untill state active state is received
- implement destroy methods
- enable setting for deprecated protocol / clean-up old code
- Settings page
* Select communication protocol (Homie | Homey)
* Homie color format (HSV | RGB)
Expand Down Expand Up @@ -51,4 +54,6 @@
- MQTT discovery (see OpenHAB / Domiticz)
- Implement Homie convention (Homey v1.5.13)
- Homie Convention for Homey v2.0
- Normalization BUG
- Normalization BUG
- Handle device & zone name changes in HomieDispatcher
- Try to combine the old topic format with the Homie Convention (&Ditch the old topic format?)
2 changes: 0 additions & 2 deletions api.js
Expand Up @@ -12,7 +12,6 @@ module.exports = [
fn: function (args, callback) {
Homey.app.getDevices()
.then(res => {
Log.debug(res);
callback(null, res);
})
.catch(error => {
Expand All @@ -30,7 +29,6 @@ module.exports = [
fn: function (args, callback) {
Homey.app.getZones()
.then(res => {
Log.debug(res);
callback(null, res);
})
.catch(error => {
Expand Down
173 changes: 145 additions & 28 deletions app.js
Expand Up @@ -20,8 +20,19 @@ const DescribeCommandHandler = require("./commands/DescribeCommandHandler.js");
const StateRequestCommandHandler = require("./commands/StateRequestCommandHandler.js");
const UpdateCommandHandler = require("./commands/UpdateCommandHandler.js");

const HOMIE_CONVENTION = true; // TODO: Read from app settings
const SYSTEM_INFO = false; // TODO: Read from app settings
/*
const defaultSettings = {
"protocol": "homie3",
"topicRoot": "homie",
"deviceId": "homey",
"topicIncludeClass": false,
"topicIncludeZone": false,
"propertyScaling": "default",
"colorFormat": "hsv",
"broadcastDevices": true,
"broadcastSystemState": true,
};
*/

class MQTTGateway extends Homey.App {

Expand All @@ -31,44 +42,136 @@ class MQTTGateway extends Homey.App {
this.settings = Homey.ManagerSettings.get('settings') || {};
this.api = await HomeyAPI.forCurrentHomey();
this.system = await this._getSystemInfo();

if (this.settings.deviceId === undefined) {
this.settings.deviceId = Topic.normalize(this.system.name || 'homey');
Homey.set('settings', this.settings);
}
this.mqttClient = new MQTTClient(this.system.name);

this.mqttClient = new MQTTClient(this.settings.deviceId);

// Suppress memory leak warning
this.api.devices.setMaxListeners(9999);
this.api.devices.setMaxListeners(9999); // HACK

// devices
this.deviceManager = new DeviceManager(this);
await this.deviceManager.register();

// TODO: Read from app settings
if (HOMIE_CONVENTION) {
this.homieDispatcher = new HomieDispatcher(this);
} else {
this.messageHandler = new MessageHandler(this);
// run
this.start();
}

// dispatchers
this.deviceStateChangeDispatcher = new DeviceStateChangeDispatcher(this);
this.flowTriggerDispatcher = new FlowTriggerDispatcher(this);
start() {
Log.debug('start');
this.mqttClient.connect();

// commands
this.messageHandler.addMessageHandler(new DescribeCommandHandler(this));
this.messageHandler.addMessageHandler(new StateRequestCommandHandler(this));
this.messageHandler.addMessageHandler(new UpdateCommandHandler(this));
const protocol = this.settings.protocol || 'homie3';
if (this.protocol !== protocol) {
this._stopCommunicationProtocol(this.protocol);
this._startCommunicationProtocol(protocol);
}

// TODO: Read from app settings
if (SYSTEM_INFO) {
this._startBroadcasters();
}

stop() {
Log.debug('stop');
this.mqttClient.disconnect();
this._stopCommunicationProtocol();
this._stopBroadcasters();
}

_startCommunicationProtocol(protocol) {
this.protocol = protocol || this.protocol;
Log.debug('start communication protocol: ' + this.protocol );
if (protocol) {
switch (protocol) {
case 'deprecated':
this._addDeprecatedDispatchers();
this._listenToDeprecatedCommands();
break;
case 'ha':
// TODO: Implement HA Discovery
break;
case 'homie3':
default:
this.homieDispatcher = new HomieDispatcher(this);
break;
}
}
}

_stopCommunicationProtocol(protocol) {
protocol = protocol || this.protocol;
if (protocol) {
Log.debug('stop communication protocol: ' + this.protocol);
if (protocol) {
switch (protocol) {
case 'deprecated':
this._removeDeprecatedDispatchers();
this._stopDeprecatedCommands();
break;
case 'ha':
// TODO: Destroy HA Discovery
break;
case 'homie3':
default:
if (this.homieDispatcher) {
this.homieDispatcher.destroy();
delete this.homieDispatcher;
}
break;
}
}
}
}

_addDeprecatedDispatchers() {
this.deviceStateChangeDispatcher = new DeviceStateChangeDispatcher(this);
//this.flowTriggerDispatcher = new FlowTriggerDispatcher(this);
}

_removeDeprecatedDispatchers() {
if (this.deviceStateChangeDispatcher) {
this.deviceStateChangeDispatcher.destroy();
delete this.deviceStateChangeDispatcher;
//this.flowTriggerDispatcher
}
}

_listenToDeprecatedCommands() {
this.messageHandler = new MessageHandler(this);
this.messageHandler.addMessageHandler(new DescribeCommandHandler(this));
this.messageHandler.addMessageHandler(new StateRequestCommandHandler(this));
this.messageHandler.addMessageHandler(new UpdateCommandHandler(this));
}
_stopDeprecatedCommands() {
if (this.messageHandler) {
this.messageHandler.destroy();
delete this.messageHandler;
}
}

_startBroadcasters() {
if (this.homieDispatcher) {
this.homieDispatcher.broadcast = this.settings.broadcastDevices !== false;
}
if (!this.systemStateDispatcher && this.settings.broadcastSystemState) {
this.systemStateDispatcher = new SystemStateDispatcher(this);
}
}

//async _getSystemName() {
// return this.api.system.getSystemName ? await this.api.system.getSystemName() : (await this.api.system.getInfo()).hostname;
//}
_stopBroadcasters() {
if (this.homieDispatcher) {
this.homieDispatcher.broadcast = false;
}

if (this.systemStateDispatcher) {
this.systemStateDispatcher.destroy();
delete this.systemStateDispatcher;
}
}

async _getSystemInfo() {
const info = await this.api.system.getInfo();
return {
Expand Down Expand Up @@ -98,12 +201,12 @@ class MQTTGateway extends Homey.App {
}

setRunning(running) {
Log.info(running ? 'connect' : 'disconnect');
Log.info(running ? 'start' : 'stop');
if (this.mqttClient) {
if (running)
this.mqttClient.connect();
this.start();
else
this.mqttClient.disconnect();
this.stop();
}
}

Expand All @@ -121,13 +224,27 @@ class MQTTGateway extends Homey.App {
Log.info("Settings changed");
this.settings = Homey.ManagerSettings.get('settings') || {};
Log.debug(this.settings);

// deviceId
if (this.mqttClient) {
this.mqttClient.topicRoot = this.settings.deviceId;
}

// devices, topicRoot
let deviceChanges = null;
if (this.deviceManager) {
deviceChanges = this.deviceManager.computeChanges(this.settings.devices);
this.deviceManager.setEnabledDevices(this.settings.devices);
if (this.homieDispatcher) {
this.homieDispatcher.registerDevices();
this.homieDispatcher.dispatchState();
}
}
Log.debug(deviceChanges);

if (this.homieDispatcher) {
this.homieDispatcher.updateSettings(this.settings, deviceChanges);
//this.homieDispatcher.dispatchState();
}

// protocol, broadcasts
this.start(); // NOTE: Changes are detected in the start method(s)
}
}

Expand Down
4 changes: 4 additions & 0 deletions dispatchers/DeviceStateChangeDispatcher.js
Expand Up @@ -66,6 +66,10 @@ class DeviceStateChangeDispatcher {
this.mqttClient.publish(msg);
Log.debug(topic + ': ' + value);
}

destroy() {
// TODO: implement
}
}

module.exports = DeviceStateChangeDispatcher;

0 comments on commit af4dfb8

Please sign in to comment.