added support for addressable strips and subsections of addressable strips
This commit is contained in:
parent
1f5203e7d4
commit
ab070e5e48
102
HCMHAddressableSubsection.js
Normal file
102
HCMHAddressableSubsection.js
Normal file
@ -0,0 +1,102 @@
|
||||
const {
|
||||
HCColorLamp,
|
||||
StateUpdateManager,
|
||||
utils,
|
||||
} = require('homecontrol-control-base');
|
||||
|
||||
class HCMHAddressableSubsection extends HCColorLamp {
|
||||
constructor(config, registry) {
|
||||
super(config);
|
||||
|
||||
if (!("parent" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "parent" is missing"`);
|
||||
}
|
||||
if (!("section_id" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "section_id" is missing"`);
|
||||
}
|
||||
if (!("section_start" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "section_start" is missing"`);
|
||||
}
|
||||
if (!("section_end" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "section_end" is missing"`);
|
||||
}
|
||||
|
||||
this._registry = registry;
|
||||
this._parent = null;
|
||||
|
||||
// the default state should be white and 100% brightness
|
||||
this._state.brightness = 100;
|
||||
this._state.color.l = 100;
|
||||
}
|
||||
|
||||
async init() {
|
||||
for (let i = 0; i < 20; i++) {
|
||||
if (this._configuration.parent in this._registry) {
|
||||
this._parent = this._registry[this._configuration.parent];
|
||||
|
||||
this._parent.on("state change", state => {
|
||||
this.pullState();
|
||||
});
|
||||
|
||||
return;
|
||||
} else {
|
||||
await utils.asyncTimeout(100);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Could not connect to parent after 2 seconds");
|
||||
}
|
||||
|
||||
turnOn() {
|
||||
let { red, green, blue } = utils.HSL_to_RGB(this.state.color);
|
||||
|
||||
red = Math.round(red * this.state.brightness / 100);
|
||||
green = Math.round(green * this.state.brightness / 100);
|
||||
blue = Math.round(blue * this.state.brightness / 100);
|
||||
|
||||
this._state.on = true;
|
||||
this.emit("state change", this.state);
|
||||
|
||||
return this._parent.setSubsectionColor(
|
||||
this._configuration.section_start,
|
||||
this._configuration.section_end,
|
||||
this._configuration.section_id,
|
||||
{ red, green, blue }
|
||||
);
|
||||
}
|
||||
|
||||
turnOff() {
|
||||
this._state.on = false;
|
||||
this.emit("state change", this.state);
|
||||
return this._parent.removeSubsection(this._configuration.section_id);
|
||||
}
|
||||
|
||||
setColor(color) {
|
||||
this._state.color = utils.fillPartialHSL(color, this._state.color);
|
||||
|
||||
return this.turnOn();
|
||||
}
|
||||
|
||||
setBrightness(brightness) {
|
||||
this._state.brightness = brightness;
|
||||
|
||||
return this.turnOn();
|
||||
}
|
||||
|
||||
pullState() {
|
||||
if (this._parent == null) return Promise.resolve();
|
||||
|
||||
const futureState = this.state;
|
||||
|
||||
futureState.on = this._parent.isSubsectionActive(this._configuration.section_id);
|
||||
|
||||
if (this.state.hash != futureState.hash) {
|
||||
this._state = futureState;
|
||||
this.emit("state change", futureState);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HCMHAddressableSubsection;
|
||||
@ -1,6 +1,7 @@
|
||||
const {
|
||||
HCColorLamp,
|
||||
StateUpdateManager
|
||||
StateUpdateManager,
|
||||
utils,
|
||||
} = require('homecontrol-control-base');
|
||||
|
||||
const { Control } = require('magic-home');
|
||||
@ -103,7 +104,7 @@ class HCMagicHome extends HCColorLamp {
|
||||
futureState.effect = "none";
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let { red, green, blue } = HSL_to_RGB(futureState.color);
|
||||
let { red, green, blue } = utils.HSL_to_RGB(futureState.color);
|
||||
|
||||
return this._control.setColorWithBrightness(red, green, blue, futureState.brightness).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
@ -124,7 +125,7 @@ class HCMagicHome extends HCColorLamp {
|
||||
futureState.effect = "none";
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let { red, green, blue } = HSL_to_RGB(futureState.color);
|
||||
let { red, green, blue } = utils.HSL_to_RGB(futureState.color);
|
||||
|
||||
return this._control.setColorWithBrightness(red, green, blue, futureState.brightness).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
@ -166,7 +167,7 @@ class HCMagicHome extends HCColorLamp {
|
||||
if(effect == 'none') {
|
||||
futureState.effect = "none";
|
||||
|
||||
let { red, green, blue } = HSL_to_RGB(futureState.color);
|
||||
let { red, green, blue } = utils.HSL_to_RGB(futureState.color);
|
||||
|
||||
promise = this._control.setColorWithBrightness(red, green, blue, futureState.brightness);
|
||||
} else {
|
||||
@ -209,7 +210,7 @@ class HCMagicHome extends HCColorLamp {
|
||||
|
||||
if (futureState.effect == 'none') { // only update color when no effects are playing
|
||||
futureState.brightness = extractBrightness(status.color);
|
||||
futureState.color = RGB_to_HSL(removeBrightness(status.color));
|
||||
futureState.color = utils.RGB_to_HSL(removeBrightness(status.color));
|
||||
}
|
||||
|
||||
if (currentState.hash != futureState.hash) {
|
||||
@ -223,71 +224,6 @@ class HCMagicHome extends HCColorLamp {
|
||||
|
||||
module.exports = HCMagicHome;
|
||||
|
||||
function HSL_to_RGB(hsl) {
|
||||
let h = hsl.hue / 360;
|
||||
let s = hsl.sat / 100;
|
||||
let l = hsl.l / 100;
|
||||
|
||||
let r, g, b;
|
||||
|
||||
if (s == 0) {
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
var p = 2 * l - q;
|
||||
|
||||
r = hue2rgb(p, q, h + 1/3);
|
||||
g = hue2rgb(p, q, h);
|
||||
b = hue2rgb(p, q, h - 1/3);
|
||||
}
|
||||
|
||||
return {
|
||||
red: Math.round(r * 255),
|
||||
green: Math.round(g * 255),
|
||||
blue: Math.round(b * 255)
|
||||
};
|
||||
}
|
||||
|
||||
function hue2rgb(p, q, t) {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1/6) return p + (q - p) * 6 * t;
|
||||
if (t < 1/2) return q;
|
||||
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
||||
return p;
|
||||
}
|
||||
|
||||
function RGB_to_HSL(rgb) {
|
||||
let r = rgb.red / 255;
|
||||
let g = rgb.green / 255;
|
||||
let b = rgb.blue / 255;
|
||||
|
||||
let max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||
|
||||
if (max == min || max - min < 0.01) {
|
||||
h = s = 0; // achromatic
|
||||
} else {
|
||||
var d = max - min;
|
||||
s = d / (2 - max - min);
|
||||
|
||||
switch (max) {
|
||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||
case g: h = (b - r) / d + 2; break;
|
||||
case b: h = (r - g) / d + 4; break;
|
||||
}
|
||||
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
let l = 1 - 0.5 * s;
|
||||
|
||||
return {
|
||||
hue: Math.round(h * 360),
|
||||
sat: Math.round(s * 100),
|
||||
l: Math.round(l * 100)
|
||||
};
|
||||
}
|
||||
|
||||
function extractBrightness(rgb) {
|
||||
let max = Math.max(rgb.red, rgb.green, rgb.blue);
|
||||
return (max / 255) * 100;
|
||||
|
||||
334
HCMagicHomeAddressable.js
Normal file
334
HCMagicHomeAddressable.js
Normal file
@ -0,0 +1,334 @@
|
||||
const {
|
||||
HCColorLamp,
|
||||
StateUpdateManager,
|
||||
utils,
|
||||
} = require('homecontrol-control-base');
|
||||
|
||||
const { ControlAddressable, AddressableColorStopMode } = require('magic-home');
|
||||
|
||||
const RBM_EFFECTS = new Array(100).fill(null).map((_,i) => {
|
||||
return { name: `Random Effect ${i}`, id: `rbm-${i}` };
|
||||
});
|
||||
|
||||
class HCMagicHomeAddressable extends HCColorLamp {
|
||||
constructor(config, registry) {
|
||||
super(config);
|
||||
|
||||
if (!("address" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "address" is missing"`);
|
||||
}
|
||||
if (!("strip_length" in this._configuration)) {
|
||||
throw new Error(`Required configuration field "strip_length" is missing"`);
|
||||
}
|
||||
|
||||
const opts = {
|
||||
log_all_received: (this._configuration.logall !== undefined) ? this._configuration.logall : false,
|
||||
connect_timeout: (this._configuration.connect_timeout !== undefined) ? this._configuration.connect_timeout : 10000,
|
||||
command_timeout: (this._configuration.command_timeout !== undefined) ? this._configuration.command_timeout : 5000,
|
||||
};
|
||||
|
||||
this._control = new ControlAddressable(this._configuration.address, opts);
|
||||
|
||||
this._sumanager = new StateUpdateManager(this._state);
|
||||
this._registry = registry;
|
||||
|
||||
if ("registry_key" in this._configuration) {
|
||||
this._registry[this._configuration.registry_key] = this;
|
||||
}
|
||||
|
||||
this._subsections = [];
|
||||
|
||||
this._initialUpdate = true;
|
||||
}
|
||||
|
||||
async deinit() {
|
||||
if ("registry_key" in this._configuration) {
|
||||
delete this._registry[this._configuration.registry_key];
|
||||
}
|
||||
}
|
||||
|
||||
static get version() {
|
||||
return require("./package.json").version;
|
||||
}
|
||||
|
||||
// overwrite to make use of the SUManager
|
||||
get state() {
|
||||
return this._sumanager.state.clone();
|
||||
}
|
||||
|
||||
get effects() {
|
||||
return [
|
||||
{ name: "Subsection Color Mode", id: "subsections" },
|
||||
...RBM_EFFECTS,
|
||||
];
|
||||
}
|
||||
|
||||
_createSubsectionMode() {
|
||||
const currentState = this.state;
|
||||
const mode = new AddressableColorStopMode(this._configuration.strip_length);
|
||||
|
||||
let { red: bgRed, green: bgGreen, blue: bgBlue } = utils.HSL_to_RGB(currentState.color);
|
||||
|
||||
bgRed = Math.round(bgRed * currentState.brightness / 100);
|
||||
bgGreen = Math.round(bgGreen * currentState.brightness / 100);
|
||||
bgBlue = Math.round(bgBlue * currentState.brightness / 100);
|
||||
|
||||
mode.addColorStop(0, bgRed, bgGreen, bgBlue);
|
||||
|
||||
for (let i = 0; i < this._subsections.length; i++) {
|
||||
const ss = this._subsections[i];
|
||||
|
||||
if (ss.start >= this._configuration.strip_length) {
|
||||
break;
|
||||
}
|
||||
|
||||
mode.addColorStop(ss.start, ss.color.red, ss.color.green, ss.color.blue);
|
||||
|
||||
if (i < this._subsections.length - 1) {
|
||||
if (this._subsections[i+1].start > ss.end && ss.end < this._configuration.strip_length) {
|
||||
mode.addColorStop(ss.end, bgRed, bgGreen, bgBlue);
|
||||
}
|
||||
} else {
|
||||
if (ss.end < this._configuration.strip_length) {
|
||||
mode.addColorStop(ss.end, bgRed, bgGreen, bgBlue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
turnOn() {
|
||||
let futureState = this.state;
|
||||
futureState.on = true;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
return this._control.setPower(true).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
}).catch(err => {
|
||||
this._sumanager.rejectUpdate(suid);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
turnOff() {
|
||||
let futureState = this.state;
|
||||
futureState.on = false;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
return this._control.setPower(false).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
}).catch(err => {
|
||||
this._sumanager.rejectUpdate(suid);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
// color = {red, green, blue}
|
||||
setSubsectionColor(start, end, ssid, color) {
|
||||
this._subsections = this._subsections.filter(ss => ss.id != ssid);
|
||||
|
||||
this._subsections.push({ start, end, id: ssid, color });
|
||||
|
||||
this._subsections.sort((a,b) => a.start - b.start);
|
||||
|
||||
return this.setEffect("subsections");
|
||||
}
|
||||
|
||||
removeSubsection(ssid) {
|
||||
this._subsections = this._subsections.filter(ss => ss.id != ssid);
|
||||
|
||||
if (this._subsections.length > 0) {
|
||||
return this.setEffect("subsections");
|
||||
} else {
|
||||
return this.setEffect("none");
|
||||
}
|
||||
}
|
||||
|
||||
isSubsectionActive(ssid) {
|
||||
return this.state.on && this.state.effect === "subsections" && this._subsections.find(ss => ss.id === ssid) !== null;
|
||||
}
|
||||
|
||||
setBrightness(brightness) {
|
||||
let futureState = this.state;
|
||||
futureState.brightness = brightness;
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let promise;
|
||||
|
||||
if (!["none", "subsections"].includes(futureState.effect)) {
|
||||
promise = this.setEffect(futureState.effect);
|
||||
} else {
|
||||
promise = this.setColor(futureState.color);
|
||||
}
|
||||
|
||||
return promise.then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
}).catch(err => {
|
||||
this._sumanager.rejectUpdate(suid);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
setColor(color) {
|
||||
const futureState = this.state;
|
||||
futureState.color = utils.fillPartialHSL(color, futureState.color);
|
||||
futureState.on = true; // setting color turns on the controller
|
||||
|
||||
let { red, green, blue } = utils.HSL_to_RGB(futureState.color);
|
||||
|
||||
red = Math.round(red * futureState.brightness / 100);
|
||||
green = Math.round(green * futureState.brightness / 100);
|
||||
blue = Math.round(blue * futureState.brightness / 100);
|
||||
|
||||
let promise;
|
||||
|
||||
if (futureState.effect !== "subsections") {
|
||||
futureState.effect = "none";
|
||||
const suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
promise = this._control.setFixedMode({
|
||||
effect: 1,
|
||||
foreground: { red, green, blue }
|
||||
}).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
});
|
||||
} else {
|
||||
const suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
const mode = this._createSubsectionMode();
|
||||
|
||||
return this._control.setMultiColorMode(mode).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
});
|
||||
}
|
||||
|
||||
return promise.catch(err => {
|
||||
this._sumanager.rejectUpdate(suid);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
setEffect(id) {
|
||||
let futureState = this.state;
|
||||
futureState.effect = id;
|
||||
|
||||
let suid = this._sumanager.registerUpdate(futureState);
|
||||
|
||||
let promise = this.turnOn();
|
||||
|
||||
if (futureState.effect == "none" || futureState.effect == "subsections") {
|
||||
promise = this.setColor(futureState.color).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
})
|
||||
} else {
|
||||
const rbmMatch = id.match(/rbm\-(\d+)/);
|
||||
|
||||
if (rbmMatch === null) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
const rbmMode = Number(rbmMatch[1]);
|
||||
|
||||
promise = this._control.setRbmMode(rbmMode, futureState.brightness, 100).then(success => {
|
||||
this._sumanager.confirmUpdate(suid);
|
||||
|
||||
if (this._sumanager.highestConfirmedId == suid) {
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
return success;
|
||||
});
|
||||
}
|
||||
|
||||
return promise.catch(err => {
|
||||
this._sumanager.rejectUpdate(suid);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
pullState() {
|
||||
return this._control.queryState().then(status => {
|
||||
let currentState = this.state;
|
||||
let futureState = currentState.clone();
|
||||
|
||||
// console.log(status);
|
||||
|
||||
futureState.on = status.on;
|
||||
|
||||
// let effect = (status.mode != 'color' && status.mode != 'warm_white' && status.mode != 'special') ? status.mode : 'none';
|
||||
// if(effect != 'none') {
|
||||
// let speed = (status.speed > 80) ? 'fast' : (status.speed > 30) ? 'medium' : 'slow';
|
||||
// futureState.effect = speed + '-' + effect;
|
||||
// } else {
|
||||
// futureState.effect = 'none';
|
||||
// }
|
||||
|
||||
if (status.mode == "fixed" || this._initialUpdate) { // only update color when no effects are playing
|
||||
futureState.brightness = extractBrightness(status.color);
|
||||
futureState.color = utils.RGB_to_HSL(removeBrightness(status.color));
|
||||
}
|
||||
|
||||
if (status.mode === "rbm") {
|
||||
futureState.effect = "rbm-" + status.effect;
|
||||
}
|
||||
|
||||
// console.log(futureState);
|
||||
|
||||
if (currentState.hash != futureState.hash) {
|
||||
// the state of the controller has changed externally
|
||||
this._sumanager.insertConfirmedState(futureState);
|
||||
this.emit("state change", this.state);
|
||||
}
|
||||
|
||||
this._initialUpdate = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HCMagicHomeAddressable;
|
||||
|
||||
function extractBrightness(rgb) {
|
||||
let max = Math.max(rgb.red, rgb.green, rgb.blue);
|
||||
return (max / 255) * 100;
|
||||
}
|
||||
|
||||
function removeBrightness(rgb) {
|
||||
let max = Math.max(rgb.red, rgb.green, rgb.blue);
|
||||
let scale = (max > 0) ? 255 / max : 0;
|
||||
|
||||
return {
|
||||
red: rgb.red * scale,
|
||||
green: rgb.green * scale,
|
||||
blue: rgb.blue * scale,
|
||||
};
|
||||
}
|
||||
38
README.md
38
README.md
@ -1,10 +1,42 @@
|
||||
## Configuration
|
||||
|
||||
- `ack`
|
||||
Bitmask to set `ack` in the constructor.
|
||||
All types:
|
||||
|
||||
- `type`
|
||||
Either `"normal"`, `"addressable"` or `"subsection"`
|
||||
|
||||
Type "normal" and "addressable":
|
||||
|
||||
- `logall`
|
||||
Sets `log_all_received` in the constructor.
|
||||
- `connect_timeout`
|
||||
Sets `connect_timeout` in the constructor. (Default: 10000)
|
||||
- `command_timeout`
|
||||
Sets `command_timeout` in the constructor. (Default: 5000)
|
||||
Sets `command_timeout` in the constructor. (Default: 5000)
|
||||
|
||||
Type "normal":
|
||||
|
||||
- `ack`
|
||||
Bitmask to set `ack` in the constructor.
|
||||
|
||||
Type "addressable":
|
||||
|
||||
- `strip_length`
|
||||
Number of segments on the strip. Required.
|
||||
|
||||
- `registry_key`
|
||||
Name to register this controller in the global registry as. Only required when this device is supposed to have subsections.
|
||||
|
||||
Type "subsection":
|
||||
|
||||
- `parent`
|
||||
Name of the parent device in the registry. Corresponds to a `registry_key`
|
||||
|
||||
- `section_id`
|
||||
Identifier of this section for the parent.
|
||||
|
||||
- `section_start`
|
||||
Which segment of the strip this subsection starts. May not be greater than `strip_length` of the parent.
|
||||
|
||||
- `section_end`
|
||||
Which segment of the strip this subsection ends. May not be greater than `strip_length` of the parent.
|
||||
|
||||
19
entry.js
Normal file
19
entry.js
Normal file
@ -0,0 +1,19 @@
|
||||
const HCMagicHome = require("./HCMagicHome");
|
||||
const HCMagicHomeAddressable = require("./HCMagicHomeAddressable");
|
||||
const HCMHAddressableSubsection = require("./HCMHAddressableSubsection");
|
||||
|
||||
const MagicHomeRegistry = {};
|
||||
|
||||
function proxy(opts) {
|
||||
switch(opts.type) {
|
||||
case "addressable":
|
||||
return new HCMagicHomeAddressable(opts, MagicHomeRegistry);
|
||||
case "subsection":
|
||||
return new HCMHAddressableSubsection(opts, MagicHomeRegistry);
|
||||
case "normal":
|
||||
default:
|
||||
return new HCMagicHome(opts);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = proxy;
|
||||
10
package-lock.json
generated
10
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hc-magichome",
|
||||
"version": "1.3.1",
|
||||
"version": "1.5.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -10,7 +10,7 @@
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"homecontrol-control-base": {
|
||||
"version": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git#304c97bdcf84b71168567046560d7777f09dceed",
|
||||
"version": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git#37eb940fbda9c423834ca3b0f6895753f446ed88",
|
||||
"from": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git",
|
||||
"requires": {
|
||||
"merge-options": "^1.0.1",
|
||||
@ -23,9 +23,9 @@
|
||||
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
|
||||
},
|
||||
"magic-home": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-home/-/magic-home-2.6.1.tgz",
|
||||
"integrity": "sha512-KU2msJWzOqqD4ofId99krddZpK3WcWAkGZ/2+VpIOYYRPKEatRvb/J5MfkXhK/MjDypPIaZh/CU5IxBCo5eKuA==",
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-home/-/magic-home-2.8.1.tgz",
|
||||
"integrity": "sha512-qKKkGcZs4utvTa3lw8mnbxPahhEmrFXAAm8MtjjENowM5ic6mOi3nqiplHSdMauvsXgt1VHa8/MCh/nfqMv3sQ==",
|
||||
"requires": {
|
||||
"commander": "^2.20.0",
|
||||
"merge-options": "^1.0.1"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "hc-magichome",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"description": "Magic Home Plugin for Homecontrol",
|
||||
"main": "HCMagicHome.js",
|
||||
"main": "entry.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
@ -14,6 +14,6 @@
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"homecontrol-control-base": "git+https://git.literalchaos.de/jan/homecontrol-control-base.git",
|
||||
"magic-home": "^2.6.1"
|
||||
"magic-home": "^2.8.1"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user