hc-philipshue/HCPhilipsHue.js
2019-01-29 23:24:32 +01:00

185 lines
4.9 KiB
JavaScript

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));
}