Skip to content

fix: round Bengle scaled MMR writes - #604

Merged
tadelv merged 1 commit into
mainfrom
odev/pr462-bengle-mmr-rounding
Aug 13, 2026
Merged

fix: round Bengle scaled MMR writes#604
tadelv merged 1 commit into
mainfrom
odev/pr462-bengle-mmr-rounding

Conversation

@ODevStudio

Copy link
Copy Markdown
Collaborator

Summary

  • Problem: protected capability MMR writes truncated scaled doubles, so a Bengle 2.3 g stop target could serialize as raw 229 instead of 230.
  • Why it matters: firmware should receive the nearest representable scaled value; floating-point representation must not bias targets downward.
  • What changed: round protected scaled writes, lock Bengle and private DE1 behavior with regressions, correct the capability description, and revise the MockBengle integrated-scale scenario for firmware-autonomous SAW.
  • What did NOT change (scope boundary): no SAW range, readback, tare, or A013 work already delivered by feat(bengle): add A013 integrated-scale telemetry #601; no public API shape or private DE1 serialization change.

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)

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: test/unit/models/device/impl/de1/unified_de1/protected_surface_test.dart
  • Scenario the test should lock in: Bengle endOfShotWeight = 2.3 writes raw 230 while plain DE1 setSteamFlow(2.3) remains raw 229.
  • If no new test added, why not: 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

Only the existing OpenAPI operation description and existing regression scenario were stale; endpoint behavior and user-facing API documentation did not change.

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: protected non-DE1 scaled MMR payloads now use nearest-integer rounding. Existing kind and range checks remain, and a regression proves the private DE1 path is unchanged.

User-Visible Changes

Bengle scaled capability values are encoded to the nearest firmware unit. Capability documentation now lists cupWarmer, integratedScale, ledStrip, and stopAtWeight.

Verification

Local gates (run before pushing)

  • dart format lib test - no remaining changes
  • flutter analyze - clean (no new warnings)
  • flutter test - all pass
  • ./scripts/fetch_dye2_plugin.sh - DYE2 plugin installed into assets/plugins/dye2.reaplugin/

Focused tests: 15 passed. The full suite ran to completion; its only failure was the pre-existing Windows CRLF-sensitive assertion in test/connect_result_schema_test.dart.

The fetch script could not be rerun because WSL startup is denied and jq is unavailable in this Windows shell. The existing bundled DYE2 v0.1.4 manifest, API version, permissions, and createPlugin entry point were validated locally.

Manual verification (if applicable)

  • OS / platform tested: Windows
  • Simulated devices? (simulate=1): Yes
  • Real hardware? (DE1/Bengle/scale): No
  • What you personally verified and how: ran the revised flow with a handler-level MockBengle smoke harness; capabilities were exactly cupWarmer, integratedScale, ledStrip, and stopAtWeight, and firmware-autonomous SAW returned the machine to idle at 36.17 g.
  • Edge cases checked: raw 230 Bengle rounding, raw 229 private DE1 truncation, all four capabilities, autonomous idle transition.
  • What you did not verify: real hardware or a native Windows live app. The local native build is blocked by VS2019/CMake and universal_ble runtime incompatibilities.

Evidence

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

Before the implementation change, the focused Bengle regression reported raw 229 instead of 230. Afterward all 15 focused tests passed.

Compatibility & Migration

  • Backward compatible? (Yes/No): Yes
  • 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 changes are required.

Risks & Mitigations

  • Risk: all protected non-DE1 scaled capability writes now round rather than truncate.
    • Mitigation: address kind/range handling remains unchanged, focused tests cover Bengle and legacy private DE1 behavior, and the full analyzer is clean.

@ODevStudio
ODevStudio marked this pull request as ready for review August 12, 2026 13:20

@tadelv tadelv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good and the scaling/rounding behavior is correct against tadelv/Bengle firmware (EndOfShotWeight is ×100, so 2.30 g must serialize as raw 230). I found no code-level blockers.

Suggestions for the PR body only:

  • Reframe provenance: this rounding fix originally came from historical B-1/#459, not #462. #462 depended on it for EndOfShotWeight, while merged #601 salvaged the relevant A013/SAW path.
  • Explicitly relate this PR to umbrella #469 and state that this is a targeted extraction from the old Bengle stack, not a continuation/acceptance of that stacked architecture.
  • It would be clearer to say that the capability/scenario doc edits are post-#601 cleanup rather than part of the rounding bug itself.
  • Uncheck the E2E-test box unless an actual running-app simulate=1 + curl/websocat smoke was performed; the handler-level MockBengle smoke is useful but is not that E2E category.

Approved with those non-blocking documentation suggestions.

@tadelv
tadelv merged commit 5f2af72 into main Aug 13, 2026
4 checks passed
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