Skip to content

Navigation Menu

Sign in
Sign up

fix(api): PUT /machine/ledStrip echoes the palette the machine stored - #794

Open
ChampionDesigns wants to merge 2 commits into
decentespresso:main from
ChampionDesigns:ben/ledstrip-canonical
Open

fix(api): PUT /machine/ledStrip echoes the palette the machine stored #794
ChampionDesigns wants to merge 2 commits into
decentespresso:main from
ChampionDesigns:ben/ledstrip-canonical

Conversation

@ChampionDesigns

@ChampionDesigns ChampionDesigns commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

PUT /api/v1/machine/ledStrip answered a bare {"status":"accepted"}, so a client had no way to
learn how its colours were actually stored. The firmware canonicalises what it is given — a
replicated-byte spelling like FFFF22220000 comes back as FF0022000000 — and a following GET
returned that canonical form. So the PUT response and the GET disagreed about the same write.

The handler now reads the stored state back and returns it. A PUT body and the following GET body
are byte-identical.

Base: main. Independent.

Design notes

MockReplayDe1.setLedStrip stored whatever it was handed, so the replay mock could hold a spelling
the machine never would. It now canonicalises too. Color16.quantized() and
ZoneLedState.quantized() hoist that arithmetic onto the model, where both the mock and any future
caller reach one copy instead of keeping their own inline.

Same class of defect as a mock that does not clamp: a mock more permissive than the hardware hides
the bug it exists to expose.

Linked Issue

N/A

Verification

  • flutter analyze — clean.

  • flutter testfull suite 3897 passed / 1 skipped, run against current main on
    5 Sep 2026.

  • flutter testde1handler_led_strip_test 18 passed, up from upstream's 12, plus the replay
    tests: 37 across both files.

  • The four new cases pin what upstream did not cover: replicated-byte input stored and echoed
    canonically, the audited F-044 write on frontStrip.awake, canonical input echoed
    byte-identically, and a reset after a PUT returning the same canonical body.

  • dart format — clean on every changed file.

  • Verified on hardware. This change ships in the Decaid-Canary build Ben runs on his own
    machine, and has been exercised in normal use rather than only under test.

Impact

  • API: the PUT /machine/ledStrip 200 body changes from {"status":"accepted"} to the stored
    palette. A client that ignored the body is unaffected; a client that parsed it for
    status == accepted must be updated.
  • Compatibility: this is the one breaking-shaped change in the set, and it is the point of the
    PR. The old body carried no information.
  • User-visible: none directly.
  • Security: none.

Contributor Responsibility

AI-assisted development is allowed. The submitter remains responsible for the submitted work.

  • I have reviewed and understand all changes in this PR and take responsibility for their correctness, security, behavior, licensing, and provenance, including any AI-assisted or AI-generated work.

ChampionDesigns and others added 2 commits September 5, 2026 07:11
The handler answered a bare {"status":"accepted"}, so a client had no way to
learn how its colours were actually stored. The firmware canonicalises what it
is given -- a replicated-byte spelling like FFFF22220000 comes back as
FF0022000000 -- and a subsequent GET returned that canonical form, so the PUT
response and the GET disagreed about the same write.
The PUT now reads the stored state back and returns it, falling back to the
old ack only when the machine reports nothing. A PUT body and the following
GET body are now byte-identical.
The tests were written first, as decide/ledstrip-canonical, and pin four
things upstream did not cover: replicated-byte input is stored and echoed
canonically, the audited F-044 write on frontStrip.awake echoes the palette
the machine recorded, canonical input is echoed byte-identically, and a reset
after a PUT returns the same canonical body.
Verified: flutter analyze clean, de1handler_led_strip_test 18 passed (was 12
upstream), dart format clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
MockReplayDe1.setLedStrip stored whatever it was handed. The firmware
canonicalises — a replicated-byte spelling like FFFF22220000 comes back as
FF0022000000 — so the mock could hold a value the machine never could, and a
GET against it answered something no real machine would say.
Color16.quantized() and ZoneLedState.quantized() hoist that arithmetic onto
the model, where both the mock and any future caller can reach it, instead of
each one keeping its own copy inline.
Same class of defect as the fan-threshold clamp: a mock more permissive than
the hardware hides the bug it is supposed to expose.
Verified: flutter analyze clean, replay + ledStrip handler tests 37 passed,
dart format clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /