Phone-controlled projector display system for FRC competitions
Find a file
Filip Kin 00afaca37d Server: keep newer ws on stale-close; client: drop FRC- prefix from AP SSID
Server hub.ts:
- handleDevice's ws.on('close') was calling devices.delete(pin) blindly.
  When the daemon force-reconnects, the OLD ws's close event can fire
  AFTER the new ws's register message has already replaced devices[pin],
  and the blind delete then wipes the live new connection out of the
  registry — devices vanish from the admin panel and become uncontactable
  from the control panel until they next reconnect.
  Now only delete if devices[pin].ws === this ws.

Client (no bump — SSID prefix is cosmetic):
- AP SSID now broadcasts as 'Display-XXXXXX' instead of 'FRC-Display-XXXXXX'.
  This product isn't FRC-specific. Updated daemon, wifi.ts scan filter,
  install.sh's frc-ap-start, and the wifi.html instructions.
2026-05-05 17:46:34 -04:00
client Server: keep newer ws on stale-close; client: drop FRC- prefix from AP SSID 2026-05-05 17:46:34 -04:00
installer Admin panel + QR screen: hostname, uptime, network info, current mode 2026-05-05 16:41:21 -04:00
server Server: keep newer ws on stale-close; client: drop FRC- prefix from AP SSID 2026-05-05 17:46:34 -04:00
tools/ndi-play Queuing+stream mode: corner YouTube/NDI overlay on Nexus pit display 2026-05-01 11:35:01 -04:00
.dockerignore Self-hosted distribution: auto-update from server, generic installer 2026-04-30 14:20:13 -04:00
.gitignore Admin panel + QR screen: hostname, uptime, network info, current mode 2026-05-05 16:41:21 -04:00
Dockerfile Bun/TypeScript migration + admin panel (v1.2.6) 2026-04-30 16:29:44 -04:00
README.md Simplify auto-update: single local script, no server-side code execution; update docs 2026-04-30 14:34:13 -04:00

frc-projector-display

Phone-controlled projector display system for FRC competitions.

A thin client runs a kiosk display (Chromium + ffplay), controlled remotely via a phone-accessible web interface served from display.filipkin.com. Connection is established via QR code displayed on screen.

The server self-hosts the client installer and update bundle — no GitHub access required on the target device.

Repo layout

server/    Node.js WebSocket hub + mobile control UI (deploys to display.filipkin.com)
client/    Node.js daemon + local web server (runs on thin client)
docs/      SETUP.md — full provisioning runbook

Display modes

Mode Description
Home / QR Default screen; shows PIN + QR code
NDI Monitor ffplay fullscreen from NDI source
FIM Queuing fim-queueing.web.app
Nexus Queuing frc.nexus pit display
YouTube Live YouTube in kiosk mode
Custom URL Any URL
Web VNC noVNC via WebSocket tunnel

Setup

See docs/SETUP.md for the full provisioning runbook.

Quick start on thin client:

curl -fsSL https://display.filipkin.com/install.sh | sudo bash

Optional env vars:

SERVER_URL=https://display.filipkin.com   # default
SERVICE_USER=display                       # local kiosk user (created if missing)
INSTALL_DIR=/opt/frc-projector-display/client

Auto-update: on every boot the daemon checks display.filipkin.com/version.json and pulls a new build if the version changed. Deploy a new version by bumping client/package.json and pushing — all devices update on next reboot.