ADR-007: Non-Blocking, Generation-Safe GPIO LED Feedback
ID: ADR-007 Status: Accepted
Context
Recognition continues while an LED remains on for several seconds. Blocking sleeps would stop WebSocket work, while detached old blink/hold threads could later turn off a newer result. Raspberry Pi gpiochip numbering also varies, and development/CI usually has no GPIO device.
Decision
Implement LED feedback in backend/leds.py with gpiozero.LED and LGPIOFactory(chip=GPIO_CHIP) using BCM pins 17 (yellow), 27 (blue), and 22 (red).
- The adapter
.on()command is issued synchronously when feedback is selected. - Only blink/hold duration waits run in daemon worker threads.
- Every action receives a generation and cancellation event. A stale worker may mutate LEDs only if it still owns the current generation.
- Recognition/enrollment orchestration invokes GPIO through FastAPI's worker-thread boundary.
- Initialization failure enters an explicit no-GPIO mode rather than failing the API.
- Shutdown cancels and joins the owned worker, turns all LEDs off, closes LED objects, and closes the pin factory.
The repository implements LEDs only; it has no motor or door-controller adapter.
Considered alternatives
- Blocking
sleepin the request/event-loop path: rejected because it stops frame processing. - An unmanaged thread per signal: rejected because stale threads race newer states and leak resources.
- Hard-code a Raspberry Pi gpiochip: rejected because host/controller numbering differs.
- Treat a fake GPIO timing test as physical evidence: rejected because it cannot measure the electrical LED transition.
Consequences
- Software dispatch is immediate and independently testable, and old workers cannot override a new result.
- The Pi Compose override must map the selected
/dev/gpiochipNto the same container-visible number configured inGPIO_CHIP. - GPIO absence is observable through logs and
/health, while recognition remains usable. - The software precheck in
tests/quality/test_hardware_feedback.pyproves call ordering only. QR-006 still needs automated Raspberry Pi hardware-in-the-loop measurement, so QRT-006 remains Planned.