Skip to content

fix(artnet): drive each effect with its own parameters, and pair Plasma with plasma - #296

Merged
BernardJen merged 1 commit into
mainfrom
feat/artnet-effect-params
Aug 26, 2026
Merged

fix(artnet): drive each effect with its own parameters, and pair Plasma with plasma#296
BernardJen merged 1 commit into
mainfrom
feat/artnet-effect-params

Conversation

@BernardJen

Copy link
Copy Markdown
Contributor

Groundwork for better Art-Net visuals, and a fix for a bug 3.1.0 shipped.

effect:plasma never actually worked

Every effect on the relay declares its own parameter set, and the relay ignores anything it doesn't recognise — silently, with a 200. 3.1.0 sent the spot's shape (r,g,b,cx,cy,diameter,softness) to whichever effect was configured. But plasma takes scale, speed, brightness — and no colour at all. So it received seven keys it had no use for, ran at its defaults forever, and never responded to the picture. It looked wired up and wasn't; nothing failed anywhere.

EFFECT_DRIVERS now maps each of the seven field effects to what it actually accepts:

effect driven by
spot, ripple colour + centroid position
plasma, aurora scale from spread, speed and brightness from frame level (no colour — they generate their own)
blobs colour + integer count and size from spread
sweep colour + width
tunnel brightness + integer rings/arms

The other ten effects (fire, police, sparkle, chase, …) aren't field-based, so the relay can't nudge them — their parameters only change by re-POSTing, which resets the animation phase. Those are now started once and left alone rather than nudged pointlessly every second.

Default pairings

Plasma → plasma, Metaballs → blobs, Wave Tank → ripple. Only where the effect genuinely mirrors the screen — a mismatched effect puts the room out of step with the wall, which is worse than the dominant colour. Everything else stays reactive, and Reactive is selectable to opt out.

Mutation testing found a bug in that pairing

The settings UI stores "Reactive" by deleting the entry. For a paired saver that meant:

  • the dropdown read Reactive while the pairing was silently in effect — stating the opposite of what the room was doing
  • choosing Reactive deleted the key, fell back through to the pairing, and opting out was impossible

The list now shows the effective mode and writes 'reactive' explicitly where a pairing exists. modeForSaver uses hasOwnProperty for the same reason — a truthiness check let a deliberately-cleared entry fall through.

Also removed a genuinely unreachable branch: every driver is field-based, a test enforces it, so the non-field guard could never fire.

Verification

  • 784 tests green (33 new), lint clean.
  • All 19 mutations caught. Three escaped first, each a real gap: integer parameters sampled only at a spread that lands on a whole number by luck, the unreachable guard, and the opt-out bug above.
  • Declared parameter sets are pinned in the test from the live GET /effects, so drift in our table is detectable.

Still unverified against the rig (#274) — this is all parameter shaping, checked against the published schema rather than against light on a wall.

Next: the spatial part of the ask — mapping specific colours on specific parts of the wall onto the strips nearest them, using POST /strips/{name}/pixels.

🤖 Generated with Claude Code

…ma with plasma

Every effect on the relay declares its own parameter set, and the relay ignores
anything it does not recognise -- silently, with a 200. 3.1.0 sent the spot's
shape (r,g,b,cx,cy,diameter,softness) to whichever effect was configured, so
`effect:plasma`, which takes scale/speed/brightness and no colour at all,
received seven keys it had no use for and ran at its defaults forever. It looked
wired up and was not, and nothing anywhere failed.

EFFECT_DRIVERS now maps each of the seven field effects to the parameters it
actually accepts, driven from the frame: colour where the effect takes colour,
brightness and scale where it generates its own, a centre where it has one, and
integer counts where the relay indexes discrete things. The ten effects the relay
cannot nudge are started once and left alone -- their parameters can only change
by re-POSTing, which resets the animation phase, so nudging them every second
would stutter in exchange for nothing.

Plasma, Metaballs and Wave Tank now pair with plasma, blobs and ripple by
default. Only pairings where the effect genuinely mirrors the screen: a
mismatched effect puts the room out of step with the wall, which is worse than
the dominant colour.

Mutation testing then found a bug in that pairing. The settings UI stores
'Reactive' by DELETING the entry, so for a paired saver the dropdown read
'Reactive' while the pairing silently applied, and choosing Reactive deleted the
key and fell straight back through to the effect -- opting out was impossible.
The list now shows the effective mode, and writes 'reactive' explicitly where a
pairing exists. modeForSaver uses hasOwnProperty for the same reason: a
truthiness check let a deliberately-cleared entry fall through to the pairing.

Also removed a genuinely unreachable branch: every driver is field-based, a test
enforces it, and the non-field guard could never fire. Dead code whose comment
implies otherwise is worse than none.

780 tests, 33 new. All 19 mutations caught; three escaped first -- integer
parameters sampled only at a spread that lands on a whole number, an unreachable
guard, and the opt-out bug above.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@BernardJen
BernardJen merged commit 1c7f8b6 into main Aug 26, 2026
1 check passed
@BernardJen
BernardJen deleted the feat/artnet-effect-params branch August 26, 2026 07:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant