- Adding ability to specify delay times per light - Adding config.schema.json
This commit is contained in:
parent
8fbfc51276
commit
feb5533419
119
config.schema.json
Normal file
119
config.schema.json
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
{
|
||||||
|
"pluginAlias": "Flux",
|
||||||
|
"pluginType": "platform",
|
||||||
|
"singular": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"ipAddress": {
|
||||||
|
"title": "IP Address",
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"userName": {
|
||||||
|
"title": "User Name",
|
||||||
|
"type": "string",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
"clientKey": {
|
||||||
|
"title": "Client Key",
|
||||||
|
"type": "string",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
"latitude": {
|
||||||
|
"title": "Latitude",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"longitude": {
|
||||||
|
"title": "Longitude",
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"hueLights": {
|
||||||
|
"title": "Hue Lights",
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true,
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"ip": {
|
||||||
|
"title": "Name",
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"cron": {
|
||||||
|
"title": "Poll Delay in MS",
|
||||||
|
"type": "string",
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"wizLights": {
|
||||||
|
"title": "Wiz Lights",
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true,
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"ip": {
|
||||||
|
"title": "Ip Address",
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"mac": {
|
||||||
|
"title": "Mac Address",
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"cron": {
|
||||||
|
"title": "Poll Delay in MS",
|
||||||
|
"type": "string",
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
"wizDiscoveryEnabled": {
|
||||||
|
"title": "Wiz Discovery Enabled",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"ceilingColorTemp": {
|
||||||
|
"title": "Ceiling Color Temperature",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"sunsetColorTemp": {
|
||||||
|
"title": "Sunset Color Temperature",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"floorColorTemp": {
|
||||||
|
"title": "Floor Color Temperature",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"sunsetDuration": {
|
||||||
|
"title": "Sunset Duration",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"transition": {
|
||||||
|
"title": "Transition Time",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"delay": {
|
||||||
|
"title": "Poll Delay in MS",
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"form": null,
|
||||||
|
"display": null
|
||||||
|
}
|
12
package-lock.json
generated
12
package-lock.json
generated
@ -119,9 +119,9 @@
|
|||||||
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ=="
|
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@watsonb8/wiz-lib": {
|
"node_modules/@watsonb8/wiz-lib": {
|
||||||
"version": "1.0.1-1c687.0",
|
"version": "1.0.1-9548b.0",
|
||||||
"resolved": "http://10.44.1.6:4873/@watsonb8%2fwiz-lib/-/wiz-lib-1.0.1-1c687.0.tgz",
|
"resolved": "http://10.44.1.6:4873/@watsonb8%2fwiz-lib/-/wiz-lib-1.0.1-9548b.0.tgz",
|
||||||
"integrity": "sha1-dag89Ke1YURYSIwyWkQM/lCbvPI=",
|
"integrity": "sha1-PL/Phi0KQ5DJGRspSHA+i1lprp4=",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dgram": "^1.0.1",
|
"dgram": "^1.0.1",
|
||||||
"getmac": "^5.20.0",
|
"getmac": "^5.20.0",
|
||||||
@ -1967,9 +1967,9 @@
|
|||||||
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ=="
|
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ=="
|
||||||
},
|
},
|
||||||
"@watsonb8/wiz-lib": {
|
"@watsonb8/wiz-lib": {
|
||||||
"version": "1.0.1-1c687.0",
|
"version": "1.0.1-9548b.0",
|
||||||
"resolved": "http://10.44.1.6:4873/@watsonb8%2fwiz-lib/-/wiz-lib-1.0.1-1c687.0.tgz",
|
"resolved": "http://10.44.1.6:4873/@watsonb8%2fwiz-lib/-/wiz-lib-1.0.1-9548b.0.tgz",
|
||||||
"integrity": "sha1-dag89Ke1YURYSIwyWkQM/lCbvPI=",
|
"integrity": "sha1-PL/Phi0KQ5DJGRspSHA+i1lprp4=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"dgram": "^1.0.1",
|
"dgram": "^1.0.1",
|
||||||
"getmac": "^5.20.0",
|
"getmac": "^5.20.0",
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin",
|
"bin",
|
||||||
"src"
|
"src",
|
||||||
|
"config.schema.json"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
@ -6,11 +6,12 @@ import { IConfig } from "./models/iConfig";
|
|||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
import { GetTimesResult, getTimes } from "suncalc";
|
import { GetTimesResult, getTimes } from "suncalc";
|
||||||
import HueError = require("node-hue-api/lib/HueError");
|
import HueError = require("node-hue-api/lib/HueError");
|
||||||
import cron from "node-cron";
|
import cron, { ScheduledTask } from "node-cron";
|
||||||
import { WizBulb } from "@watsonb8/wiz-lib/build/wizBulb";
|
import { WizBulb } from "@watsonb8/wiz-lib/build/wizBulb";
|
||||||
import { colorTemperature2rgb, RGB } from "@watsonb8/wiz-lib";
|
import { colorTemperature2rgb, RGB } from "@watsonb8/wiz-lib";
|
||||||
import { PlatformAccessory } from "homebridge";
|
import { PlatformAccessory } from "homebridge";
|
||||||
import { Platform } from "./platform";
|
import { Platform } from "./platform";
|
||||||
|
import { colorTempToRgb } from "./util/colorUtil";
|
||||||
|
|
||||||
const SECONDS_IN_DAY = 86400000;
|
const SECONDS_IN_DAY = 86400000;
|
||||||
const MINUTES_IN_MILLISECOND = 60000;
|
const MINUTES_IN_MILLISECOND = 60000;
|
||||||
@ -29,6 +30,9 @@ export class FluxAccessory {
|
|||||||
private readonly _accessory: PlatformAccessory;
|
private readonly _accessory: PlatformAccessory;
|
||||||
private _config: IConfig;
|
private _config: IConfig;
|
||||||
private _isActive: boolean;
|
private _isActive: boolean;
|
||||||
|
private _hueRGB: RGB;
|
||||||
|
private _wizRGB: RGB;
|
||||||
|
private _fade: number;
|
||||||
|
|
||||||
//Service fields
|
//Service fields
|
||||||
private _switchService;
|
private _switchService;
|
||||||
@ -39,6 +43,7 @@ export class FluxAccessory {
|
|||||||
private _wizLights: Array<WizBulb> = [];
|
private _wizLights: Array<WizBulb> = [];
|
||||||
|
|
||||||
private _times: GetTimesResult;
|
private _times: GetTimesResult;
|
||||||
|
private _tasks: Array<ScheduledTask> = [];
|
||||||
|
|
||||||
constructor(props: IFluxProps) {
|
constructor(props: IFluxProps) {
|
||||||
//Assign class variables
|
//Assign class variables
|
||||||
@ -47,6 +52,11 @@ export class FluxAccessory {
|
|||||||
this._config = props.config;
|
this._config = props.config;
|
||||||
this._isActive = false;
|
this._isActive = false;
|
||||||
this._wizLights = props.wizBulbs;
|
this._wizLights = props.wizBulbs;
|
||||||
|
this._hue = props.hue;
|
||||||
|
this.name = this._config.name;
|
||||||
|
this._hueRGB = { r: 0, g: 0, b: 0 };
|
||||||
|
this._wizRGB = { r: 0, g: 0, b: 0 };
|
||||||
|
this._fade = this._config.transition ?? 30000;
|
||||||
|
|
||||||
this._times = getTimes(
|
this._times = getTimes(
|
||||||
new Date(),
|
new Date(),
|
||||||
@ -70,8 +80,20 @@ export class FluxAccessory {
|
|||||||
}
|
}
|
||||||
).start();
|
).start();
|
||||||
|
|
||||||
this._hue = props.hue;
|
//Schedule job to refresh hues every minute
|
||||||
this.name = this._config.name;
|
this.updateRGB();
|
||||||
|
cron.schedule(
|
||||||
|
"* * * * *",
|
||||||
|
() => {
|
||||||
|
this.updateRGB();
|
||||||
|
this._platform.log.info("Updated hues");
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scheduled: true,
|
||||||
|
}
|
||||||
|
).start();
|
||||||
|
|
||||||
|
this.scheduleLights();
|
||||||
|
|
||||||
this._accessory
|
this._accessory
|
||||||
.getService(this._platform.api.hap.Service.AccessoryInformation)!
|
.getService(this._platform.api.hap.Service.AccessoryInformation)!
|
||||||
@ -126,9 +148,11 @@ export class FluxAccessory {
|
|||||||
this._config.latitude,
|
this._config.latitude,
|
||||||
this._config.longitude
|
this._config.longitude
|
||||||
);
|
);
|
||||||
this.update();
|
this._isActive = true;
|
||||||
|
this.enable();
|
||||||
} else {
|
} else {
|
||||||
this._isActive = false;
|
this._isActive = false;
|
||||||
|
this.disable();
|
||||||
}
|
}
|
||||||
return callback();
|
return callback();
|
||||||
};
|
};
|
||||||
@ -148,112 +172,19 @@ export class FluxAccessory {
|
|||||||
* Populates internal lights array using the configuration values
|
* Populates internal lights array using the configuration values
|
||||||
*/
|
*/
|
||||||
private getLights = async (): Promise<void> => {
|
private getLights = async (): Promise<void> => {
|
||||||
for (const value of this._config.lights) {
|
for (const value of this._config.hueLights) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const light: Light = await this._hue.lights.getLightByName(value);
|
const light: Light = await this._hue.lights.getLightByName(
|
||||||
|
value.name
|
||||||
|
);
|
||||||
this._lights.push(light);
|
this._lights.push(light);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private colorTempToRgb = (kelvin: number): RGB => {
|
|
||||||
var temp = kelvin / 100;
|
|
||||||
var red, green, blue;
|
|
||||||
if (temp <= 66) {
|
|
||||||
red = 255;
|
|
||||||
green = temp;
|
|
||||||
green = 99.4708025861 * Math.log(green) - 161.1195681661;
|
|
||||||
|
|
||||||
if (temp <= 19) {
|
|
||||||
blue = 0;
|
|
||||||
} else {
|
|
||||||
blue = temp - 10;
|
|
||||||
blue = 138.5177312231 * Math.log(blue) - 305.0447927307;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
red = temp - 60;
|
|
||||||
red = 329.698727446 * Math.pow(red, -0.1332047592);
|
|
||||||
|
|
||||||
green = temp - 60;
|
|
||||||
green = 288.1221695283 * Math.pow(green, -0.0755148492);
|
|
||||||
|
|
||||||
blue = 255;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
r: this.clamp(red, 0, 255),
|
|
||||||
g: this.clamp(green, 0, 255),
|
|
||||||
b: this.clamp(blue, 0, 255),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
private clamp(x: number, min: number, max: number) {
|
|
||||||
if (x < min) {
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
if (x > max) {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isHueError = (object: any): object is HueError => {
|
private isHueError = (object: any): object is HueError => {
|
||||||
return "_hueError" in object;
|
return "_hueError" in object;
|
||||||
};
|
};
|
||||||
|
|
||||||
private setHueLights = async (state: LightState) => {
|
|
||||||
const promises: Array<Promise<unknown> | PromiseLike<unknown>> = [];
|
|
||||||
this._lights.map(async (light: Light) => {
|
|
||||||
try {
|
|
||||||
await this._hue.lights.setLightState(light.id, state);
|
|
||||||
} catch (err) {
|
|
||||||
if (
|
|
||||||
this.isHueError(err) &&
|
|
||||||
err.message ===
|
|
||||||
"parameter, xy, is not modifiable. Device is set to off."
|
|
||||||
) {
|
|
||||||
//Eat this
|
|
||||||
} else {
|
|
||||||
this._platform.log.info(
|
|
||||||
`Error while setting lights: ${err}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
};
|
|
||||||
|
|
||||||
private setWizLights = async (rgb: RGB, fade: number): Promise<void> => {
|
|
||||||
await Promise.all(
|
|
||||||
this._wizLights.map(async (bulb) => {
|
|
||||||
const pilot = await bulb.get();
|
|
||||||
bulb.set(rgb, pilot?.dimming, fade);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to generate a UUID
|
|
||||||
*/
|
|
||||||
private generateUUID(): string {
|
|
||||||
// Public Domain/MIT
|
|
||||||
var d = new Date().getTime();
|
|
||||||
if (
|
|
||||||
typeof performance !== "undefined" &&
|
|
||||||
typeof performance.now === "function"
|
|
||||||
) {
|
|
||||||
d += performance.now(); //use high-precision timer if available
|
|
||||||
}
|
|
||||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
|
|
||||||
/[xy]/g,
|
|
||||||
function (c) {
|
|
||||||
var r = (d + Math.random() * 16) % 16 | 0;
|
|
||||||
d = Math.floor(d / 16);
|
|
||||||
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets adjusted color temperature.
|
* Gets adjusted color temperature.
|
||||||
*/
|
*/
|
||||||
@ -283,13 +214,7 @@ export class FluxAccessory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private update = async (): Promise<void> => {
|
private updateRGB = (): void => {
|
||||||
this._isActive = true;
|
|
||||||
while (this._isActive) {
|
|
||||||
if (this._lights.length === 0) {
|
|
||||||
await this.getLights();
|
|
||||||
}
|
|
||||||
|
|
||||||
const now = this.getNow();
|
const now = this.getNow();
|
||||||
//Pad start time by an hour before sunset
|
//Pad start time by an hour before sunset
|
||||||
const start = new Date(
|
const start = new Date(
|
||||||
@ -306,15 +231,9 @@ export class FluxAccessory {
|
|||||||
this._times.sunrise.getTime() + 1 * SECONDS_IN_DAY
|
this._times.sunrise.getTime() + 1 * SECONDS_IN_DAY
|
||||||
);
|
);
|
||||||
|
|
||||||
const startColorTemp = this._config.ceilingColorTemp
|
const startColorTemp = this._config.ceilingColorTemp ?? 4000;
|
||||||
? this._config.ceilingColorTemp
|
const sunsetColorTemp = this._config.sunsetColorTemp ?? 2800;
|
||||||
: 4000;
|
const floorColorTemp = this._config.floorColorTemp ?? 1900;
|
||||||
const sunsetColorTemp = this._config.sunsetColorTemp
|
|
||||||
? this._config.sunsetColorTemp
|
|
||||||
: 2800;
|
|
||||||
const floorColorTemp = this._config.floorColorTemp
|
|
||||||
? this._config.floorColorTemp
|
|
||||||
: 1900;
|
|
||||||
|
|
||||||
let newTemp = 0;
|
let newTemp = 0;
|
||||||
|
|
||||||
@ -338,29 +257,99 @@ export class FluxAccessory {
|
|||||||
newTemp = this._config.floorColorTemp;
|
newTemp = this._config.floorColorTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set lights
|
//Set RGB
|
||||||
const hueRGB = this.colorTempToRgb(newTemp);
|
this._hueRGB = colorTempToRgb(newTemp);
|
||||||
const wizRGB = colorTemperature2rgb(newTemp);
|
this._wizRGB = colorTemperature2rgb(newTemp);
|
||||||
if (hueRGB && newTemp !== 0) {
|
};
|
||||||
const lightState = new LightState();
|
|
||||||
lightState
|
private scheduleLights = async (): Promise<void> => {
|
||||||
.transitionInMillis(
|
if (this._lights.length === 0) {
|
||||||
this._config.transition ? this._config.transition : 5000
|
await this.getLights();
|
||||||
)
|
}
|
||||||
.rgb(hueRGB.r ?? 0, hueRGB.g ?? 0, hueRGB.b ?? 0);
|
this._tasks = [...this.getHueTasks(), ...this.getWizTasks()];
|
||||||
await this.setHueLights(lightState);
|
};
|
||||||
await this.setWizLights(
|
|
||||||
wizRGB,
|
private getHueTasks(): Array<ScheduledTask> {
|
||||||
this._config.transition ? this._config.transition / 1000 : 5
|
return this._config.hueLights.map((hueLightConfig) => {
|
||||||
);
|
let light = this._lights.find((x) => x.name == hueLightConfig.name);
|
||||||
|
let schedule: string = hueLightConfig.cron ?? "*/6 * * * *";
|
||||||
this._platform.log.info(
|
this._platform.log.info(
|
||||||
`Adjusting light temp to ${newTemp}, ${JSON.stringify(
|
`Scheduling task for ${light?.name}: ${schedule}`
|
||||||
hueRGB
|
|
||||||
)}`
|
|
||||||
);
|
);
|
||||||
|
return cron.schedule(
|
||||||
|
schedule,
|
||||||
|
async () => {
|
||||||
|
await this.updateHueLight(light);
|
||||||
|
this._platform.log.info("Updated hues");
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scheduled: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await Sleep(this._config.delay ? this._config.delay : 60000);
|
private getWizTasks(): Array<ScheduledTask> {
|
||||||
|
return this._wizLights.map((wizBulb) => {
|
||||||
|
let wizLightConfig = this._config.wizLights.find(
|
||||||
|
(x) => x.ip == wizBulb.getIp()
|
||||||
|
);
|
||||||
|
let schedule: string = wizLightConfig?.cron ?? "*/6 * * * *";
|
||||||
|
this._platform.log.info(
|
||||||
|
`Scheduling task for ${wizBulb.getMac()}: ${schedule}`
|
||||||
|
);
|
||||||
|
return cron.schedule(
|
||||||
|
schedule,
|
||||||
|
async () => {
|
||||||
|
await this.updateWizLight(wizBulb);
|
||||||
|
this._platform.log.info("Updated hues");
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scheduled: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateWizLight = async (wizBulb: WizBulb): Promise<void> => {
|
||||||
|
const pilot = await wizBulb.get();
|
||||||
|
this._platform.log.info(`Adjusting wiz bulb: ${wizBulb.getMac()}`);
|
||||||
|
wizBulb.set(this._wizRGB, pilot?.dimming, this._fade);
|
||||||
|
};
|
||||||
|
|
||||||
|
private updateHueLight = async (
|
||||||
|
hueLight: Light | undefined
|
||||||
|
): Promise<void> => {
|
||||||
|
if (!hueLight) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._platform.log.info(`Adjusting wiz bulb: ${hueLight.name}`);
|
||||||
|
|
||||||
|
const lightState = new LightState();
|
||||||
|
lightState
|
||||||
|
.transitionInMillis(this._fade)
|
||||||
|
.rgb(this._hueRGB.r ?? 0, this._hueRGB.g ?? 0, this._hueRGB.b ?? 0);
|
||||||
|
try {
|
||||||
|
await this._hue.lights.setLightState(hueLight.id, lightState);
|
||||||
|
} catch (err) {
|
||||||
|
if (
|
||||||
|
this.isHueError(err) &&
|
||||||
|
err.message ===
|
||||||
|
"parameter, xy, is not modifiable. Device is set to off."
|
||||||
|
) {
|
||||||
|
//Eat this
|
||||||
|
} else {
|
||||||
|
this._platform.log.info(`Error while setting lights: ${err}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private enable() {
|
||||||
|
this._tasks.forEach((task) => task.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
private disable() {
|
||||||
|
this._tasks.forEach((task) => task.stop());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,14 @@ export interface IConfig {
|
|||||||
/**
|
/**
|
||||||
* The list of lights to affect
|
* The list of lights to affect
|
||||||
*/
|
*/
|
||||||
lights: Array<string>;
|
hueLights: Array<{ name: string; cron?: string }>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of wiz lights to affect
|
||||||
|
*/
|
||||||
|
wizLights: Array<{ ip: string; mac: string; cron?: string }>;
|
||||||
|
|
||||||
|
wizDiscoveryEnabled: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the enable switch in homekit
|
* The name of the enable switch in homekit
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import discover from "@watsonb8/wiz-lib/build/discovery";
|
import { Discover } from "@watsonb8/wiz-lib/build/discovery";
|
||||||
|
import { WizBulb } from "@watsonb8/wiz-lib/build/wizBulb";
|
||||||
import {
|
import {
|
||||||
API,
|
API,
|
||||||
Characteristic,
|
Characteristic,
|
||||||
@ -19,6 +20,7 @@ import { Sleep } from "./sleep";
|
|||||||
|
|
||||||
export class Platform implements DynamicPlatformPlugin {
|
export class Platform implements DynamicPlatformPlugin {
|
||||||
private hue: Api | undefined;
|
private hue: Api | undefined;
|
||||||
|
private wiz: Discover;
|
||||||
private accessory: PlatformAccessory | undefined = undefined;
|
private accessory: PlatformAccessory | undefined = undefined;
|
||||||
private config: IConfig;
|
private config: IConfig;
|
||||||
constructor(
|
constructor(
|
||||||
@ -27,6 +29,7 @@ export class Platform implements DynamicPlatformPlugin {
|
|||||||
public readonly api: API
|
public readonly api: API
|
||||||
) {
|
) {
|
||||||
this.config = config as unknown as IConfig;
|
this.config = config as unknown as IConfig;
|
||||||
|
this.wiz = new Discover();
|
||||||
this.log.info("INFO - Registering Flux platform");
|
this.log.info("INFO - Registering Flux platform");
|
||||||
this.api.on("didFinishLaunching", this.didFinishLaunching.bind(this));
|
this.api.on("didFinishLaunching", this.didFinishLaunching.bind(this));
|
||||||
}
|
}
|
||||||
@ -77,7 +80,26 @@ export class Platform implements DynamicPlatformPlugin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await discover();
|
let bulbs: Array<WizBulb> = await this.wiz.createWizBulbs(
|
||||||
|
this.config.wizLights
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.config.wizDiscoveryEnabled) {
|
||||||
|
let discoveredBulbs: Array<WizBulb> = await this.wiz.discover();
|
||||||
|
let filtered = [];
|
||||||
|
for (const bulb of discoveredBulbs) {
|
||||||
|
if (
|
||||||
|
!bulbs.some(
|
||||||
|
(manualBulb) => manualBulb.getIp() === bulb.getIp()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
filtered.push(bulb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bulbs.push(...filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bulbs;
|
||||||
};
|
};
|
||||||
|
|
||||||
private connectHue = async () => {
|
private connectHue = async () => {
|
||||||
|
41
src/util/colorUtil.ts
Normal file
41
src/util/colorUtil.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { RGB } from "@watsonb8/wiz-lib";
|
||||||
|
|
||||||
|
export const colorTempToRgb = (kelvin: number): RGB => {
|
||||||
|
var temp = kelvin / 100;
|
||||||
|
var red, green, blue;
|
||||||
|
if (temp <= 66) {
|
||||||
|
red = 255;
|
||||||
|
green = temp;
|
||||||
|
green = 99.4708025861 * Math.log(green) - 161.1195681661;
|
||||||
|
|
||||||
|
if (temp <= 19) {
|
||||||
|
blue = 0;
|
||||||
|
} else {
|
||||||
|
blue = temp - 10;
|
||||||
|
blue = 138.5177312231 * Math.log(blue) - 305.0447927307;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
red = temp - 60;
|
||||||
|
red = 329.698727446 * Math.pow(red, -0.1332047592);
|
||||||
|
|
||||||
|
green = temp - 60;
|
||||||
|
green = 288.1221695283 * Math.pow(green, -0.0755148492);
|
||||||
|
|
||||||
|
blue = 255;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
r: clamp(red, 0, 255),
|
||||||
|
g: clamp(green, 0, 255),
|
||||||
|
b: clamp(blue, 0, 255),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const clamp = (x: number, min: number, max: number) => {
|
||||||
|
if (x < min) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
if (x > max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user