Sources and universes
How output is addressed and how handles work.
A source owns scheduling, persistence, and transport for one or more outputs. A universe handle is a typed view over one output address.
Addresses
Each output is identified by (universe, priority):
| Field | Range | Default |
|---|---|---|
universe | 1..63999 | — |
priority | 0..200 | 100 |
Receivers merge competing sources by priority. Pick priorities deliberately so you do not override a console by accident.
Creating a source
On Node, prefer the composition helper:
import { createSacnSource } from "@helioslx/core/node";
const source = createSacnSource({
name: "My lighting app",
transportOptions: { iface: "192.168.10.20" },
});That creates and owns a NodeSacnTransport. From the root module you inject a
transport yourself:
import { createSacnSource } from "@helioslx/core";
import { NodeSacnTransport } from "@helioslx/core/node";
const source = createSacnSource({
transport: new NodeSacnTransport({ iface: "192.168.10.20" }),
ownsTransport: true,
});Construction does not open the send loop. The first output mutation (or an
explicit start()) restores stored targets and starts scheduling.
Universe handles
const universe = source.universe(1, {
priority: 100,
sourceName: "Dimmers",
// cid: "...",
// idleFps: 2,
});Handles for the same (universe, priority) are cached. The first call wins
for priority, cid, sourceName, and idleFps defaults on that address.
Useful source methods:
listUniverses()— immutable snapshots, ordered by universe then priority. Does not auto-start.getTelemetry()— synchronous engine counterssubscribe(listener)—started,stopped,output-updated,output-cleared,closed
Channels vs frames
Public channel maps use one-based keys (1..512). Full frames are always
512 values; slot 0 is channel 1 on the wire.
await universe.setChannels({ 1: 255 }); // channel 1
const frame = new Uint8Array(512);
frame[0] = 255; // also channel 1
await universe.write(frame);What this package is not
Fixture patching, attribute resolution, scenes, and show playback are out of scope. Resolve those into channel maps or frames, then call a universe handle.