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.

204 lines (178 loc) 5.25 kB
module.exports = function(RED) { "use strict"; function HueBrightness(config) { RED.nodes.createNode(this, config); const scope = this; const bridge = RED.nodes.getNode(config.bridge); const async = require('async'); // SAVE LAST COMMAND this.lastCommand = null; // // CHECK CONFIG if(bridge == null) { this.status({fill: "red", shape: "ring", text: "hue-brightness.node.not-configured"}); return false; } // // UNIVERSAL MODE? if(!config.sensorid) { this.status({fill: "grey", shape: "dot", text: "hue-brightness.node.universal"}); } // // UPDATE STATE if(typeof bridge.disableupdates != 'undefined' || bridge.disableupdates == false) { this.status({fill: "grey", shape: "dot", text: "hue-brightness.node.init"}); } // // SUBSCRIBE TO UPDATES FROM THE BRIDGE bridge.subscribe("light_level", config.sensorid, function(info) { let currentState = bridge.get("light_level", info.id); // RESOURCE FOUND? if(currentState !== false) { // SEND MESSAGE if(!config.skipevents && (config.initevents || info.suppressMessage == false)) { // SET LAST COMMAND if(scope.lastCommand !== null) { currentState.command = scope.lastCommand; } scope.send(currentState); // RESET LAST COMMAND scope.lastCommand = null; } // NOT IN UNIVERAL MODE? -> CHANGE UI STATES if(config.sensorid) { if(currentState.payload.reachable == false) { scope.status({fill: "red", shape: "ring", text: "hue-brightness.node.not-reachable"}); } else if(currentState.payload.active == true) { if(currentState.payload.dark) { var statusMessage = RED._("hue-brightness.node.lux-dark", { lux: currentState.payload.lux }); scope.status({fill: "blue", shape: "dot", text: statusMessage }); } else if(currentState.payload.daylight) { var statusMessage = RED._("hue-brightness.node.lux-daylight", { lux: currentState.payload.lux }); scope.status({fill: "yellow", shape: "dot", text: statusMessage }); } else { var statusMessage = RED._("hue-brightness.node.lux", { lux: currentState.payload.lux }); scope.status({fill: "grey", shape: "dot", text: statusMessage }); } } else if(currentState.payload.active == false) { scope.status({fill: "red", shape: "ring", text: "hue-brightness.node.deactivated"}); } } } }); // // 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); // CREATE PATCH let patchObject = {}; // DEFINE SENSOR ID & CURRENT STATE const tempSensorID = (!config.sensorid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.sensorid; if(!tempSensorID) { scope.error("Please submit a valid sensor ID."); return false; } let currentState = bridge.get("light_level", tempSensorID); if(!currentState) { scope.error("The sensor in not yet available. Please wait until HueMagic has established a connection with the bridge or check whether the resource ID in the configuration is valid."); return false; } // GET CURRENT STATE if( (typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined') || (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "status") ) { // SET LAST COMMAND if(scope.lastCommand !== null) { currentState.command = scope.lastCommand; } // SEND STATE scope.send(currentState); // RESET LAST COMMAND scope.lastCommand = null; if(done) { done(); } return true; } // TURN ON / OFF if((msg.payload === true || msg.payload === false) && (msg.payload != currentState.payload.active)) { // PREPARE PATCH patchObject["enabled"] = (msg.payload == true); } // // SHOULD PATCH? if(Object.values(patchObject).length > 0) { // CHANGE NODE UI STATE if(config.sensorid) { scope.status({fill: "grey", shape: "ring", text: "hue-brightness.node.command"}); } // PATCH! async.retry({ times: 3, errorFilter: function(err) { return (err.status == 503); }, interval: function(retryCount) { return retryCount*2000; } }, function(callback, results) { bridge.patch("light_level", tempSensorID, patchObject) .then(function() { callback(null, true); }) .catch(function(errors) { callback(errors, null); }); }, function(errors, success) { if(errors) { scope.error(errors); } else if(done) { done(); } }); } else { // SET LAST COMMAND if(scope.lastCommand !== null) { currentState.command = scope.lastCommand; } // SEND STATE scope.send(currentState); // RESET LAST COMMAND scope.lastCommand = null; } }); } RED.nodes.registerType("hue-brightness", HueBrightness); }