import { EventEmitter } from "node:events"; import type { PrinterStatus } from "@parking/devices"; // Internal event bus for device-originated events (button presses, etc.). // Hardware drivers / inbound device pushes emit here; business logic (entry // flow, event-log) subscribes — keeping the HTTP/transport layer thin and the // app device-agnostic. See wiki/entities/fastify.md. export interface DeviceInputEvent { readonly driverId: string; // e.g. "dingtian" readonly deviceId: string; // which configured device (lane_devices id) readonly input: number; // 1-based input/channel readonly edge: "on" | "off"; // active / inactive readonly at: string; // ISO-8601 (server receive time) readonly source: "push" | "poll"; } // A credential read at a lane: a ticket scanned at exit, a plate from LPR, a card // at a reader. Drives identity-based flows (exit validation, and later permits / // pay-station lookup). `kind` mirrors IdentitySource. See parking-session.md. export interface DeviceReadEvent { readonly driverId: string; readonly deviceId: string; // lane_devices id of the reader/scanner/camera readonly value: string; // the ticket id / plate / card number readonly kind: "ticket" | "plate" | "qr" | "card"; readonly at: string; // ISO-8601 } /** A printer's status as tracked by the live monitor (status + identity). */ export interface PrinterStatusEvent { readonly deviceId: string; // lane_devices id readonly lane: number; readonly driverId: string; readonly role?: string; // entry-dispenser | booth-receipt readonly status: PrinterStatus; } class DeviceEventBus extends EventEmitter { emitInput(event: DeviceInputEvent): void { this.emit("input", event); } onInput(cb: (event: DeviceInputEvent) => void): () => void { this.on("input", cb); return () => this.off("input", cb); } /** A credential read (ticket scan, plate, card) at a lane. */ emitRead(event: DeviceReadEvent): void { this.emit("read", event); } onRead(cb: (event: DeviceReadEvent) => void): () => void { this.on("read", cb); return () => this.off("read", cb); } /** Emitted by the printer monitor whenever a printer's status CHANGES. */ emitPrinterStatus(event: PrinterStatusEvent): void { this.emit("printer-status", event); } onPrinterStatus(cb: (event: PrinterStatusEvent) => void): () => void { this.on("printer-status", cb); return () => this.off("printer-status", cb); } } /** Process-wide device event bus. */ export const deviceEvents = new DeviceEventBus();