Add a status LED driven by card events
The workstation app lit an LED on GPIO 23 with the card. This brings that
across, with three deliberate differences: it never blocks the reader, it
cannot be fatal, and its state is reported.
WMT toggled the LED directly inside card_inserted, on the reader thread, where
a slow write stalls card detection. Here every change is queued to a worker, so
insert() returns immediately (tested with a deliberately slow pin).
Two modes, because the light can mean two things:
error (default) lit while the reader runs, dark while reading, blinks on a
bad read - a health indicator
presence lit only while a card is on the reader
gpiozero raises BadPinFactory on a machine with no GPIO, and that subclasses
ImportError - so a single except ImportError reports 'gpiozero is not
installed' when the library is present but has no usable pin provider. The
library check and the pin construction are therefore separate.
Vendors gpiozero + colorzero (~180 KB) so the LED installs offline too, and
deliberately not setuptools: gpiozero declares it via colorzero, but it is only
a packaging requirement and is never imported at runtime. Installing to the
bundled wheels therefore uses --no-deps, saving 818 KB.
Verified end to end over a pseudo-terminal with a fake pin: a real RDM6300
frame drives the LED through the app's own CLI in both modes.
This commit is contained in:
@@ -352,6 +352,69 @@ Exit codes: `0` ok, `1` no port, `2` library missing, `3` port ambiguous.
|
||||
|
||||
---
|
||||
|
||||
## Status LED
|
||||
|
||||
An LED driven by card events, on **GPIO 23** by default — the same pin the
|
||||
workstation app used.
|
||||
|
||||
```bash
|
||||
rdm-card-reader # lit while running, blinks on a bad read
|
||||
rdm-card-reader --led-pin 17 # a different pin
|
||||
rdm-card-reader --led-mode presence # lit only while a card is on the reader
|
||||
rdm-card-reader --no-led # no LED at all
|
||||
```
|
||||
|
||||
| Flag | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `--no-led` | off | Do not drive a LED |
|
||||
| `--led-pin` | `23` | GPIO pin (matches the workstation app) |
|
||||
| `--led-mode` | `error` | See the two readings below |
|
||||
| `--led-no-error-blink` | off | Do not blink on a bad read |
|
||||
|
||||
Two modes, because the light can mean two different things:
|
||||
|
||||
| Mode | Behaviour | Use when |
|
||||
| --- | --- | --- |
|
||||
| `error` (default) | **Lit whenever the reader is running.** Dark while a card is being read, blinks on a bad read | The light should mean "the reader is alive and ready" |
|
||||
| `presence` | **Lit only while a card is on the reader** | The light should mean "a card is here" |
|
||||
|
||||
Wiring: LED anode to the GPIO pin through a ~330 Ω resistor, cathode to GND.
|
||||
|
||||
### It cannot break the reader
|
||||
|
||||
Three deliberate choices, because a LED is a convenience and the reader is the
|
||||
point:
|
||||
|
||||
* **Never blocks.** The workstation app toggled the LED directly on the reader
|
||||
thread, which stalls card detection. Here every change is queued to a worker
|
||||
thread, so a toggle returns immediately even with slow hardware.
|
||||
* **Never fatal.** On a machine with no GPIO, `gpiozero` raises
|
||||
`BadPinFactory`. The app falls back to a no-op LED and says why, rather than
|
||||
refusing to run.
|
||||
* **Never crashes on a dead pin.** A failed toggle is logged and ignored.
|
||||
|
||||
Startup reports which of the three states it is in:
|
||||
|
||||
```
|
||||
LED on GPIO 23 (error mode, gpiozero) # working
|
||||
LED unavailable: gpiozero not installed # library missing
|
||||
LED unavailable: no usable GPIO on pin 23: ... # no pin factory / pin busy
|
||||
```
|
||||
|
||||
That distinction matters: `BadPinFactory` subclasses `ImportError`, so a naive
|
||||
check reports "not installed" when the library is present but has no usable pin
|
||||
provider — which would send you to the wrong fix.
|
||||
|
||||
> **If the workstation app also runs on this device, use a different pin** — two
|
||||
> processes driving GPIO 23 will fight, and the LED will flicker.
|
||||
|
||||
`gpiozero` and `colorzero` are installed automatically on first use, from the
|
||||
bundled wheels, so this works offline. They add ~180 KB. `setuptools`, which
|
||||
`gpiozero` pulls in as a *packaging* dependency, is deliberately not vendored:
|
||||
it is never imported at runtime and would add 818 KB for nothing.
|
||||
|
||||
---
|
||||
|
||||
## Wiring
|
||||
|
||||
The RDM6300 talks plain serial at **9600 baud, 8N1**. Connect it to the Pi's
|
||||
|
||||
Reference in New Issue
Block a user