added some effects and fixed a lot of bugs

This commit is contained in:
Jan Scheiper 2020-02-20 22:58:51 +01:00
parent 5c614646b5
commit 07646b952a
2 changed files with 216 additions and 21 deletions

View File

@ -7,6 +7,56 @@ const {
const axios = require('axios'); const axios = require('axios');
const { URL } = require('url'); const { URL } = require('url');
class ColorJumpEffect {
constructor(colors, delay, sendCommand) {
this._colors = colors;
this._delay = delay;
this._next = 0;
this.sendCommand = sendCommand;
}
get delay() {
return this._delay;
}
step() {
let color = this._colors[this._next];
let cmd = `Color ${color[0]},${color[1]},${color[2]}`;
this._next = (this._next + 1) % this._colors.length;
// console.log(cmd);
return this.sendCommand(cmd);
}
init() {
return Promise.resolve();
}
deinit() {
return Promise.resolve();
}
}
class SchemeEffect {
constructor(scheme, speed, sendCommand) {
this._scheme = scheme;
this._speed = speed;
this.sendCommand = sendCommand;
}
init() {
return this.sendCommand(`Backlog Speed ${this._speed}; Scheme ${this._scheme}`);
}
deinit() {
return this.sendCommand(`Scheme 0`);
}
}
class HCTasmota extends HCColorLamp { class HCTasmota extends HCColorLamp {
constructor(config) { constructor(config) {
super(config); super(config);
@ -16,6 +66,9 @@ class HCTasmota extends HCColorLamp {
} }
this._sumanager = new StateUpdateManager(this._state); this._sumanager = new StateUpdateManager(this._state);
this._effectInterval = null;
this._effect = null;
} }
// overwrite to make use of the SUManager // overwrite to make use of the SUManager
@ -23,52 +76,176 @@ class HCTasmota extends HCColorLamp {
return this._sumanager.state.clone(); return this._sumanager.state.clone();
} }
get effects() {
return [
{ name: "Color Jump 3 SLOW", id: "jump3-slow" },
{ name: "Color Jump 3 FAST", id: "jump3-fast" },
{ name: "Color Cycle Up SLOW", id: "scheme-2-slow" },
{ name: "Color Cycle Up FAST", id: "scheme-2-fast" },
{ name: "Color Cycle Down SLOW", id: "scheme-3-slow" },
{ name: "Color Cycle Down FAST", id: "scheme-3-fast" },
{ name: "Color Cycle Random SLOW", id: "scheme-4-slow" },
{ name: "Color Cycle Random FAST", id: "scheme-4-fast" },
];
}
_sendCommand(cmd) {
let url = new URL("/cm", this._configuration.address);
url.searchParams.append("cmnd", cmd);
return axios.post(url.toString());
}
init() {
return this._sendCommand("State").then(res => {
if (res.data.Scheme != 0) {
return this._sendCommand("Scheme 0");
}
});
}
turnOn() { turnOn() {
if (this.state.effect != "none") {
return this.setEffect("none").then(() => this.turnOn());
}
let futureState = this.state; let futureState = this.state;
futureState.on = true; futureState.on = true;
let suid = this._sumanager.registerUpdate(futureState); let suid = this._sumanager.registerUpdate(futureState);
let url = new URL("/cm", this._configuration.address); return this._sendCommand("Power on").then(resolveHelper(this, suid), rejectHelper(this, suid));
url.searchParams.append("cmnd", "Power on");
return axios.post(url.toString()).then(resolveHelper(this, suid), rejectHelper(this, suid));
} }
turnOff() { turnOff() {
if (this.state.effect != "none") {
return this.setEffect("none").then(() => this.turnOff());
}
let futureState = this.state; let futureState = this.state;
futureState.on = false; futureState.on = false;
let suid = this._sumanager.registerUpdate(futureState); let suid = this._sumanager.registerUpdate(futureState);
let url = new URL("/cm", this._configuration.address); return this._sendCommand("Power off").then(resolveHelper(this, suid), rejectHelper(this, suid));
url.searchParams.append("cmnd", "Power off");
return axios.post(url.toString()).then(resolveHelper(this, suid), rejectHelper(this, suid));
} }
setBrightness(brightness) { setBrightness(brightness) {
if (this.state.effect != "none") {
return this.setEffect("none").then(() => this.setBrightness(brightness));
}
let futureState = this.state; let futureState = this.state;
futureState.brightness = brightness; futureState.brightness = Math.round(brightness);
futureState.on = true;
let suid = this._sumanager.registerUpdate(futureState); let suid = this._sumanager.registerUpdate(futureState);
let url = new URL("/cm", this._configuration.address); return this._sendCommand(`HsbColor3 ${futureState.brightness}`).then(resolveHelper(this, suid), rejectHelper(this, suid));
url.searchParams.append("cmnd", `HsbColor3 ${Math.round(brightness)}`);
return axios.post(url.toString()).then(resolveHelper(this, suid), rejectHelper(this, suid));
} }
setColor(color) { setColor(color) {
if (this.state.effect != "none") {
return this.setEffect("none").then(() => this.setColor(color));
}
let futureState = this.state; let futureState = this.state;
futureState.on = true;
futureState.color = utils.fillPartialHSL(color, futureState.color); futureState.color = utils.fillPartialHSL(color, futureState.color);
futureState.color.hue = Math.round(futureState.color.hue);
futureState.color.sat = Math.round(futureState.color.sat);
futureState.color.l = Math.round(futureState.color.l);
let suid = this._sumanager.registerUpdate(futureState); let suid = this._sumanager.registerUpdate(futureState);
let url = new URL("/cm", this._configuration.address); let url = new URL("/cm", this._configuration.address);
url.searchParams.append("cmnd", `HsbColor ${Math.round(color.hue)},${Math.round(color.sat)},${futureState.brightness}`); url.searchParams.append("cmnd", `HsbColor ${futureState.color.hue},${futureState.color.sat},${futureState.brightness}`);
return axios.post(url.toString()).then(resolveHelper(this, suid), rejectHelper(this, suid)); return axios.post(url.toString()).then(resolveHelper(this, suid), rejectHelper(this, suid));
} }
setEffect(id) { setEffect(id) {
let futureState = this.state;
let promise;
if (this._effectInterval != null) {
clearTimeout(this._effectInterval);
}
if (this._effect != null) {
promise = this._effect.deinit();
} else {
promise = Promise.resolve();
}
if (id == "none") {
promise.then(() => {
this._effectInterval = null;
this._effect = null;
futureState.effect = "none";
let url = new URL("/cm", this._configuration.address);
url.searchParams.append("cmnd", `HsbColor ${Math.round(futureState.color.hue)},${Math.round(futureState.color.sat)},${futureState.brightness}`);
return axios.post(url.toString());
});
} else {
promise.then(() => {
switch(id) {
case "jump3-fast":
futureState.effect = id;
this._effect = new ColorJumpEffect([
[255, 0, 0],
[0, 255, 0],
[0, 0, 255],
], 200, this._sendCommand.bind(this));
return this._effect.init().then(() => {
return this._stepEffect();
});
case "jump3-slow":
futureState.effect = id;
this._effect = new ColorJumpEffect([
[255, 0, 0],
[0, 255, 0],
[0, 0, 255],
], 800, this._sendCommand.bind(this));
return this._effect.init().then(() => {
return this._stepEffect();
});
case "scheme-2-slow":
futureState.effect = id;
this._effect = new SchemeEffect(2, 30, this._sendCommand.bind(this));
return this._effect.init();
case "scheme-3-slow":
futureState.effect = id;
this._effect = new SchemeEffect(3, 30, this._sendCommand.bind(this));
return this._effect.init();
case "scheme-4-slow":
futureState.effect = id;
this._effect = new SchemeEffect(4, 30, this._sendCommand.bind(this));
return this._effect.init();
case "scheme-2-fast":
futureState.effect = id;
this._effect = new SchemeEffect(2, 1, this._sendCommand.bind(this));
return this._effect.init();
case "scheme-3-fast":
futureState.effect = id;
this._effect = new SchemeEffect(3, 1, this._sendCommand.bind(this));
return this._effect.init();
case "scheme-4-fast":
futureState.effect = id;
this._effect = new SchemeEffect(4, 1, this._sendCommand.bind(this));
return this._effect.init();
default:
return Promise.reject(new Error("Invalid effect id"));
}
});
}
let suid = this._sumanager.registerUpdate(futureState);
return promise.then(resolveHelper(this, suid), rejectHelper(this, suid));
} }
pullState() { pullState() {
@ -82,8 +259,16 @@ class HCTasmota extends HCColorLamp {
let { hsl, brightness } = parseHsbString(res.data.HSBColor); let { hsl, brightness } = parseHsbString(res.data.HSBColor);
futureState.on = res.data.POWER == "ON"; // only update color info if we're not currently changing it constantly with an effect
if (currentState.effect == "none") {
futureState.color = hsl; futureState.color = hsl;
if (res.data.Scheme != 0) {
this.sendCommand("Scheme 0");
}
}
futureState.on = res.data.POWER == "ON";
futureState.brightness = brightness; futureState.brightness = brightness;
if (currentState.hash != futureState.hash) { if (currentState.hash != futureState.hash) {
@ -96,6 +281,16 @@ class HCTasmota extends HCColorLamp {
} }
}); });
} }
_stepEffect() {
if (this._effect != null) {
return this._effect.step().then(() => {
this._effectInterval = setTimeout(() => this._stepEffect(), this._effect.delay);
});
} {
return Promise.resolve();
}
}
} }
module.exports = HCTasmota; module.exports = HCTasmota;

View File

@ -1,6 +1,6 @@
{ {
"name": "hc-tasmota", "name": "hc-tasmota",
"version": "1.0.1", "version": "1.1.0",
"description": "A plugin to support the communication with Tasmota devices via http", "description": "A plugin to support the communication with Tasmota devices via http",
"main": "HCTasmota.js", "main": "HCTasmota.js",
"scripts": { "scripts": {