@ecopoesis/homebridge-dmx 0.5.4 → 0.6.0

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.
Files changed (73) hide show
  1. package/CLAUDE.md +1 -0
  2. package/README.md +67 -0
  3. package/config.schema.json +104 -0
  4. package/dist/color/types.d.ts +9 -0
  5. package/dist/color/types.d.ts.map +1 -1
  6. package/dist/color/types.js +34 -0
  7. package/dist/color/types.js.map +1 -1
  8. package/dist/config.d.ts +5 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +18 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/controller.d.ts +3 -2
  13. package/dist/controller.d.ts.map +1 -1
  14. package/dist/controller.js +7 -4
  15. package/dist/controller.js.map +1 -1
  16. package/dist/dmxController.d.ts +9 -1
  17. package/dist/dmxController.d.ts.map +1 -1
  18. package/dist/platform.d.ts +1 -0
  19. package/dist/platform.d.ts.map +1 -1
  20. package/dist/platform.js +37 -2
  21. package/dist/platform.js.map +1 -1
  22. package/dist/platformAccessory.d.ts +8 -0
  23. package/dist/platformAccessory.d.ts.map +1 -1
  24. package/dist/platformAccessory.js +45 -17
  25. package/dist/platformAccessory.js.map +1 -1
  26. package/dist/sacn.d.ts +3 -2
  27. package/dist/sacn.d.ts.map +1 -1
  28. package/dist/sacn.js +7 -4
  29. package/dist/sacn.js.map +1 -1
  30. package/dist/settings.d.ts +13 -0
  31. package/dist/settings.d.ts.map +1 -1
  32. package/dist/settings.js +14 -0
  33. package/dist/settings.js.map +1 -1
  34. package/dist/show/colors.d.ts +25 -0
  35. package/dist/show/colors.d.ts.map +1 -0
  36. package/dist/show/colors.js +216 -0
  37. package/dist/show/colors.js.map +1 -0
  38. package/dist/show/dsl.d.ts +56 -0
  39. package/dist/show/dsl.d.ts.map +1 -0
  40. package/dist/show/dsl.js +326 -0
  41. package/dist/show/dsl.js.map +1 -0
  42. package/dist/show/engine.d.ts +50 -0
  43. package/dist/show/engine.d.ts.map +1 -0
  44. package/dist/show/engine.js +264 -0
  45. package/dist/show/engine.js.map +1 -0
  46. package/dist/showAccessory.d.ts +9 -0
  47. package/dist/showAccessory.d.ts.map +1 -0
  48. package/dist/showAccessory.js +33 -0
  49. package/dist/showAccessory.js.map +1 -0
  50. package/dist/stateRegistry.d.ts +8 -3
  51. package/dist/stateRegistry.d.ts.map +1 -1
  52. package/dist/stateRegistry.js +4 -4
  53. package/dist/stateRegistry.js.map +1 -1
  54. package/dist/zoneAccessory.d.ts +3 -0
  55. package/dist/zoneAccessory.d.ts.map +1 -1
  56. package/dist/zoneAccessory.js +36 -13
  57. package/dist/zoneAccessory.js.map +1 -1
  58. package/examples/dmx.yaml +76 -0
  59. package/package.json +1 -1
  60. package/src/color/types.ts +30 -0
  61. package/src/config.ts +22 -1
  62. package/src/controller.ts +8 -5
  63. package/src/dmxController.ts +10 -1
  64. package/src/platform.ts +35 -2
  65. package/src/platformAccessory.ts +43 -16
  66. package/src/sacn.ts +8 -4
  67. package/src/settings.ts +19 -0
  68. package/src/show/colors.ts +224 -0
  69. package/src/show/dsl.ts +370 -0
  70. package/src/show/engine.ts +280 -0
  71. package/src/showAccessory.ts +46 -0
  72. package/src/stateRegistry.ts +11 -5
  73. package/src/zoneAccessory.ts +36 -14
