RDM card reader: print card events, select the right port, serve taps to a web app

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.
This commit is contained in:
2026-10-01 15:31:04 +03:00
commit 576f22268f
26 changed files with 3771 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
# Give the RFID reader a stable name: /dev/rdm-reader
#
# Without this, the adapter is /dev/ttyUSB0 or /dev/ttyUSB1 depending on the
# order the kernel enumerated USB devices, which changes between reboots and
# whenever anything else is plugged in. Authenticating against the wrong reader
# is a real failure, so pin the identity here instead of hoping.
#
# Match on the USB-serial bridge chip. Add serial numbers once you know them -
# see README "Identifying the right ttyUSB" for how to read them off:
#
# SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", \
# ATTRS{serial}=="REPLACE_WITH_YOUR_SERIAL", SYMLINK+="rdm-reader", MODE="0660", GROUP="dialout"
#
# Current rule: match by vendor:product (CH340 is 1a86:7523).
# Commented-out alternatives for other common bridge chips are listed below.
# Only ONE rule should be active - remove or comment the others.
# CH340 / CH341 (most common on cheap USB-TTL adapters)
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="rdm-reader", MODE="0660", GROUP="dialout"
# FTDI FT232R
# SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="REPLACE_ME", SYMLINK+="rdm-reader", MODE="0660", GROUP="dialout"
# Silicon Labs CP2102
# SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="REPLACE_ME", SYMLINK+="rdm-reader", MODE="0660", GROUP="dialout"
# Prolific PL2303
# SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", ATTRS{serial}=="REPLACE_ME", SYMLINK+="rdm-reader", MODE="0660", GROUP="dialout"