Skip to content

fix: handle profile transition and maintenance rejection - #23

Merged
flowcool merged 1 commit into
V2R1from
fix/profile-transition-rejection
Oct 20, 2026
Merged

flowcool merged 1 commit into
V2R1from
fix/profile-transition-rejection

Conversation

@flowcool

@flowcool flowcool commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Behavior

Switching from MQTT to the API profile could restore persisted Storage state. A healthy API device then showed the Storage page and slept for 24 hours, although the API profile has no Storage control. API boot now clears local Storage state. It preserves low-battery hysteresis and does not change the broker's retained command.

A rejected Maintenance request sampled only the battery, then rendered plant values that had never been acquired. Rejection now returns to full normal acquisition unless Storage is requested. The rejection status survives that cycle and its retained OFF echo.

Verification

  • Command: python3 -B -m unittest discover -s tests -v; pinned ESPHome Python runs test_api_boot.py separately.
  • Expected result: actual YAML actions and compiled C++ policy lambdas prove restored profile transitions, fresh acquisition after rejection, low-battery precedence and retained rejection status.
  • Observed result: 92 system tests pass with one optional API class skipped; all nine API boot tests pass with ESPHome 2026.9.0. Before fixes, four restored-Storage API cases failed; two MQTT mode checks failed. The fixed MQTT policy passes all 22 mode tests.
  • Synthetic API and MQTT configs validate and compile to full firmware locally with ESPHome 2026.9.0: API 0x0a11c39a, MQTT 0x0bc88d1f. Credentials and broker are synthetic; fonts and label are local fixtures. No device, shared builder or live fleet operation is used.

AI assistance

Codex assisted implementation and verification. The author checked source behavior, regressions, semantic diff and firmware compilation. Core hardware, calibration and fleet configuration are unchanged.

CodeRabbit review

  • Verify a completed review on the current PR head.
  • Address confirmed findings and record the review URL/head SHA.

Review evidence: pending publication.

Summary by CodeRabbit

  • Bug Fixes
    • Storage control is now reset when the API starts, preventing settings from a previous profile from affecting current operation.
    • After maintenance is rejected due to low battery, the system now performs a normal sensor acquisition before returning to sleep.
    • Maintenance status is preserved when configured, while status updates continue to reflect the current operating state.
    • API-mode display and sleep behavior is now determined reliably by the current battery condition, regardless of restored storage settings.

@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 68c20fac-752b-4265-82e1-d0855b03fbf6
📥 Commits

Reviewing files that changed from the base of the PR and between 6c69bb0 and eebb3db.

📒 Files selected for processing: 5
  • examples/multi-device/packages/smart_plant_profile_api.yaml
  • examples/multi-device/packages/smart_plant_profile_mqtt.yaml
  • tests/display_automation.py
  • tests/test_api_boot.py
  • tests/test_maintenance_storage.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout: 1
  • GitHub Check: yaml-syntax
🧰 Additional context used
📚 Code guidelines: 2
.claude/rules/esphome-yaml.md — auto-discovered
AGENTS.md — auto-discovered
📓 Path-based instructions: 3
Check compatibility with the supported ESPHome version and package composition.

⚙️ CodeRabbit configuration file

Files:

  • examples/multi-device/packages/smart_plant_profile_api.yaml
  • examples/multi-device/packages/smart_plant_profile_mqtt.yaml
Source excerpt: `use_address` must be in the `wifi:` block of the device YAML, not only in `substitutions:` — the ESPHome CLI reads YAML without resolving packages.

📄 CodeRabbit inference engine (.claude/rules/esphome-yaml.md)

Files:

  • examples/multi-device/packages/smart_plant_profile_api.yaml
  • examples/multi-device/packages/smart_plant_profile_mqtt.yaml
Source excerpt: Parse changed YAML and run `git diff --check`; inspect both `git diff --numstat` and the semantic diff before committing.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • examples/multi-device/packages/smart_plant_profile_api.yaml
  • examples/multi-device/packages/smart_plant_profile_mqtt.yaml
