f87e4c0d6b
Generalise printer-only monitoring to every configured device. New DeviceMonitor polls all enabled devices each tick (default 8s): printers via rich readStatus(), relays/readers/cameras via the generic healthCheck() reachability probe, flattened to one traffic-light (ready/degraded/offline) + detail, deduped (emit on change only), fail-toward-offline. - device-status bus event + GET /api/devices/status snapshot. - Pushed over the existing /api/ws (hello carries the initial set; device-status frame per change). - Web: live-store devices map, WS handler, DeviceFooter chip-per-device (role label not vendor; click a degraded/offline chip for an issues panel). Verified roleKind resolution + change-only emit on a fresh DB. Note: the footer's UI surface (api type, router mount, i18n devices) rides in the subsequent subscription commit due to shared-file overlap. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
22 lines
932 B
TypeScript
22 lines
932 B
TypeScript
import type { FastifyInstance } from "fastify";
|
|
import { requireRole } from "../auth.js";
|
|
import type { DeviceMonitor } from "../device-monitor.js";
|
|
|
|
// Unified device-status snapshot for the booth footer. The DeviceMonitor polls all
|
|
// configured devices (relays/readers/cameras via healthCheck, printers via their
|
|
// rich readStatus) in the background; this exposes its cache. Live updates ride the
|
|
// booth WebSocket (kind:"device-status") — this REST route is the initial load /
|
|
// fallback. Any authenticated role may read (operational, not a setup action).
|
|
// See wiki/concepts/device-status-monitoring.md, booth-console.md.
|
|
|
|
export async function deviceStatusRoutes(
|
|
app: FastifyInstance,
|
|
monitor: DeviceMonitor,
|
|
): Promise<void> {
|
|
const guard = requireRole("admin", "operator", "cashier", "readonly");
|
|
|
|
app.get("/api/devices/status", { preHandler: guard }, async () => ({
|
|
devices: monitor.snapshot(),
|
|
}));
|
|
}
|