Skip to content

Commit

Permalink
Merge branch 'add_colors'
Browse files Browse the repository at this point in the history
* add_colors:
  update README.md
  Add possibility for Hue and Saturation
  • Loading branch information
Theo van Hoesel authored and Theo van Hoesel committed Dec 25, 2022
2 parents 05abf61 + 1cf9b77 commit 502e46b
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Unofficial [Homebridge](http://github.com/nfarina/homebridge) plugin for [Twinkl
Use Siri or HomeKit automation to:
- Turn lights on or off
- Change brightness
- Change the color

A simple command line tool is also included.

Expand All @@ -23,6 +24,7 @@ A simple command line tool is also included.
| Value | Default | Description |
|--------------------------------|---------------|-------------------------------------------------------------|
| allowBrightnessControl | true | Adds a brightness control instead of a simple on/off switch |
| allowColorControl | true | Adds a color picker/wheel to the brightness control slider |
| removeUnreachableDeviceMinutes | 0 | When to remove unreachable devices (0 meaning never) |

The options can be configured using the UI or manually in a config.json.
Expand All @@ -37,6 +39,7 @@ The options can be configured using the UI or manually in a config.json.
"platforms": [{
"platform": "Twinkly",
"allowBrightnessControl": true,
"allowColorControl": true,
"removeUnreachableDeviceMinutes": 0
}]
}
Expand All @@ -56,6 +59,7 @@ You'll need to find the IP address of each light using the Twinkly app. It might
| name | (required) | The name for light as it will appear in HomeKit |
| ip | (required) | The IP address of the lights. |
| allowBrightnessControl | true | Adds a brightness control instead of a simple on/off switch |
| allowColorControl | true | Adds a color picker/wheel to the brightness control slider |

The options can be configured using the UI or manually in a config.json.
Multiple lights are can be added as individual accessories.
Expand All @@ -72,6 +76,7 @@ Multiple lights are can be added as individual accessories.
"name": "Christmas Lights",
"ip": "192.168.4.1",
"allowBrightnessControl": true
"allowColorControl": true
}]
}
```
Expand Down
5 changes: 5 additions & 0 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
"type": "boolean",
"description": "Shows a brightness slider. Otherwise a simple on/off switch will be shown."
},
"allowColorControl": {
"title": "Allow color control",
"type": "boolean",
"description": "Shows a color controls."
},
"removeUnreachableDeviceMinutes": {
"title": "Remove unreachable devices after",
"type": "integer",
Expand Down
30 changes: 29 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ let hap, Service, Characteristic;
// "accessory": "Twinkly",
// "name": "Christmas Tree",
// "ip": "192.168.4.1",
// "allowBrightnessControl": true
// "allowBrightnessControl": true,
// "allowColorControl": true
// }]

class TwinklyHomebridge extends Twinkly {
Expand All @@ -30,6 +31,8 @@ class TwinklyHomebridge extends Twinkly {
this.name = name;
this.isBrightnessControlEnabled = config["allowBrightnessControl"];
if (this.isBrightnessControlEnabled === undefined) { this.isBrightnessControlEnabled = true; }
this.isColorControlEnabled = config["allowColorControl"];
if (this.isColorControlEnabled === undefined) { this.isColorControlEnabled = false; }
}

getServices() {
Expand All @@ -48,6 +51,15 @@ class TwinklyHomebridge extends Twinkly {
value => this.setBrightness(value));
}

if (this.isColorControlEnabled) {
this.registerCharacteristic(lightService, Characteristic.Hue,
() => this.getHue(),
value => this.setHue(value));
this.registerCharacteristic(lightService, Characteristic.Saturation,
() => this.getSaturation(),
value => this.setSaturation(value));
}

return [lightService, informationService];
}

Expand Down Expand Up @@ -79,6 +91,7 @@ function wrap(promise, callback, isSet = false) {
// "platforms": [{
// "platform": "Twinkly",
// "allowBrightnessControl": true,
// "allowColorControl": true,
// "removeUnreachableDeviceMinutes": false
// }]

Expand All @@ -89,6 +102,9 @@ class TwinklyPlatform {
this.isBrightnessControlEnabled = config["allowBrightnessControl"];
if (this.isBrightnessControlEnabled === undefined) { this.isBrightnessControlEnabled = true; }

this.isColorControlEnabled = config["allowColorControl"];
if (this.isColorControlEnabled === undefined) { this.isColorControlEnabled = true; }

this.verbose = config.verbose;
this.timeout = config.timeout || 1000;
this.scanInterval = config.scanInterval || 60_000;
Expand Down Expand Up @@ -212,6 +228,18 @@ class TwinklyPlatform {
device => device.getBrightness(),
(device, value) => device.setBrightness(value));
}

if (this.isColorControlEnabled) {
this.registerCharacteristic(uuid, lightService, Characteristic.Hue,
device => device.getHue(),
(device, value) => device.setHue(value));
}

if (this.isColorControlEnabled) {
this.registerCharacteristic(uuid, lightService, Characteristic.Saturation,
device => device.getSaturation(),
(device, value) => device.setSaturation(value));
}

this.accessories.set(uuid, accessory);
}
Expand Down
36 changes: 36 additions & 0 deletions lib/Color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
function rgbColors(obj) {
rgbInt = HSB2RGB({h: obj.hue, s: obj.saturation, b: obj.brightness});
return [rgbInt.r, rgbInt.g, rgbInt.b];
};

// https://stackoverflow.com/questions/17242144/javascript-convert-hsb-hsv-color-to-rgb-accurately
function HSB2RGB(hsb) {

var rgb = { };
var h = Math.round(hsb.h % 360);
var s = Math.round(hsb.s * 255 / 100);
var v = Math.round(hsb.b * 255 / 100);

if (s == 0) {

rgb.r = rgb.g = rgb.b = v;
} else {
var t1 = v;
var t2 = (255 - s) * v / 255;
var t3 = (t1 - t2) * (h % 60) / 60;

if (h == 360) h = 0;

if (h < 60) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3 }
else if (h < 120) { rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3 }
else if (h < 180) { rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3 }
else if (h < 240) { rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3 }
else if (h < 300) { rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3 }
else if (h < 360) { rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3 }
else { rgb.r = 0; rgb.g = 0; rgb.b = 0 }
}

return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) };
};

exports.rgbColors = rgbColors;
41 changes: 41 additions & 0 deletions lib/Twinkly.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const {RequestQueue} = require("./RequestQueue");
const {Movie} = require("./Movie");
const Color = require("./Color");

class Twinkly {
constructor(log, address, timeout, isVerbose) {
Expand All @@ -20,6 +21,10 @@ class Twinkly {
this.ledProfile = null;
this.generation = null;
this.initPromise = null;

this.hue = 180;
this.saturation = 70;
this.brightness = 100;
}

logVerbose(msg) {
Expand Down Expand Up @@ -81,9 +86,45 @@ class Twinkly {
}

setBrightness(brightness) {
this.brightness = brightness;
this.log("Set Brightness: " + this.brightness);
return this.requestService.postJson("led/out/brightness", {type: "A", value: brightness});
}

getHue() {
return this.requestService.get("led/out/brightness")
.then(json => this.hue);
}

setHue(hue) {
this.hue = hue;
this.log("Set Hue: " + this.hue);
return this.setColorEffect();
}

getSaturation() {
return this.requestService.get("led/out/brightness")
.then(json => this.saturation);
}

setSaturation(saturation) {
this.saturation = saturation || 70; // not sure why this is being called with an undefined value
this.log("Set Saturation: " + this.saturation);
return this.setColorEffect();
}

setColorEffect() {
var color = Color.rgbColors(
{
hue: this.hue,
saturation: this.saturation,
brightness: 100
}
);
this.log("Color: " + color);
return this.setColor(color)
}

setColor(color) {
return this.ensureDeviceInfo()
.then(() => this.setMovie(Movie.repeatedColors(this.ledCount, [color])));
Expand Down

0 comments on commit 502e46b

Please sign in to comment.