Add device discovery (UHPPOTE LAN scan) to setup

UHPPOTE controllers self-announce via UDP broadcast, but the frontend had no way
to find them — the admin had to type the serial blind. Add a generic discovery
capability and surface it in the setup wizard.

packages/devices:
- DiscoverableDriver capability + DiscoveredDevice type + isDiscoverable() guard
  on the registry (optional, so any driver can opt in).
- uhppote driver implements discover() via uhppoted getDevices (UDP broadcast),
  mapping each controller's serial/IP/firmware into a DiscoveredDevice; extract
  shared buildCtx().

apps/server:
- GET /api/setup/discover/:driverId (admin-only): runs discover() and
  health-checks each found device so reachability shows before assigning.
- catalog now returns a `discoverable` driver-id list.

apps/web:
- SetupWizard "Scan for controllers" button for discoverable drivers; lists found
  devices with health badges; selecting one auto-fills serial + host. api client
  gains discoverDevices().

wiki: new device-discovery concept; cross-link from registry/setup/uhppote;
note the broadcast-permission (EACCES) deployment caveat; index + log.

Verified: catalog flags uhppote discoverable; discover runs and fails gracefully
without hardware; non-discoverable driver -> 400; missing token -> 401.
This commit is contained in:
2026-06-14 08:21:27 +02:00
parent 7438c0bdc2
commit a0e0fd9118
12 changed files with 320 additions and 39 deletions
+17
View File
@@ -24,6 +24,22 @@ declare module "uhppoted" {
locale?: string;
}
export interface DiscoveredController {
deviceId: number;
device: {
serialNumber: number;
address: string;
netmask: string;
gateway: string;
MAC: string;
version: string;
date: string;
};
}
/** UDP broadcast discovery — returns every controller answering on the LAN. */
export function getDevices(ctx: Ctx): Promise<DiscoveredController[]>;
export function openDoor(
ctx: Ctx,
controller: Controller,
@@ -56,6 +72,7 @@ declare module "uhppoted" {
// CommonJS default export (module.exports = { ... }). Destructure from this.
const uhppoted: {
Config: typeof Config;
getDevices: typeof getDevices;
openDoor: typeof openDoor;
getStatus: typeof getStatus;
getEvent: typeof getEvent;