diff --git a/README.md b/README.md index 67bc71d..370af29 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Built for a Raspberry Pi, but it runs anywhere with a serial port. - [Install](#install) - [Usage](#usage) - [Serving card data to a web app (`--serve`)](#serving-card-data-to-a-web-app---serve) -- [Running at boot (Raspberry Pi)](#running-at-boot-raspberry-pi) +- [Quick start on a Raspberry Pi](#quick-start-on-a-raspberry-pi) - [Status LED](#status-led) - [Wiring](#wiring) - [The protocol](#the-protocol) @@ -411,50 +411,145 @@ actually cost you something. --- -## Running at boot (Raspberry Pi) +## Quick start on a Raspberry Pi -The defaults already match the common wiring — **`/dev/serial0`** for the -reader on the Pi's UART and **GPIO 23** for the LED — so the LED pin and device -usually need no arguments at all: +End-to-end: enable the serial port, confirm the reader is visible, install the +service, verify it runs. Steps 1–2 change nothing on disk and are safe to run +first. + +### 1. Enable the serial port + +`/dev/serial0` is the Pi's on-board UART, and it does not exist until the UART +is switched on: + +```bash +sudo raspi-config +# Interface Options -> Serial Port +# "Would you like a login shell to be accessible over serial?" -> No +# "Would you like the serial port hardware to be enabled?" -> Yes +sudo reboot +``` + +Menu numbering shifts between `raspi-config` releases, so navigate by name: +**Interface Options**, then **Serial Port**. + +**Both answers matter.** Answering *Yes* to the login shell leaves a console on +the port, so the reader gets nothing: the app either reports `device not found` +or opens the port and never sees a card. + +### 2. Confirm the device appears + +```bash +ls -l /dev/serial0 /dev/rdm-reader 2>&1 +``` + +| What you see | Wiring | Device to pass | +| --- | --- | --- | +| `/dev/serial0 -> ttyAMA0` (or `ttyS0`) | UART, header pins **8 / 10** | `--device /dev/serial0` | +| `/dev/rdm-reader` | USB-to-serial adapter | `--device /dev/rdm-reader` | +| `No such file or directory` for both | nothing openable yet | see below | + +`/dev/rdm-reader` is created by the udev rule and matches a **USB** bridge chip, +so it can never exist on a UART setup. The two are mutually exclusive — a +service pointing at the wrong one exits `1` on every start. + +If neither exists, ask what the system does see: + +```bash +ls /dev/ttyUSB* /dev/ttyACM* /dev/ttyS* 2>/dev/null +dmesg | grep -iE "ttyUSB|ttyAMA|ch34|ftdi|cp210|pl2303" | tail +``` + +No `ttyUSB`/`ttyACM` line in `dmesg` means the adapter is not enumerating at +all — a cable, power or hardware problem that no `--device` value can fix. + +If a `/dev/ttyUSB0` appears but `/dev/rdm-reader` does not, the adapter's chip +is not the CH340 the rule matches by default. See **Identifying the right +ttyUSB** below. + +### 3. Install the service + +The defaults already match the common wiring — `/dev/serial0` for the reader on +the UART, GPIO 23 for the LED: ```bash sudo ./deploy/install.sh --origin https://your.web.app ``` -To be explicit (and safe if the defaults ever change): +`deploy/install.sh` is the only installer — there is no `deploy.sh`. It sets up +a service account, a virtualenv, a udev rule and a systemd unit, then enables +the service. + +Tell it which device you have, since the two are not interchangeable: ```bash -sudo ./deploy/install.sh --origin https://your.web.app \ - --device /dev/serial0 \ - --led-pin 23 \ - --led-mode presence +sudo ./deploy/install.sh --device /dev/serial0 # UART, pins 8 / 10 +sudo ./deploy/install.sh --device /dev/rdm-reader # USB adapter ``` -| Argument | Why | +It refuses to enable the service unless the device exists **and** opens at +9600 baud, so a wrong port fails here instead of becoming a crash-looping unit +that burns its restart limit within seconds and then stays dead. Success looks +like: + +``` + /dev/serial0 opened at 9600 baud +``` + +If it stops instead, the message is one of exactly two: + +| Message | Cause | | --- | --- | -| `--device /dev/serial0` | The reader is wired to the UART pins (8 / 10). This is the default. For a USB-to-serial adapter pass `--device /dev/rdm-reader` instead — that alias is created by udev for USB adapters only, so it never exists on a UART setup | -| `--led-pin 23` | BCM GPIO 23, which is **physical pin 16**. The default | -| `--led-mode presence` | Lit while a card is on the reader, dark otherwise. The default | +| ` does not exist, so the service could never start` | step 1 or 2 not done, or the wrong of the two devices | +| `could not open at 9600 baud` | device exists but is not usable — UART held by the serial console, or the user is not in `dialout` | -> **`--led-pin` is the BCM GPIO number, not the header pin.** If your LED wire -> is on physical pin 16, pass `--led-pin 23` (the default). Passing -> `--led-pin 16` would drive **GPIO 16**, which is physical pin 36 — a different -> pin entirely. The LED is optional: with no LED, pass `--led-mode presence` -> regardless and ignore the light, or add `--no-led` to the unit if you want -> the app to stop trying. +Nothing is enabled in either case, and re-running is safe: the account, udev +rule and virtualenv are all idempotent. -### Standalone install +### 4. Verify it runs -`deploy/install.sh` is the only installer — there is no `deploy.sh`. +```bash +systemctl status rdm-card-reader # state +systemctl is-enabled rdm-card-reader # should be 'enabled' (starts at boot) +journalctl -u rdm-card-reader -f # live log +ss -ltnp | grep 8765 # confirms something is listening +``` -That installs a service account, a virtualenv, a systemd unit and a udev rule, -then enables the service. The device defaults to `/dev/rdm-reader`; if the -reader is on the Pi's UART instead, add `--device /dev/serial0` — see -**UART or USB?** above. The installer refuses to enable the service unless the -device exists and opens, so a misconfigured port fails during install rather -than as a crash-looping unit. +A healthy startup logs one line: -Useful installer options: +``` + OK reader on /dev/serial0 ; bridge on http://127.0.0.1:8765 (mode: login) +``` + +Then tap a card and check — or just open **** for the +status page, which shows the reader state and a live event log: + +```bash +curl -sS http://127.0.0.1:8765/api/card | python3 -m json.tool +``` + +### 5. If cards are not detected + +Run the reader in the foreground, using the venv the installer built, to see +the failure directly instead of through the journal: + +```bash +sudo /opt/rdm-card-reader/.venv/bin/rdm-card-reader --port /dev/serial0 +``` + +`--list-ports --verbose-ports` answers "is the port even there?" — it prints +candidates with `OK`/`---` (exists?) and then every identified port with its +`by-id` path, USB id and serial number: + +```bash +sudo /opt/rdm-card-reader/.venv/bin/rdm-card-reader --list-ports --verbose-ports +``` + +A service that cannot see cards while the foreground run works usually means +the unit is pointed at the other device — compare its `ExecStart` (below) with +what `--list-ports` reports. + +### Installer options | Option | Default | Meaning | | --- | --- | --- | @@ -468,7 +563,16 @@ Useful installer options: | `--user NAME` | `rdmcard` | Service account | | `--no-service` | off | Install and configure, but do not enable the service | -The unit runs the app as: +> **`--no-service` does not skip the device checks.** They run before it, so an +> install with no reader attached still exits `1`. + +> **`--led-pin` is the BCM GPIO number, not the header pin.** If your LED wire +> is on physical pin 16, pass `--led-pin 23` (the default). Passing +> `--led-pin 16` would drive **GPIO 16**, which is physical pin 36 — a different +> pin entirely. The LED is optional: with no LED, leave the default and ignore +> the light, or add `--no-led` to the unit to stop the app trying. + +### What the unit runs ``` /opt/rdm-card-reader/.venv/bin/rdm-card-reader \ @@ -481,22 +585,6 @@ The unit runs the app as: added. `--serve` is what makes the API available; without it the app only prints events, which a service sends to the journal. -Afterwards: - -```bash -systemctl status rdm-card-reader # state -systemctl is-enabled rdm-card-reader # should be 'enabled' (starts at boot) -journalctl -u rdm-card-reader -f # live log -ss -ltnp | grep 8765 # confirms something is listening -curl -sS http://127.0.0.1:8765/api/card # tap a card, then run this -``` - -A healthy startup logs one line: - -``` - OK reader on /dev/serial0 ; bridge on http://127.0.0.1:8765 (mode: login) -``` - ### Checking the reader from the command line ```bash