finished first version
This commit is contained in:
commit
1010d2e47f
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
207
HCmilight.js
Normal file
207
HCmilight.js
Normal file
@ -0,0 +1,207 @@
|
||||
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;
|
||||
}
|
||||
60
package-lock.json
generated
Normal file
60
package-lock.json
generated
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "hc-milight",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
|
||||
},
|
||||
"homecontrol-control-base": {
|
||||
"version": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git#b7ed807affe888d61efd9dbff3d55bcc128215b7",
|
||||
"requires": {
|
||||
"merge-options": "1.0.1",
|
||||
"node-object-hash": "1.4.2"
|
||||
}
|
||||
},
|
||||
"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.0"
|
||||
}
|
||||
},
|
||||
"node-milight-promise": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-milight-promise/-/node-milight-promise-0.3.2.tgz",
|
||||
"integrity": "sha512-AyWLXGQ8SIDkAhirSZe8kh1g1t5MJAaRBPNlWGxKuztYDCdtZID+IASamvQtGaWgb0FvGvVWs8aMXSP5Rx2a7Q==",
|
||||
"requires": {
|
||||
"bluebird": "3.5.3",
|
||||
"promise-retryer": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node-object-hash": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.4.2.tgz",
|
||||
"integrity": "sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ=="
|
||||
},
|
||||
"promise-object": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/promise-object/-/promise-object-0.1.7.tgz",
|
||||
"integrity": "sha1-MsQ6Fn38xq6NIKiu47GAc14yYQc="
|
||||
},
|
||||
"promise-retryer": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-retryer/-/promise-retryer-0.0.1.tgz",
|
||||
"integrity": "sha1-H8QiUAN++keClmKNmnOKynobIEk=",
|
||||
"requires": {
|
||||
"promise-object": "0.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "hc-milight",
|
||||
"version": "1.0.0",
|
||||
"description": "Homecontrol plugin for milight bulbs",
|
||||
"main": "HCmilight.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.literalchaos.de:jan/hc-milight.git"
|
||||
},
|
||||
"keywords": [
|
||||
"homecontrol-plugin"
|
||||
],
|
||||
"author": "Jan Scheiper",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"homecontrol-control-base": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git",
|
||||
"merge-options": "^1.0.1",
|
||||
"node-milight-promise": "^0.3.2"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user