hc-milight/HCmilight.js
2019-03-02 14:45:30 +01:00

207 lines
4.8 KiB
JavaScript

const {
HCColorLamp,
StateUpdateManager
} = require('homecontrol-control-base');
const {
MilightController,
commands2,
} = require('node-milight-promise');
const mergeOptions = require('merge-options');
class HCmilight extends HCColorLamp {
constructor(config) {
super(config);
if (!("address" in this._configuration)) {
throw new Error(`Required configuration field "address" is missing"`);
}
this._zone = (this._configuration.zone !== undefined) ? this._configuration.zone : 1;
let opts = {
ip: this._configuration.address
};
opts = mergeOptions(opts, {
commandRepeat: 2,
}, this._configuration.controllerOpts);
this._state.brightness = 100;
this._state.color.l = 100;
this._state.color.sat = 0;
this._light = new MilightController(opts);
this._sumanager = new StateUpdateManager(this._state);
}
// overwrite to make use of the SUManager
get state() {
return this._sumanager.state.clone();
}
get effects() {
return [
{name: "Disco Mode", id: "disco"}
];
}
turnOn() {
let futureState = this.state;
futureState.on = true;
let suid = this._sumanager.registerUpdate(futureState);
this._light.sendCommands(commands2.rgbw.on(this._zone));
return this._light.close().then(() => {
this._sumanager.confirmUpdate(suid);
if (this._sumanager.highestConfirmedId == suid) {
this.emit("state change", this.state);
}
}).catch(err => {
this._sumanager.rejectUpdate(suid);
throw err;
});
}
turnOff() {
let futureState = this.state;
futureState.on = false;
let suid = this._sumanager.registerUpdate(futureState);
this._light.sendCommands(commands2.rgbw.off(this._zone));
return this._light.close().then(() => {
this._sumanager.confirmUpdate(suid);
if (this._sumanager.highestConfirmedId == suid) {
this.emit("state change", this.state);
}
}).catch(err => {
this._sumanager.rejectUpdate(suid);
throw err;
});
}
setBrightness(brightness) {
let futureState = this.state;
futureState.brightness = brightness;
let suid = this._sumanager.registerUpdate(futureState);
this._light.sendCommands(
commands2.rgbw.on(this._zone),
commands2.rgbw.brightness(brightness)
);
return this._light.close().then(() => {
this._sumanager.confirmUpdate(suid);
if (this._sumanager.highestConfirmedId == suid) {
this.emit("state change", this.state);
}
}).catch(err => {
this._sumanager.rejectUpdate(suid);
throw err;
});
}
setColor(color) {
let futureState = this.state;
futureState.color = fillPartialHSL(color, futureState.color);
futureState.effect = 'none';
let suid = this._sumanager.registerUpdate(futureState);
if (futureState.color.sat < 60) {
this._light.sendCommands(
commands2.rgbw.on(this._zone),
commands2.rgbw.whiteMode(this._zone)
);
} else {
let hue = Math.round(convertHue(futureState.color.hue) * (255/360));
this._light.sendCommands(
commands2.rgbw.on(this._zone),
commands2.rgbw.hue(hue)
);
}
return this._light.close().then(() => {
this._sumanager.confirmUpdate(suid);
if (this._sumanager.highestConfirmedId == suid) {
this.emit("state change", this.state);
}
}).catch(err => {
this._sumanager.rejectUpdate(suid);
throw err;
});
}
setEffect(id) {
let futureState = this.state;
if (id == 'none') {
if (futureState.color.sat < 60) {
this._light.sendCommands(
commands2.rgbw.on(this._zone),
commands2.rgbw.whiteMode(this._zone)
);
} else {
let hue = Math.round(convertHue(futureState.color.hue) * (255/360));
this._light.sendCommands(
commands2.rgbw.on(this._zone),
commands2.rgbw.hue(hue)
);
}
futureState.effect = "none";
} else if (id == 'disco') {
this._light.sendCommands(
commands2.rgbw.on(this._zone),
commands2.rgbw.effectModeNext()
);
futureState.effect = 'disco';
} else {
return Promise.reject(new Error("Invalid effect id"));
}
let suid = this._sumanager.registerUpdate(futureState);
return this._light.close().then(() => {
this._sumanager.confirmUpdate(suid);
if (this._sumanager.highestConfirmedId == suid) {
this.emit("state change", this.state);
}
}).catch(err => {
this._sumanager.rejectUpdate(suid);
throw err;
});
}
}
module.exports = HCmilight;
//the milight hue values are fucking stupid
function convertHue(hue) {
if(hue < 240) {
return 240 - hue;
} else {
return 600 - hue;
}
}
function fillPartialHSL(newcolor, oldcolor) {
if(newcolor.sat != undefined && newcolor.l == undefined) {
newcolor.l = (newcolor.sat > 50) ? 50 : 100 - newcolor.sat;
}
//console.log(newcolor, oldcolor);
let 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;
}