version 1.0.0
This commit is contained in:
commit
ba32781a11
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
184
HCPhilipsHue.js
Normal file
184
HCPhilipsHue.js
Normal file
@ -0,0 +1,184 @@
|
||||
const {
|
||||
HCColorLamp,
|
||||
StateUpdateManager
|
||||
} = require('homecontrol-control-base');
|
||||
|
||||
const PhilipsHueApi = require('node-hue-api');
|
||||
|
||||
class HCMagicHome extends HCColorLamp {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
|
||||
if (!("address" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "address" is missing"`);
|
||||
}
|
||||
|
||||
if (!("username" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "username" is missing"`);
|
||||
}
|
||||
|
||||
if (!("uniqueid" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "uniqueid" is missing"`);
|
||||
}
|
||||
|
||||
this._api = new PhilipsHueApi.HueApi(this._configuration.address, this._configuration.username);
|
||||
this._lightid = null;
|
||||
|
||||
this._sumanager = new StateUpdateManager(this._state);
|
||||
}
|
||||
|
||||
// overwrite to make use of the SUManager
|
||||
get state() {
|
||||
return this._sumanager.state.clone();
|
||||
}
|
||||
|
||||
get effects() {
|
||||
return [
|
||||
{name: "Color Loop", id: "colorloop"}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch idmap and resolve uniqueId into a local id
|
||||
*/
|
||||
init() {
|
||||
return this._api.lights().then((resp) => {
|
||||
let lights = resp.lights;
|
||||
|
||||
for(let l of lights) {
|
||||
if (l.uniqueid == this._configuration.uniqueid) {
|
||||
this._lightid = l.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._lightid == null) throw new Error(`Light with unique id "${this._configuration.uniqueid}" was not found on the bridge.`);
|
||||
});
|
||||
}
|
||||
|
||||
turnOn() {
|
||||
let futureState = this.state;
|
||||
futureState.on = true;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let lightState = PhilipsHueApi.lightState.create();
|
||||
lightState.on();
|
||||
|
||||
return this._api.setLightState(this._lightid, lightState).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
||||
}
|
||||
|
||||
turnOff() {
|
||||
let futureState = this.state;
|
||||
futureState.on = false;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let lightState = PhilipsHueApi.lightState.create();
|
||||
lightState.off();
|
||||
|
||||
return this._api.setLightState(this._lightid, lightState).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
||||
}
|
||||
|
||||
setBrightness(brightness) {
|
||||
let futureState = this.state;
|
||||
futureState.brightness = brightness;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let lightState = PhilipsHueApi.lightState.create();
|
||||
lightState.bri(brightness * (255 / 100));
|
||||
|
||||
return this._api.setLightState(this._lightid, lightState).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
||||
}
|
||||
|
||||
setColor(color) {
|
||||
let futureState = this.state;
|
||||
futureState.color = fillPartialHSL(color, futureState.color);
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let lightState = PhilipsHueApi.lightState.create();
|
||||
let { hue, sat } = convertHSLtoHue(futureState.color.hue, futureState.color.sat, futureState.color.l);
|
||||
lightState.hue(hue).sat(sat);
|
||||
|
||||
return this._api.setLightState(this._lightid, lightState).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
||||
}
|
||||
|
||||
setEffect(id) {
|
||||
let futureState = this.state;
|
||||
futureState.effect = id;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let lightState = PhilipsHueApi.lightState.create();
|
||||
lightState.effect(id);
|
||||
|
||||
return this._api.setLightState(this._lightid, lightState).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
||||
}
|
||||
|
||||
pullState() {
|
||||
return this._api.lightStatus(this._lightid).then((resp) => {
|
||||
let lampstate = resp.state;
|
||||
|
||||
let currentState = this.state;
|
||||
let futureState = currentState.clone();
|
||||
|
||||
futureState.on = lampstate.on;
|
||||
futureState.color = convertHuetoHSL(lampstate.hue, lampstate.sat);
|
||||
futureState.brightness = lampstate.bri * (100/255);
|
||||
futureState.effect = lampstate.effect;
|
||||
|
||||
if (currentState.hash != futureState.hash) {
|
||||
// the state of the controller has changed externally
|
||||
this._sumanager.insertConfirmedState(futureState);
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HCMagicHome;
|
||||
|
||||
function rejectHelper(self, suid) {
|
||||
return (err) => {
|
||||
self._sumanager.rejectUpdate(suid);
|
||||
throw err; // rethrow so we can catch it at a higher level
|
||||
};
|
||||
}
|
||||
|
||||
function resolveHelper(self, suid) {
|
||||
return () => {
|
||||
self._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (self._sumanager.highestConfirmedId == suid) {
|
||||
self.emit("state change", self.state);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fillPartialHSL(newcolor, oldcolor) {
|
||||
//console.log(newcolor, oldcolor);
|
||||
var color = {};
|
||||
color["hue"] = (newcolor.hue != null) ? newcolor.hue : oldcolor.hue;
|
||||
color["sat"] = (newcolor.sat != null) ? newcolor.sat : oldcolor.sat;
|
||||
color["l"] = (newcolor.l != null) ? newcolor.l : oldcolor.l;
|
||||
return color;
|
||||
}
|
||||
|
||||
function convertHSLtoHue(h, s, l) {
|
||||
let hue = clamp(h, 0, 360) * (65539 / 360);
|
||||
let sat = clamp(s, 0, 100) * (255 / 100);
|
||||
|
||||
return {hue, sat};
|
||||
}
|
||||
|
||||
function convertHuetoHSL(hue, sat) {
|
||||
hue = clamp(hue, 0, 65539);
|
||||
sat = clamp(sat, 0, 255);
|
||||
|
||||
var h = hue * (360 / 65539);
|
||||
var s = sat * (100 / 255);
|
||||
var l = 100 - sat * ((100-50) / 255)
|
||||
|
||||
return {hue: Math.round(h), sat: Math.round(s), l: Math.round(l)};
|
||||
}
|
||||
|
||||
function clamp(value, min, max) {
|
||||
return Math.min(max, Math.max(min, value));
|
||||
}
|
||||
109
package-lock.json
generated
Normal file
109
package-lock.json
generated
Normal file
@ -0,0 +1,109 @@
|
||||
{
|
||||
"name": "hc-philipshue",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"axios": {
|
||||
"version": "0.15.3",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz",
|
||||
"integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=",
|
||||
"requires": {
|
||||
"follow-redirects": "1.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz",
|
||||
"integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=",
|
||||
"requires": {
|
||||
"debug": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"homecontrol-control-base": {
|
||||
"version": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git#809acfad8245dad9d974cba5b1eff2dfc5419cc9",
|
||||
"from": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git",
|
||||
"requires": {
|
||||
"merge-options": "^1.0.1",
|
||||
"node-object-hash": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"is-plain-obj": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
||||
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
|
||||
},
|
||||
"merge-options": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz",
|
||||
"integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==",
|
||||
"requires": {
|
||||
"is-plain-obj": "^1.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node-hue-api": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/node-hue-api/-/node-hue-api-2.4.4.tgz",
|
||||
"integrity": "sha512-526lV8pK2x4HW2JufXHVcFHj8Z9mOuPR37Gu+/w9Vw/CAPvzKXY5BkG8KmOLbpzjiWljN3s+JMO3n4xDra3l9Q==",
|
||||
"requires": {
|
||||
"axios": "~0.15.3",
|
||||
"deep-extend": "^0.6.0",
|
||||
"q": "~1.4",
|
||||
"traits": "~0.4.0",
|
||||
"xml2js": "~0.4"
|
||||
}
|
||||
},
|
||||
"node-object-hash": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.4.1.tgz",
|
||||
"integrity": "sha512-JQVqSM5/mOaUoUhCYR0t1vgm8RFo7qpJtPvnoFCLeqQh1xrfmr3BCD3nGBnACzpIEF7F7EVgqGD3O4lao/BY/A=="
|
||||
},
|
||||
"q": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
|
||||
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4="
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"traits": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/traits/-/traits-0.4.0.tgz",
|
||||
"integrity": "sha1-QW7cq9yL9kvSkQKnRT3N3YVzcaE="
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
||||
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~9.0.1"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||
}
|
||||
}
|
||||
}
|
||||
19
package.json
Normal file
19
package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "hc-philipshue",
|
||||
"version": "1.0.0",
|
||||
"description": "Philips Hue Plugin for Homecontrol",
|
||||
"main": "HCPhilipsHue.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.literalchaos.de:jan/hc-philipshue.git"
|
||||
},
|
||||
"author": "Jan Scheiper",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"homecontrol-control-base": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git",
|
||||
"node-hue-api": "^2.4.4"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user