@ecopoesis/homebridge-dmx 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/color/types.d.ts +9 -0
- package/dist/color/types.d.ts.map +1 -1
- package/dist/color/types.js +34 -0
- package/dist/color/types.js.map +1 -1
- package/dist/platformAccessory.d.ts +8 -0
- package/dist/platformAccessory.d.ts.map +1 -1
- package/dist/platformAccessory.js +45 -17
- package/dist/platformAccessory.js.map +1 -1
- package/dist/zoneAccessory.d.ts +3 -0
- package/dist/zoneAccessory.d.ts.map +1 -1
- package/dist/zoneAccessory.js +42 -9
- package/dist/zoneAccessory.js.map +1 -1
- package/package.json +1 -1
- package/src/color/types.ts +30 -0
- package/src/platformAccessory.ts +43 -16
- package/src/zoneAccessory.ts +42 -10
package/dist/color/types.d.ts
CHANGED
|
@@ -55,6 +55,15 @@ export declare function rgbBytes(rgb01: {
|
|
|
55
55
|
b: number;
|
|
56
56
|
};
|
|
57
57
|
export declare function clamp(v: number, lo: number, hi: number): number;
|
|
58
|
+
/** Approximate a mired white point as HomeKit hue/sat — the swatch the Home
|
|
59
|
+
* app itself renders for that color temperature (Tanner Helland blackbody
|
|
60
|
+
* fit; 200 mireds/5000 K → rgb(255,228,206) → h27 s19, matching iOS).
|
|
61
|
+
* Needed for the dual-mode display convention (HAP-NodeJS#618): in white
|
|
62
|
+
* mode, Hue/Saturation must mirror the CCT's representation. */
|
|
63
|
+
export declare function miredsToHueSat(mireds: number): {
|
|
64
|
+
hue: number;
|
|
65
|
+
saturation: number;
|
|
66
|
+
};
|
|
58
67
|
/** Tag a single-byte channel index plus its fine companion (if any), and
|
|
59
68
|
* emit the right 16-bit split into `out`. Returns the index advanced past
|
|
60
69
|
* any fine companion. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/color/types.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GACxB,IAAI,GACJ,YAAY,GACZ,KAAK,GACL,YAAY,GACZ,kBAAkB,CAAC;AAEvB;oDACoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,KAAK,GACL,YAAY,GACZ,KAAK,GACL,KAAK,GACL,OAAO,GACP,MAAM,GACN,OAAO,GACP,YAAY,GACZ,YAAY,GACZ,OAAO,CAAC;AAEZ;;mFAEmF;AACnF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,EAAE,gBAAgB,EAAE,CAAC;IAC7C,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IACvC,8EAA8E;IAC9E,MAAM,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC;IACrE,yDAAyD;IACzD,KAAK,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,iBAAiB,CAAC;CACtE;AAID,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAI7D;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAG5D;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED;kDACkD;AAClD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAc9F;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,iBAAiB,GAC3F;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAOpC;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;0BAE0B;AAC1B,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,UAAU,EAAE,EACtB,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,MAAM,GACd,MAAM,CASR;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAY/E"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/color/types.ts"],"names":[],"mappings":"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"}
|
package/dist/color/types.js
CHANGED
|
@@ -61,6 +61,40 @@ export function rgbBytes(rgb01, state) {
|
|
|
61
61
|
export function clamp(v, lo, hi) {
|
|
62
62
|
return v < lo ? lo : v > hi ? hi : v;
|
|
63
63
|
}
|
|
64
|
+
/** Approximate a mired white point as HomeKit hue/sat — the swatch the Home
|
|
65
|
+
* app itself renders for that color temperature (Tanner Helland blackbody
|
|
66
|
+
* fit; 200 mireds/5000 K → rgb(255,228,206) → h27 s19, matching iOS).
|
|
67
|
+
* Needed for the dual-mode display convention (HAP-NodeJS#618): in white
|
|
68
|
+
* mode, Hue/Saturation must mirror the CCT's representation. */
|
|
69
|
+
export function miredsToHueSat(mireds) {
|
|
70
|
+
const t = clamp(1_000_000 / mireds, 1000, 40000) / 100;
|
|
71
|
+
let r, g, b;
|
|
72
|
+
if (t <= 66) {
|
|
73
|
+
r = 255;
|
|
74
|
+
g = clamp(99.4708025861 * Math.log(t) - 161.1195681661, 0, 255);
|
|
75
|
+
b = t <= 19 ? 0 : clamp(138.5177312231 * Math.log(t - 10) - 305.0447927307, 0, 255);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
r = clamp(329.698727446 * Math.pow(t - 60, -0.1332047592), 0, 255);
|
|
79
|
+
g = clamp(288.1221695283 * Math.pow(t - 60, -0.0755148492), 0, 255);
|
|
80
|
+
b = 255;
|
|
81
|
+
}
|
|
82
|
+
const max = Math.max(r, g, b);
|
|
83
|
+
const min = Math.min(r, g, b);
|
|
84
|
+
const d = max - min;
|
|
85
|
+
let h = 0;
|
|
86
|
+
if (d !== 0) {
|
|
87
|
+
if (max === r)
|
|
88
|
+
h = 60 * (((g - b) / d) % 6);
|
|
89
|
+
else if (max === g)
|
|
90
|
+
h = 60 * (((b - r) / d) + 2);
|
|
91
|
+
else
|
|
92
|
+
h = 60 * (((r - g) / d) + 4);
|
|
93
|
+
}
|
|
94
|
+
if (h < 0)
|
|
95
|
+
h += 360;
|
|
96
|
+
return { hue: Math.round(h), saturation: Math.round(max === 0 ? 0 : (d / max) * 100) };
|
|
97
|
+
}
|
|
64
98
|
/** Tag a single-byte channel index plus its fine companion (if any), and
|
|
65
99
|
* emit the right 16-bit split into `out`. Returns the index advanced past
|
|
66
100
|
* any fine companion. */
|
package/dist/color/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/color/types.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,qEAAqE;AACrE,6CAA6C;AAwD7C,8EAA8E;AAE9E,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,IAAI,CAAC,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IACxB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,WAAW,CAAC,KAAwB;IAClD,IAAI,CAAC,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IACxB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AACnE,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,MAAM,CAAC,MAA0B,EAAE,IAAY,EAAE,IAAY;IAC3E,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC9C,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC;IAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED;kDACkD;AAClD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,MAAc;IACvD,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IACvC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;IACtC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAwB,oBAAoB;IACxD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACjD,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE;QAAS,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SACvC,IAAI,CAAC,GAAG,GAAG;QAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SACvC,IAAI,CAAC,GAAG,GAAG;QAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SACvC,IAAI,CAAC,GAAG,GAAG;QAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SACvC,IAAI,CAAC,GAAG,GAAG;QAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;;QACzB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAoB,mBAAmB;IACvD,OAAO,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,QAAQ,CAAC,KAA0C,EAAE,KAAwB;IAE3F,MAAM,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAChC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAChC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,CAAS,EAAE,EAAU,EAAE,EAAU;IACrD,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED;;0BAE0B;AAC1B,MAAM,UAAU,YAAY,CAC1B,GAAe,EACf,QAAsB,EACtB,CAAS,EACT,OAAe;IAEf,MAAM,MAAM,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACrC,MAAM,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAChB,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,QAAsB,EAAE,KAAoB;IACvE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACnE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,GAAG,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,kBAAkB,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/color/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,14 @@ export declare class StickFixture {
|
|
|
12
12
|
private pending;
|
|
13
13
|
private bulb;
|
|
14
14
|
constructor(platform: DmxPlatform, accessory: PlatformAccessory, fixture: Fixture, controller: DmxController, registry: StateRegistry);
|
|
15
|
+
/** HomeKit-facing view of the registry state, per the dual-mode display
|
|
16
|
+
* convention (HAP-NodeJS#618): in white mode (sat 0) Hue/Saturation
|
|
17
|
+
* mirror the CCT's hue/sat representation and ColorTemperature carries
|
|
18
|
+
* the real mireds; in color mode Hue/Saturation are the real values and
|
|
19
|
+
* ColorTemperature parks at the characteristic's minimum — that's how
|
|
20
|
+
* the Home app recognizes color mode on a fresh read (a "real" CT value
|
|
21
|
+
* makes reopened tiles render the CCT swatch instead of the color). */
|
|
22
|
+
private display;
|
|
15
23
|
private pushFromRegistry;
|
|
16
24
|
private schedule;
|
|
17
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platformAccessory.d.ts","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,qBAAa,YAAY;IAKrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,IAAI,CAAU;gBAGH,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,aAAa,EACzB,QAAQ,EAAE,aAAa;IAoE1C,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"platformAccessory.d.ts","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,qBAAa,YAAY;IAKrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,IAAI,CAAU;gBAGH,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,aAAa,EACzB,QAAQ,EAAE,aAAa;IAoE1C;;;;;;4EAMwE;IACxE,OAAO,CAAC,OAAO;IAkBf,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,QAAQ;CAcjB"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// State is owned by the platform-wide StateRegistry. We read on .onGet,
|
|
4
4
|
// write on .onSet, and subscribe to changes so the HomeKit-displayed
|
|
5
5
|
// values track the registry (e.g. when a zone updates this fixture).
|
|
6
|
+
import { miredsToHueSat } from './color/types.js';
|
|
6
7
|
import { CHARACTERISTIC_UPDATE_DELAY_MS } from './settings.js';
|
|
7
8
|
export class StickFixture {
|
|
8
9
|
platform;
|
|
@@ -44,7 +45,7 @@ export class StickFixture {
|
|
|
44
45
|
}
|
|
45
46
|
if (chars.includes('Hue')) {
|
|
46
47
|
this.bulb.getCharacteristic(C.Hue)
|
|
47
|
-
.onGet(() =>
|
|
48
|
+
.onGet(() => this.display().hue)
|
|
48
49
|
.onSet((v) => {
|
|
49
50
|
registry.update(fixture.id, { hue: Number(v) });
|
|
50
51
|
this.schedule();
|
|
@@ -52,7 +53,7 @@ export class StickFixture {
|
|
|
52
53
|
}
|
|
53
54
|
if (chars.includes('Saturation')) {
|
|
54
55
|
this.bulb.getCharacteristic(C.Saturation)
|
|
55
|
-
.onGet(() =>
|
|
56
|
+
.onGet(() => this.display().saturation)
|
|
56
57
|
.onSet((v) => {
|
|
57
58
|
registry.update(fixture.id, { saturation: Number(v) });
|
|
58
59
|
this.schedule();
|
|
@@ -60,7 +61,7 @@ export class StickFixture {
|
|
|
60
61
|
}
|
|
61
62
|
if (chars.includes('ColorTemperature')) {
|
|
62
63
|
this.bulb.getCharacteristic(C.ColorTemperature)
|
|
63
|
-
.onGet(() =>
|
|
64
|
+
.onGet(() => this.display().ct)
|
|
64
65
|
.onSet((v) => {
|
|
65
66
|
// CCT change implies white mode; zero saturation.
|
|
66
67
|
registry.update(fixture.id, {
|
|
@@ -78,24 +79,51 @@ export class StickFixture {
|
|
|
78
79
|
this.pushFromRegistry();
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
+
/** HomeKit-facing view of the registry state, per the dual-mode display
|
|
83
|
+
* convention (HAP-NodeJS#618): in white mode (sat 0) Hue/Saturation
|
|
84
|
+
* mirror the CCT's hue/sat representation and ColorTemperature carries
|
|
85
|
+
* the real mireds; in color mode Hue/Saturation are the real values and
|
|
86
|
+
* ColorTemperature parks at the characteristic's minimum — that's how
|
|
87
|
+
* the Home app recognizes color mode on a fresh read (a "real" CT value
|
|
88
|
+
* makes reopened tiles render the CCT swatch instead of the color). */
|
|
89
|
+
display() {
|
|
82
90
|
const s = this.registry.get(this.fixture.id);
|
|
91
|
+
const chars = this.fixture.profile.model.characteristics;
|
|
92
|
+
const base = { on: s.on, brightness: s.brightness };
|
|
93
|
+
if (!chars.includes('ColorTemperature') || !chars.includes('Hue')) {
|
|
94
|
+
return { ...base, hue: s.hue ?? 0, saturation: s.saturation ?? 0,
|
|
95
|
+
ct: s.colorTemperatureMireds ?? 200, whiteMode: (s.saturation ?? 0) === 0 };
|
|
96
|
+
}
|
|
97
|
+
if ((s.saturation ?? 0) === 0) {
|
|
98
|
+
const ct = s.colorTemperatureMireds ?? 200;
|
|
99
|
+
const rep = miredsToHueSat(ct);
|
|
100
|
+
return { ...base, hue: rep.hue, saturation: rep.saturation, ct, whiteMode: true };
|
|
101
|
+
}
|
|
102
|
+
const ctChar = this.bulb.getCharacteristic(this.platform.Characteristic.ColorTemperature);
|
|
103
|
+
const minCt = ctChar.props.minValue ?? 140;
|
|
104
|
+
return { ...base, hue: s.hue ?? 0, saturation: s.saturation, ct: minCt, whiteMode: false };
|
|
105
|
+
}
|
|
106
|
+
pushFromRegistry() {
|
|
107
|
+
const d = this.display();
|
|
83
108
|
const C = this.platform.Characteristic;
|
|
84
109
|
const chars = this.fixture.profile.model.characteristics;
|
|
85
|
-
this.bulb.updateCharacteristic(C.On,
|
|
110
|
+
this.bulb.updateCharacteristic(C.On, d.on);
|
|
86
111
|
if (chars.includes('Brightness'))
|
|
87
|
-
this.bulb.updateCharacteristic(C.Brightness,
|
|
88
|
-
if (chars.includes('Hue')
|
|
89
|
-
this.bulb.updateCharacteristic(C.Hue,
|
|
90
|
-
if (chars.includes('Saturation')
|
|
91
|
-
this.bulb.updateCharacteristic(C.Saturation,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
this.bulb.updateCharacteristic(C.Brightness, d.brightness);
|
|
113
|
+
if (chars.includes('Hue'))
|
|
114
|
+
this.bulb.updateCharacteristic(C.Hue, d.hue);
|
|
115
|
+
if (chars.includes('Saturation'))
|
|
116
|
+
this.bulb.updateCharacteristic(C.Saturation, d.saturation);
|
|
117
|
+
if (chars.includes('ColorTemperature')) {
|
|
118
|
+
if (d.whiteMode) {
|
|
119
|
+
// Real CCT, pushed last so temperature wins the display-mode race.
|
|
120
|
+
this.bulb.updateCharacteristic(C.ColorTemperature, d.ct);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// Park CT at min WITHOUT an event (a CT event would flip the Home
|
|
124
|
+
// app to temperature display); plain .value assignment is silent.
|
|
125
|
+
this.bulb.getCharacteristic(C.ColorTemperature).value = d.ct;
|
|
126
|
+
}
|
|
99
127
|
}
|
|
100
128
|
}
|
|
101
129
|
schedule() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platformAccessory.js","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,wEAAwE;AACxE,qEAAqE;AACrE,qEAAqE;
|
|
1
|
+
{"version":3,"file":"platformAccessory.js","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"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"}
|
package/dist/zoneAccessory.d.ts
CHANGED
|
@@ -14,6 +14,9 @@ export declare class ZoneFixture {
|
|
|
14
14
|
constructor(platform: DmxPlatform, accessory: PlatformAccessory, zone: Zone, controllers: Map<string, DmxController>, registry: StateRegistry);
|
|
15
15
|
/** Compute majority state across members, per characteristic. */
|
|
16
16
|
private majorityState;
|
|
17
|
+
/** HomeKit-facing view of the majority state — same dual-mode display
|
|
18
|
+
* convention as StickFixture.display() (HAP-NodeJS#618). */
|
|
19
|
+
private display;
|
|
17
20
|
/** A HomeKit set on the zone: build the new state from the current
|
|
18
21
|
* majority + the patch the user is applying, write it into every
|
|
19
22
|
* member, and trigger the controller after a small debounce so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zoneAccessory.d.ts","sourceRoot":"","sources":["../src/zoneAccessory.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AAEjE,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAEzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,IAAI,CAAU;gBAGH,QAAQ,EAAE,WAAW,EACtC,SAAS,EAAE,iBAAiB,EACX,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACvC,QAAQ,EAAE,aAAa;IAmD1C,iEAAiE;IACjE,OAAO,CAAC,aAAa;IAWrB;;;mDAG+C;IAC/C,OAAO,CAAC,cAAc;
|
|
1
|
+
{"version":3,"file":"zoneAccessory.d.ts","sourceRoot":"","sources":["../src/zoneAccessory.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AAEjE,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAEzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,IAAI,CAAU;gBAGH,QAAQ,EAAE,WAAW,EACtC,SAAS,EAAE,iBAAiB,EACX,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACvC,QAAQ,EAAE,aAAa;IAmD1C,iEAAiE;IACjE,OAAO,CAAC,aAAa;IAWrB;iEAC6D;IAC7D,OAAO,CAAC,OAAO;IAiBf;;;mDAG+C;IAC/C,OAAO,CAAC,cAAc;IAiBtB;qDACiD;IACjD,OAAO,CAAC,gBAAgB;IAuBxB;8CAC0C;IAC1C,OAAO,CAAC,eAAe;CA4BxB;AAGD,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC"}
|
package/dist/zoneAccessory.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// When ANY member's state changes (by any path), the zone's HomeKit
|
|
15
15
|
// characteristics push the new majority — so zones containing overlapping
|
|
16
16
|
// members stay coherent with each other.
|
|
17
|
+
import { miredsToHueSat } from './color/types.js';
|
|
17
18
|
import { CHARACTERISTIC_UPDATE_DELAY_MS } from './settings.js';
|
|
18
19
|
import { pickMajority } from './stateRegistry.js';
|
|
19
20
|
export class ZoneFixture {
|
|
@@ -49,17 +50,17 @@ export class ZoneFixture {
|
|
|
49
50
|
}
|
|
50
51
|
if (has('Hue')) {
|
|
51
52
|
this.bulb.getCharacteristic(C.Hue)
|
|
52
|
-
.onGet(() => this.
|
|
53
|
+
.onGet(() => this.display().hue)
|
|
53
54
|
.onSet((v) => this.applyToMembers({ hue: Number(v) }));
|
|
54
55
|
}
|
|
55
56
|
if (has('Saturation')) {
|
|
56
57
|
this.bulb.getCharacteristic(C.Saturation)
|
|
57
|
-
.onGet(() => this.
|
|
58
|
+
.onGet(() => this.display().saturation)
|
|
58
59
|
.onSet((v) => this.applyToMembers({ saturation: Number(v) }));
|
|
59
60
|
}
|
|
60
61
|
if (has('ColorTemperature')) {
|
|
61
62
|
this.bulb.getCharacteristic(C.ColorTemperature)
|
|
62
|
-
.onGet(() => this.
|
|
63
|
+
.onGet(() => this.display().ct)
|
|
63
64
|
.onSet((v) => this.applyToMembers({
|
|
64
65
|
colorTemperatureMireds: Number(v),
|
|
65
66
|
saturation: 0,
|
|
@@ -83,12 +84,36 @@ export class ZoneFixture {
|
|
|
83
84
|
colorTemperatureMireds: pickMajority(ss.map((s) => ({ id: s.id, v: s.state.colorTemperatureMireds }))),
|
|
84
85
|
};
|
|
85
86
|
}
|
|
87
|
+
/** HomeKit-facing view of the majority state — same dual-mode display
|
|
88
|
+
* convention as StickFixture.display() (HAP-NodeJS#618). */
|
|
89
|
+
display() {
|
|
90
|
+
const s = this.majorityState();
|
|
91
|
+
if (!this.zone.characteristics.includes('ColorTemperature')
|
|
92
|
+
|| !this.zone.characteristics.includes('Hue')) {
|
|
93
|
+
return { hue: s.hue ?? 0, saturation: s.saturation ?? 0,
|
|
94
|
+
ct: s.colorTemperatureMireds ?? 200, whiteMode: (s.saturation ?? 0) === 0 };
|
|
95
|
+
}
|
|
96
|
+
if ((s.saturation ?? 0) === 0) {
|
|
97
|
+
const ct = s.colorTemperatureMireds ?? 200;
|
|
98
|
+
const rep = miredsToHueSat(ct);
|
|
99
|
+
return { hue: rep.hue, saturation: rep.saturation, ct, whiteMode: true };
|
|
100
|
+
}
|
|
101
|
+
const ctChar = this.bulb.getCharacteristic(this.platform.Characteristic.ColorTemperature);
|
|
102
|
+
const minCt = ctChar.props.minValue ?? 140;
|
|
103
|
+
return { hue: s.hue ?? 0, saturation: s.saturation, ct: minCt, whiteMode: false };
|
|
104
|
+
}
|
|
86
105
|
/** A HomeKit set on the zone: build the new state from the current
|
|
87
106
|
* majority + the patch the user is applying, write it into every
|
|
88
107
|
* member, and trigger the controller after a small debounce so
|
|
89
108
|
* multi-characteristic dispatch coalesces. */
|
|
90
109
|
applyToMembers(patch) {
|
|
91
110
|
const next = { ...this.majorityState(), ...patch };
|
|
111
|
+
// A color set puts the members in color mode; don't drag the stale CCT
|
|
112
|
+
// majority into their states (it would win the Home app's last-updated
|
|
113
|
+
// display-mode race and flip the tile to temperature mode).
|
|
114
|
+
if (patch.hue != null || (patch.saturation ?? 0) > 0) {
|
|
115
|
+
delete next.colorTemperatureMireds;
|
|
116
|
+
}
|
|
92
117
|
// Push the next state into every member's registry entry. This fires
|
|
93
118
|
// per-fixture change events so the individual StickFixture accessories
|
|
94
119
|
// refresh their own HomeKit displays.
|
|
@@ -128,19 +153,27 @@ export class ZoneFixture {
|
|
|
128
153
|
this.refreshPending = setTimeout(() => {
|
|
129
154
|
this.refreshPending = null;
|
|
130
155
|
const s = this.majorityState();
|
|
156
|
+
const d = this.display();
|
|
131
157
|
const C = this.platform.Characteristic;
|
|
132
158
|
this.bulb.updateCharacteristic(C.On, s.on);
|
|
133
159
|
if (this.zone.characteristics.includes('Brightness')) {
|
|
134
160
|
this.bulb.updateCharacteristic(C.Brightness, s.brightness);
|
|
135
161
|
}
|
|
136
|
-
if (this.zone.characteristics.includes('Hue')
|
|
137
|
-
this.bulb.updateCharacteristic(C.Hue,
|
|
162
|
+
if (this.zone.characteristics.includes('Hue')) {
|
|
163
|
+
this.bulb.updateCharacteristic(C.Hue, d.hue);
|
|
138
164
|
}
|
|
139
|
-
if (this.zone.characteristics.includes('Saturation')
|
|
140
|
-
this.bulb.updateCharacteristic(C.Saturation,
|
|
165
|
+
if (this.zone.characteristics.includes('Saturation')) {
|
|
166
|
+
this.bulb.updateCharacteristic(C.Saturation, d.saturation);
|
|
141
167
|
}
|
|
142
|
-
if (this.zone.characteristics.includes('ColorTemperature')
|
|
143
|
-
|
|
168
|
+
if (this.zone.characteristics.includes('ColorTemperature')) {
|
|
169
|
+
if (d.whiteMode) {
|
|
170
|
+
// Real CCT, pushed last so temperature wins the display-mode race.
|
|
171
|
+
this.bulb.updateCharacteristic(C.ColorTemperature, d.ct);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Park CT at min silently (see StickFixture.pushFromRegistry).
|
|
175
|
+
this.bulb.getCharacteristic(C.ColorTemperature).value = d.ct;
|
|
176
|
+
}
|
|
144
177
|
}
|
|
145
178
|
}, CHARACTERISTIC_UPDATE_DELAY_MS);
|
|
146
179
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zoneAccessory.js","sourceRoot":"","sources":["../src/zoneAccessory.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,YAAY;AACZ,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,yCAAyC;AACzC,EAAE;AACF,0EAA0E;AAC1E,uEAAuE;AACvE,wEAAwE;AACxE,mDAAmD;AACnD,EAAE;AACF,oEAAoE;AACpE,0EAA0E;AAC1E,yCAAyC;
|
|
1
|
+
{"version":3,"file":"zoneAccessory.js","sourceRoot":"","sources":["../src/zoneAccessory.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/color/types.ts
CHANGED
|
@@ -115,6 +115,36 @@ export function clamp(v: number, lo: number, hi: number): number {
|
|
|
115
115
|
return v < lo ? lo : v > hi ? hi : v;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
/** Approximate a mired white point as HomeKit hue/sat — the swatch the Home
|
|
119
|
+
* app itself renders for that color temperature (Tanner Helland blackbody
|
|
120
|
+
* fit; 200 mireds/5000 K → rgb(255,228,206) → h27 s19, matching iOS).
|
|
121
|
+
* Needed for the dual-mode display convention (HAP-NodeJS#618): in white
|
|
122
|
+
* mode, Hue/Saturation must mirror the CCT's representation. */
|
|
123
|
+
export function miredsToHueSat(mireds: number): { hue: number; saturation: number } {
|
|
124
|
+
const t = clamp(1_000_000 / mireds, 1000, 40000) / 100;
|
|
125
|
+
let r: number, g: number, b: number;
|
|
126
|
+
if (t <= 66) {
|
|
127
|
+
r = 255;
|
|
128
|
+
g = clamp(99.4708025861 * Math.log(t) - 161.1195681661, 0, 255);
|
|
129
|
+
b = t <= 19 ? 0 : clamp(138.5177312231 * Math.log(t - 10) - 305.0447927307, 0, 255);
|
|
130
|
+
} else {
|
|
131
|
+
r = clamp(329.698727446 * Math.pow(t - 60, -0.1332047592), 0, 255);
|
|
132
|
+
g = clamp(288.1221695283 * Math.pow(t - 60, -0.0755148492), 0, 255);
|
|
133
|
+
b = 255;
|
|
134
|
+
}
|
|
135
|
+
const max = Math.max(r, g, b);
|
|
136
|
+
const min = Math.min(r, g, b);
|
|
137
|
+
const d = max - min;
|
|
138
|
+
let h = 0;
|
|
139
|
+
if (d !== 0) {
|
|
140
|
+
if (max === r) h = 60 * (((g - b) / d) % 6);
|
|
141
|
+
else if (max === g) h = 60 * (((b - r) / d) + 2);
|
|
142
|
+
else h = 60 * (((r - g) / d) + 4);
|
|
143
|
+
}
|
|
144
|
+
if (h < 0) h += 360;
|
|
145
|
+
return { hue: Math.round(h), saturation: Math.round(max === 0 ? 0 : (d / max) * 100) };
|
|
146
|
+
}
|
|
147
|
+
|
|
118
148
|
/** Tag a single-byte channel index plus its fine companion (if any), and
|
|
119
149
|
* emit the right 16-bit split into `out`. Returns the index advanced past
|
|
120
150
|
* any fine companion. */
|
package/src/platformAccessory.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
} from 'homebridge';
|
|
12
12
|
|
|
13
13
|
import { Fixture } from './config.js';
|
|
14
|
-
import { HomeKitLightState } from './color/types.js';
|
|
14
|
+
import { HomeKitLightState, miredsToHueSat } from './color/types.js';
|
|
15
15
|
import { DmxController } from './dmxController.js';
|
|
16
16
|
import type { DmxPlatform } from './platform.js';
|
|
17
17
|
import { CHARACTERISTIC_UPDATE_DELAY_MS } from './settings.js';
|
|
@@ -59,7 +59,7 @@ export class StickFixture {
|
|
|
59
59
|
}
|
|
60
60
|
if (chars.includes('Hue')) {
|
|
61
61
|
this.bulb.getCharacteristic(C.Hue)
|
|
62
|
-
.onGet(() =>
|
|
62
|
+
.onGet(() => this.display().hue)
|
|
63
63
|
.onSet((v) => {
|
|
64
64
|
registry.update(fixture.id, { hue: Number(v) });
|
|
65
65
|
this.schedule();
|
|
@@ -67,7 +67,7 @@ export class StickFixture {
|
|
|
67
67
|
}
|
|
68
68
|
if (chars.includes('Saturation')) {
|
|
69
69
|
this.bulb.getCharacteristic(C.Saturation)
|
|
70
|
-
.onGet(() =>
|
|
70
|
+
.onGet(() => this.display().saturation)
|
|
71
71
|
.onSet((v) => {
|
|
72
72
|
registry.update(fixture.id, { saturation: Number(v) });
|
|
73
73
|
this.schedule();
|
|
@@ -75,7 +75,7 @@ export class StickFixture {
|
|
|
75
75
|
}
|
|
76
76
|
if (chars.includes('ColorTemperature')) {
|
|
77
77
|
this.bulb.getCharacteristic(C.ColorTemperature)
|
|
78
|
-
.onGet(() =>
|
|
78
|
+
.onGet(() => this.display().ct)
|
|
79
79
|
.onSet((v) => {
|
|
80
80
|
// CCT change implies white mode; zero saturation.
|
|
81
81
|
registry.update(fixture.id, {
|
|
@@ -94,21 +94,48 @@ export class StickFixture {
|
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
/** HomeKit-facing view of the registry state, per the dual-mode display
|
|
98
|
+
* convention (HAP-NodeJS#618): in white mode (sat 0) Hue/Saturation
|
|
99
|
+
* mirror the CCT's hue/sat representation and ColorTemperature carries
|
|
100
|
+
* the real mireds; in color mode Hue/Saturation are the real values and
|
|
101
|
+
* ColorTemperature parks at the characteristic's minimum — that's how
|
|
102
|
+
* the Home app recognizes color mode on a fresh read (a "real" CT value
|
|
103
|
+
* makes reopened tiles render the CCT swatch instead of the color). */
|
|
104
|
+
private display(): { on: boolean; brightness: number; hue: number; saturation: number; ct: number; whiteMode: boolean } {
|
|
98
105
|
const s = this.registry.get(this.fixture.id);
|
|
106
|
+
const chars = this.fixture.profile.model.characteristics;
|
|
107
|
+
const base = { on: s.on, brightness: s.brightness };
|
|
108
|
+
if (!chars.includes('ColorTemperature') || !chars.includes('Hue')) {
|
|
109
|
+
return { ...base, hue: s.hue ?? 0, saturation: s.saturation ?? 0,
|
|
110
|
+
ct: s.colorTemperatureMireds ?? 200, whiteMode: (s.saturation ?? 0) === 0 };
|
|
111
|
+
}
|
|
112
|
+
if ((s.saturation ?? 0) === 0) {
|
|
113
|
+
const ct = s.colorTemperatureMireds ?? 200;
|
|
114
|
+
const rep = miredsToHueSat(ct);
|
|
115
|
+
return { ...base, hue: rep.hue, saturation: rep.saturation, ct, whiteMode: true };
|
|
116
|
+
}
|
|
117
|
+
const ctChar = this.bulb.getCharacteristic(this.platform.Characteristic.ColorTemperature);
|
|
118
|
+
const minCt = (ctChar.props.minValue as number | undefined) ?? 140;
|
|
119
|
+
return { ...base, hue: s.hue ?? 0, saturation: s.saturation!, ct: minCt, whiteMode: false };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private pushFromRegistry(): void {
|
|
123
|
+
const d = this.display();
|
|
99
124
|
const C = this.platform.Characteristic;
|
|
100
125
|
const chars = this.fixture.profile.model.characteristics;
|
|
101
|
-
this.bulb.updateCharacteristic(C.On,
|
|
102
|
-
if (chars.includes('Brightness')) this.bulb.updateCharacteristic(C.Brightness,
|
|
103
|
-
if (chars.includes('Hue')
|
|
104
|
-
if (chars.includes('Saturation')
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
126
|
+
this.bulb.updateCharacteristic(C.On, d.on);
|
|
127
|
+
if (chars.includes('Brightness')) this.bulb.updateCharacteristic(C.Brightness, d.brightness);
|
|
128
|
+
if (chars.includes('Hue')) this.bulb.updateCharacteristic(C.Hue, d.hue);
|
|
129
|
+
if (chars.includes('Saturation')) this.bulb.updateCharacteristic(C.Saturation, d.saturation);
|
|
130
|
+
if (chars.includes('ColorTemperature')) {
|
|
131
|
+
if (d.whiteMode) {
|
|
132
|
+
// Real CCT, pushed last so temperature wins the display-mode race.
|
|
133
|
+
this.bulb.updateCharacteristic(C.ColorTemperature, d.ct);
|
|
134
|
+
} else {
|
|
135
|
+
// Park CT at min WITHOUT an event (a CT event would flip the Home
|
|
136
|
+
// app to temperature display); plain .value assignment is silent.
|
|
137
|
+
this.bulb.getCharacteristic(C.ColorTemperature).value = d.ct;
|
|
138
|
+
}
|
|
112
139
|
}
|
|
113
140
|
}
|
|
114
141
|
|
package/src/zoneAccessory.ts
CHANGED
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
} from 'homebridge';
|
|
23
23
|
|
|
24
24
|
import { Fixture, Zone } from './config.js';
|
|
25
|
-
import { HKCharacteristic, HomeKitLightState } from './color/types.js';
|
|
25
|
+
import { HKCharacteristic, HomeKitLightState, miredsToHueSat } from './color/types.js';
|
|
26
26
|
import { DmxController } from './dmxController.js';
|
|
27
27
|
import type { DmxPlatform } from './platform.js';
|
|
28
28
|
import { CHARACTERISTIC_UPDATE_DELAY_MS } from './settings.js';
|
|
@@ -65,17 +65,17 @@ export class ZoneFixture {
|
|
|
65
65
|
}
|
|
66
66
|
if (has('Hue')) {
|
|
67
67
|
this.bulb.getCharacteristic(C.Hue)
|
|
68
|
-
.onGet(() => this.
|
|
68
|
+
.onGet(() => this.display().hue)
|
|
69
69
|
.onSet((v) => this.applyToMembers({ hue: Number(v) }));
|
|
70
70
|
}
|
|
71
71
|
if (has('Saturation')) {
|
|
72
72
|
this.bulb.getCharacteristic(C.Saturation)
|
|
73
|
-
.onGet(() => this.
|
|
73
|
+
.onGet(() => this.display().saturation)
|
|
74
74
|
.onSet((v) => this.applyToMembers({ saturation: Number(v) }));
|
|
75
75
|
}
|
|
76
76
|
if (has('ColorTemperature')) {
|
|
77
77
|
this.bulb.getCharacteristic(C.ColorTemperature)
|
|
78
|
-
.onGet(() => this.
|
|
78
|
+
.onGet(() => this.display().ct)
|
|
79
79
|
.onSet((v) => this.applyToMembers({
|
|
80
80
|
colorTemperatureMireds: Number(v),
|
|
81
81
|
saturation: 0,
|
|
@@ -101,12 +101,37 @@ export class ZoneFixture {
|
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/** HomeKit-facing view of the majority state — same dual-mode display
|
|
105
|
+
* convention as StickFixture.display() (HAP-NodeJS#618). */
|
|
106
|
+
private display(): { hue: number; saturation: number; ct: number; whiteMode: boolean } {
|
|
107
|
+
const s = this.majorityState();
|
|
108
|
+
if (!this.zone.characteristics.includes('ColorTemperature')
|
|
109
|
+
|| !this.zone.characteristics.includes('Hue')) {
|
|
110
|
+
return { hue: s.hue ?? 0, saturation: s.saturation ?? 0,
|
|
111
|
+
ct: s.colorTemperatureMireds ?? 200, whiteMode: (s.saturation ?? 0) === 0 };
|
|
112
|
+
}
|
|
113
|
+
if ((s.saturation ?? 0) === 0) {
|
|
114
|
+
const ct = s.colorTemperatureMireds ?? 200;
|
|
115
|
+
const rep = miredsToHueSat(ct);
|
|
116
|
+
return { hue: rep.hue, saturation: rep.saturation, ct, whiteMode: true };
|
|
117
|
+
}
|
|
118
|
+
const ctChar = this.bulb.getCharacteristic(this.platform.Characteristic.ColorTemperature);
|
|
119
|
+
const minCt = (ctChar.props.minValue as number | undefined) ?? 140;
|
|
120
|
+
return { hue: s.hue ?? 0, saturation: s.saturation!, ct: minCt, whiteMode: false };
|
|
121
|
+
}
|
|
122
|
+
|
|
104
123
|
/** A HomeKit set on the zone: build the new state from the current
|
|
105
124
|
* majority + the patch the user is applying, write it into every
|
|
106
125
|
* member, and trigger the controller after a small debounce so
|
|
107
126
|
* multi-characteristic dispatch coalesces. */
|
|
108
127
|
private applyToMembers(patch: Partial<HomeKitLightState>): void {
|
|
109
128
|
const next = { ...this.majorityState(), ...patch };
|
|
129
|
+
// A color set puts the members in color mode; don't drag the stale CCT
|
|
130
|
+
// majority into their states (it would win the Home app's last-updated
|
|
131
|
+
// display-mode race and flip the tile to temperature mode).
|
|
132
|
+
if (patch.hue != null || (patch.saturation ?? 0) > 0) {
|
|
133
|
+
delete next.colorTemperatureMireds;
|
|
134
|
+
}
|
|
110
135
|
// Push the next state into every member's registry entry. This fires
|
|
111
136
|
// per-fixture change events so the individual StickFixture accessories
|
|
112
137
|
// refresh their own HomeKit displays.
|
|
@@ -148,19 +173,26 @@ export class ZoneFixture {
|
|
|
148
173
|
this.refreshPending = setTimeout(() => {
|
|
149
174
|
this.refreshPending = null;
|
|
150
175
|
const s = this.majorityState();
|
|
176
|
+
const d = this.display();
|
|
151
177
|
const C = this.platform.Characteristic;
|
|
152
178
|
this.bulb.updateCharacteristic(C.On, s.on);
|
|
153
179
|
if (this.zone.characteristics.includes('Brightness')) {
|
|
154
180
|
this.bulb.updateCharacteristic(C.Brightness, s.brightness);
|
|
155
181
|
}
|
|
156
|
-
if (this.zone.characteristics.includes('Hue')
|
|
157
|
-
this.bulb.updateCharacteristic(C.Hue,
|
|
182
|
+
if (this.zone.characteristics.includes('Hue')) {
|
|
183
|
+
this.bulb.updateCharacteristic(C.Hue, d.hue);
|
|
158
184
|
}
|
|
159
|
-
if (this.zone.characteristics.includes('Saturation')
|
|
160
|
-
this.bulb.updateCharacteristic(C.Saturation,
|
|
185
|
+
if (this.zone.characteristics.includes('Saturation')) {
|
|
186
|
+
this.bulb.updateCharacteristic(C.Saturation, d.saturation);
|
|
161
187
|
}
|
|
162
|
-
if (this.zone.characteristics.includes('ColorTemperature')
|
|
163
|
-
|
|
188
|
+
if (this.zone.characteristics.includes('ColorTemperature')) {
|
|
189
|
+
if (d.whiteMode) {
|
|
190
|
+
// Real CCT, pushed last so temperature wins the display-mode race.
|
|
191
|
+
this.bulb.updateCharacteristic(C.ColorTemperature, d.ct);
|
|
192
|
+
} else {
|
|
193
|
+
// Park CT at min silently (see StickFixture.pushFromRegistry).
|
|
194
|
+
this.bulb.getCharacteristic(C.ColorTemperature).value = d.ct;
|
|
195
|
+
}
|
|
164
196
|
}
|
|
165
197
|
}, CHARACTERISTIC_UPDATE_DELAY_MS);
|
|
166
198
|
}
|