Compare commits
No commits in common. "a1264913ecc85371b82ae1f41655ae8fe7076ab4" and "5c614646b563fc3a16bc073553563b3be1e6b31e" have entirely different histories.
a1264913ec
...
5c614646b5
254
HCTasmota.js
254
HCTasmota.js
@ -7,56 +7,6 @@ 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);
|
||||||
@ -65,10 +15,7 @@ class HCTasmota extends HCColorLamp {
|
|||||||
throw new Error(`Required configuration field "address" is missing"`);
|
throw new Error(`Required configuration field "address" is missing"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -76,187 +23,52 @@ 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" },
|
|
||||||
{ name: "Police", id: "police" },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
_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);
|
||||||
|
|
||||||
return this._sendCommand("Power on").then(resolveHelper(this, suid), rejectHelper(this, suid));
|
let url = new URL("/cm", this._configuration.address);
|
||||||
|
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);
|
||||||
|
|
||||||
return this._sendCommand("Power off").then(resolveHelper(this, suid), rejectHelper(this, suid));
|
let url = new URL("/cm", this._configuration.address);
|
||||||
|
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 = Math.round(brightness);
|
futureState.brightness = brightness;
|
||||||
futureState.on = true;
|
|
||||||
let suid = this._sumanager.registerUpdate(futureState);
|
|
||||||
|
|
||||||
return this._sendCommand(`HsbColor3 ${futureState.brightness}`).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
|
||||||
}
|
|
||||||
|
|
||||||
setColor(color) {
|
|
||||||
if (this.state.effect != "none") {
|
|
||||||
return this.setEffect("none").then(() => this.setColor(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
let futureState = this.state;
|
|
||||||
futureState.on = true;
|
|
||||||
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 ${futureState.color.hue},${futureState.color.sat},${futureState.brightness}`);
|
url.searchParams.append("cmnd", `HsbColor3 ${Math.round(brightness)}`);
|
||||||
|
|
||||||
|
return axios.post(url.toString()).then(resolveHelper(this, suid), rejectHelper(this, suid));
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(color) {
|
||||||
|
let futureState = this.state;
|
||||||
|
futureState.color = utils.fillPartialHSL(color, futureState.color);
|
||||||
|
let suid = this._sumanager.registerUpdate(futureState);
|
||||||
|
|
||||||
|
let url = new URL("/cm", this._configuration.address);
|
||||||
|
url.searchParams.append("cmnd", `HsbColor ${Math.round(color.hue)},${Math.round(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 "police":
|
|
||||||
futureState.effect = id;
|
|
||||||
this._effect = new ColorJumpEffect([
|
|
||||||
[255, 0, 0],
|
|
||||||
[0, 0, 255],
|
|
||||||
], 300, 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() {
|
||||||
@ -270,16 +82,8 @@ class HCTasmota extends HCColorLamp {
|
|||||||
|
|
||||||
let { hsl, brightness } = parseHsbString(res.data.HSBColor);
|
let { hsl, brightness } = parseHsbString(res.data.HSBColor);
|
||||||
|
|
||||||
// only update color info if we're not currently changing it constantly with an effect
|
|
||||||
if (currentState.effect == "none") {
|
|
||||||
futureState.color = hsl;
|
|
||||||
|
|
||||||
if (res.data.Scheme != 0) {
|
|
||||||
this.sendCommand("Scheme 0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
futureState.on = res.data.POWER == "ON";
|
futureState.on = res.data.POWER == "ON";
|
||||||
|
futureState.color = hsl;
|
||||||
futureState.brightness = brightness;
|
futureState.brightness = brightness;
|
||||||
|
|
||||||
if (currentState.hash != futureState.hash) {
|
if (currentState.hash != futureState.hash) {
|
||||||
@ -291,17 +95,7 @@ class HCTasmota extends HCColorLamp {
|
|||||||
throw new Error(`Got HTTP ${res.status}: ${res.data}`);
|
throw new Error(`Got HTTP ${res.status}: ${res.data}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_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;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hc-tasmota",
|
"name": "hc-tasmota",
|
||||||
"version": "1.1.0",
|
"version": "1.0.1",
|
||||||
"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": {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user