Files
planeMapper/_bmad-output/implementation-artifacts/4-2-config-wipe-setup-screen-and-return-to-provisioning.md
T
Matt Edholm 7f34a7b926 feat(reset): config wipe, setup screen, and re-exec into provisioning (story 4-2)
Add _handle_reset() and _make_setup_screen() to main.py; integrate ButtonHoldDetector
and LEDController into the radar loop; LED lights immediately on hold, config is wiped,
setup screen shown, then os.execvp hands off to planemapper-provision. Wipe failures
log ERROR and abort without exec. Completes epic-4.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 23:59:22 -04:00

3.0 KiB
Raw Blame History

Story 4.2: Config Wipe, Setup Screen & Return to Provisioning

Status: done

Story

As a user who has triggered a reset, I want the device to wipe its configuration, show a setup screen on the e-ink display, and restart into the provisioning flow, So that I can re-configure the device from scratch.

Acceptance Criteria

AC1: Given ButtonHoldDetector.check() returns True When the reset handler runs Then config.wipe() is called

AC2: Given config has been wiped When the reset handler continues Then display.show(setup_screen_image) is called

AC3: Given setup screen is shown When reset handler completes Then os.execvp('planemapper-provision', ['planemapper-provision']) replaces the current process

AC4: Given config.wipe() raises an unexpected error When the reset handler encounters it Then ERROR is logged and os.execvp is NOT called

Tasks / Subtasks

  • Task 1: Implement _handle_reset() and _make_setup_screen() in src/planemapper/main.py (AC: #1#4)

    • 1.1 Add import os to imports
    • 1.2 Add from planemapper.provisioning.config import wipe as wipe_config
    • 1.3 Add from planemapper.gpio_ctrl import ButtonHoldDetector, LEDController
    • 1.4 Implement _make_setup_screen() -> Image.Image
    • 1.5 Implement _handle_reset(display, led) -> None
    • 1.6 Update main() to instantiate ButtonHoldDetector and LEDController
    • 1.7 Add reset check at top of loop
  • Task 2: Write tests in tests/test_reset.py (AC: #1#4)

  • Task 3: Run quality gates

    • 3.1 python -m pytest tests/ — all tests pass
    • 3.2 python -m ruff check . — zero violations
    • 3.3 python -m ruff format --check . — no formatting issues

Implementation Notes

_handle_reset flow

  1. led.on() — immediate LED feedback before any wipe attempt
  2. wipe_config() — deletes config file; on failure, log ERROR, call led.off(), return
  3. display.show(_make_setup_screen()) — render "Resetting..." screen
  4. os.execvp("planemapper-provision", ["planemapper-provision"]) — replaces process (never returns)

_make_setup_screen()

Returns a white 800×480 PIL Image with "Resetting..." text. Same pattern as _make_startup_screen().

main() loop update

ButtonHoldDetector and LEDController are instantiated once in main() before the loop. Inside the loop, button.check() is called once per cycle (non-blocking). If True, _handle_reset is called (which never returns on success).

TID251 per-file-ignore

main.py already has TID251 in per-file-ignores in pyproject.toml, so importing from planemapper.provisioning.config is allowed.

Patching in tests

  • wipe_config is patched at planemapper.main.wipe_config
  • os.execvp is patched at planemapper.main.os.execvp

Files changed

File Change
src/planemapper/main.py Add import os, new imports, _make_setup_screen(), _handle_reset(), update main()
tests/test_reset.py New file with 3 tests