UNPKG

node-red-contrib-huemagic

Version:

Philips Hue node to control bridges, lights, groups, scenes, rules, taps, switches, buttons, motion sensors, temperature sensors and Lux sensors using Node-RED.

304 lines (262 loc) 7.89 kB
module.exports = function(RED) { "use strict"; function HueBridgeNode(config) { RED.nodes.createNode(this, config); const scope = this; const bridge = RED.nodes.getNode(config.bridge); // IS CONNECTED? this.connected = false; // GET BRIDGE INFORMATION INITIALLY this.lastBridgeInformation = null; // SAVE LAST COMMAND this.lastCommand = null; // NODE UI STATUS TIMEOUT this.timeout = null; // // ACTIVE STATE this.nodeActive = true; // // CHECK CONFIG if(bridge == null) { this.status({fill: "red", shape: "ring", text: "hue-bridge.node.not-configured"}); return false; } // // UPDATE STATE scope.status({fill: "grey", shape: "dot", text: "hue-bridge.node.connecting"}); this.setInitialState = function() { scope.status({fill: "green", shape: "dot", text: "hue-bridge.node.connected"}); } // // GET BRIDGE INFORMATION this.getBridgeInformation = async function(forceReload = false) { return new Promise(function(resolve, reject) { if(forceReload === true) { // REFRESH INFORMATION bridge.getBridgeInformation(true) .then(function(updated) { return scope.getBridgeInformation(); }) .then(function(bridgeInformation) { resolve(bridgeInformation); }); } else if(scope.lastBridgeInformation !== null) { let bridgeInformationCopy = Object.assign({}, scope.lastBridgeInformation); resolve(bridgeInformationCopy); } else { let bridgeInformation = bridge.get("bridge", "bridge", { autoupdate: ((bridge.config.autoupdates && bridge.config.autoupdates == true) || typeof bridge.config.autoupdates == 'undefined') }); scope.lastBridgeInformation = Object.assign({}, bridgeInformation); resolve(bridgeInformation); } }); } // // SUBSCRIBE TO UPDATES FROM THE BRIDGE bridge.subscribe("bridge", "globalResourceUpdates", async function(info) { let currentState = bridge.get(info.updatedType, info.id); // RESOURCE FOUND? if(currentState !== false) { // UPDATE COUNTER if(info.suppressMessage === false) { scope.status({fill: "blue", shape: "dot", text: "hue-bridge.node.connected"}); if(scope.timeout !== null) { clearTimeout(scope.timeout); } scope.timeout = setTimeout(function() { scope.setInitialState(); }, 1000); } // SEND MESSAGE if(!config.skipglobalevents && (config.initevents || info.suppressMessage == false)) { scope.getBridgeInformation() .then(function(info) { // ADD DEVICE UPDATE TO RESPONSE info.updated = currentState; // SET LAST COMMAND if(scope.lastCommand !== null) { info.command = scope.lastCommand; } // SEND MESSAGE scope.send(info); // RESET LAST COMMAND scope.lastCommand = null; }); } } // CONNECTED? if(scope.connected == false) { scope.connected = true; scope.setInitialState(); } }); // // ON COMMAND this.on('input', function(msg, send, done) { // REDEFINE SEND AND DONE IF NOT AVAILABLE send = send || function() { scope.send.apply(scope,arguments); } done = done || function() { scope.done.apply(scope,arguments); } // SET LAST COMMAND scope.lastCommand = RED.util.cloneMessage(msg); // GET BRIDGE INFORMATION scope.getBridgeInformation() .then(function(bridgeInformation) { // START TOUCHLINK if(typeof msg.payload != 'undefined' && typeof msg.payload.touchLink != 'undefined') { // SET STATUS scope.status({fill: "yellow", shape: "dot", text: "hue-bridge.node.starting-tl" }); // ENABLE TOUCHLINK bridge.patch("bridge", "/config", { touchlink: true }, 1) .then(function(status) { // SET STATUS scope.status({fill: "blue", shape: "ring", text: "hue-bridge.node.started-tl" }); if(done) { done(); } // RESET STATUS AFTER 30 SECONDS setTimeout(function() { scope.setInitialState(); scope.getBridgeInformation(true); }, 30000); }) .catch(function(error) { scope.error(error); if(done) { done(error); } }); } // FETCH RESOURCES else if(typeof msg.payload != 'undefined' && typeof msg.payload.fetch != 'undefined') { let fetchTypes = []; if(typeof msg.payload.fetch == 'string') { fetchTypes.push(msg.payload.fetch); } else if(typeof msg.payload.fetch == 'object') { fetchTypes = msg.payload.fetch; } else { return false; } scope.status({fill: "blue", shape: "dot", text: "hue-bridge.node.f-resources" }); // FETCH bridgeInformation.results = {}; fetchTypes.forEach(function(fetch) { bridgeInformation.results[fetch] = bridge.get(fetch); }); // SEND RESULTS if(scope.lastCommand !== null) { bridgeInformation.command = scope.lastCommand; } send(bridgeInformation); // RESET LAST COMMAND scope.lastCommand = null; if(done) { done(); } // RESET STATUS setTimeout(function(){ scope.setInitialState(); }, 2000); } // UPDATE SETTINGS else if(typeof msg.payload != 'undefined' && typeof msg.payload.settings != 'undefined') { let patchObject = {}; if(typeof msg.payload.settings.name != 'undefined') { patchObject.name = msg.payload.settings.name; } if(typeof msg.payload.settings.zigbeeChannel != 'undefined') { patchObject.zigbeechannel = msg.payload.settings.zigbeeChannel; } if(typeof msg.payload.settings.ipAddress != 'undefined') { patchObject.ipaddress = msg.payload.settings.ipAddress; } if(typeof msg.payload.settings.dhcpEnabled != 'undefined') { patchObject.dhcp = msg.payload.settings.dhcpEnabled; } if(typeof msg.payload.settings.netmask != 'undefined') { patchObject.netmask = msg.payload.settings.netmask; } if(typeof msg.payload.settings.gateway != 'undefined') { patchObject.gateway = msg.payload.settings.gateway; } if(typeof msg.payload.settings.proxyPort != 'undefined') { patchObject.proxyport = msg.payload.settings.proxyPort; } if(typeof msg.payload.settings.proxyAddress != 'undefined') { patchObject.proxyaddress = msg.payload.settings.proxyAddress; } if(typeof msg.payload.settings.timeZone != 'undefined') { patchObject.timezone = msg.payload.settings.timeZone; } // PATCH BRIDGE! if(Object.values(patchObject).length > 0) { // SET UPDATING STATUS scope.status({fill: "yellow", shape: "dot", text: "hue-bridge.node.updating-settings" }); // PATCH BRIDGE bridge.patch("bridge", "/config", patchObject, 1) .then(function(patched) { // GET RELOADED BRIDGE INFORMATION return scope.getBridgeInformation(true); }) .then(function(bridgeInformation) { scope.status({fill: "blue", shape: "dot", text: "hue-bridge.node.settings-updated" }); // SET LAST COMMAND if(scope.lastCommand !== null) { bridgeInformation.command = scope.lastCommand; } scope.send(bridgeInformation); // RESET LAST COMMAND scope.lastCommand = null; if(done) { done(); } setTimeout(function(){ scope.setInitialState(); }, 3000); }) .catch(function(error) { scope.error(error); if(done) { done(error); } }); } } // GIVE BACK CURRENT STATE else { // SEND MESSAGE if(scope.lastCommand !== null) { bridgeInformation.command = scope.lastCommand; } scope.send(bridgeInformation); // RESET LAST COMMAND scope.lastCommand = null; } }); }); } RED.nodes.registerType("hue-bridge-node", HueBridgeNode); }