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.

160 lines (137 loc) 3.77 kB
module.exports = function(RED) { "use strict"; function HueRules(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-rules.node.no-rule"}); return false; } // // UNIVERSAL MODE? if(!config.ruleid) { this.status({fill: "grey", shape: "dot", text: "hue-rules.node.universal"}); } // // UPDATE STATE if(typeof bridge.disableupdates != 'undefined' || bridge.disableupdates == false) { this.status({fill: "grey", shape: "dot", text: "hue-rules.node.init"}); } // // SUBSCRIBE TO UPDATES FROM THE BRIDGE bridge.subscribe("rule", config.ruleid, function(info) { let currentState = bridge.get("rule", info.id); // RESOURCE FOUND? if(currentState !== false) { // NOT IN UNIVERAL MODE? -> CHANGE UI STATES if(config.ruleid) { if(currentState.payload.enabled == true) { scope.status({fill: "green", shape: "dot", text: "hue-rules.node.enabled"}); } else { scope.status({fill: "red", shape: "ring", text: "hue-rules.node.disabled"}); } } // SEND MESSAGE if(!config.skipevents && (config.initevents || info.suppressMessage == false)) { // SET LAST COMMAND if(scope.lastCommand !== null) { currentState.command = scope.lastCommand; } // SEND STATE scope.send(currentState); // RESET LAST COMMAND scope.lastCommand = null; } } }); // // DISABLE / ENABLE RULE 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); } // SAVE LAST COMMAND scope.lastCommand = RED.util.cloneMessage(msg); // CREATE PATCH let patchObject = {}; // DEFINE SENSOR ID & CURRENT STATE const tempRuleID = (!config.ruleid && typeof msg.topic != 'undefined' && isNaN(msg.topic) == false) ? msg.topic : config.ruleid; if(!tempRuleID) { scope.error("Please submit a valid rule ID."); return false; } let currentState = bridge.get("rule", "rule_" + tempRuleID); if(!currentState) { scope.error("The rule 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; } // CONTROL RULE if(msg.payload === true || msg.payload === false) { if(msg.payload === currentState.payload.enabled) { return false; } patchObject["status"] = (msg.payload == true) ? 'enabled' : 'disabled'; // PATCH! async.retry({ times: 3, errorFilter: function(err) { return (err.status == 503); }, interval: function(retryCount) { return retryCount*2000; } }, function(callback, results) { bridge.patch("rules", "/rules/"+tempRuleID, patchObject, 1) .then(function(response) { bridge.refetchRule(tempRuleID); 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; if(done) {done();} } }); } RED.nodes.registerType("hue-rules", HueRules); }