A freshly flashed device needed manual pip work before the reader would
start. It now checks its dependencies, installs whatever is missing, and
carries on.
- bootstrap.py: import check, pip invocation, and a re-check that does not
trust pip's exit code alone. Installs nothing when the libraries are
already present, so a normal start does no network work.
- --wheel-dir installs from local wheels with --no-index, for devices with
no internet. --no-install-deps opts out entirely.
- Outside a venv pip gets --break-system-packages, which Debian and
Raspberry Pi OS require before touching the system Python.
- reload_library() re-imports rdm6300 when it was installed at runtime, since
the module-level import already ran and failed.
- A failed install reports exit 2 and the exact manual command rather than
raising; stdout is flushed so the explanation is not printed after the
error when piped.
Card reading (rdm6300 + pyserial) printing card inserted/removed with the
full card data, plus a --serve mode that publishes taps over HTTP so a web
page can authenticate a tap.
The bridge reports card ids only - mapping a card to a user stays on the
server. The tap is latched for --tap-ttl seconds, including after the card is
lifted, and is single use, so a page reload cannot replay one tap into two
logins.
Port selection identifies the reader by serial number or by-id path instead of
/dev/ttyUSBn, and refuses to guess when a selector matches several adapters.
deploy/ has the systemd unit, a udev rule for a stable /dev/rdm-reader, and
install.sh. Covered by unit tests plus PTY end-to-end tests.