Skip to content

Commit 585edc8

Browse files
Some initial work on Philips Hue bridge integration.
1 parent d523745 commit 585edc8

File tree

3 files changed

+211
-1
lines changed

3 files changed

+211
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Node
66
node_modules/
77
npm-debug.log
8+
.node-version
89

910
# Intellij
1011
.idea/

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"request": "2.49.x",
1414
"node-persist": "0.0.x",
1515
"xmldoc": "0.1.x",
16-
16+
"node-hue-api": "^1.0.5",
1717
"carwingsjs": "0.0.x",
1818
"sonos": "0.8.x",
1919
"wemo": "0.2.x",

platforms/PhilipsHue.js

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// Philips Hue Platform Shim for HomeBridge
2+
//
3+
// Remember to add platform to config.json. Example:
4+
// "platforms": [
5+
// {
6+
// "platform": "PhilipsHue",
7+
// "name": "Philips Hue",
8+
// "ip_address": "127.0.0.1",
9+
// "username": "252deadbeef0bf3f34c7ecb810e832f"
10+
// }
11+
// ],
12+
//
13+
// When you attempt to add a device, it will ask for a "PIN code".
14+
// The default code for all HomeBridge accessories is 031-45-154.
15+
//
16+
17+
/* jslint node: true */
18+
/* globals require: false */
19+
/* globals config: false */
20+
21+
"use strict";
22+
23+
var types = require("../lib/HAP-NodeJS/accessories/types.js");
24+
25+
function PhilipsHuePlatform(log, config) {
26+
this.log = log;
27+
this.ip_address = config["ip_address"];
28+
this.username = config["username"];
29+
}
30+
31+
function PhilipsHueAccessory(log, accessoryName, philipsHueLightID, model, philipsHueLightNumber) {
32+
return {
33+
displayName: accessoryName,
34+
username: philipsHueLightID,
35+
pincode: '031-45-154',
36+
services: [{
37+
sType: types.ACCESSORY_INFORMATION_STYPE,
38+
characteristics: [{
39+
cType: types.NAME_CTYPE,
40+
onUpdate: null,
41+
perms: ["pr"],
42+
format: "string",
43+
initialValue: accessoryName,
44+
supportEvents: false,
45+
supportBonjour: false,
46+
manfDescription: "Name of the accessory",
47+
designedMaxLength: 255
48+
},{
49+
cType: types.MANUFACTURER_CTYPE,
50+
onUpdate: null,
51+
perms: ["pr"],
52+
format: "string",
53+
initialValue: "Philips",
54+
supportEvents: false,
55+
supportBonjour: false,
56+
manfDescription: "Manufacturer",
57+
designedMaxLength: 255
58+
},{
59+
cType: types.MODEL_CTYPE,
60+
onUpdate: null,
61+
perms: ["pr"],
62+
format: "string",
63+
initialValue: model,
64+
supportEvents: false,
65+
supportBonjour: false,
66+
manfDescription: "Model",
67+
designedMaxLength: 255
68+
},{
69+
cType: types.IDENTIFY_CTYPE,
70+
onUpdate: function(value) { console.log("Change:",value); execute(accessoryName, philipsHueLightNumber, "identify", value); },
71+
perms: ["pw"],
72+
format: "bool",
73+
initialValue: false,
74+
supportEvents: false,
75+
supportBonjour: false,
76+
manfDescription: "Identify Accessory",
77+
designedMaxLength: 1
78+
}]
79+
},{
80+
sType: types.LIGHTBULB_STYPE,
81+
characteristics: [{
82+
cType: types.NAME_CTYPE,
83+
onUpdate: null,
84+
perms: ["pr"],
85+
format: "string",
86+
initialValue: accessoryName,
87+
supportEvents: false,
88+
supportBonjour: false,
89+
manfDescription: "Name of service",
90+
designedMaxLength: 255
91+
},{
92+
cType: types.POWER_STATE_CTYPE,
93+
onUpdate: function(value) { console.log("Change:",value); execute(accessoryName, philipsHueLightNumber, "on", value); },
94+
perms: ["pw","pr","ev"],
95+
format: "bool",
96+
initialValue: false,
97+
supportEvents: false,
98+
supportBonjour: false,
99+
manfDescription: "Turn On the Light",
100+
designedMaxLength: 1
101+
},{
102+
cType: types.HUE_CTYPE,
103+
onUpdate: function(value) { console.log("Change:",value); execute(accessoryName, philipsHueLightNumber, "hue", value); },
104+
perms: ["pw","pr","ev"],
105+
format: "int",
106+
initialValue: 0,
107+
supportEvents: false,
108+
supportBonjour: false,
109+
manfDescription: "Adjust Hue of Light",
110+
designedMinValue: 0,
111+
designedMaxValue: 65535,
112+
designedMinStep: 1,
113+
unit: "arcdegrees"
114+
},{
115+
cType: types.BRIGHTNESS_CTYPE,
116+
onUpdate: function(value) { console.log("Change:",value); execute(accessoryName, philipsHueLightNumber, "brightness", value); },
117+
perms: ["pw","pr","ev"],
118+
format: "int",
119+
initialValue: 0,
120+
supportEvents: false,
121+
supportBonjour: false,
122+
manfDescription: "Adjust Brightness of Light",
123+
designedMinValue: 0,
124+
designedMaxValue: 100,
125+
designedMinStep: 1,
126+
unit: "%"
127+
},{
128+
cType: types.SATURATION_CTYPE,
129+
onUpdate: function(value) { console.log("Change:",value); execute(accessoryName, philipsHueLightNumber, "saturation", value); },
130+
perms: ["pw","pr","ev"],
131+
format: "int",
132+
initialValue: 0,
133+
supportEvents: false,
134+
supportBonjour: false,
135+
manfDescription: "Adjust Saturation of Light",
136+
designedMinValue: 0,
137+
designedMaxValue: 100,
138+
designedMinStep: 1,
139+
unit: "%"
140+
}]
141+
}]
142+
};
143+
}
144+
145+
var execute = function(accessory, lightID, characteristic, value) {
146+
var http = require('http');
147+
var body = {};
148+
characteristic = characteristic.toLowerCase();
149+
if(characteristic === "identify") {
150+
body = {alert:"select"};
151+
} else if(characteristic === "on") {
152+
body = {on:value};
153+
} else if(characteristic === "hue") {
154+
body = {hue:value};
155+
} else if(characteristic === "brightness") {
156+
value = value/100;
157+
value = value*255;
158+
value = Math.round(value);
159+
body = {bri:value};
160+
} else if(characteristic === "saturation") {
161+
value = value/100;
162+
value = value*255;
163+
value = Math.round(value);
164+
body = {sat:value};
165+
}
166+
var post_data = JSON.stringify(body);
167+
var post_options = {
168+
host: config["ip_address"],
169+
port: '80',
170+
path: '/api/' + config["username"] + '/lights/' + lightID + '/state/',
171+
method: 'PUT',
172+
headers: {
173+
'Content-Type': 'application/json',
174+
'Content-Length': post_data.length
175+
}
176+
};
177+
var post_req = http.request(post_options, function(res) {
178+
res.setEncoding('utf8');
179+
res.on('data', function (chunk) {
180+
console.log('Response: ' + chunk);
181+
});
182+
});
183+
post_req.write(post_data);
184+
post_req.end();
185+
console.log("executed accessory: " + accessory + ", and characteristic: " + characteristic + ", with value: " + value + ".");
186+
};
187+
188+
PhilipsHuePlatform.prototype = {
189+
accessories: function(callback) {
190+
this.log("Fetching Philips Hue lights...");
191+
192+
var that = this;
193+
var foundAccessories = [];
194+
195+
var HueApi = require("node-hue-api").HueApi;
196+
var api = new HueApi(this.ip_address, this.username);
197+
198+
// Connect to the API and loop through lights
199+
api.lights(function(err, response) {
200+
response.lights.map(function(s) {
201+
var accessory = new PhilipsHueAccessory(that.log, s.name, s.uniqueid, s.modelid, s.id);
202+
foundAccessories.push(accessory);
203+
});
204+
callback(foundAccessories);
205+
});
206+
}
207+
};
208+
209+
module.exports.platform = PhilipsHuePlatform;

0 commit comments

Comments
 (0)