Skip to content

ARES Vehicle Light Controller

Touch dashboard on the field laptop that drives a USB relay board for amber warning and scene-light triggers, with simulation mode, a watchdog and fail-safe ALL OFF.

Status
In progress
Category
Software and Automation
Started
TBD
Last updated
2026-10-26

Release details

Version
0.1.0
Platform
Windows 11, Python 3.12+
Stack
FastAPI, Uvicorn, Jinja2, Pydantic, pySerial
UI
Touch-friendly dark console, WebSocket status updates
Binding
Local only by default (127.0.0.1:8765)
Tests
pytest, 14 tests
Built with
OpenAI Codex

Source: Project README, pyproject.toml and default config (repository not public)

Let the operator control amber warning and scene lighting triggers from the same laptop that runs the ARES CF-33 Field Dashboard, with large touch buttons, one-tap profiles, and an ALL OFF that is always visible and always tried first when anything goes wrong.

  • Low current only: the software controls a relay board that triggers an external automotive relay and fuse box or a professional lighting controller.
  • No law-enforcement features: no siren tones, no red and blue patterns, and no police-specific modes, by design.
  • Offline: no cloud, no external database and no internet-hosted assets.
  • Fail-safe: channels default to off, and the app attempts ALL OFF on startup, shutdown, disconnect, watchdog timeout and command faults.
Laptop dashboard (FastAPI + WebSocket)
│ pySerial, configurable byte templates
▼
USB serial relay board (8 channels, low-current triggers)
▼
Automotive relay / fuse box or professional controller (fused)
▼
Lights

The relay driver layer has a simulation (mock) driver, a generic serial driver and a KMTronic-style driver. Command templates are set in config, so another board can be supported by changing the byte format rather than the code.

  • One command at a time: every channel, profile, pulse and ALL OFF command runs under a single lock, so two taps can never interleave on the serial line.
  • Fault handling: if a relay command fails, the system state goes to FAULT, the fault is recorded (the last 25 are kept in memory and all are logged to disk), and the controller immediately tries ALL OFF. Channels switched off this way are marked as controlled by the “safety lockout”.
  • Honest ALL OFF: if ALL OFF itself fails, every channel is shown as FAULT with “ALL OFF could not be confirmed” instead of pretending the lights are off.
  • Pulse: a channel can be pulsed for a set number of milliseconds and is left off afterwards.
  • Watchdog: a background health check runs once per watchdog interval (5 seconds by default, never more often than once a second) and triggers the fault path if the board stops responding.
  • Command templates: each template renders the channel number, a zero-based channel index and the on/off state into either hex bytes (hex:FF 01 01) or ASCII text, and malformed templates are rejected with a clear error. A write that sends fewer bytes than expected is treated as a timeout fault.
  • Raw command logging: an optional debug setting logs the exact bytes sent to the board, which helps when confirming a board’s protocol on the bench.
  • Live status: the dashboard updates over a WebSocket, so every open screen shows the same channel states, faults and active profile.
Endpoint Purpose
GET /api/health Compact read-only summary for a parent dashboard tile: ok flag, connection state, simulation mode, watchdog state, active channel count, recent fault count
GET /api/status Full status, including every channel’s state, who last controlled it, and faults
GET /api/config Public configuration (channels and profiles)
POST /api/connect, POST /api/disconnect Open or close the relay board connection
POST /api/channel/{id}/on, /off, /toggle, /pulse Channel commands
POST /api/profile/{id}/activate Apply a profile
POST /api/all-off ALL OFF
POST /api/simulation-mode Turn simulation mode on or off
GET /api/logs/recent Recent command and fault log entries
WS /ws/status Live status stream

Logs are written as JSON Lines files (command_log.jsonl and fault_log.jsonl), one timestamped entry per command or fault.

PartSKUPrice paidKey specsSourceStatus
Field laptop (Windows 11)TBDTBDTBDTBDInstalled
USB serial relay board, 8 channels (KMTronic or Devantech style)TBDTBDModel and byte format to confirm from the board manualTBDPlanned
Automotive relay and fuse boxTBDTBDLoad-rated, fused near the batteryTBDPlanned
Physical kill switch and backup switch panelTBDTBDTBDTBDPlanned

Default relay channels (labels are editable in config):

Channel Label Default
1 Rear Warning (amber) Off
2 Side Warning (amber) Off
3 Front Warning (amber or white) Off
4 Scene Left Off
5 Scene Right Off
6 Rear Scene / Work Light Off
7 Brake Override / Brake Pop Hold (only through a compliant controller) Off
8 Spare Off

Profiles: Parked Incident, Roadside Warning, Scene Lighting, Low Power, Night (dims the dashboard only) and All Off. A profile changes only the channels it lists.

Laptop-specific settings, such as the COM port, go in a local config file that is never committed.

  1. Install Python 3.12 or newer.
  2. Run install_windows.bat, then run_windows.bat. The dashboard opens at http://127.0.0.1:8765.
  3. Leave simulation mode on until the relay board’s command format is confirmed on the bench.
  4. Copy the example local config, set the board’s COM port, and verify ALL OFF with no lighting loads connected.
  5. Only then connect low-current trigger wiring to the fused, relay-controlled lighting system.
Area Status
pytest suite (config, mock driver, controller safety, profiles, API) 14 passed on 2026-10-26, run in simulation mode on Linux with Python 3.13 for this page
Windows install and run scripts Not re-run for this page
Relay board on the bench Not yet tested
In-vehicle installation Not installed

The 14 tests:

  • Config: the default config loads correctly; a malformed config fails with a clear error; an environment override file layers over the defaults.
  • Mock relay driver: turns channels on and off; ALL OFF turns every channel off; an invalid channel is rejected.
  • Controller: an invalid channel is rejected; activating a profile applies its channel states; ALL OFF turns every channel off.
  • API: the status endpoint returns the expected structure; the health endpoint is usable by a parent dashboard; the dashboard page renders; simulation mode works with no serial hardware; the buttons toggle profiles and ALL OFF.
  • Fuse every lighting circuit near the battery, use load-rated relays and wire, and route wiring through grommets and loom.
  • Keep a physical kill switch and a backup switch panel so the lights can be controlled if the laptop, relay board or software fails.
  • Keep the server bound to the local machine. The LAN test runner is for bench testing on a trusted network only.

My F-150 upfit is built around a Whelen CanTrol WC Gen 3 as the lighting controller and siren amplifier. This controller is a separate software project. It is not part of the CanTrol output plan and does not change the truck’s install configuration.

  • Writing the safety rules into the project’s instructions for the coding agent (low current only, ALL OFF always visible, no siren features) kept every later change inside those limits.
  • Choose and document the relay board model, and confirm its byte format from the manual.
  • Bench test ALL OFF and the watchdog on the real board with no loads connected.
  • Run the test suite on Windows with Python 3.12 and record the result.
  • Decide whether the repository will be public.
  1. 2026-10-26

    Project page published.

    Rollback: Revert the commit that added this page.