a0e0fd9118
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.
84 lines
2.1 KiB
TypeScript
84 lines
2.1 KiB
TypeScript
// Minimal ambient types for the `uhppoted` CommonJS module (no bundled types).
|
|
// Only the surface we use; extend as we adopt more of the API.
|
|
// Upstream: https://github.com/uhppoted/uhppoted-lib-nodejs
|
|
declare module "uhppoted" {
|
|
export class Config {
|
|
constructor(
|
|
name?: string,
|
|
bindAddr?: string,
|
|
broadcastAddr?: string,
|
|
listenAddr?: string,
|
|
timeout?: number,
|
|
controllers?: unknown[],
|
|
debug?: boolean,
|
|
);
|
|
}
|
|
|
|
/** Either a bare controller serial, or an addressable descriptor. */
|
|
export type Controller =
|
|
| number
|
|
| { id: number; address?: string; protocol?: "udp" | "tcp" };
|
|
|
|
export interface Ctx {
|
|
config: Config;
|
|
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,
|
|
door: number,
|
|
): Promise<{ deviceId: number; opened: boolean }>;
|
|
|
|
export function getStatus(
|
|
ctx: Ctx,
|
|
controller: Controller,
|
|
): Promise<Record<string, unknown>>;
|
|
|
|
export function getEvent(
|
|
ctx: Ctx,
|
|
controller: Controller,
|
|
index: number,
|
|
): Promise<Record<string, unknown>>;
|
|
|
|
export function getEventIndex(
|
|
ctx: Ctx,
|
|
controller: Controller,
|
|
): Promise<{ deviceId: number; index: number }>;
|
|
|
|
export function setListener(
|
|
ctx: Ctx,
|
|
controller: Controller,
|
|
address: string,
|
|
port: number,
|
|
): Promise<unknown>;
|
|
|
|
// 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;
|
|
getEventIndex: typeof getEventIndex;
|
|
setListener: typeof setListener;
|
|
};
|
|
export default uhppoted;
|
|
}
|