wiki: Dingtian relay decision, HTTP-over-MQTT, unmanned direction

- dingtian-relay: relay+input controller (4ch on hand). Inputs are decoupled
  from relays (configurable via input_link_relay) — solves the
  access-controller-button-flow blocker the UHPPOTE couldn't. Full protocol from
  the SDK (UDP string control :60001, `00` status parse, input_link_url push,
  multicast discovery). Driver + hardware test still to build.
- dingtian-vs-mqtt: use direct HTTP/UDP now; MQTT skipped (broker = extra infra
  + failure mode + overkill at one-host/few-devices scale) but kept for later
  multi-lane scale.
- autonomous-direction: record the roadmap to fully unmanned (no booth) and how
  it reshapes the threat model (operator-fraud -> unattended-machine threats),
  makes host-in-the-loop entry mandatory, and raises fail-state stakes.
- threat-model: note the unmanned shift. index + log.

gitignore the vendor SDK (dingtian/, 71MB of binaries/examples) — reference
only, protocol captured in the wiki.
This commit is contained in:
2026-06-14 13:27:01 +02:00
parent dbf1fa17d7
commit 4319fb86dc
7 changed files with 160 additions and 1 deletions
+45
View File
@@ -0,0 +1,45 @@
---
type: decision
tags: [parking, direction, roadmap]
sources: []
updated: 2026-06-15
status: open
---
# Project Direction: Toward Fully Autonomous (Unmanned)
> Stated goal (2026-06-15): the system will evolve to **fully automatic operation — no human
> operator, no booth at all**. Recorded because "unmanned" is an architectural force that shapes
> several existing decisions, not just a feature.
## What "unmanned" changes
- **Threat model shift.** The original primary adversary was *"the legitimate operator at the
booth"* ([[threat-model]]). Remove the operator and that specific fraud vector (take cash → void
the record) largely disappears — but it's replaced by **unattended-machine threats**: tailgating,
plate spoofing/obscuring, physical tampering with a box nobody is watching, and forced entry.
The [[append-only-event-chain]] + [[reconciliation]] controls still apply; the emphasis moves
from "catch the cashier" to "trust the automated record + detect tampering."
- **Host-in-the-loop entry becomes mandatory, not optional.** With no person to hand over a ticket
or wave a car through, the machine must own the whole flow: detect arrival → issue ticket / read
plate → open. This is exactly why the [[access-controller-button-flow]] blocker matters and why
a controller whose input does **not** auto-fire the relay (see [[dingtian-relay]]) is required.
- **Reliability / fail-state get more critical** ([[fail-state-safety]]). No operator to recover a
stuck barrier or a trapped car ⇒ watchdogs, **exit-fails-open**, and hardware manual override
stop being nice-to-haves. Unattended uptime is a hard requirement.
- **Payment goes unmanned.** Pay-station / pay-on-foot or in-lane unmanned terminal rather than a
booth P2PE + cash drawer — sharpens [[open-questions]] #3 toward the unmanned option (PCI scope
still kept out of the app via a certified terminal).
- **Identity leans on automation.** Plate recognition ([[lpr-camera]]) and permit reads become the
primary identity sources, since there's no one to issue/inspect a paper ticket by hand.
## Near-term stance
Build for the unmanned target but don't over-engineer ahead of it. Current concrete step: the
**[[dingtian-relay]]** controller over **HTTP** (device pushes input events to the host; host
commands relays) — see [[dingtian-vs-mqtt]] for why HTTP over a message bus for now.
## Open
Lane topology, payment subsystem, and reconciliation channel ([[open-questions]]) should all be
(re)evaluated through the **unmanned** lens before procurement.
+46
View File
@@ -0,0 +1,46 @@
---
type: decision
tags: [parking, decision, devices, transport]
sources: []
updated: 2026-06-15
status: settled
---
# Transport for the Relay Controller: HTTP/UDP now, MQTT parked
**Decision (2026-06-15): use direct HTTP + UDP for the [[dingtian-relay]] controller now. MQTT is
deliberately skipped, but kept on the radar** for when the system scales.
## Options the device supports
The Dingtian relay board speaks several protocols: Dingtian string (UDP/TCP), Dingtian binary
(UDP, optional multicast/password), **HTTP CGI**, **HTTP input-link push** (`input_link_url`),
**Modbus** (RTU/TCP/ASCII), and **MQTT**.
## Why not MQTT (yet)
- **A broker is new infrastructure** on a deliberately **single-purpose hardened appliance**
([[disk-os-hardening]]) — another service to install, secure, supervise, and keep alive.
- **Extra failure mode on the critical path.** Today host→UDP→relay. MQTT inserts a broker on both
control and event paths; if it stalls, the lane stalls — and there are 3 processes to debug, not 2.
- **Doesn't fit [[offline-first]] for this scale.** MQTT earns its keep with *many* devices/consumers
and intermittent links. Here it's **one host + a few devices on one isolated LAN, metres apart** —
request/response control + a single input event, no fleet.
- **The device's MQTT input publish is periodic** ("default every 30 s"), so it's not even a clean
on-press event without relying on unverified on-change behaviour.
## Why HTTP/UDP fits
- **Relay control:** direct **UDP string protocol** (port 60001) — `11`=relay1 on, `21`=off,
`T1`=toggle, `11*`=jog/pulse. No deps, no broker.
- **Input/button events:** the device's **`input_link_url`** can **HTTP POST to the host backend
when an input fires** — real push, device calls our existing Fastify server directly, no broker.
(Polling `00` status over UDP every ~50 ms is the self-contained fallback.)
- Fewest moving parts; matches the local same-origin model already in use.
## When to revisit MQTT
If the system grows to **many lanes / many controllers**, or multiple subsystems (LPR, payment,
signage) all need to share events, a broker becomes a worthwhile central event bus. That aligns
with the [[autonomous-direction|unmanned]] roadmap at multi-lane scale — re-evaluate then. Until
then, direct HTTP/UDP wins on simplicity and reliability.