Files
parking_solution/wiki/concepts/button-light-indicator.md
T
julian 2915d141aa feat(devices): radar presence input + button-light output on the controller
Model the entry button (I1) and a Hikvision radar (I2) as named children of the
access controller, and drive the button's 12V lamp on a spare relay.

- Radar = the existing relays[].presenceInput one-car-one-ticket gate, now labelled
  presenceKind: loop|radar. A radar may idle opposite the button, so add a per-input
  active-level override: relays[].presenceActiveLow -> driver inputActiveLow set,
  inverting just that terminal (pure helper inputActive()). The Dingtian has one
  board-wide resting level otherwise.
- AuxOutputDevice.setAux(channel,on) capability on the device interface (Dingtian
  latch) so business logic drives a NON-barrier lamp through the interface. Barriers
  still only pulseOpen — barrier-not-a-door preserved.
- ButtonLightController: subscribes to the radar input edge + the camera lane status
  and drives a 3-state lamp — radar+car=solid, radar-only=blink (~1Hz), else off.
  Fails OFF on host loss/error; de-duped. A radar detection never opens a barrier on
  its own (advisory; threat model).
- SetupWizard: presence kind + active-low + a button-light relay picker; sq+en i18n.

Tests: button-light.test.ts (truth table + blink + fail-OFF + de-dupe),
access-dingtian.test.ts (active-level inversion). Workspace build+lint+test green
(158 server tests). Wiki: hikvision-radar, button-light-indicator + updates.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
2026-06-24 11:45:22 +02:00

3.0 KiB
Raw Blame History

type, tags, sources, updated, status
type tags sources updated status
concept
parking
device
indicator
radar
camera
aux-output
barrier-not-a-door
2026-06-24 settled

Button-light indicator (radar × camera disagreement lamp)

The entry button has a 12 V light. It is driven by the host on a spare relay of the dingtian-relay controller as a 3-state indicator that combines the [[hikvision-radar| radar]] input with the camera "car in zone" signal:

Radar input Camera (lane entry busy) Button light
detecting free — no car confirmed BLINK (~1 Hz)
detecting busy — camera confirms a car SOLID on
clear — OFF

It is a disagreement indicator: the radar sees something but the camera hasn't confirmed a real vehicle → blink (attention / "pull forward"); both agree → solid; nothing there → off.

Signals

  • Radar = the presence input edge on the entry relay (relays[].presenceInput, the same edge the entry-double-press gate observes — so the lamp and the gate always agree on "a car is here").
  • Camera "car in zone" = the existing lpr-camera (LaneStatusEvent entry busy/free, from camera vehicle detection). Already advisory; already drives the booth's barrier lights. No new camera plumbing.

Config

A controller-level config.buttonLight = { relay, blinkOnMs?, blinkOffMs? } (the operator picks a spare relay — not a barrier relay; the setup UI warns if it overlaps one). Blink defaults to 500 ms / 500 ms.

Implementation

apps/server/src/button-light.ts — ButtonLightController subscribes to deviceEvents.onInput (radar) + onLaneStatus (camera), computes the target state per controller, and drives the lamp via a device-agnostic aux-output capability.

  • Aux-output capability. AuxOutputDevice { setAux(channel, on) } on the device interface (the Dingtian driver implements it as a latch). Business logic drives the lamp through this — never the driver's barrier methods.
  • Barrier-not-a-door is preserved. The lamp is not a barrier, so holding / blinking it on a timer is fine — the barrier-not-a-door rule forbids timing a barrier closed, and barriers still only ever pulseOpen. The lamp uses the separate setAux latch.
  • Fails OFF. On host loss, shutdown, or a setAux error the lamp defaults OFF — a dead lamp is "no hint", never a misleading solid "go". SOLID is only ever held while busy + present is actively true (never latched on through a crash path).
  • De-duped. Only writes when the effective output changes, so the 50 ms input poll doesn't spam the controller over UDP.

Status

Built 2026-06-24 for the first booth (button I1, radar I2, lamp on a spare relay). Covered by apps/server/src/button-light.test.ts (the truth table + blink toggling + fail-OFF + de-dupe). Related: hikvision-radar, entry-double-press, lpr-camera, dingtian-relay, barrier-not-a-door.