wiki: ER80 protocol = HTTP GET poll + JSON verdict (from QRCode SDK)

The QRCode SDK v1.6.5 settles the reader protocol (supersedes the earlier
serial guess). On each scan the reader HTTP-GETs the host
(/qa/mcardsea.php?cardid&mjihao&cjihao&status&time); the host replies JSON
{data:[{...,status,output}],code:0}. Reply status 1=valid(beep 2x)/0=invalid
(beep 1x); output 0=Access/1=WG26/2=WG34; time syncs the clock. The GET's status
low digit is the direction (1=in/0=out).

Key: the beep/accept is decided by the SERVER REPLY, not locally -- the 'no
beep' during bring-up was a plain-text reply, not a scan failure. Host-in-the-
loop and synchronous. 'Server language' only selects the URL path; transport is
plain HTTP.

New source page qrcode-sdk; updated gee-qr-er80 (protocol resolved), index.
This commit is contained in:
2026-06-16 12:05:05 +02:00
parent bf37106c5c
commit f67c1ead87
4 changed files with 113 additions and 28 deletions
+32 -27
View File
@@ -23,37 +23,42 @@ scanner** the design called for — read at the pay station and exit lane — an
- **Multi-interface** (Wiegand 26/34, RS-232, RS-485, USB, TCP/IP); the `-W` variant exposes
**Wiegand + RS-232/RS-485**.
## How it fits our architecture — host-side reader
## How it integrates — HTTP-GET push, server replies the verdict (confirmed via SDK)
It's a **host-side identity source** ([[entry-exit-readers]]): the host sees the scan, decides, and
commands the relay — exactly the model the read-driven flows already use. A scan becomes a
`DeviceReadEvent` on the internal `read` bus (`kind: "qr"`/`"ticket"`, value = the scanned string),
consumed by the **exit flow** and the **QR-permit** path ([[parking-session]], [[permit]]) — both
**already built**. So integration is a new **`ReaderDevice` adapter**, no business-logic change
([[device-adapter-pattern]]).
The protocol is settled by the **[[qrcode-sdk|QRCode SDK v1.6.5]]** (not serial as first guessed).
The reader is configured (Windows tool `QRCode_v1_6_5.exe`) with a **server IP/port** and a "server
language" (only picks the URL path, e.g. `/qa/mcardsea.php`). **On each scan it HTTP-GETs the host:**
- **Interface choice:** prefer **RS-232/RS-485 (serial)** for the QR variant — Wiegand can't carry a
variable-length QR string well (it's built for fixed-width card IDs). The host reads scans over a
serial port (USB-serial on TX/RX, or the USB variant); no Wiegand-decode hardware needed. This
suits [[offline-first]] (local serial, no network) and sidesteps the [[dingtian-relay|Dingtian]]'s
lack of an onboard card list (we never wanted autonomy here anyway).
- **LED/BEEP control lines** mean the host can drive scan feedback (accepted/rejected) — nice for an
unmanned lane.
- **Linux-supported**, 4–15 VDC — fits the [[disk-os-hardening|appliance]].
```
GET /qa/mcardsea.php?cardid=<QR>&mjihao=<devId>&cjihao=<devSN>&status=<2 chars>&time=<utc>
```
`cardid` = scanned data; `status` low digit = **direction (1=in / 0=out)**. The host replies JSON
`{data:[{cardid,cjihao,mjihao,status,time,output}],code:0}` where reply **`status` 1=valid (beep
2×) / 0=invalid (beep 1×)**, **`output` 0=Access/1=WG26/2=WG34**, `time` syncs the clock.
## Open questions (block the adapter)
This is **host-in-the-loop and SYNCHRONOUS**: the GET *is* the access query and **our reply is the
decision** — it drives the reader's beep + output. So unlike a fire-and-forget reader, the endpoint
must decide (valid/invalid, direction from `status`) and reply, then also emit a `DeviceReadEvent`
on the `read` bus for the entry/exit/permit flows ([[parking-session]], [[permit]]) to open the
barrier. ([[device-input-flow]] is the analogous push pattern; this one also returns a verdict.)
1. **RS-232/RS-485 protocol:** baud rate + frame format, and confirm a QR scan emits as an **ASCII
string** (expected) terminated by CR/LF vs. a framed/checksummed protocol. This is the one fact
the adapter needs and the datasheet omits. Resolve via vendor docs or by observing the port on a
scan.
2. **Serial vs. USB-CDC vs. TCP/IP** for *this* unit: `-W` is Wiegand/RS-232/485. Decide the host
wiring (a USB-RS232/485 adapter on TX/RX, most likely).
3. **Does Wiegand mode even carry QR?** Likely Wiegand is for the optional *card* modes only; confirm
so we don't design a Wiegand path for QR.
> **This explains the "no beep":** feedback comes from the server's JSON reply, not locally. A
> non-JSON / missing reply ⇒ no beep even though the scan worked. So "no beep" ≠ "didn't scan."
- Pushes over plain **HTTP** to our `10.0.10.x` host (on the device subnet); no serial wiring, no
Wiegand-decode hardware. Suits the host-in-the-loop model; autonomy is moot anyway
([[dingtian-relay]] has no onboard ACL).
- **Linux-supported**, 4–15 VDC, default IP `192.168.1.99` — fits the [[disk-os-hardening|appliance]].
## Resolved (2026-06-16)
- Protocol = HTTP GET poll + JSON verdict (above). The earlier "serial/Wiegand, find the baud"
open questions are **moot** — it's HTTP. Wiegand is the reader's *output line* on a valid read
(the reply `output` field), not the host transport.
## Next
A `ReaderDevice` driver in `packages/devices` (serial transport) emitting `read` events. Add it to
the [[device-registry]] under the `reader` category so the [[first-run-setup]] wizard can assign it
per lane. Pending open-question #1 (the serial frame) before coding.
A backend route (like `routes/devices.ts` for the Dingtian push) that parses the GET, **decides**
(reuse the permit/exit lookup), replies the JSON verdict, and emits on the `read` bus. The
[[device-registry]] `reader` entry can model it for [[first-run-setup]] (server IP/port are set in
the vendor tool; the app side is the endpoint). Build-ready — protocol fully known.