import { EventEmitter } from 'events'; import { IBedHardware, PinState, PinChange, BedHardwareConfig } from '../types/bedhardware'; import { BedHardwareSerial } from './BedHardwareSerial'; import { BedHardwareMQTT } from './BedHardwareMQTT'; /** * BedHardware - Factory class for creating bed hardware implementations * * Usage: * // MQTT (connects to broker.hivemq.com with base topic /Jtkcp2N/pressurebed/) * const hardware = BedHardware.createSimpleMQTT(); * * // Serial * const hardware = BedHardware.createSerial('COM3', 9600); * * // With custom topics * const hardware = BedHardware.createMQTT({ * topics: { * pinState: '/custom/pin/state', * pinChange: '/custom/pin/change', * initialization: '/custom/init' * } * }); */ export class BedHardware extends EventEmitter implements IBedHardware { private implementation: IBedHardware; constructor(config: BedHardwareConfig) { super(); if (config.type === 'serial') { if (!config.serial?.portPath) { throw new Error('Serial port path is required for serial connection'); } this.implementation = new BedHardwareSerial( config.serial.portPath, config.serial.baudRate || 9600 ); } else if (config.type === 'mqtt') { this.implementation = new BedHardwareMQTT({ topics: config.mqtt?.topics }); } else { throw new Error(`Unsupported hardware type: ${config.type}`); } // Forward all events from the implementation this.forwardEvents(); } private forwardEvents(): void { const events = [ 'connected', 'disconnected', 'error', 'initialized', 'pinInitialized', 'pinChanged' ]; events.forEach(event => { this.implementation.on(event, (...args: unknown[]) => { this.emit(event, ...args); }); }); // Forward dynamic pin events (pin{number}Changed) this.implementation.on('pinChanged', (pinChange: PinChange) => { this.emit(`pin${pinChange.pin}Changed`, pinChange); }); } async connect(): Promise { return this.implementation.connect(); } async disconnect(): Promise { return this.implementation.disconnect(); } getPinState(pin: number): PinState | undefined { return this.implementation.getPinState(pin); } getAllPinStates(): PinState[] { return this.implementation.getAllPinStates(); } isConnected(): boolean { return this.implementation.isConnected(); } // Static factory methods for convenience static createSerial(portPath: string, baudRate: number = 9600): BedHardware { return new BedHardware({ type: 'serial', serial: { portPath, baudRate } }); } static createMQTT(config?: { topics?: { pinState: string; pinChange: string; initialization: string; }; }): BedHardware { return new BedHardware({ type: 'mqtt', mqtt: config }); } static createSimpleMQTT(): BedHardware { return new BedHardware({ type: 'mqtt', mqtt: {} }); } // Static method to list available serial ports (for serial implementation) static async listSerialPorts(): Promise { return BedHardwareSerial.listPorts(); } } // Export all classes for direct access if needed export { BedHardwareSerial, BedHardwareMQTT }; export * from '../types/bedhardware';