Skip to content

feat(bengle): add A013 integrated-scale telemetry - #601

Merged
tadelv merged 4 commits into
mainfrom
odev/bengle-a013-telemetry
Aug 12, 2026
Merged

feat(bengle): add A013 integrated-scale telemetry#601
tadelv merged 4 commits into
mainfrom
odev/bengle-a013-telemetry

Conversation

@ODevStudio

@ODevStudio ODevStudio commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Problem: Decaid did not consume Bengle's dedicated 0xA013 shot packet, so current integrated weight, firmware GFlow, and milk-probe data were unavailable.
  • Why it matters: Bengle firmware already provides tare-net weight and filtered gravimetric flow; estimating the same flow again in Decaid creates competing telemetry, and the milk probe needs a live feed.
  • What changed: 0xA013 is consumed as the Bengle transport telemetry source and fanned out into Decaid's existing abstractions — machine fields feed the normal MachineSnapshot stream, Weight/GFlow feed the integrated scale surface (weightFlow is device-provided), and MilkTemp drives the existing Bengle milk-probe Sensor (probeAttached / probeTemperature), which appears through the normal /ws/v1/sensors/<id>/snapshot API.
  • Also wired the real firmware TargetMilkTemp MMR (stop-at-temperature) and fixed SteamSequencer so firmware-autonomous stop fires only when the Bengle internal probe is actually attached; a Bengle with only a third-party sensor keeps the app-side stop path.
  • What did NOT change (scope boundary): ordinary DE1 remains on 0xA00D; no inherited USB, discovery, UI, MTU, calibration, or unrelated Bengle work was added.

Firmware Source of Truth

Bengle constants, packet layout, and MMR behavior in this PR were verified directly against the tadelv/Bengle firmware source (fork of rheasman/Bengle).

  • Current firmware revision verified: 2377c7e0e48e9ee2c43cf02ad2f82028252f56e8 (tadelv/Bengle master, fetched during implementation).
  • Verified items: T_BengleShotSample layout in BengleMynewtBLE/src/APIDataTypes.hpp (28 bytes, offsets/scaling incl. MilkTemp U16D2 with 0 = no probe); EndOfShotWeight 0x00803864 ×100 RWD and ScaleTare 0x0080388C write-trigger in BengleMainCPUFirmware/src/Classes/Data/MMR.def; TargetMilkTemp 0x008038A8 ×10 RWD, range 0..85, 0 = disabled, consumed by the steam state machine in ShotMachine.cpp.
  • One upstream documentation discrepancy remains: MemMap.c registers S/A013 as the 19th characteristic while its comments still say 18, and BengleMynewtBLE/MemMap.def omits S.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore / infra
  • Plugin (DYE2 or bundled skin)

Scope (select all touched areas)

  • BLE transport / device comms
  • REST API / handlers
  • WebSocket API
  • Machine state / shot logic
  • Scale / weight / flow
  • Profiles / beans / grinders / workflows
  • WebUI skins
  • Plugins / JS runtime
  • UI / Flutter widgets
  • Storage / Drift database
  • CI / build / infra
  • Docs / specs

Linked Issues

Root Cause (if bug fix)

N/A (feature).

Regression Test Plan (if bug fix or refactor)

  • Coverage level that should have caught this:
    • Unit test
    • Integration test (mock transport edge)
    • End-to-end test (simulate=1 + curl/websocat)
    • Existing coverage already sufficient
  • Target test or file: bengle_telemetry_test.dart, bengle_steam_stop_test.dart, bengle_saw_test.dart, scale_controller_test.dart, steam_sequencer_test.dart, serial_parity_test.dart
  • Scenario the test should lock in: one real A013 frame fans out to machine + integrated-scale + probe surfaces (machine snapshot carries no weight/GFlow/milk-temp); device flow passes through display while control flow stays estimator-derived; tare writes the real MMR and telemetry continues; stop-at-weight/stop-at-temperature write the real registers with ×100/×10 scaling; Bengle-internal-probe vs third-party-sensor select firmware vs app-side stop; plain DE1 stays on A00D.
  • If no new test added, why: N/A

Documentation Obligations (required)

  • API spec updated: assets/api/rest_v1.yml or assets/api/websocket_v1.yml (if REST/WebSocket changed)
  • API docs updated: doc/Api.md (if user-facing endpoint changed)
  • Plugin docs updated: doc/Plugins.md (if events/API changed)
  • Skin docs updated: doc/Skins.md (if skin behavior changed)
  • Profile docs updated: doc/Profiles.md (if profile handling changed)
  • Device docs updated: doc/DeviceManagement.md (if device flows changed)
  • N/A - no docs affected

Security Impact (required)

  • New or changed REST endpoints? (Yes/No) No.
  • New or changed WebSocket topics? (Yes/No) No.
  • New or changed network calls? (Yes/No) No.
  • BLE/USB surface changed? (Yes/No) Yes.
  • File system access changed? (Yes/No) No.
  • Plugin sandbox boundary changed? (Yes/No) No.
  • If any Yes, explain risk and mitigation: only a model-confirmed Bengle subscribes to A013/serial S; short frames are rejected, all constants were checked against current firmware, and a plain-DE1 regression test locks the existing path.

