Replaces the "Running at boot" section with a five-step guide that
starts from enabling the UART, the step that is easiest to miss and
the one that produces the "device not found" failure:
1. enable the serial port with raspi-config (and answer No to the
login shell, or the console holds the port)
2. confirm which device exists, with a table mapping what you see
to the --device value to pass
3. install the service, with both possible failure messages and
what each one means
4. verify via systemd, the journal and the status page
5. fall back to a foreground run and --list-ports when cards are
not detected
Also fixes a contradiction: the section claimed the installer
defaults --device to /dev/rdm-reader when it is /dev/serial0, while
the options table three lines below said /dev/serial0. That mismatch
is exactly what leads someone to install against the wrong device.
Notes that --no-service does not skip the device checks, verified
against the script's control flow, and drops the raspi-config menu
number rather than assert one that varies by release.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GET / now returns a dashboard for the reader: mode, port, uptime,
card presence, the current card, event counters and a live event log
seeded from /api/taps and updated over the /api/events SSE stream.
The page is read-only on purpose - it has no claim button, because
POST /api/card/claim spends the tap and merely viewing the status
would otherwise consume a real login.
Serving the page requires allowing same-origin browser requests: a
browser sends Origin even for a request to the same origin, so
_cors_ok() used to reject the page's own API calls with 403 unless
--allow-origin was passed. Loopback and same-host origins are now
accepted, and the Access-Control-Allow-Origin echo is applied
consistently in one helper instead of four copies.
--no-page reverts POST-free deployments to API-only.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- drop unused BAR import, _VALID_MODES, _is_optional(),
OPTIONAL_IMPORTS and is_loopback()
- replace hand-written event name strings with EVENT_INSERTED,
EVENT_REMOVED and EVENT_INVALID, so a typo cannot silently
disable an event path
- drop the now-moot pytest/coverage entries from .gitignore
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
keyboard.py was never wired in: no module imported it, the CLI had no
--type flag, and neither the docs nor install.sh referenced it, so the
virtual-keyboard path could never run.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The tests are not part of what ships to a device, and nothing in
pyproject.toml, the deploy scripts or the docs referenced them.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- keyboard.py: emulate a commercial USB RFID reader by typing card ids
into the focused window via a /dev/uinput virtual keyboard
- led.py / bridge.py: drive the status LED from card events
- cli.py, card.py: wire up the new options and event flow
- deploy: harden install.sh and the systemd unit
- README: document keyboard mode, LED support, and deployment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>