🪛 Ruff (0.16.9)
tests/test_maintenance_storage.py

[warning] 415-415: Function definition does not bind loop variable runtime

(B023)

🔇 Additional comments: 5
examples/multi-device/packages/smart_plant_profile_api.yaml: 1

47-48: LGTM!

tests/display_automation.py: 1

48-49: LGTM!

Also applies to: 74-74, 76-76, 186-186, 191-192, 216-219, 273-274

tests/test_api_boot.py: 1

130-132: LGTM!

tests/test_maintenance_storage.py: 1

53-53: LGTM!

Also applies to: 274-276, 354-381, 403-429

examples/multi-device/packages/smart_plant_profile_mqtt.yaml: 1

388-390: LGTM!

Also applies to: 411-417

Walkthrough

The API profile now resets storage_active at boot. The MQTT profile changes rejected-maintenance recovery and conditionally publishes maintenance status. Tests extend the display runtime and cover API storage isolation, sensor reacquisition, and maintenance behavior.

Changes

Plant profile flows

Layer / File(s) Summary
API boot storage reset and isolation
examples/multi-device/packages/smart_plant_profile_api.yaml, tests/display_automation.py, tests/test_api_boot.py, tests/test_maintenance_storage.py
The API profile clears storage_active at boot. The display test runtime supports optional scripts, API subscriber conditions, and a sensor-update callback. Tests verify the boot reset and confirm restored MQTT storage state does not change API-mode page or sleep selection.
MQTT maintenance rejection and recovery
examples/multi-device/packages/smart_plant_profile_mqtt.yaml, tests/display_automation.py, tests/test_maintenance_storage.py
When maintenance is rejected without Storage Mode, the flow runs acquire_normal. The plain-sleep branch publishes maintenance status OFF only when preserve_maintenance_status is false. Tests check sensor reacquisition, refresh counts, and maintenance outcomes.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to eebb3

The reviewed changes restore normal readings after rejected Maintenance requests and prevent restored Storage state from controlling API-mode sleep. No actionable merge-blocking issue remains.

Security architecture risk: 🔵 Low · up to eebb3

The changes improve profile isolation and restore sensor acquisition after rejected maintenance. No new access path or increased privilege was identified. Remaining uncertainty concerns battery consumption and physical failure behavior during the longer recovery cycle, rather than a demonstrated security regression.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed command-driven behavior acts on the receiving device's sensor acquisition, display, status and sleep lifecycle. Exploiting it through MQTT would require the ability to deliver commands to that device's topic. Broker authorization and deployment credentials were not supplied, so independent fleet-wide reachability is not established.

Trust Boundaries and Controls

  • observed — The base-to-head changes leave API encryption-key configuration, OTA password configuration and MQTT credential references unchanged. The API Storage reset is a local boot action, not a newly callable remote operation.

Resilience and Maintainability Implications

  • observed — The recovery path retains the shared display-safe-to-sleep check and low-battery-first sleep-duration selection. These controls bound the intended terminal behavior, but the offline executor explicitly does not establish physical sleep timing or hardware failure behavior.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 3 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the two primary changes: profile transition handling and maintenance rejection handling.
Description check Passed The description includes the required Behavior, Verification, AI assistance, and CodeRabbit review sections. It provides specific behavior changes, commands, results, test coverage, and synthetic vali…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required Behavior, Verification, AI assistance, and CodeRabbit review sections. It provides specific behavior changes, commands, results, test coverage, and synthetic validation details. Review evidence is explicitly marked as pending, but the description is otherwise complete and focused.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 3 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@flowcool
flowcool merged commit 80b6246 into V2R1 Oct 20, 2026
2 checks passed
@flowcool
flowcool deleted the fix/profile-transition-rejection branch October 20, 2026 18:47
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