From 5747dfe25dd8c52a63ab4284b51a5523caff19e4 Mon Sep 17 00:00:00 2001 From: Charalampos Doukas Date: Tue, 5 Nov 2013 16:32:42 +0100 Subject: [PATCH 1/6] added philips_hue node --- hardware/philips_hue/103-philips_hue.html | 79 +++++++++++ hardware/philips_hue/103-philips_hue.js | 154 ++++++++++++++++++++++ hardware/philips_hue/philipshue.png | Bin 0 -> 9134 bytes 3 files changed, 233 insertions(+) create mode 100644 hardware/philips_hue/103-philips_hue.html create mode 100644 hardware/philips_hue/103-philips_hue.js create mode 100644 hardware/philips_hue/philipshue.png diff --git a/hardware/philips_hue/103-philips_hue.html b/hardware/philips_hue/103-philips_hue.html new file mode 100644 index 00000000..13d8005b --- /dev/null +++ b/hardware/philips_hue/103-philips_hue.html @@ -0,0 +1,79 @@ + + + + + + + + + diff --git a/hardware/philips_hue/103-philips_hue.js b/hardware/philips_hue/103-philips_hue.js new file mode 100644 index 00000000..2d5b8239 --- /dev/null +++ b/hardware/philips_hue/103-philips_hue.js @@ -0,0 +1,154 @@ +/** + * philips_hue.js + * Basic functionality for accessing and contolling a Philips Hue wireless Lamp + * Allows for bridge/gateway and light scanning, as well as Light ON/OFF/ALERT status update + * Requires node-hue-api https://github.com/peter-murray/node-hue-api + * Copyright 2013 Charalampos Doukas - @BuildingIoT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +//Require node-hue-api +var hue = require("node-hue-api"); +var HueApi = require("node-hue-api").HueApi; + +// Require main module +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +//store the IP address of the Hue Gateway +var gw_ipaddress = ""; + +var lights_discovered = ""; + + +// The main node definition - most things happen in here +function HueNode(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + + var username, discovery_mode, lamp_status, lamp_id; + + //get parameters from user + this.username = n.username; + this.discovery_mode = n.discovery_mode; + this.lamp_status = n.lamp_status; + this.lamp_id = n.lamp_id; + + + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + + var msg = {}; + + msg.topic = this.topic; + + this.on("input", function(msg){ + //check if users has selected discovery mode, provide output: + if(this.discovery_mode==1) { + //start with detecting the IP address of the Hue gateway in the local network: + hue.locateBridges(function(err, result) { + + var msg2 = {}; + msg2.topic = this.topic; + if (err) throw err; + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; + msg2.payload = this.gw_ipaddress; + node.send(msg2); + + //get light info: + var api = new HueApi(this.gw_ipaddress, node.username); + api.lights(function(err, lights) { + var msg2 = {}; + if (err) throw err; + var lights_discovered = JSON.stringify(lights, null, 2); + msg2 = { topic:node.topic, payload: { ipaddress:this.gw_ipaddress, lights:lights_discovered} }; + node.send(msg2); + + }); + + }); + + + } + + else { + //set the lamp status + //first locate the Hue gateway: + hue.locateBridges(function(err, result) { + + var msg2 = {}; + msg2.topic = this.topic; + if (err) throw err; + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; + + + //set light status + var api = new HueApi(this.gw_ipaddress, node.username); + var lightState = hue.lightState; + var state = lightState.create(); + + var status; + if(msg.payload=="ALERT"){ + status = "ALERT"; + } + else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; + else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; + + + if(status=="ALERT") { + api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); + } + else if(status=="ON") { + api.setLightState(node.lamp_id, state.on()).then(displayResult).fail(displayError).done(); + } + else { + api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); + } + + msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; + node.send(msg2); + + }); + } + }); + + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); + + } + + //hue debugging on the output: + var displayResult = function(result) { + console.log(result); +}; + +var displayError = function(err) { + console.error(err); +}; + + + +// Register the node by name. This must be called before overriding any of the +// Node functions. +RED.nodes.registerType("HueNode",HueNode); \ No newline at end of file diff --git a/hardware/philips_hue/philipshue.png b/hardware/philips_hue/philipshue.png new file mode 100644 index 0000000000000000000000000000000000000000..a77aa2bf3635caee8ff90b2f5c82c937ab851b7b GIT binary patch literal 9134 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 F@IRp-tFHh6 literal 0 HcmV?d00001 From d491aa61c93f6955e43a574e5d5a35741e06716d Mon Sep 17 00:00:00 2001 From: Charalampos Doukas Date: Sat, 9 Nov 2013 13:18:04 +0100 Subject: [PATCH 2/6] Added check for no Philip Hue bridge located --- hardware/philips_hue/103-philips_hue.js | 58 ++++++++++++++----------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/hardware/philips_hue/103-philips_hue.js b/hardware/philips_hue/103-philips_hue.js index 2d5b8239..bca70c0d 100644 --- a/hardware/philips_hue/103-philips_hue.js +++ b/hardware/philips_hue/103-philips_hue.js @@ -58,6 +58,7 @@ function HueNode(n) { msg.topic = this.topic; this.on("input", function(msg){ + //check if users has selected discovery mode, provide output: if(this.discovery_mode==1) { //start with detecting the IP address of the Hue gateway in the local network: @@ -95,35 +96,42 @@ function HueNode(n) { var msg2 = {}; msg2.topic = this.topic; if (err) throw err; - //save the IP address of the 1st bridge found - this.gw_ipaddress = result[0].ipaddress; - - //set light status - var api = new HueApi(this.gw_ipaddress, node.username); - var lightState = hue.lightState; - var state = lightState.create(); - - var status; - if(msg.payload=="ALERT"){ - status = "ALERT"; - } - else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; - else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; - - - if(status=="ALERT") { - api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); - } - else if(status=="ON") { - api.setLightState(node.lamp_id, state.on()).then(displayResult).fail(displayError).done(); + if(result[0]==null) { + msg2.payload="No Philips Hue Bridge located! Nothing to be done."; + console.log("No Philips Hue Bridge located!"); + node.send(msg2); } else { - api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); - } + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; - msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; - node.send(msg2); + //set light status + var api = new HueApi(this.gw_ipaddress, node.username); + var lightState = hue.lightState; + var state = lightState.create(); + + var status; + if(msg.payload=="ALERT"){ + status = "ALERT"; + } + else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; + else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; + + + if(status=="ALERT") { + api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); + } + else if(status=="ON") { + api.setLightState(node.lamp_id, state.on()).then(displayResult).fail(displayError).done(); + } + else { + api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); + } + + msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; + node.send(msg2); + } }); } From 5ebcfdbc66efb570cd16ce8fd2c672d98c0cde9b Mon Sep 17 00:00:00 2001 From: Charalampos Doukas Date: Mon, 11 Nov 2013 14:48:20 +0100 Subject: [PATCH 3/6] Removed single Philips Hue node --- hardware/philips_hue/103-philips_hue.html | 79 ----------- hardware/philips_hue/103-philips_hue.js | 162 ---------------------- hardware/philips_hue/philipshue.png | Bin 9134 -> 0 bytes 3 files changed, 241 deletions(-) delete mode 100644 hardware/philips_hue/103-philips_hue.html delete mode 100644 hardware/philips_hue/103-philips_hue.js delete mode 100644 hardware/philips_hue/philipshue.png diff --git a/hardware/philips_hue/103-philips_hue.html b/hardware/philips_hue/103-philips_hue.html deleted file mode 100644 index 13d8005b..00000000 --- a/hardware/philips_hue/103-philips_hue.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - diff --git a/hardware/philips_hue/103-philips_hue.js b/hardware/philips_hue/103-philips_hue.js deleted file mode 100644 index bca70c0d..00000000 --- a/hardware/philips_hue/103-philips_hue.js +++ /dev/null @@ -1,162 +0,0 @@ -/** - * philips_hue.js - * Basic functionality for accessing and contolling a Philips Hue wireless Lamp - * Allows for bridge/gateway and light scanning, as well as Light ON/OFF/ALERT status update - * Requires node-hue-api https://github.com/peter-murray/node-hue-api - * Copyright 2013 Charalampos Doukas - @BuildingIoT - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - - -//Require node-hue-api -var hue = require("node-hue-api"); -var HueApi = require("node-hue-api").HueApi; - -// Require main module -var RED = require(process.env.NODE_RED_HOME+"/red/red"); - -//store the IP address of the Hue Gateway -var gw_ipaddress = ""; - -var lights_discovered = ""; - - -// The main node definition - most things happen in here -function HueNode(n) { - // Create a RED node - RED.nodes.createNode(this,n); - - var node = this; - - var username, discovery_mode, lamp_status, lamp_id; - - //get parameters from user - this.username = n.username; - this.discovery_mode = n.discovery_mode; - this.lamp_status = n.lamp_status; - this.lamp_id = n.lamp_id; - - - - // Store local copies of the node configuration (as defined in the .html) - this.topic = n.topic; - - - var msg = {}; - - msg.topic = this.topic; - - this.on("input", function(msg){ - - //check if users has selected discovery mode, provide output: - if(this.discovery_mode==1) { - //start with detecting the IP address of the Hue gateway in the local network: - hue.locateBridges(function(err, result) { - - var msg2 = {}; - msg2.topic = this.topic; - if (err) throw err; - //save the IP address of the 1st bridge found - this.gw_ipaddress = result[0].ipaddress; - msg2.payload = this.gw_ipaddress; - node.send(msg2); - - //get light info: - var api = new HueApi(this.gw_ipaddress, node.username); - api.lights(function(err, lights) { - var msg2 = {}; - if (err) throw err; - var lights_discovered = JSON.stringify(lights, null, 2); - msg2 = { topic:node.topic, payload: { ipaddress:this.gw_ipaddress, lights:lights_discovered} }; - node.send(msg2); - - }); - - }); - - - } - - else { - //set the lamp status - //first locate the Hue gateway: - hue.locateBridges(function(err, result) { - - var msg2 = {}; - msg2.topic = this.topic; - if (err) throw err; - - if(result[0]==null) { - msg2.payload="No Philips Hue Bridge located! Nothing to be done."; - console.log("No Philips Hue Bridge located!"); - node.send(msg2); - } - else { - //save the IP address of the 1st bridge found - this.gw_ipaddress = result[0].ipaddress; - - //set light status - var api = new HueApi(this.gw_ipaddress, node.username); - var lightState = hue.lightState; - var state = lightState.create(); - - var status; - if(msg.payload=="ALERT"){ - status = "ALERT"; - } - else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; - else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; - - - if(status=="ALERT") { - api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); - } - else if(status=="ON") { - api.setLightState(node.lamp_id, state.on()).then(displayResult).fail(displayError).done(); - } - else { - api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); - } - - msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; - node.send(msg2); - } - - }); - } - }); - - - this.on("close", function() { - // Called when the node is shutdown - eg on redeploy. - // Allows ports to be closed, connections dropped etc. - // eg: this.client.disconnect(); - }); - - } - - //hue debugging on the output: - var displayResult = function(result) { - console.log(result); -}; - -var displayError = function(err) { - console.error(err); -}; - - - -// Register the node by name. This must be called before overriding any of the -// Node functions. -RED.nodes.registerType("HueNode",HueNode); \ No newline at end of file diff --git a/hardware/philips_hue/philipshue.png b/hardware/philips_hue/philipshue.png deleted file mode 100644 index a77aa2bf3635caee8ff90b2f5c82c937ab851b7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9134 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 F@IRp-tFHh6 From b35ff010e2ae066e5b4e72a81750a5a532544e6f Mon Sep 17 00:00:00 2001 From: Charalampos Doukas Date: Mon, 11 Nov 2013 15:04:32 +0100 Subject: [PATCH 4/6] Added 2 Philips Hue nodes, hue_discover and hue_manage --- hardware/hue_discover/103-hue_discover.html | 54 ++++++++ hardware/hue_discover/103-hue_discover.js | 105 +++++++++++++++ hardware/hue_discover/icons/philipshue.png | Bin 0 -> 9372 bytes hardware/hue_manage/104-hue_manage.html | 80 ++++++++++++ hardware/hue_manage/104-hue_manage.js | 136 ++++++++++++++++++++ hardware/hue_manage/icons/hue.png | Bin 0 -> 8876 bytes 6 files changed, 375 insertions(+) create mode 100644 hardware/hue_discover/103-hue_discover.html create mode 100644 hardware/hue_discover/103-hue_discover.js create mode 100644 hardware/hue_discover/icons/philipshue.png create mode 100644 hardware/hue_manage/104-hue_manage.html create mode 100644 hardware/hue_manage/104-hue_manage.js create mode 100644 hardware/hue_manage/icons/hue.png diff --git a/hardware/hue_discover/103-hue_discover.html b/hardware/hue_discover/103-hue_discover.html new file mode 100644 index 00000000..14f7fa0a --- /dev/null +++ b/hardware/hue_discover/103-hue_discover.html @@ -0,0 +1,54 @@ + + + + + + + + + diff --git a/hardware/hue_discover/103-hue_discover.js b/hardware/hue_discover/103-hue_discover.js new file mode 100644 index 00000000..4106aeff --- /dev/null +++ b/hardware/hue_discover/103-hue_discover.js @@ -0,0 +1,105 @@ +/** + * philips_hue.js + * Basic functionality for accessing a Philips Hue wireless Lamp + * Allows for bridge/gateway detection and light scanning. + * Requires node-hue-api https://github.com/peter-murray/node-hue-api + * Copyright 2013 Charalampos Doukas - @BuildingIoT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +//Require node-hue-api +var hue = require("node-hue-api"); +var HueApi = require("node-hue-api").HueApi; + +// Require main module +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +//store the IP address of the Hue Gateway +var gw_ipaddress = ""; + +var username; + +// The main node definition - most things happen in here +function HueNodeDiscovery(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + + //get username from user input + this.username = n.username; + + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + this.on("input", function(msg){ + + //start with detecting the IP address of the Hue gateway in the local network: + hue.locateBridges(function(err, result) { + var msg = {}; + if (err) throw err; + //check for found bridges + if(result[0]!=null) { + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; + msg.payload = this.gw_ipaddress; + + //get light info: + var api = new HueApi(this.gw_ipaddress, node.username); + api.lights(function(err, lights) { + var msg2 = {}; + if (err) throw err; + var lights_discovered = JSON.stringify(lights, null, 2); + msg2.topic = "Lights"; + msg2.payload = lights_discovered; + node.send([msg, msg2]); + + }); + } + else { + //bridge not found: + var msg = {}; + msg.payload = "Bridge not found!"; + node.send(msg); + } + + }); + + }); + + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); + + } + + //hue debugging on the output: + var displayResult = function(result) { + console.log(result); +}; + +var displayError = function(err) { + console.error(err); +}; + + + +// Register the node by name. This must be called before overriding any of the +// Node functions. +RED.nodes.registerType("Discover",HueNodeDiscovery); \ No newline at end of file diff --git a/hardware/hue_discover/icons/philipshue.png b/hardware/hue_discover/icons/philipshue.png new file mode 100644 index 0000000000000000000000000000000000000000..261b38d195b32744852cf19e7ed994535dedf376 GIT binary patch literal 9372 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 m;*>y8gD%+pbFA3HD}c + + + + + + + + diff --git a/hardware/hue_manage/104-hue_manage.js b/hardware/hue_manage/104-hue_manage.js new file mode 100644 index 00000000..8d3bf05d --- /dev/null +++ b/hardware/hue_manage/104-hue_manage.js @@ -0,0 +1,136 @@ +/** + * philips_hue.js + * Basic functionality for accessing and contolling a Philips Hue wireless Lamp + * Allows for bridge/gateway and light scanning, as well as Light ON/OFF/ALERT status update + * Requires node-hue-api https://github.com/peter-murray/node-hue-api + * Copyright 2013 Charalampos Doukas - @BuildingIoT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +//Require node-hue-api +var hue = require("node-hue-api"); +var HueApi = require("node-hue-api").HueApi; + +// Require main module +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +//store the IP address of the Hue Gateway +var gw_ipaddress = ""; + + +var username, lamp_status, lamp_id, color; + +function hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} + + +// The main node definition - most things happen in here +function HueNode(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + + //get parameters from user + this.username = n.username; + this.lamp_status = n.lamp_status; + this.lamp_id = n.lamp_id; + this.color = n.color; + + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + + var msg = {}; + + msg.topic = this.topic; + + this.on("input", function(msg){ + //set the lamp status + //first locate the Hue gateway: + hue.locateBridges(function(err, result) { + + var msg2 = {}; + msg2.topic = this.topic; + if (err) throw err; + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; + + + //set light status + var api = new HueApi(this.gw_ipaddress, node.username); + var lightState = hue.lightState; + var state = lightState.create(); + + var status; + if(msg.payload=="ALERT"){ + status = "ALERT"; + } + else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; + else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; + + + if(status=="ALERT") { + api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); + } + else if(status=="ON") { + if(node.color==null) { + api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(msg.topic).r,hexToRgb(msg.topic).g,hexToRgb(msg.topic).b)).then(displayResult).fail(displayError).done(); + } + else { + api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(node.color).r,hexToRgb(node.color).g,hexToRgb(node.color).b)).then(displayResult).fail(displayError).done(); + } + } + else { + api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); + } + + msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; + node.send(msg2); + + }); + }); + + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); + + } + + //hue debugging on the output: + var displayResult = function(result) { + console.log(result); +}; + +var displayError = function(err) { + console.error(err); +}; + + + + +// Register the node by name. This must be called before overriding any of the +// Node functions. +RED.nodes.registerType("HueNode",HueNode); \ No newline at end of file diff --git a/hardware/hue_manage/icons/hue.png b/hardware/hue_manage/icons/hue.png new file mode 100644 index 0000000000000000000000000000000000000000..6a265a2de1e96657421dfedb7ee58816122f57e9 GIT binary patch literal 8876 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 Date: Mon, 11 Nov 2013 16:36:25 +0100 Subject: [PATCH 5/6] added a no bridge check --- hardware/hue_manage/104-hue_manage.js | 55 ++++++++++++++++----------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/hardware/hue_manage/104-hue_manage.js b/hardware/hue_manage/104-hue_manage.js index 8d3bf05d..954a8f16 100644 --- a/hardware/hue_manage/104-hue_manage.js +++ b/hardware/hue_manage/104-hue_manage.js @@ -72,41 +72,50 @@ function HueNode(n) { var msg2 = {}; msg2.topic = this.topic; if (err) throw err; - //save the IP address of the 1st bridge found - this.gw_ipaddress = result[0].ipaddress; + //check for found bridges + if(result[0]!=null) { + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; - //set light status - var api = new HueApi(this.gw_ipaddress, node.username); - var lightState = hue.lightState; - var state = lightState.create(); + //set light status + var api = new HueApi(this.gw_ipaddress, node.username); + var lightState = hue.lightState; + var state = lightState.create(); - var status; - if(msg.payload=="ALERT"){ - status = "ALERT"; - } - else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; - else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; + var status; + if(msg.payload=="ALERT"){ + status = "ALERT"; + } + else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; + else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; - if(status=="ALERT") { - api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); - } - else if(status=="ON") { - if(node.color==null) { - api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(msg.topic).r,hexToRgb(msg.topic).g,hexToRgb(msg.topic).b)).then(displayResult).fail(displayError).done(); + if(status=="ALERT") { + api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); + } + else if(status=="ON") { + if(node.color==null) { + api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(msg.topic).r,hexToRgb(msg.topic).g,hexToRgb(msg.topic).b)).then(displayResult).fail(displayError).done(); + } + else { + api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(node.color).r,hexToRgb(node.color).g,hexToRgb(node.color).b)).then(displayResult).fail(displayError).done(); + } } else { - api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(node.color).r,hexToRgb(node.color).g,hexToRgb(node.color).b)).then(displayResult).fail(displayError).done(); + api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); } + + msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; + node.send(msg2); } else { - api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); + //bridge not found: + var msg = {}; + msg.payload = "Bridge not found!"; + node.send(msg); } - msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; - node.send(msg2); - }); }); From 60c7911964e2552fd94b8f54f0c1a671add6106a Mon Sep 17 00:00:00 2001 From: Charalampos Doukas Date: Thu, 28 Nov 2013 23:52:26 +0100 Subject: [PATCH 6/6] addedd nodes under common directory --- hardware/hue/103-hue_discover.html | 54 +++++++++++ hardware/hue/103-hue_discover.js | 105 +++++++++++++++++++++ hardware/hue/104-hue_manage.html | 80 ++++++++++++++++ hardware/hue/104-hue_manage.js | 145 +++++++++++++++++++++++++++++ 4 files changed, 384 insertions(+) create mode 100644 hardware/hue/103-hue_discover.html create mode 100644 hardware/hue/103-hue_discover.js create mode 100644 hardware/hue/104-hue_manage.html create mode 100644 hardware/hue/104-hue_manage.js diff --git a/hardware/hue/103-hue_discover.html b/hardware/hue/103-hue_discover.html new file mode 100644 index 00000000..ac6c1d39 --- /dev/null +++ b/hardware/hue/103-hue_discover.html @@ -0,0 +1,54 @@ + + + + + + + + + diff --git a/hardware/hue/103-hue_discover.js b/hardware/hue/103-hue_discover.js new file mode 100644 index 00000000..4106aeff --- /dev/null +++ b/hardware/hue/103-hue_discover.js @@ -0,0 +1,105 @@ +/** + * philips_hue.js + * Basic functionality for accessing a Philips Hue wireless Lamp + * Allows for bridge/gateway detection and light scanning. + * Requires node-hue-api https://github.com/peter-murray/node-hue-api + * Copyright 2013 Charalampos Doukas - @BuildingIoT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +//Require node-hue-api +var hue = require("node-hue-api"); +var HueApi = require("node-hue-api").HueApi; + +// Require main module +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +//store the IP address of the Hue Gateway +var gw_ipaddress = ""; + +var username; + +// The main node definition - most things happen in here +function HueNodeDiscovery(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + + //get username from user input + this.username = n.username; + + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + this.on("input", function(msg){ + + //start with detecting the IP address of the Hue gateway in the local network: + hue.locateBridges(function(err, result) { + var msg = {}; + if (err) throw err; + //check for found bridges + if(result[0]!=null) { + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; + msg.payload = this.gw_ipaddress; + + //get light info: + var api = new HueApi(this.gw_ipaddress, node.username); + api.lights(function(err, lights) { + var msg2 = {}; + if (err) throw err; + var lights_discovered = JSON.stringify(lights, null, 2); + msg2.topic = "Lights"; + msg2.payload = lights_discovered; + node.send([msg, msg2]); + + }); + } + else { + //bridge not found: + var msg = {}; + msg.payload = "Bridge not found!"; + node.send(msg); + } + + }); + + }); + + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); + + } + + //hue debugging on the output: + var displayResult = function(result) { + console.log(result); +}; + +var displayError = function(err) { + console.error(err); +}; + + + +// Register the node by name. This must be called before overriding any of the +// Node functions. +RED.nodes.registerType("Discover",HueNodeDiscovery); \ No newline at end of file diff --git a/hardware/hue/104-hue_manage.html b/hardware/hue/104-hue_manage.html new file mode 100644 index 00000000..7aa408e2 --- /dev/null +++ b/hardware/hue/104-hue_manage.html @@ -0,0 +1,80 @@ + + + + + + + + + diff --git a/hardware/hue/104-hue_manage.js b/hardware/hue/104-hue_manage.js new file mode 100644 index 00000000..954a8f16 --- /dev/null +++ b/hardware/hue/104-hue_manage.js @@ -0,0 +1,145 @@ +/** + * philips_hue.js + * Basic functionality for accessing and contolling a Philips Hue wireless Lamp + * Allows for bridge/gateway and light scanning, as well as Light ON/OFF/ALERT status update + * Requires node-hue-api https://github.com/peter-murray/node-hue-api + * Copyright 2013 Charalampos Doukas - @BuildingIoT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +//Require node-hue-api +var hue = require("node-hue-api"); +var HueApi = require("node-hue-api").HueApi; + +// Require main module +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +//store the IP address of the Hue Gateway +var gw_ipaddress = ""; + + +var username, lamp_status, lamp_id, color; + +function hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} + + +// The main node definition - most things happen in here +function HueNode(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + + //get parameters from user + this.username = n.username; + this.lamp_status = n.lamp_status; + this.lamp_id = n.lamp_id; + this.color = n.color; + + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + + var msg = {}; + + msg.topic = this.topic; + + this.on("input", function(msg){ + //set the lamp status + //first locate the Hue gateway: + hue.locateBridges(function(err, result) { + + var msg2 = {}; + msg2.topic = this.topic; + if (err) throw err; + //check for found bridges + if(result[0]!=null) { + //save the IP address of the 1st bridge found + this.gw_ipaddress = result[0].ipaddress; + + + //set light status + var api = new HueApi(this.gw_ipaddress, node.username); + var lightState = hue.lightState; + var state = lightState.create(); + + var status; + if(msg.payload=="ALERT"){ + status = "ALERT"; + } + else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON"; + else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF"; + + + if(status=="ALERT") { + api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done(); + } + else if(status=="ON") { + if(node.color==null) { + api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(msg.topic).r,hexToRgb(msg.topic).g,hexToRgb(msg.topic).b)).then(displayResult).fail(displayError).done(); + } + else { + api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(node.color).r,hexToRgb(node.color).g,hexToRgb(node.color).b)).then(displayResult).fail(displayError).done(); + } + } + else { + api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done(); + } + + msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status; + node.send(msg2); + } + else { + //bridge not found: + var msg = {}; + msg.payload = "Bridge not found!"; + node.send(msg); + } + + }); + }); + + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); + + } + + //hue debugging on the output: + var displayResult = function(result) { + console.log(result); +}; + +var displayError = function(err) { + console.error(err); +}; + + + + +// Register the node by name. This must be called before overriding any of the +// Node functions. +RED.nodes.registerType("HueNode",HueNode); \ No newline at end of file