feat: Refactor BedHardware to use a singleton instance and remove serial implementation
This commit is contained in:
parent
fb87e74ec9
commit
fd8cacd62b
4 changed files with 25 additions and 54 deletions
|
@ -1,5 +1,5 @@
|
||||||
import { NextRequest, NextResponse } from 'next/server';
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
import { BedHardware, PinState, PinChange } from '@/services/BedHardware';
|
import { bedHardwareInstance, PinState, PinChange } from '@/services/BedHardware';
|
||||||
import { SensorDataStorage, SensorDataPoint } from '@/services/SensorDataStorage';
|
import { SensorDataStorage, SensorDataPoint } from '@/services/SensorDataStorage';
|
||||||
import { SensorConfig } from '@/types/sensor';
|
import { SensorConfig } from '@/types/sensor';
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ SENSOR_CONFIG.forEach(sensor => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let bedHardware: BedHardware | null = null;
|
|
||||||
const sensorDataStorage = SensorDataStorage.getInstance();
|
const sensorDataStorage = SensorDataStorage.getInstance();
|
||||||
const sensorData: Record<string, {
|
const sensorData: Record<string, {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -108,41 +107,33 @@ function generateTimeSeriesData(hours = 1) {
|
||||||
|
|
||||||
// Initialize hardware connection
|
// Initialize hardware connection
|
||||||
async function initializeHardware() {
|
async function initializeHardware() {
|
||||||
if (bedHardware && isHardwareConnected) return;
|
if (isHardwareConnected) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to find available serial ports
|
bedHardwareInstance.on('connected', () => {
|
||||||
const availablePorts = await BedHardware.listPorts();
|
|
||||||
const portPath = availablePorts.find(port =>
|
|
||||||
port.includes('ttyUSB') || port.includes('ttyACM') || port.includes('cu.usbmodem')
|
|
||||||
) || '/dev/ttyUSB0'; // Default fallback
|
|
||||||
|
|
||||||
bedHardware = new BedHardware(portPath, 9600);
|
|
||||||
|
|
||||||
bedHardware.on('connected', () => {
|
|
||||||
console.log('BedHardware connected');
|
console.log('BedHardware connected');
|
||||||
isHardwareConnected = true;
|
isHardwareConnected = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
bedHardware.on('disconnected', () => {
|
bedHardwareInstance.on('disconnected', () => {
|
||||||
console.log('BedHardware disconnected');
|
console.log('BedHardware disconnected');
|
||||||
isHardwareConnected = false;
|
isHardwareConnected = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
bedHardware.on('pinChanged', (change: PinChange) => {
|
bedHardwareInstance.on('pinChanged', (change: PinChange) => {
|
||||||
updateSensorFromPin(change.pin, change.currentState);
|
updateSensorFromPin(change.pin, change.currentState);
|
||||||
});
|
});
|
||||||
|
|
||||||
bedHardware.on('pinInitialized', (pinState: PinState) => {
|
bedHardwareInstance.on('pinInitialized', (pinState: PinState) => {
|
||||||
updateSensorFromPin(pinState.pin, pinState.state);
|
updateSensorFromPin(pinState.pin, pinState.state);
|
||||||
});
|
});
|
||||||
|
|
||||||
bedHardware.on('error', (error) => {
|
bedHardwareInstance.on('error', (error) => {
|
||||||
console.error('BedHardware error:', error);
|
console.error('BedHardware error:', error);
|
||||||
isHardwareConnected = false;
|
isHardwareConnected = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
await bedHardware.connect();
|
await bedHardwareInstance.connect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to connect to hardware, using mock data:', error);
|
console.warn('Failed to connect to hardware, using mock data:', error);
|
||||||
isHardwareConnected = false;
|
isHardwareConnected = false;
|
||||||
|
@ -283,7 +274,7 @@ export async function GET() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize hardware if not already done
|
// Initialize hardware if not already done
|
||||||
if (!bedHardware) {
|
if (!isHardwareConnected) {
|
||||||
await initializeHardware();
|
await initializeHardware();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,8 +282,8 @@ export async function GET() {
|
||||||
updateMockSensorData();
|
updateMockSensorData();
|
||||||
|
|
||||||
// If hardware is connected, get current pin states
|
// If hardware is connected, get current pin states
|
||||||
if (isHardwareConnected && bedHardware) {
|
if (isHardwareConnected) {
|
||||||
const pinStates = bedHardware.getAllPinStates();
|
const pinStates = bedHardwareInstance.getAllPinStates();
|
||||||
for (const pinState of pinStates) {
|
for (const pinState of pinStates) {
|
||||||
await updateSensorFromPin(pinState.pin, pinState.state);
|
await updateSensorFromPin(pinState.pin, pinState.state);
|
||||||
}
|
}
|
||||||
|
@ -332,9 +323,8 @@ export async function POST(request: NextRequest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.action === 'disconnect') {
|
if (body.action === 'disconnect') {
|
||||||
if (bedHardware) {
|
if (bedHardwareInstance) {
|
||||||
await bedHardware.disconnect();
|
await bedHardwareInstance.disconnect();
|
||||||
bedHardware = null;
|
|
||||||
isHardwareConnected = false;
|
isHardwareConnected = false;
|
||||||
}
|
}
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { IBedHardware, PinState, PinChange, BedHardwareConfig } from '../types/bedhardware';
|
import { IBedHardware, PinState, PinChange, BedHardwareConfig } from '../types/bedhardware';
|
||||||
import { BedHardwareSerial } from './BedHardwareSerial';
|
|
||||||
import { BedHardwareMQTT } from './BedHardwareMQTT';
|
import { BedHardwareMQTT } from './BedHardwareMQTT';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BedHardware - Factory class for creating bed hardware implementations
|
* BedHardware - MQTT-based bed hardware implementation
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* // MQTT (connects to broker.hivemq.com with base topic /Jtkcp2N/pressurebed/)
|
* MQTT (connects to broker.hivemq.com with base topic /Jtkcp2N/pressurebed/)
|
||||||
* const hardware = BedHardware.createSimpleMQTT();
|
* const hardware = BedHardware.createSimpleMQTT();
|
||||||
*
|
*
|
||||||
* // Serial
|
* With custom topics
|
||||||
* const hardware = BedHardware.createSerial('COM3', 9600);
|
|
||||||
*
|
|
||||||
* // With custom topics
|
|
||||||
* const hardware = BedHardware.createMQTT({
|
* const hardware = BedHardware.createMQTT({
|
||||||
* topics: {
|
* topics: {
|
||||||
* pinState: '/custom/pin/state',
|
* pinState: '/custom/pin/state',
|
||||||
|
@ -24,18 +20,10 @@ import { BedHardwareMQTT } from './BedHardwareMQTT';
|
||||||
*/
|
*/
|
||||||
export class BedHardware extends EventEmitter implements IBedHardware {
|
export class BedHardware extends EventEmitter implements IBedHardware {
|
||||||
private implementation: IBedHardware;
|
private implementation: IBedHardware;
|
||||||
|
|
||||||
constructor(config: BedHardwareConfig) {
|
constructor(config: BedHardwareConfig) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (config.type === 'serial') {
|
if (config.type === 'mqtt') {
|
||||||
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({
|
this.implementation = new BedHardwareMQTT({
|
||||||
topics: config.mqtt?.topics
|
topics: config.mqtt?.topics
|
||||||
});
|
});
|
||||||
|
@ -88,14 +76,8 @@ export class BedHardware extends EventEmitter implements IBedHardware {
|
||||||
isConnected(): boolean {
|
isConnected(): boolean {
|
||||||
return this.implementation.isConnected();
|
return this.implementation.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static factory methods for convenience
|
// Static factory methods for convenience
|
||||||
static createSerial(portPath: string, baudRate: number = 9600): BedHardware {
|
static createMQTT(config?: {
|
||||||
return new BedHardware({
|
|
||||||
type: 'serial',
|
|
||||||
serial: { portPath, baudRate }
|
|
||||||
});
|
|
||||||
} static createMQTT(config?: {
|
|
||||||
topics?: {
|
topics?: {
|
||||||
pinState: string;
|
pinState: string;
|
||||||
pinChange: string;
|
pinChange: string;
|
||||||
|
@ -114,13 +96,12 @@ export class BedHardware extends EventEmitter implements IBedHardware {
|
||||||
mqtt: {}
|
mqtt: {}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static method to list available serial ports (for serial implementation)
|
|
||||||
static async listSerialPorts(): Promise<string[]> {
|
|
||||||
return BedHardwareSerial.listPorts();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export all classes for direct access if needed
|
// Create and export a default MQTT instance
|
||||||
export { BedHardwareSerial, BedHardwareMQTT };
|
export const bedHardwareInstance = new BedHardware({
|
||||||
|
type: 'mqtt',
|
||||||
|
mqtt: {}
|
||||||
|
});
|
||||||
|
|
||||||
export * from '../types/bedhardware';
|
export * from '../types/bedhardware';
|
|
@ -23,6 +23,6 @@
|
||||||
"@/*": ["./*"]
|
"@/*": ["./*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "services/BedHardwareSerial.ts.disabled"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue