--- type: entity tags: [parking, hardware, access-control, current-choice] sources: [parking-system-architecture] updated: 2026-06-15 --- # UHPPOTE Controller (current choice) The starting access-control hardware: a **UHPPOTE Wiegand 26/34 network controller (4-door)** — a cheap reader-plus-relay frontend, acceptable **provided you understand its limits**. The plan is UHPPOTE now → ZKTeco later (see [[bom]]). (See [[parking-system-architecture]] §6.) > **⚠️ Entry-flow blocker (verified on hardware):** the push-button input **auto-opens the relay > in firmware** — there's no command to make it report-without-opening — so it **cannot** do > ticket-first entry (`button → print → open`). Fine as a host-**commanded relay** and for > [[wiegand]]/permit lanes, but **not** the button-driven entry lane as wired. Full detail and > options: [[access-controller-button-flow]]. > > **Verified working on the real unit** (serial 225088491, fw 09120): host-commanded `openDoor` > on doors 1 & 2 (physically actuated, `reason="remote open door"`); button presses captured live > (`reason="push button ok"`); [[device-discovery]] scan. Test scripts: `apps/server/scripts/`. > **Implementation:** integrated via the official **`uhppoted`** npm package (MIT, by the > `uhppoted` org — `github.com/uhppoted/uhppoted-lib-nodejs`), added to `@parking/devices` as the > `uhppote` access driver ([[device-registry]]). It exposes exactly the protocol commands this > design needs: `openDoor`, `getStatus`, and the event-log set (`getEvent`, `getEventIndex`, > `setEventIndex`, `recordSpecialEvents`) plus `setListener`/`listen` for auto-push — see > [[event-log-ingestion]]. Transport defaults to **UDP** (broadcast `…:60000`), with optional > per-call TCP on newer firmware. The driver also implements **[[device-discovery]]** > (`getDevices` broadcast) so the setup wizard can scan for controllers. Note: the lib pulls one > trivial extra dep (the npm `os` shim) and uses UDP broadcast, which needs socket broadcast > permission on the host. ## What it is - Combines reader input ([[wiegand]]) and door relays, with an onboard card list enabling **autonomous offline decisions** for Wiegand lanes. - Stores an **indexed event log** (see [[event-log-ingestion]]): `get-events` returns the stored range + current index; each record has event ID, timestamp, card number, door, access-granted flag, reason code. **At the record level it's effectively append-only** — no command edits/deletes an individual event. ## The catch It speaks the [[uhppote-udp-protocol]]: **UDP port 60000, no auth, no encryption**. Anyone on the LAN can open any door — and several unauthenticated commands can blind/reset/skew the log. So the device is **tamper-evident, not tamper-proof**, and only trustworthy behind [[network-isolation]] (mandatory). **Firmware cannot be customized** — the open-source `uhppoted` ecosystem is protocol reverse-engineering only; the controller accepts only the manufacturer's official firmware images. Make the log trustworthy via [[event-log-ingestion]] (host-side index tracking) landing into the [[append-only-event-chain]]. For prevention-grade authentication, see the [[esp32-custom-controller]]. The choice between them is the [[trust-boundary]] decision.