@ecopoesis/homebridge-dmx 0.5.5 → 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.
- package/CLAUDE.md +1 -0
- package/README.md +67 -0
- package/config.schema.json +104 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -1
- package/dist/config.js.map +1 -1
- package/dist/controller.d.ts +3 -2
- package/dist/controller.d.ts.map +1 -1
- package/dist/controller.js +7 -4
- package/dist/controller.js.map +1 -1
- package/dist/dmxController.d.ts +9 -1
- package/dist/dmxController.d.ts.map +1 -1
- package/dist/platform.d.ts +1 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +37 -2
- package/dist/platform.js.map +1 -1
- package/dist/sacn.d.ts +3 -2
- package/dist/sacn.d.ts.map +1 -1
- package/dist/sacn.js +7 -4
- package/dist/sacn.js.map +1 -1
- package/dist/settings.d.ts +13 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +14 -0
- package/dist/settings.js.map +1 -1
- package/dist/show/colors.d.ts +25 -0
- package/dist/show/colors.d.ts.map +1 -0
- package/dist/show/colors.js +216 -0
- package/dist/show/colors.js.map +1 -0
- package/dist/show/dsl.d.ts +56 -0
- package/dist/show/dsl.d.ts.map +1 -0
- package/dist/show/dsl.js +326 -0
- package/dist/show/dsl.js.map +1 -0
- package/dist/show/engine.d.ts +50 -0
- package/dist/show/engine.d.ts.map +1 -0
- package/dist/show/engine.js +264 -0
- package/dist/show/engine.js.map +1 -0
- package/dist/showAccessory.d.ts +9 -0
- package/dist/showAccessory.d.ts.map +1 -0
- package/dist/showAccessory.js +33 -0
- package/dist/showAccessory.js.map +1 -0
- package/dist/stateRegistry.d.ts +8 -3
- package/dist/stateRegistry.d.ts.map +1 -1
- package/dist/stateRegistry.js +4 -4
- package/dist/stateRegistry.js.map +1 -1
- package/examples/dmx.yaml +76 -0
- package/package.json +1 -1
- package/src/config.ts +22 -1
- package/src/controller.ts +8 -5
- package/src/dmxController.ts +10 -1
- package/src/platform.ts +35 -2
- package/src/sacn.ts +8 -4
- package/src/settings.ts +19 -0
- package/src/show/colors.ts +224 -0
- package/src/show/dsl.ts +370 -0
- package/src/show/engine.ts +280 -0
- package/src/showAccessory.ts +46 -0
- package/src/stateRegistry.ts +11 -5
|
@@ -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"}
|
package/dist/stateRegistry.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { HomeKitLightState } from './color/types.js';
|
|
2
|
-
|
|
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
|
|
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;
|
|
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"}
|
package/dist/stateRegistry.js
CHANGED
|
@@ -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":"AAAA,0EAA0E;AAC1E,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,uEAAuE;AACvE,uEAAuE;AACvE,oEAAoE;AACpE,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,UAAU;
|
|
1
|
+
{"version":3,"file":"stateRegistry.js","sourceRoot":"","sources":["../src/stateRegistry.ts"],"names":[],"mappings":"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"}
|
package/examples/dmx.yaml
CHANGED
|
@@ -74,3 +74,79 @@ patch:
|
|
|
74
74
|
type: Dimmer
|
|
75
75
|
controller: main
|
|
76
76
|
start: 200
|
|
77
|
+
|
|
78
|
+
zones:
|
|
79
|
+
# Virtual multi-member Lightbulbs. Also handy as show targets.
|
|
80
|
+
- id: up
|
|
81
|
+
name: Up Lights
|
|
82
|
+
members: [a_down] # list every "up" fixture here
|
|
83
|
+
|
|
84
|
+
groups:
|
|
85
|
+
# Named fixture sets for show looks. Unlike zones they create no HomeKit
|
|
86
|
+
# tile. Members may be fixture ids or zone ids.
|
|
87
|
+
odd: [a_down, shed_dimmer]
|
|
88
|
+
even: [post_light]
|
|
89
|
+
|
|
90
|
+
palette:
|
|
91
|
+
# Optional color names for shows. Any CSS color name already works
|
|
92
|
+
# (indigo, hotpink, orange, ...); add gel names or brand colors here.
|
|
93
|
+
# Names match ignoring case, spaces, dashes and underscores.
|
|
94
|
+
surprise pink: "#f2a1ff"
|
|
95
|
+
boat teal: "hsv(180, 80, 100)"
|
|
96
|
+
|
|
97
|
+
shows:
|
|
98
|
+
# Timed light shows. Each runnable show is a HomeKit Switch; only one
|
|
99
|
+
# show runs at a time (starting one stops the other); shows loop unless
|
|
100
|
+
# `loop: false`; turning the switch off freezes the lights where they
|
|
101
|
+
# are; touching one of a show's lights from HomeKit stops the show.
|
|
102
|
+
#
|
|
103
|
+
# A show is a list of STEPS. Each step has a LOOK (target → color), a
|
|
104
|
+
# FADE time to crossfade into it, and a HOLD time to sit on it. Targets
|
|
105
|
+
# unmentioned in a step keep their previous value (tracking). Targets
|
|
106
|
+
# are fixture ids, zone ids, group ids or `all`. Times are seconds or
|
|
107
|
+
# "500ms".
|
|
108
|
+
#
|
|
109
|
+
# Colors: CSS names, palette names, "#hex", "3000K", "hsv(h, s, v)",
|
|
110
|
+
# "off"; append "@ 60%" to set brightness (CSS colors otherwise take
|
|
111
|
+
# their own value, so "indigo" is dimmer than "blue").
|
|
112
|
+
|
|
113
|
+
# A parameterized template. Params with `~` (null) have no default, so
|
|
114
|
+
# this show is a template only — no switch until something binds them.
|
|
115
|
+
- id: crossfade
|
|
116
|
+
params: { a: ~, b: ~, secs: 10 }
|
|
117
|
+
steps:
|
|
118
|
+
- look: { odd: $a, even: $b }
|
|
119
|
+
fade: $secs
|
|
120
|
+
- look: { odd: $b, even: $a }
|
|
121
|
+
fade: $secs
|
|
122
|
+
|
|
123
|
+
# Instances bind the params. Each becomes its own switch.
|
|
124
|
+
- id: texture
|
|
125
|
+
name: Texture
|
|
126
|
+
extends: crossfade
|
|
127
|
+
params: { a: indigo, b: surprise pink, secs: 20 }
|
|
128
|
+
|
|
129
|
+
- id: halloween
|
|
130
|
+
name: Halloween
|
|
131
|
+
extends: crossfade
|
|
132
|
+
params: { a: orange @ 100%, b: darkviolet, secs: 6 }
|
|
133
|
+
|
|
134
|
+
# A plain chase: no fades, quarter-second steps.
|
|
135
|
+
- id: chase
|
|
136
|
+
name: Chase
|
|
137
|
+
fade: 0
|
|
138
|
+
hold: 250ms
|
|
139
|
+
steps:
|
|
140
|
+
- look: { a_down: red, post_light: off }
|
|
141
|
+
- look: { a_down: off, post_light: red }
|
|
142
|
+
|
|
143
|
+
# A one-shot: runs once, then the switch turns itself off.
|
|
144
|
+
- id: sunrise
|
|
145
|
+
name: Sunrise
|
|
146
|
+
loop: false
|
|
147
|
+
ease: sine
|
|
148
|
+
steps:
|
|
149
|
+
- look: { all: "2000K @ 5%" }
|
|
150
|
+
fade: 2
|
|
151
|
+
- look: { all: "4000K @ 100%" }
|
|
152
|
+
fade: 5m
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
// "patch": [
|
|
23
23
|
// { "id": "a_down", "name": "A Down", "type": "WAC",
|
|
24
24
|
// "controller": "main", "universe": "A", "start": 6 }
|
|
25
|
-
// ]
|
|
25
|
+
// ],
|
|
26
|
+
// "zones": [ { "id": "up", "name": "Up Lights", "members": ["b_up", ...] } ],
|
|
27
|
+
// "groups": { "odd": ["b_up", ...] },
|
|
28
|
+
// "palette": { "surprise pink": "#f2a1ff" },
|
|
29
|
+
// "shows": [ ...see show/dsl.ts... ]
|
|
26
30
|
// }
|
|
27
31
|
//
|
|
28
32
|
// Output: a normalized `LoadedConfig` the platform consumes. Validates:
|
|
@@ -41,6 +45,7 @@ import { ChannelDef, ColorModel, HKCharacteristic } from './color/types.js';
|
|
|
41
45
|
import { REFRESH_MINUTES_DEFAULT, SACN_PRIORITY_DEFAULT } from './settings.js';
|
|
42
46
|
import { getColorModel } from './color/index.js';
|
|
43
47
|
import { parseChannelName } from './color/parsers.js';
|
|
48
|
+
import { Show, ShowSpec, loadShows, parseGroups, parsePalette } from './show/dsl.js';
|
|
44
49
|
|
|
45
50
|
export interface ControllerSpec {
|
|
46
51
|
id: string; // unique handle, referenced from patch entries
|
|
@@ -79,6 +84,9 @@ export interface RawConfig {
|
|
|
79
84
|
profiles?: ProfileSpec[];
|
|
80
85
|
patch?: PatchSpec[];
|
|
81
86
|
zones?: ZoneSpec[];
|
|
87
|
+
groups?: Record<string, string[]>; // show targets: group id → fixture/zone ids (no HomeKit tile)
|
|
88
|
+
palette?: Record<string, unknown>; // show color names → specs (see show/colors.ts)
|
|
89
|
+
shows?: ShowSpec[]; // see show/dsl.ts
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
export interface Profile {
|
|
@@ -124,6 +132,7 @@ export interface LoadedConfig {
|
|
|
124
132
|
controllers: Controller[];
|
|
125
133
|
fixtures: Fixture[];
|
|
126
134
|
zones: Zone[];
|
|
135
|
+
shows: Show[];
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
export const DEFAULT_PLATFORM_NAME = 'DMX';
|
|
@@ -323,10 +332,22 @@ export function loadConfig(rawJson: RawConfig, cwd?: string): LoadedConfig {
|
|
|
323
332
|
});
|
|
324
333
|
}
|
|
325
334
|
|
|
335
|
+
// Shows — parameterized step lists, each runnable one a HomeKit Switch.
|
|
336
|
+
const showSpecs = raw.shows ?? [];
|
|
337
|
+
if (!Array.isArray(showSpecs)) throw new Error('shows: must be an array');
|
|
338
|
+
const groups = parseGroups(raw.groups, fixtures, zones);
|
|
339
|
+
const shows = loadShows(showSpecs, fixtures, zones, groups, parsePalette(raw.palette));
|
|
340
|
+
for (const s of shows) {
|
|
341
|
+
if (fixturesById.has(s.id) || seenZoneIds.has(s.id) || groups.has(s.id)) {
|
|
342
|
+
throw new Error(`show id "${s.id}" collides with a fixture, zone or group id`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
326
346
|
return {
|
|
327
347
|
name: raw.name ?? DEFAULT_PLATFORM_NAME,
|
|
328
348
|
controllers: [...controllersById.values()],
|
|
329
349
|
fixtures,
|
|
330
350
|
zones,
|
|
351
|
+
shows,
|
|
331
352
|
};
|
|
332
353
|
}
|
package/src/controller.ts
CHANGED
|
@@ -15,8 +15,8 @@ import path from 'node:path';
|
|
|
15
15
|
|
|
16
16
|
import { Fixture } from './config.js';
|
|
17
17
|
import { HomeKitLightState } from './color/types.js';
|
|
18
|
-
import { DmxController } from './dmxController.js';
|
|
19
|
-
import { DEBOUNCE_MS, REFRESH_CHECK_MS } from './settings.js';
|
|
18
|
+
import { DmxController, SetOptions } from './dmxController.js';
|
|
19
|
+
import { DEBOUNCE_MS, REFRESH_CHECK_MS, STICK_FRAME_MS } from './settings.js';
|
|
20
20
|
import { sleep } from './stick/protocol.js';
|
|
21
21
|
|
|
22
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -35,6 +35,7 @@ export class StickController implements DmxController {
|
|
|
35
35
|
* we can't detect in-band) the probe is required to (re-)register
|
|
36
36
|
* the client. Subsequent subprocesses can skip it. */
|
|
37
37
|
private needsProbe = true;
|
|
38
|
+
readonly frameIntervalMs = STICK_FRAME_MS;
|
|
38
39
|
|
|
39
40
|
constructor(
|
|
40
41
|
private readonly ip: string,
|
|
@@ -68,15 +69,17 @@ export class StickController implements DmxController {
|
|
|
68
69
|
|
|
69
70
|
/** Stage a fixture's bytes into the universe target buffer and ensure
|
|
70
71
|
* the streaming loop is running. */
|
|
71
|
-
setFixture(fixture: Fixture, state: HomeKitLightState): void {
|
|
72
|
+
setFixture(fixture: Fixture, state: HomeKitLightState, opts?: SetOptions): void {
|
|
72
73
|
const arr = this.universeBuf(fixture.universe);
|
|
73
74
|
const bytes = fixture.profile.model.render(state, fixture.profile.channels);
|
|
74
75
|
for (let i = 0; i < bytes.length; i++) {
|
|
75
76
|
arr[fixture.startCh - 1 + i] = bytes[i];
|
|
76
77
|
}
|
|
77
78
|
this.lastChangeAt = Date.now();
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
if (!opts?.quiet) {
|
|
80
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
81
|
+
this.log.info(`setFixture ${fixture.id}@DMX${fixture.startCh}=${hex} streaming=${this.streaming}`);
|
|
82
|
+
}
|
|
80
83
|
if (!this.streaming) {
|
|
81
84
|
this.streaming = true;
|
|
82
85
|
this.run().catch((e) => {
|
package/src/dmxController.ts
CHANGED
|
@@ -4,11 +4,20 @@
|
|
|
4
4
|
import { Fixture } from './config.js';
|
|
5
5
|
import { HomeKitLightState } from './color/types.js';
|
|
6
6
|
|
|
7
|
+
export interface SetOptions {
|
|
8
|
+
/** Skip per-call info logging (the show engine calls at frame rate). */
|
|
9
|
+
quiet?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
7
12
|
export interface DmxController {
|
|
8
13
|
/** Render `state` through the fixture's color model into the universe
|
|
9
14
|
* buffer and (eventually) put it on the wire. Must be safe to call at
|
|
10
15
|
* HomeKit interaction rates. */
|
|
11
|
-
setFixture(fixture: Fixture, state: HomeKitLightState): void;
|
|
16
|
+
setFixture(fixture: Fixture, state: HomeKitLightState, opts?: SetOptions): void;
|
|
17
|
+
/** How often a show may push a new frame through this controller.
|
|
18
|
+
* Streaming transports (sACN) take 25 Hz; the Stick's subprocess
|
|
19
|
+
* transaction costs seconds, so shows on it step coarsely. */
|
|
20
|
+
readonly frameIntervalMs: number;
|
|
12
21
|
/** Homebridge shutdown hook: stop timers, close sockets. */
|
|
13
22
|
shutdown(): void;
|
|
14
23
|
}
|
package/src/platform.ts
CHANGED
|
@@ -20,6 +20,8 @@ import { DmxController } from './dmxController.js';
|
|
|
20
20
|
import { readEthergateUniverse } from './ethergate.js';
|
|
21
21
|
import { SacnController } from './sacn.js';
|
|
22
22
|
import { StickFixture } from './platformAccessory.js';
|
|
23
|
+
import { ShowEngine } from './show/engine.js';
|
|
24
|
+
import { ShowSwitch } from './showAccessory.js';
|
|
23
25
|
import { StateRegistry } from './stateRegistry.js';
|
|
24
26
|
import { ZoneFixture } from './zoneAccessory.js';
|
|
25
27
|
import { DEBOUNCE_MS, PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
|
|
@@ -32,6 +34,7 @@ export class DmxPlatform implements DynamicPlatformPlugin {
|
|
|
32
34
|
private cfg: LoadedConfig | null = null;
|
|
33
35
|
private controllers = new Map<string, DmxController>();
|
|
34
36
|
private registry = new StateRegistry();
|
|
37
|
+
private engine: ShowEngine | null = null;
|
|
35
38
|
private statePollTimers: NodeJS.Timeout[] = [];
|
|
36
39
|
|
|
37
40
|
constructor(
|
|
@@ -60,8 +63,16 @@ export class DmxPlatform implements DynamicPlatformPlugin {
|
|
|
60
63
|
`DMX platform configured: ${this.cfg.controllers.length} controller` +
|
|
61
64
|
`${this.cfg.controllers.length === 1 ? '' : 's'}, ` +
|
|
62
65
|
`${this.cfg.fixtures.length} fixture${this.cfg.fixtures.length === 1 ? '' : 's'}, ` +
|
|
63
|
-
`${this.cfg.zones.length} zone${this.cfg.zones.length === 1 ? '' : 's'}
|
|
66
|
+
`${this.cfg.zones.length} zone${this.cfg.zones.length === 1 ? '' : 's'}, ` +
|
|
67
|
+
`${this.cfg.shows.length} show${this.cfg.shows.length === 1 ? '' : 's'}`,
|
|
64
68
|
);
|
|
69
|
+
for (const s of this.cfg.shows) {
|
|
70
|
+
if (!s.runnable) {
|
|
71
|
+
this.log.info(`show "${s.id}": template only (unset params: ${s.unboundParams.join(', ')})`);
|
|
72
|
+
} else if (!s.exposeSwitch) {
|
|
73
|
+
this.log.info(`show "${s.id}": hidden (switch: false)`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
65
76
|
|
|
66
77
|
this.api.on('didFinishLaunching', () => {
|
|
67
78
|
this.discoverDevices();
|
|
@@ -69,6 +80,7 @@ export class DmxPlatform implements DynamicPlatformPlugin {
|
|
|
69
80
|
});
|
|
70
81
|
this.api.on('shutdown', () => {
|
|
71
82
|
for (const t of this.statePollTimers) clearInterval(t);
|
|
83
|
+
this.engine?.shutdown();
|
|
72
84
|
for (const c of this.controllers.values()) c.shutdown();
|
|
73
85
|
});
|
|
74
86
|
}
|
|
@@ -121,7 +133,7 @@ export class DmxPlatform implements DynamicPlatformPlugin {
|
|
|
121
133
|
const state = fx.profile.model.parse!(bytes, fx.profile.channels);
|
|
122
134
|
const cur = this.registry.get(fx.id);
|
|
123
135
|
if (JSON.stringify(cur) !== JSON.stringify(state)) {
|
|
124
|
-
this.registry.set(fx.id, state);
|
|
136
|
+
this.registry.set(fx.id, state, 'sync');
|
|
125
137
|
}
|
|
126
138
|
}
|
|
127
139
|
|
|
@@ -190,6 +202,27 @@ export class DmxPlatform implements DynamicPlatformPlugin {
|
|
|
190
202
|
}
|
|
191
203
|
}
|
|
192
204
|
|
|
205
|
+
// Shows — one Switch per runnable show; the engine enforces "one at a time".
|
|
206
|
+
this.engine = new ShowEngine(this.cfg.shows, this.controllers, this.registry, this.log);
|
|
207
|
+
for (const show of this.cfg.shows) {
|
|
208
|
+
if (!show.exposeSwitch) continue;
|
|
209
|
+
const uuid = this.api.hap.uuid.generate(`dmx-show:${show.id}`);
|
|
210
|
+
wantUuids.add(uuid);
|
|
211
|
+
const existing = this.accessories.find((a) => a.UUID === uuid);
|
|
212
|
+
if (existing) {
|
|
213
|
+
this.log.debug(`wiring cached show ${show.id}`);
|
|
214
|
+
existing.context.show = { id: show.id };
|
|
215
|
+
new ShowSwitch(this, existing, show, this.engine);
|
|
216
|
+
} else {
|
|
217
|
+
this.log.info(`registering new show: ${show.name} (${show.id}, ${show.steps.length} steps)`);
|
|
218
|
+
const accessory = new this.api.platformAccessory(show.name, uuid);
|
|
219
|
+
accessory.context.show = { id: show.id };
|
|
220
|
+
new ShowSwitch(this, accessory, show, this.engine);
|
|
221
|
+
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
222
|
+
this.accessories.push(accessory);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
193
226
|
const stale = this.accessories.filter((a) => !wantUuids.has(a.UUID));
|
|
194
227
|
if (stale.length) {
|
|
195
228
|
this.log.info(`unregistering ${stale.length} stale accessor${stale.length === 1 ? 'y' : 'ies'}`);
|
package/src/sacn.ts
CHANGED
|
@@ -23,9 +23,10 @@ import { randomBytes } from 'node:crypto';
|
|
|
23
23
|
|
|
24
24
|
import { Fixture } from './config.js';
|
|
25
25
|
import { HomeKitLightState } from './color/types.js';
|
|
26
|
-
import { DmxController } from './dmxController.js';
|
|
26
|
+
import { DmxController, SetOptions } from './dmxController.js';
|
|
27
27
|
import {
|
|
28
28
|
SACN_COALESCE_MS,
|
|
29
|
+
SACN_FRAME_MS,
|
|
29
30
|
SACN_KEEPALIVE_MS,
|
|
30
31
|
SACN_PORT,
|
|
31
32
|
SACN_PRIORITY_DEFAULT,
|
|
@@ -45,6 +46,7 @@ export class SacnController implements DmxController {
|
|
|
45
46
|
* Read by the platform's state-poll guard so a read-back never clobbers
|
|
46
47
|
* an in-flight HomeKit change. */
|
|
47
48
|
public lastChangeAt = 0;
|
|
49
|
+
readonly frameIntervalMs = SACN_FRAME_MS;
|
|
48
50
|
private readonly socket: dgram.Socket;
|
|
49
51
|
private readonly cid = randomBytes(16);
|
|
50
52
|
private closed = false;
|
|
@@ -58,7 +60,7 @@ export class SacnController implements DmxController {
|
|
|
58
60
|
this.socket.on('error', (e) => this.log.error('sACN socket error:', e.message));
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
setFixture(fixture: Fixture, state: HomeKitLightState): void {
|
|
63
|
+
setFixture(fixture: Fixture, state: HomeKitLightState, opts?: SetOptions): void {
|
|
62
64
|
const arr = this.universeBuf(fixture.universe);
|
|
63
65
|
const bytes = fixture.profile.model.render(state, fixture.profile.channels);
|
|
64
66
|
for (let i = 0; i < bytes.length; i++) {
|
|
@@ -66,8 +68,10 @@ export class SacnController implements DmxController {
|
|
|
66
68
|
}
|
|
67
69
|
this.dirty.add(fixture.universe);
|
|
68
70
|
this.lastChangeAt = Date.now();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
if (!opts?.quiet) {
|
|
72
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
73
|
+
this.log.info(`setFixture ${fixture.id}@DMX${fixture.startCh}/U${fixture.universe + 1}=${hex}`);
|
|
74
|
+
}
|
|
71
75
|
this.scheduleSend();
|
|
72
76
|
if (!this.keepaliveTimer) {
|
|
73
77
|
this.keepaliveTimer = setInterval(() => this.sendAll(), SACN_KEEPALIVE_MS);
|
package/src/settings.ts
CHANGED
|
@@ -48,3 +48,22 @@ export const SACN_PRIORITY_DEFAULT = 100;
|
|
|
48
48
|
|
|
49
49
|
/** Source name advertised in every E1.31 framing layer (max 63 chars). */
|
|
50
50
|
export const SACN_SOURCE_NAME = 'homebridge-dmx';
|
|
51
|
+
|
|
52
|
+
/** Show frame interval on sACN: 25 Hz, the same cadence the Nicolaudie
|
|
53
|
+
* tools stream at and well inside what a gateway accepts. */
|
|
54
|
+
export const SACN_FRAME_MS = 40;
|
|
55
|
+
|
|
56
|
+
// ── Shows ──────────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
/** Show frame interval on the Stick-DE3. Each frame becomes a full
|
|
59
|
+
* subprocess transaction (~2 s) after the 750 ms debounce, so fades on
|
|
60
|
+
* the Stick are a slow staircase rather than a glide. */
|
|
61
|
+
export const STICK_FRAME_MS = 3000;
|
|
62
|
+
|
|
63
|
+
/** Fallback frame interval for a controller that doesn't declare one. */
|
|
64
|
+
export const SHOW_FRAME_MS_DEFAULT = 40;
|
|
65
|
+
|
|
66
|
+
/** Minimum spacing between the registry keyframes a running show writes
|
|
67
|
+
* (each one fans out into HomeKit characteristic events for every
|
|
68
|
+
* fixture and zone involved). */
|
|
69
|
+
export const SHOW_KEYFRAME_MIN_MS = 1000;
|