@@ -0,0 +1,50 @@
1
+ import type { Logger } from 'homebridge';
2
+ import { Fixture } from '../config.js';
3
+ import { HomeKitLightState } from '../color/types.js';
4
+ import { DmxController } from '../dmxController.js';
5
+ import { StateRegistry } from '../stateRegistry.js';
6
+ import { LookColor } from './colors.js';
7
+ import { Show } from './dsl.js';
8
+ export type ShowListener = (runningId: string | null) => void;
9
+ export declare class ShowEngine {
10
+ private readonly controllers;
11
+ private readonly registry;
12
+ private readonly log;
13
+ private run;
14
+ private listeners;
15
+ private lastEmitted;
16
+ private shows;
17
+ constructor(shows: Show[], controllers: Map<string, DmxController>, registry: StateRegistry, log: Logger);
18
+ running(): string | null;
19
+ onChange(cb: ShowListener): () => void;
20
+ start(id: string): void;
21
+ /** Stop the running show, freezing the lights where they are: the
22
+ * registry gets the last frame that actually went on the wire. `except`
23
+ * names a fixture whose registry state must NOT be overwritten (it was
24
+ * just set from HomeKit and is the reason we're stopping). */
25
+ stop(reason?: string, except?: string): void;
26
+ /** `notify: false` on a handoff inside start(): the switches hear one
27
+ * transition (A → B) instead of A → nothing → B, which would bounce
28
+ * the tapped tile off and back on. */
29
+ private stopRun;
30
+ shutdown(): void;
31
+ /** Notify switches of the running show — only on an actual transition,
32
+ * so the handoff inside start() (stop A, start B) doesn't bounce B's
33
+ * tile off and back on. */
34
+ private emit;
35
+ private fixture;
36
+ private tick;
37
+ private applyFinal;
38
+ /** Where every fixture is at wall-clock `now`. Null once a one-shot show
39
+ * has run past its end. */
40
+ private frameAt;
41
+ }
42
+ export declare function fromState(s: HomeKitLightState): LookColor;
43
+ /** Shape a look for a specific fixture: only the characteristics its color
44
+ * model exposes, HomeKit-style on/brightness. A dark look parks the
45
+ * brightness at 100 so the next HomeKit "on" restores full (mirrors
46
+ * hsvcct.parse). `precise` keeps fractional values — the wire path
47
+ * renders 16-bit intensity, so fades stay smooth below 1 % steps; the
48
+ * registry (HomeKit) gets integers. */
49
+ export declare function toState(look: LookColor, fx: Fixture, precise?: boolean): HomeKitLightState;
50
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/show/engine.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAW,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,MAAM,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;AAgB9D,qBAAa,UAAU;IAQnB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,KAAK,CAA2B;gBAGtC,KAAK,EAAE,IAAI,EAAE,EACI,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACvC,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,MAAM;IAY9B,OAAO,IAAI,MAAM,GAAG,IAAI;IAIxB,QAAQ,CAAC,EAAE,EAAE,YAAY,GAAG,MAAM,IAAI;IAKtC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IA0CvB;;;mEAG+D;IAC/D,IAAI,CAAC,MAAM,SAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAIpD;;2CAEuC;IACvC,OAAO,CAAC,OAAO;IAgBf,QAAQ,IAAI,IAAI;IAIhB;;gCAE4B;IAC5B,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,IAAI;IAiCZ,OAAO,CAAC,UAAU;IAalB;gCAC4B;IAC5B,OAAO,CAAC,OAAO;CAoChB;AAID,wBAAgB,SAAS,CAAC,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAMzD;AAED;;;;;wCAKwC;AACxC,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,UAAQ,GAAG,iBAAiB,CAexF"}
@@ -0,0 +1,264 @@
1
+ // ShowEngine — runs at most one show at a time.
2
+ //
3
+ // Every frame (the involved controllers' fastest frame interval, 25 Hz on
4
+ // sACN) the engine works out where each fixture is between the previous
5
+ // step's look and the current one, renders it through the controller
6
+ // (quietly — no per-frame logging) and moves on. The registry only hears
7
+ // about it at step boundaries (throttled) and when the show stops, so
8
+ // HomeKit tiles track the show without a 25 Hz event storm.
9
+ //
10
+ // Rules:
11
+ // - starting a show stops whichever one was running (its switch flips off)
12
+ // - the first fade starts from the fixtures' live registry state, so a
13
+ // show fades IN from whatever the lights were doing
14
+ // - stopping freezes the lights on the current frame and writes that
15
+ // frame to the registry (so tiles are accurate)
16
+ // - a HomeKit change to any fixture in the running show stops the show;
17
+ // the fixture that was touched keeps the user's new value
18
+ import { SHOW_FRAME_MS_DEFAULT, SHOW_KEYFRAME_MIN_MS } from '../settings.js';
19
+ import { mixLook } from './colors.js';
20
+ export class ShowEngine {
21
+ controllers;
22
+ registry;
23
+ log;
24
+ run = null;
25
+ listeners = new Set();
26
+ lastEmitted = null;
27
+ shows = new Map();
28
+ constructor(shows, controllers, registry, log) {
29
+ this.controllers = controllers;
30
+ this.registry = registry;
31
+ this.log = log;
32
+ for (const s of shows)
33
+ this.shows.set(s.id, s);
34
+ // Any HomeKit change to a fixture in the running show ends the show.
35
+ registry.onChange((id, source) => {
36
+ if (source !== 'homekit' || !this.run)
37
+ return;
38
+ if (this.run.fixtures.has(id)) {
39
+ this.stop(`"${id}" changed from HomeKit`, id);
40
+ }
41
+ });
42
+ }
43
+ running() {
44
+ return this.run?.show.id ?? null;
45
+ }
46
+ onChange(cb) {
47
+ this.listeners.add(cb);
48
+ return () => this.listeners.delete(cb);
49
+ }
50
+ start(id) {
51
+ const show = this.shows.get(id);
52
+ if (!show) {
53
+ this.log.error(`show "${id}": unknown`);
54
+ return;
55
+ }
56
+ if (!show.runnable) {
57
+ this.log.error(`show "${id}": unbound params (${show.unboundParams.join(', ')})`);
58
+ return;
59
+ }
60
+ if (this.run?.show.id === id)
61
+ return;
62
+ if (this.run)
63
+ this.stopRun(`"${id}" starting`, undefined, false);
64
+ const snapshot = new Map();
65
+ for (const fx of show.fixtures)
66
+ snapshot.set(fx.id, fromState(this.registry.get(fx.id)));
67
+ // One timer drives every involved controller, so tick at the SLOWEST
68
+ // frame interval among them: flooding the Stick with 25 Hz sets would
69
+ // keep resetting its debounce and it would never transact at all.
70
+ const frameMs = show.fixtures.reduce((max, fx) => {
71
+ const c = this.controllers.get(fx.controller.id);
72
+ return Math.max(max, c?.frameIntervalMs ?? SHOW_FRAME_MS_DEFAULT);
73
+ }, 0) || SHOW_FRAME_MS_DEFAULT;
74
+ const run = {
75
+ show,
76
+ startedAt: Date.now(),
77
+ timer: setInterval(() => this.tick(), frameMs),
78
+ snapshot,
79
+ fixtures: new Map(show.fixtures.map((f) => [f.id, f])),
80
+ frameMs,
81
+ lastFrame: null,
82
+ lastKeyframeStep: -1,
83
+ lastKeyframeAt: 0,
84
+ };
85
+ run.timer.unref?.();
86
+ this.run = run;
87
+ this.log.info(`show "${show.id}" started: ${show.steps.length} steps, ${show.fixtures.length} fixtures, ` +
88
+ `cycle ${(show.cycleMs / 1000).toFixed(1)} s, ${show.loop ? 'looping' : 'one-shot'}, ` +
89
+ `${frameMs} ms frames`);
90
+ this.tick();
91
+ this.emit();
92
+ }
93
+ /** Stop the running show, freezing the lights where they are: the
94
+ * registry gets the last frame that actually went on the wire. `except`
95
+ * names a fixture whose registry state must NOT be overwritten (it was
96
+ * just set from HomeKit and is the reason we're stopping). */
97
+ stop(reason = 'switched off', except) {
98
+ this.stopRun(reason, except, true);
99
+ }
100
+ /** `notify: false` on a handoff inside start(): the switches hear one
101
+ * transition (A → B) instead of A → nothing → B, which would bounce
102
+ * the tapped tile off and back on. */
103
+ stopRun(reason, except, notify) {
104
+ const run = this.run;
105
+ if (!run)
106
+ return;
107
+ clearInterval(run.timer);
108
+ this.run = null;
109
+ // Before the first tick nothing has been sent; after a one-shot's end
110
+ // the final look is on the wire (see applyFinal).
111
+ const frozen = run.lastFrame ?? run.show.steps[run.show.steps.length - 1].targets;
112
+ for (const [id, look] of frozen) {
113
+ if (id === except)
114
+ continue;
115
+ this.registry.set(id, toState(look, this.fixture(run, id)), 'show');
116
+ }
117
+ this.log.info(`show "${run.show.id}" stopped (${reason})`);
118
+ if (notify)
119
+ this.emit();
120
+ }
121
+ shutdown() {
122
+ if (this.run) {
123
+ clearInterval(this.run.timer);
124
+ this.run = null;
125
+ }
126
+ }
127
+ /** Notify switches of the running show — only on an actual transition,
128
+ * so the handoff inside start() (stop A, start B) doesn't bounce B's
129
+ * tile off and back on. */
130
+ emit() {
131
+ const id = this.running();
132
+ if (id === this.lastEmitted)
133
+ return;
134
+ this.lastEmitted = id;
135
+ for (const l of this.listeners)
136
+ l(id);
137
+ }
138
+ fixture(run, id) {
139
+ return run.fixtures.get(id);
140
+ }
141
+ tick() {
142
+ const run = this.run;
143
+ if (!run)
144
+ return;
145
+ const now = Date.now();
146
+ const frame = this.frameAt(run, now);
147
+ if (!frame) {
148
+ // One-shot show ran off the end: land on the final look and stop.
149
+ this.applyFinal(run);
150
+ return;
151
+ }
152
+ for (const [id, look] of frame.looks) {
153
+ const fx = this.fixture(run, id);
154
+ const c = this.controllers.get(fx.controller.id);
155
+ c?.setFixture(fx, toState(look, fx, true), { quiet: true });
156
+ }
157
+ run.lastFrame = frame.looks;
158
+ // Keyframe: on entering a new step, tell the registry where the lights
159
+ // are heading — the step's destination, not the in-between value, so
160
+ // a long fade shows its target for the whole fade. Throttled so fast
161
+ // chases don't flood HomeKit; on a sub-second chase the tiles lag by
162
+ // an unbounded amount, which is fine for a chase.
163
+ if (now - run.lastKeyframeAt >= SHOW_KEYFRAME_MIN_MS) {
164
+ run.lastKeyframeAt = now;
165
+ if (frame.step !== run.lastKeyframeStep) {
166
+ run.lastKeyframeStep = frame.step;
167
+ const targets = run.show.steps[frame.step].targets;
168
+ for (const [id, look] of targets) {
169
+ this.registry.set(id, toState(look, this.fixture(run, id)), 'show');
170
+ }
171
+ }
172
+ }
173
+ }
174
+ applyFinal(run) {
175
+ clearInterval(run.timer);
176
+ this.run = null; // before any registry write, same as stop()
177
+ const last = run.show.steps[run.show.steps.length - 1];
178
+ for (const [id, look] of last.targets) {
179
+ const fx = this.fixture(run, id);
180
+ this.controllers.get(fx.controller.id)?.setFixture(fx, toState(look, fx, true), { quiet: true });
181
+ this.registry.set(id, toState(look, fx), 'show');
182
+ }
183
+ this.log.info(`show "${run.show.id}" finished`);
184
+ this.emit();
185
+ }
186
+ /** Where every fixture is at wall-clock `now`. Null once a one-shot show
187
+ * has run past its end. */
188
+ frameAt(run, now) {
189
+ const { show, snapshot } = run;
190
+ let e = now - run.startedAt;
191
+ let firstCycle = true;
192
+ if (show.loop) {
193
+ if (e >= show.cycleMs) {
194
+ firstCycle = false;
195
+ e = e % show.cycleMs;
196
+ }
197
+ }
198
+ else if (e >= show.cycleMs) {
199
+ return null;
200
+ }
201
+ // Locate the step and the position within its fade/hold.
202
+ let i = 0;
203
+ let t = 1;
204
+ let acc = 0;
205
+ for (; i < show.steps.length; i++) {
206
+ const st = show.steps[i];
207
+ const len = st.fadeMs + st.holdMs;
208
+ if (e < acc + len || i === show.steps.length - 1) {
209
+ const local = e - acc;
210
+ t = st.fadeMs > 0 ? Math.min(1, local / st.fadeMs) : 1;
211
+ break;
212
+ }
213
+ acc += len;
214
+ }
215
+ const st = show.steps[i];
216
+ const from = i > 0 ? show.steps[i - 1].targets
217
+ : firstCycle ? null : show.steps[show.steps.length - 1].targets;
218
+ const eased = st.ease === 'sine' ? (1 - Math.cos(Math.PI * t)) / 2 : t;
219
+ const looks = new Map();
220
+ for (const fx of show.fixtures) {
221
+ const start = snapshot.get(fx.id);
222
+ const a = from?.get(fx.id) ?? start;
223
+ const b = st.targets.get(fx.id) ?? start;
224
+ looks.set(fx.id, mixLook(a, b, eased));
225
+ }
226
+ return { step: i, looks };
227
+ }
228
+ }
229
+ // ── LookColor ↔ HomeKitLightState ──────────────────────────────────────────
230
+ export function fromState(s) {
231
+ const out = { brightness: s.on ? s.brightness : 0 };
232
+ if (s.hue != null)
233
+ out.hue = s.hue;
234
+ if (s.saturation != null)
235
+ out.saturation = s.saturation;
236
+ if (s.colorTemperatureMireds != null)
237
+ out.mireds = s.colorTemperatureMireds;
238
+ return out;
239
+ }
240
+ /** Shape a look for a specific fixture: only the characteristics its color
241
+ * model exposes, HomeKit-style on/brightness. A dark look parks the
242
+ * brightness at 100 so the next HomeKit "on" restores full (mirrors
243
+ * hsvcct.parse). `precise` keeps fractional values — the wire path
244
+ * renders 16-bit intensity, so fades stay smooth below 1 % steps; the
245
+ * registry (HomeKit) gets integers. */
246
+ export function toState(look, fx, precise = false) {
247
+ const chars = fx.profile.model.characteristics;
248
+ const r = precise ? (n) => n : Math.round;
249
+ const on = look.brightness > 0.5;
250
+ const s = {
251
+ on,
252
+ brightness: on ? Math.max(1, r(look.brightness)) : 100,
253
+ };
254
+ const colorMode = look.hue != null && (look.saturation ?? 0) > 0;
255
+ if (chars.includes('Hue') && look.hue != null)
256
+ s.hue = r(look.hue);
257
+ if (chars.includes('Saturation'))
258
+ s.saturation = r(look.saturation ?? 0);
259
+ if (chars.includes('ColorTemperature') && look.mireds != null && !colorMode) {
260
+ s.colorTemperatureMireds = r(look.mireds);
261
+ }
262
+ return s;
263
+ }
264
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/show/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { PlatformAccessory } from 'homebridge';
2
+ import type { DmxPlatform } from './platform.js';
3
+ import { Show } from './show/dsl.js';
4
+ import { ShowEngine } from './show/engine.js';
5
+ export declare class ShowSwitch {
6
+ private sw;
7
+ constructor(platform: DmxPlatform, accessory: PlatformAccessory, show: Show, engine: ShowEngine);
8
+ }
9
+ //# sourceMappingURL=showAccessory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showAccessory.d.ts","sourceRoot":"","sources":["../src/showAccessory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAU;gBAGlB,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,UAAU;CAwBrB"}
@@ -0,0 +1,33 @@
1
+ // ShowSwitch — one HomeKit Switch per runnable show.
2
+ //
3
+ // On → engine.start(id): whatever show was running stops (its own switch
4
+ // flips off through the engine's change listener).
5
+ // Off → engine.stop(): lights freeze on the current frame.
6
+ // The switch also flips off by itself when a one-shot show finishes or a
7
+ // user touches one of the show's lights.
8
+ export class ShowSwitch {
9
+ sw;
10
+ constructor(platform, accessory, show, engine) {
11
+ const C = platform.Characteristic;
12
+ const info = accessory.getService(platform.Service.AccessoryInformation);
13
+ info?.setCharacteristic(C.Manufacturer, 'DMX')
14
+ ?.setCharacteristic(C.Model, `Show (${show.steps.length} steps, ${show.fixtures.length} fixtures)`)
15
+ ?.setCharacteristic(C.SerialNumber, `show-${show.id}`);
16
+ this.sw =
17
+ accessory.getService(platform.Service.Switch)
18
+ ?? accessory.addService(platform.Service.Switch, show.name);
19
+ this.sw.setCharacteristic(C.Name, show.name);
20
+ this.sw.getCharacteristic(C.On)
21
+ .onGet(() => engine.running() === show.id)
22
+ .onSet((v) => {
23
+ if (v)
24
+ engine.start(show.id);
25
+ else if (engine.running() === show.id)
26
+ engine.stop();
27
+ });
28
+ engine.onChange((runningId) => {
29
+ this.sw.updateCharacteristic(C.On, runningId === show.id);
30
+ });
31
+ }
32
+ }
33
+ //# sourceMappingURL=showAccessory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showAccessory.js","sourceRoot":"","sources":["../src/showAccessory.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,0EAA0E;AAC1E,yDAAyD;AACzD,2DAA2D;AAC3D,yEAAyE;AACzE,yCAAyC;AAQzC,MAAM,OAAO,UAAU;IACb,EAAE,CAAU;IAEpB,YACE,QAAqB,EACrB,SAA4B,EAC5B,IAAU,EACV,MAAkB;QAElB,MAAM,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC;QAClC,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACzE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC;YAC1C,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC,KAAK,CAAC,MAAM,WAAW,IAAI,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC;YACnG,EAAE,iBAAiB,CAAC,CAAC,CAAC,YAAY,EAAE,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAE3D,IAAI,CAAC,EAAE;YACL,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;mBAC1C,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5B,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;aACzC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACX,IAAI,CAAC;gBAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;iBACxB,IAAI,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE;gBAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QACvD,CAAC,CAAC,CAAC;QAEL,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE;YAC5B,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1,14 +1,19 @@
1
1
  import { HomeKitLightState } from './color/types.js';
2
- export type StateChangeListener = (fixtureId: string) => void;
2
+ /** Who made a change. Accessories write as 'homekit' (the default);
3
+ * the gateway read-back writes 'sync'; the show engine writes 'show'.
4
+ * The engine uses this to end a show when a user touches one of its
5
+ * lights without reacting to its own keyframes or to read-back. */
6
+ export type StateSource = 'homekit' | 'sync' | 'show';
7
+ export type StateChangeListener = (fixtureId: string, source: StateSource) => void;
3
8
  export declare class StateRegistry {
4
9
  private states;
5
10
  private listeners;
6
11
  get(id: string): HomeKitLightState;
7
12
  /** Replace a fixture's state and fire change listeners. */
8
- set(id: string, state: HomeKitLightState): void;
13
+ set(id: string, state: HomeKitLightState, source?: StateSource): void;
9
14
  /** Merge a partial update into a fixture's state, returning the new full
10
15
  * state. Fires listeners. */
11
- update(id: string, patch: Partial<HomeKitLightState>): HomeKitLightState;
16
+ update(id: string, patch: Partial<HomeKitLightState>, source?: StateSource): HomeKitLightState;
12
17
  onChange(cb: StateChangeListener): () => void;
13
18
  }
14
19
  /** Bucket members' values; return the value with the largest bucket. Ties
@@ -1 +1 @@
1
- {"version":3,"file":"stateRegistry.d.ts","sourceRoot":"","sources":["../src/stateRegistry.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AAI9D,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,SAAS,CAAkC;IAEnD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB;IAIlC,2DAA2D;IAC3D,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAK/C;kCAC8B;IAC9B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,iBAAiB;IAMxE,QAAQ,CAAC,EAAE,EAAE,mBAAmB,GAAG,MAAM,IAAI;CAI9C;AAED;;6BAE6B;AAC7B,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAoBjF"}
1
+ {"version":3,"file":"stateRegistry.d.ts","sourceRoot":"","sources":["../src/stateRegistry.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;oEAGoE;AACpE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtD,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;AAInF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,SAAS,CAAkC;IAEnD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB;IAIlC,2DAA2D;IAC3D,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,GAAE,WAAuB,GAAG,IAAI;IAKhF;kCAC8B;IAC9B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAE,WAAuB,GAAG,iBAAiB;IAMzG,QAAQ,CAAC,EAAE,EAAE,mBAAmB,GAAG,MAAM,IAAI;CAI9C;AAED;;6BAE6B;AAC7B,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAoBjF"}
@@ -18,16 +18,16 @@ export class StateRegistry {
18
18
  return this.states.get(id) ?? { ...DEFAULT_STATE };
19
19
  }
20
20
  /** Replace a fixture's state and fire change listeners. */
