Skip to content

Bring bounded display recovery and safe rendering to the standalone example - #31

Merged
flowcool merged 6 commits into
JGAguado:V2R1from
flowcool:prep/72-03-standalone
Oct 21, 2026
Merged

flowcool merged 6 commits into
JGAguado:V2R1from
flowcool:prep/72-03-standalone

Conversation

@flowcool

@flowcool flowcool commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Behavior

The standalone example has older display guards and boot ordering. The shared core also retries BUSY recovery without a total time budget, so an oscillating BUSY signal can keep the device awake.

Both entry points now use the same refresh cancellation, settling, recovery budget and reset actions. Missing readings show --. Numeric labels keep measured values while needles and icons stay in range. One timer bounds all recovery retries, including the final sleep delay. A new refresh cancels pending recovery and releases an interrupted reset pulse.

This revision addresses the maintainer review:

  • Port the same recovery to smart_plant_core.yaml, with regression tests for both transport profiles and standalone.
  • Keep the newcomer note short. Put timing and shutdown details beside the code.
  • Probe compiler/runtime UBSan support separately. Run all renderer assertions without sanitizer flags when unavailable. Keep real renderer compilation failures fatal. Release the Windows native-library handle before temporary-file cleanup.

The branch includes upstream PR #30. Normal and emergency sleep preserve its configurable low-battery duration and explicit OTA confirmation.

Verification

  • Pinned ESPHome 2026.9.0: python -B -m unittest discover -s tests -v: 39 tests pass, no skips. This covers actual C++ lambdas and YAML automation, both scheduler orders, permanent/oscillating/late BUSY, cancellation during reset, fresh budgets and low-battery sleep duration.
  • Simulated a compiler without UBSan: all display assertions execute successfully. A separate negative control proves a renderer compilation error still fails the suite.
  • Strict Sphinx HTML build passes. YAML parsing, semantic diff, line-ending preservation and git -c core.whitespace=cr-at-eol diff --check pass.
  • Isolated full API, MQTT and standalone firmware builds use synthetic credentials, a public image and local replacement fonts. Final combined-source results are recorded in the review reply.

The native Windows path has not been executed on Windows. Replacement fonts prove compilation, not exact artwork or glyphs. The recovery bound ends at the deep-sleep action; stock shutdown hooks can still send the display sleep command. No hardware test or firmware deployment was performed.

Rollback: revert this PR through a separate PR. A source revert does not deploy firmware. No fleet inventory, private identity, HA migration or deployment tooling is included.

AI assistance

Codex prepared the source and tests. The author checked both firmware entry points, the exact upstream merge, native test behavior, synthetic compiler fixtures, semantic diff and line endings.

Review

The prior maintainer request for changes needs re-review. The original CodeRabbit request received no status or completed review; no automated approval is claimed. Required CI and repository review rules apply.

@flowcool

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@JGAguado JGAguado left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for bringing safe rendering and BUSY handling to the standalone example. Two requests before merging:

  1. One recovery implementation, not two. This PR adds a shared display_recovery_budget, which fixes the unbounded retry loop when BUSY keeps toggling. The multi-device core (smart_plant_core.yaml) still has the older self-re-executing recover_display_busy without that budget. Please port the same recovery to the core, so both files behave the same and fixes don't drift apart.
  2. Simpler docs. The new note in programming.rst is aimed at newcomers. Details such as "30.510 seconds … event-loop scheduling latency" and the shutdown-hook discussion belong in a code comment. Something like "invalid readings show --, and the device waits for the e-paper to finish refreshing, with a bounded recovery if it doesn't" is enough there.

Minor: on Windows with MinGW, test_standalone_display errors because -fsanitize=undefined needs libubsan, and tearDownClass fails while removing the temp dir. Skipping the sanitizer when it isn't available would make the tests portable.

@flowcool

Copy link
Copy Markdown
Collaborator Author

Addressed all three findings from your review:

  1. The shared core now uses the same refresh cancellation, BUSY settling, recovery budget and terminal-reset actions as the standalone example. The budget survives LOW/HIGH retries and the final sleep delay. The tests execute both the API and MQTT compositions as well as standalone, and a parity test checks the shared recovery actions directly.
  2. The newcomer note now only describes invalid readings, waiting for refresh and bounded recovery. The timing and native shutdown boundary are code comments beside the budget.
  3. The renderer probes UBSan with a separate valid executable. If the compiler or runtime cannot use it, the renderer assertions still execute without sanitizer flags. A renderer compilation failure still fails the suite. The native DLL is released before temporary-file cleanup on Windows; UTF-8 and executable/library suffixes are explicit.

The merged PR #30 is included. Both normal and fault paths keep its configurable low-battery sleep; a runtime regression test covers that merge. All 39 tests and strict Sphinx HTML pass.

Validation uses pinned ESPHome 2026.9.0, synthetic inputs and private local builds. No device, NAS, broker or production build service was touched. The native Windows path has not been run on Windows; the no-UBSan fallback and real compilation-failure case were exercised locally.

Please re-review the corrected head. The previous changes-requested review remains yours to clear. I do not treat the fixes or local validation as your approval.

Final combined-source firmware builds all pass (ESPHome 2026.9.0):

  • api: 0x80b187e2.
  • mqtt: 0xc0084c02.
  • standalone: 0xe351ec84.

Exact head: e3970b0 (includes upstream merge d56ce6a). Six YAML documents parse; target-to-head diff and original line endings pass. The final strict Sphinx build disables external intersphinx inventory fetch after a stalled remote fetch; the earlier full strict HTML build also passed. External link checking was interrupted at that fetch, so I do not claim a completed link check. The changed newcomer note introduces no link.

@JGAguado JGAguado left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

All three requests addressed: the core and standalone now share identical refresh, settle, recovery-budget and fault scripts (the only difference left is the core's low-battery sleep duration), the newcomer note is short, and the tests no longer depend on UBSan. Approving.

@JGAguado

Copy link
Copy Markdown
Owner

All five open PRs are approved. They conflict pairwise (mostly examples/multi-device/README.md), so please merge them in this order and rebase each remaining one after every merge:

  1. Make public examples independent of the fork and validate both transports #40, which updates the example URLs and CI
  2. Bring bounded display recovery and safe rendering to the standalone example #31
  3. Add retained MQTT Maintenance and Storage modes #39, rebased onto Bring bounded display recovery and safe rendering to the standalone example #31 (core + display_automation.py)
  4. Generate generic label bands from explicit input scales #38 (README)
  5. docs: refresh project entry points and first-install guides #37 (programming.rst after Bring bounded display recovery and safe rendering to the standalone example #31)

CI must stay green on each rebased head.

@flowcool
flowcool merged commit e6480b9 into JGAguado:V2R1 Oct 21, 2026
1 check passed
@flowcool
flowcool deleted the prep/72-03-standalone branch October 21, 2026 15:24
flowcool added a commit that referenced this pull request Oct 21, 2026
…very

Drop the globals duplicated by the #31 merge. Let the parity test accept the
multi-device extensions (fault hook, counter, logs, MQTT status) and the
per-profile sleep_after_display. Bound the flow tests by each profile's
on_display_fault delay.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017fn1KdJJTY7LedVqZ7SxcA
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