User-Visible Changes

0xA013 is consumed as the Bengle transport telemetry source and routed into Decaid's existing machine, scale and sensor abstractions: machine telemetry (including the existing steamTemperature) on /ws/v1/machine/snapshot, integrated weight + firmware GFlow on the normal scale surface, and the internal milk probe as a normal sensor on /ws/v1/sensors/<id>/snapshot. Stop-at-temperature and stop-at-weight now drive real firmware registers (TargetMilkTemp, EndOfShotWeight).

Verification

Local gates (run before pushing)

  • dart format lib test - 694 files, 0 changed
  • flutter analyze - no issues
  • flutter test - 2,899 passed; 7 pre-existing failures in plugin JS-sandbox (plugin_manager_permissions_test.dart) and webui token tests (webui_token_injection_test.dart), reproduced identically on main and unrelated to this PR
  • ./scripts/fetch_dye2_plugin.sh - not re-run in this revision

Manual verification (if applicable)

  • OS / platform tested: macOS (this revision)
  • Simulated devices? (simulate=1): No.
  • Real hardware? (DE1/Bengle/scale): No
  • What you personally verified and how: current firmware source (tadelv/Bengle @ 2377c7e0), focused fake-transport machine/scale/probe integration, serial command order, MMR write bytes (address + ×10/×100 scaling), reconnect behavior, plain-DE1 isolation, and full repository tests.
  • Edge cases checked: 27-byte malformed frame, no synthetic initial packet, MilkTemp 0 detaches probe, device flow after tare, decreasing-weight control flow stays signed, and plain DE1 isolation.
  • What you did not verify: a live Bengle or a running simulate=1 REST/WebSocket session.

Evidence

  • Test output (failing before + passing after)
  • Log snippets
  • Screenshot / recording (UI changes)
  • curl / websocat output (API changes)

Compatibility & Migration

  • Backward compatible? (Yes/No) Yes; the machine snapshot loses the temporary nullable weight/weightFlow/milkTemperature fields added by the draft (they were never on main), and plain DE1 behavior is unchanged.
  • Config / env changes needed? (Yes/No) No.
  • Database migration needed? (Yes/No) No.
  • If any No or Yes, explain exact steps: No migration or configuration steps.

Risks & Mitigations

  • Risk: Bengle firmware and app wire declarations can drift.
    • Mitigation: constants and layout were verified against tadelv/Bengle master 2377c7e0; the compact golden decoder and transport tests pin observable behavior.
  • Risk: real hardware was not available for this revision.
    • Mitigation: fake-transport end-to-end coverage, plain-DE1 regression coverage, and explicit hardware verification follow-up.

Decode Bengle's dedicated shot packet, expose its integrated weight and firmware gravimetric flow through existing machine and scale surfaces, and wire the current tare and end-of-shot MMRs without changing plain DE1 telemetry.
@ODevStudio
ODevStudio marked this pull request as ready for review August 11, 2026 19:02
tadelv added 2 commits August 12, 2026 09:59
…actions

Revise PR #601 in place:
- MachineSnapshot stays pure machine telemetry (weight/weightFlow/milkTemperature removed; steamTemperature retained).
- MilkTemp from A013 drives Bengle probeAttached/probeTemperature via an independent subscription; BengleProbeBridge registers BengleMilkProbe as before.
- Wire real TargetMilkTemp MMR (0x008038A8, x10, 0-85C, 0=disabled); remove Awaiting-FW stub.
- SteamSequencer tracks actual Bengle probe state for firmware-autonomous stop; third-party sensors keep the app-side path.
- ScaleController always feeds the control estimator; display weightFlow uses device flow when provided, settle-zero applies only to app-derived flow.
- Revert unrelated CRLF test change; update API specs and docs for the fan-out.
- EndOfShotWeight declared range 0..10000 g at x100 (raw max 1,000,000); setStopAtWeightTarget clamps to 10000.
- MockBengle SAW clamp 0..10000 g, stop-at-temperature clamp 0..85 C to match real Bengle.
- Pin ranges in bengle_saw_test, mock_bengle_test, mock_bengle_steam_probe_test.
- Docs/PR wording: A013 is consumed as the Bengle transport telemetry source.
@tadelv
tadelv merged commit 2e9e6b3 into main Aug 12, 2026
4 checks passed
tadelv added a commit that referenced this pull request Aug 12, 2026
…actions

Revise PR #601 in place:
- MachineSnapshot stays pure machine telemetry (weight/weightFlow/milkTemperature removed; steamTemperature retained).
- MilkTemp from A013 drives Bengle probeAttached/probeTemperature via an independent subscription; BengleProbeBridge registers BengleMilkProbe as before.
- Wire real TargetMilkTemp MMR (0x008038A8, x10, 0-85C, 0=disabled); remove Awaiting-FW stub.
- SteamSequencer tracks actual Bengle probe state for firmware-autonomous stop; third-party sensors keep the app-side path.
- ScaleController always feeds the control estimator; display weightFlow uses device flow when provided, settle-zero applies only to app-derived flow.
- Revert unrelated CRLF test change; update API specs and docs for the fan-out.
@tadelv
tadelv deleted the odev/bengle-a013-telemetry branch August 12, 2026 13:26
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.

2 participants