21
- set(id, state) {
21
+ set(id, state, source = 'homekit') {
22
22
  this.states.set(id, { ...state });
23
23
  for (const l of this.listeners)
24
- l(id);
24
+ l(id, source);
25
25
  }
26
26
  /** Merge a partial update into a fixture's state, returning the new full
27
27
  * state. Fires listeners. */
28
- update(id, patch) {
28
+ update(id, patch, source = 'homekit') {
29
29
  const next = { ...this.get(id), ...patch };
30
- this.set(id, next);
30
+ this.set(id, next, source);
31
31
  return next;
32
32
  }
33
33
  onChange(cb) {
@@ -1 +1 @@
1
- {"version":3,"file":"stateRegistry.js","sourceRoot":"","sources":["../src/stateRegistry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stateRegistry.js","sourceRoot":"","sources":["../src/stateRegistry.ts"],"names":[],"mappings":"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"}
@@ -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;IAiBtB;qDACiD;IACjD,OAAO,CAAC,gBAAgB;IAuBxB;8CAC0C;IAC1C,OAAO,CAAC,eAAe;CAyBxB;AAGD,MAAM,MAAM,UAAU,GAAG,OAAO,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"}
@@ -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.majorityState().hue ?? 0)
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.majorityState().saturation ?? 0)
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.majorityState().colorTemperatureMireds ?? 200)
63
+ .onGet(() => this.display().ct)
63
64
  .onSet((v) => this.applyToMembers({
64
65
  colorTemperatureMireds: Number(v),
65
66
  saturation: 0,
@@ -83,6 +84,24 @@ 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
@@ -134,23 +153,27 @@ export class ZoneFixture {
134
153
  this.refreshPending = setTimeout(() => {
135
154
  this.refreshPending = null;
136
155
  const s = this.majorityState();
156
+ const d = this.display();
137
157
  const C = this.platform.Characteristic;
138
158
  this.bulb.updateCharacteristic(C.On, s.on);
139
159
  if (this.zone.characteristics.includes('Brightness')) {
140
160
  this.bulb.updateCharacteristic(C.Brightness, s.brightness);
141
161
  }
142
- if (this.zone.characteristics.includes('Hue') && s.hue != null) {
143
- this.bulb.updateCharacteristic(C.Hue, s.hue);
162
+ if (this.zone.characteristics.includes('Hue')) {
163
+ this.bulb.updateCharacteristic(C.Hue, d.hue);
144
164
  }
145
- if (this.zone.characteristics.includes('Saturation') && s.saturation != null) {
146
- this.bulb.updateCharacteristic(C.Saturation, s.saturation);
165
+ if (this.zone.characteristics.includes('Saturation')) {
166
+ this.bulb.updateCharacteristic(C.Saturation, d.saturation);
147
167
  }
148
- // Same rule as StickFixture.pushFromRegistry: the Home app displays
149
- // whichever mode updated last, so only push ColorTemperature when the
150
- // zone majority is actually in white mode (sat 0).
151
- if (this.zone.characteristics.includes('ColorTemperature') && s.colorTemperatureMireds != null
152
- && (s.saturation ?? 0) === 0) {
153
- this.bulb.updateCharacteristic(C.ColorTemperature, s.colorTemperatureMireds);
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
+ }
154
177
  }
155
178
  }, CHARACTERISTIC_UPDATE_DELAY_MS);
156
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;AAYzC,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAiB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,OAAO,WAAW;IAMH;IAEA;IACA;IACA;IATX,OAAO,GAA0B,IAAI,CAAC;IACtC,cAAc,GAA0B,IAAI,CAAC;IAC7C,IAAI,CAAU;IAEtB,YACmB,QAAqB,EACtC,SAA4B,EACX,IAAU,EACV,WAAuC,EACvC,QAAuB;QAJvB,aAAQ,GAAR,QAAQ,CAAa;QAErB,SAAI,GAAJ,IAAI,CAAM;QACV,gBAAW,GAAX,WAAW,CAA4B;QACvC,aAAQ,GAAR,QAAQ,CAAe;QAExC,MAAM,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC;QAClC,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACzE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC;YAC1C,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,YAAY,CAAC;YACtE,EAAE,iBAAiB,CAAC,CAAC,CAAC,YAAY,EAAE,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAE3D,IAAI,CAAC,IAAI;YACP,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC;mBAC7C,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjE,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/C,MAAM,GAAG,GAAG,CAAC,CAAmB,EAAW,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE/E,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9B,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC;aACpC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEzD,IAAI,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC;iBACtC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC;iBAC5C,KAAK,CAAC,CAAC,CAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC;iBAC/B,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;iBAC1C,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC;iBACtC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,UAAU,IAAI,CAAC,CAAC;iBACjD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,CAAC;iBAC5C,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,sBAAsB,IAAI,GAAG,CAAC;iBAC/D,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;gBAChC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjC,UAAU,EAAE,CAAC;aACd,CAAC,CAAC,CAAC;QACR,CAAC;QAED,gCAAgC;QAChC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzD,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE;YACvB,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,IAAI,CAAC,eAAe,EAAE,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,iEAAiE;IACzD,aAAa;QACnB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxF,OAAO;YACL,EAAE,EAAwB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK;YAC7F,UAAU,EAAgB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG;YACnG,GAAG,EAAuB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACrF,UAAU,EAAgB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YAC5F,sBAAsB,EAAI,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;SACzG,CAAC;IACJ,CAAC;IAED;;;mDAG+C;IACvC,cAAc,CAAC,KAAiC;QACtD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC;QACnD,uEAAuE;QACvE,uEAAuE;QACvE,4DAA4D;QAC5D,IAAI,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC,sBAAsB,CAAC;QACrC,CAAC;QACD,qEAAqE;QACrE,uEAAuE;QACvE,sCAAsC;QACtC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAED;qDACiD;IACzC,gBAAgB;QACtB,IAAI,IAAI,CAAC,OAAO;YAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CACpB,SAAS,IAAI,CAAC,IAAI,CAAC,EAAE,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,UAAU,EAAE;gBAC9D,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClD,CAAC,CAAC,CAAC,sBAAsB,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,UAAU,CACzC,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBAChD,IAAI,CAAC,CAAC,EAAE,CAAC;oBACP,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,EAAE,yBAAyB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBAC/E,SAAS;gBACX,CAAC;gBACD,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC,EAAE,8BAA8B,CAAC,CAAC;IACrC,CAAC;IAED;8CAC0C;IAClC,eAAe;QACrB,IAAI,IAAI,CAAC,cAAc;YAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3C,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACrD,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;YAC7D,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;gBAC/D,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;gBAC7E,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;YAC7D,CAAC;YACD,oEAAoE;YACpE,sEAAsE;YACtE,mDAAmD;YACnD,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,sBAAsB,IAAI,IAAI;mBACvF,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,sBAAsB,CAAC,CAAC;YAC/E,CAAC;QACH,CAAC,EAAE,8BAA8B,CAAC,CAAC;IACrC,CAAC;CACF"}
1
+ {"version":3,"file":"zoneAccessory.js","sourceRoot":"","sources":["../src/zoneAccessory.ts"],"names":[],"mappings":"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"}