-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for RGBW lights #2
base: main
Are you sure you want to change the base?
Changes from 9 commits
1d49f69
1c2735d
798b450
ece3f44
3e73ee3
09f67e3
38cdbc4
8ccc934
f8c1197
7fe5cb7
e96bb39
10db6c3
1d23cbd
2b68474
7b5a9dd
af5eedf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,9 @@ export class Led { | |
red: number; | ||
green: number; | ||
blue: number; | ||
white?: number; | ||
|
||
private _type: 'rgb'|'rgbw'; | ||
|
||
/** | ||
* Creates an instance of the Led class. | ||
|
@@ -19,10 +22,51 @@ export class Led { | |
* @param {number} green - Green value (0-255). | ||
* @param {number} blue - Blue value (0-255). | ||
*/ | ||
constructor(red: number, green: number, blue: number) { | ||
constructor(red: number, green: number, blue: number, white?: number) { | ||
this.red = red; | ||
this.green = green; | ||
this.blue = blue; | ||
this.white = white; | ||
this._type = typeof white === 'number' ? 'rgbw' : 'rgb'; | ||
} | ||
|
||
/** | ||
* Gets the LED type. | ||
* @returns {'rgb'|'rgbw'} The LED type. | ||
*/ | ||
get type(): 'rgb' | 'rgbw' { | ||
return this._type; | ||
} | ||
|
||
/** | ||
* Converts the LED to RGBW. | ||
* | ||
* @returns {Led} The updated Led instance. | ||
*/ | ||
toRgbw(): this { | ||
if (this._type === 'rgbw') return this; | ||
this.white = 0; | ||
this._type = 'rgbw'; | ||
return this; | ||
} | ||
|
||
/** | ||
* Converts the LED to RGB. | ||
* | ||
* @param {boolean} [preserveWhite] - If true, the white value will be preserved. | ||
* @returns {Led} The updated Led instance. | ||
*/ | ||
toRgb(preserveWhite = false): this { | ||
const white = this.white; | ||
if (this._type === 'rgb') return this; | ||
this.white = undefined; | ||
this._type = 'rgb'; | ||
|
||
if (white && preserveWhite) { | ||
this.brighten(white / 255); | ||
} | ||
Comment on lines
+65
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tbf this is probably unnecessary |
||
|
||
return this; | ||
} | ||
|
||
/** | ||
|
@@ -31,7 +75,11 @@ export class Led { | |
* @returns {Uint8Array} The RGB values in a Uint8Array format. | ||
*/ | ||
toOctet(): Uint8Array { | ||
return new Uint8Array([this.red, this.green, this.blue]); | ||
return new Uint8Array( | ||
this._type === 'rgbw' | ||
? [this.white!, this.red, this.green, this.blue] | ||
: [this.red, this.green, this.blue] | ||
); | ||
Comment on lines
+78
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently RGBW products use white as the first byte 🤷 |
||
} | ||
|
||
/** | ||
|
@@ -40,7 +88,7 @@ export class Led { | |
* @returns {boolean} True if the LED is on, false otherwise. | ||
*/ | ||
isOn(): boolean { | ||
return this.red > 0 || this.green > 0 || this.blue > 0; | ||
return this.red > 0 || this.green > 0 || this.blue > 0 || this.white! > 0; | ||
} | ||
|
||
/** | ||
|
@@ -52,6 +100,7 @@ export class Led { | |
this.red = 0; | ||
this.green = 0; | ||
this.blue = 0; | ||
this._type === 'rgbw' && (this.white = 0); | ||
return this; | ||
} | ||
|
||
|
@@ -63,10 +112,14 @@ export class Led { | |
* @param {number} blue - New blue value. | ||
* @returns {Led} The updated Led instance. | ||
*/ | ||
setColor(red: number, green: number, blue: number): this { | ||
setColor(red: number, green: number, blue: number, white?: number): this { | ||
this.red = red; | ||
this.green = green; | ||
this.blue = blue; | ||
if (typeof white === 'number') { | ||
this.white = white; | ||
this._type = 'rgbw'; | ||
} | ||
return this; | ||
} | ||
|
||
|
@@ -79,6 +132,7 @@ export class Led { | |
this.red = 255 - this.red; | ||
this.green = 255 - this.green; | ||
this.blue = 255 - this.blue; | ||
typeof this.white === 'number' && (this.white = 255 - this.white); | ||
return this; | ||
} | ||
|
||
|
@@ -88,7 +142,7 @@ export class Led { | |
* @returns {string} String in the format 'rgb(r, g, b)'. | ||
*/ | ||
toString(): string { | ||
return `rgb(${this.red}, ${this.green}, ${this.blue})`; | ||
return `${this._type}(${this.red}, ${this.green}, ${this.blue}, ${this.white})`; | ||
} | ||
|
||
/** | ||
|
@@ -101,6 +155,7 @@ export class Led { | |
this.red = Math.min(255, Math.round(this.red * factor)); | ||
this.green = Math.min(255, Math.round(this.green * factor)); | ||
this.blue = Math.min(255, Math.round(this.blue * factor)); | ||
this._type === 'rgbw' && (this.white = Math.min(255, Math.round((this.white || 0) * factor))); | ||
return this; | ||
} | ||
|
||
|
@@ -114,6 +169,7 @@ export class Led { | |
this.red = Math.max(0, Math.round(this.red * factor)); | ||
this.green = Math.max(0, Math.round(this.green * factor)); | ||
this.blue = Math.max(0, Math.round(this.blue * factor)); | ||
this._type === 'rgbw' && (this.white = Math.max(0, Math.round((this.white || 0) * factor))); | ||
return this; | ||
} | ||
|
||
|
@@ -137,6 +193,10 @@ export class Led { | |
255, | ||
Math.max(0, average + factor * (this.blue - average)) | ||
); | ||
this._type === 'rgbw' && (this.white = Math.min( | ||
255, | ||
Math.max(0, average + factor * ((this.white || 0) - average)) | ||
)); | ||
return this; | ||
} | ||
|
||
|
@@ -151,7 +211,7 @@ export class Led { | |
this.red = this.red + factor * (average - this.red); | ||
this.green = this.green + factor * (average - this.green); | ||
this.blue = this.blue + factor * (average - this.blue); | ||
this._type === 'rgbw' && (this.white = (this.white || 0) + factor * (average - (this.white || 0))); | ||
return this; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,14 @@ | ||
import { generateRandomHex } from "./utils.js"; | ||
|
||
import axios, { AxiosInstance, AxiosResponse } from "axios"; | ||
import FetchWrapper, { FetchResponse } from "./fetchwrapper.js"; | ||
import FetchWrapper, { FetchResponse } from "./fetchwrapper"; | ||
import delay from "delay"; | ||
// dynamically import udp for compatibility with browser | ||
// import * as udp from "node:dgram"; | ||
|
||
import { Led } from "./led.js"; | ||
import { Frame } from "./frame.js"; | ||
import { Movie } from "./movie.js"; | ||
import { Led } from "./led"; | ||
import { Frame } from "./frame"; | ||
import { Movie } from "./movie"; | ||
Comment on lines
+9
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the |
||
|
||
import { | ||
rgbColor, | ||
|
@@ -18,7 +18,7 @@ import { | |
timer, | ||
coordinate, | ||
layout, | ||
} from "./interfaces.js"; | ||
} from "./interfaces"; | ||
|
||
// create error | ||
let errNoToken = Error("No valid token"); | ||
|
@@ -35,6 +35,7 @@ export class Light { | |
token: AuthenticationToken | undefined; | ||
activeLoginCall: boolean; | ||
nleds: number | undefined; | ||
name: string | undefined; | ||
udpClient: any; //udp.Socket; | ||
/** | ||
* Creates an instance of Light. | ||
|
@@ -239,6 +240,8 @@ export class Light { | |
*/ | ||
async getDeviceDetails(): Promise<object> { | ||
let data = await this.sendGetRequest("/gestalt", undefined, false); | ||
this.nleds ??= data.number_of_led; | ||
this.name ??= data.device_name; | ||
return data; | ||
} | ||
/** | ||
|
@@ -264,6 +267,7 @@ export class Light { | |
* @returns {Promise<string>} Name of device | ||
*/ | ||
async getName(): Promise<string> { | ||
if (this.name) return this.name; | ||
let data = await this.sendGetRequest("/device_name"); | ||
let res: string = data.name; | ||
return res; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made this function configurable so it'll match the device's specs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh also
nFrames = nLeds + tailLength
lets the tail fade out rather than cutting it off