- Added @elysiajs/swagger dependency to package.json for API documentation. - Removed the old bed router and replaced it with a new history router. - Created a new state router to manage WebSocket connections and state updates. - Implemented a comprehensive state management system with the StateManager service. - Introduced AlarmManagement and BedService services for handling alarms and sensor readings. - Established a new MQTT service for managing MQTT connections and subscriptions. - Created an AlarmStateStore to manage volatile alerts and their states. - Defined FrontendState types for structured state management and WebSocket messaging.
148 lines
No EOL
4.1 KiB
TypeScript
148 lines
No EOL
4.1 KiB
TypeScript
import { EventEmitter } from 'events';
|
|
import { AlarmStateStore, VolatileAlert } from '../store/AlarmStateStore';
|
|
import { MeasurementPointState } from '../types/FrontendState';
|
|
|
|
export class AlarmManagement extends EventEmitter {
|
|
private alarmStore: AlarmStateStore;
|
|
private measurementPoints: Map<string, MeasurementPointState> = new Map();
|
|
|
|
constructor() {
|
|
super();
|
|
this.alarmStore = new AlarmStateStore();
|
|
this.setupEventListeners();
|
|
}
|
|
|
|
private setupEventListeners(): void {
|
|
// Forward alarm store events
|
|
this.alarmStore.on('alertCreated', (alert: VolatileAlert) => {
|
|
this.emit('alertCreated', alert);
|
|
});
|
|
|
|
this.alarmStore.on('alertUpdated', (alert: VolatileAlert) => {
|
|
this.emit('alertUpdated', alert);
|
|
});
|
|
|
|
this.alarmStore.on('alertRemoved', (alert: VolatileAlert) => {
|
|
this.emit('alertRemoved', alert);
|
|
});
|
|
}
|
|
|
|
// Update measurement points for reference
|
|
updateMeasurementPoints(measurementPoints: Record<string, MeasurementPointState>): void {
|
|
this.measurementPoints.clear();
|
|
Object.values(measurementPoints).forEach(mp => {
|
|
this.measurementPoints.set(mp.id, mp);
|
|
});
|
|
}
|
|
|
|
// Process sensor reading and check for alerts
|
|
processSensorReading(sensorId: string, value: number, timestamp: Date): void {
|
|
// Find measurement point by sensorId
|
|
const measurementPoint = Array.from(this.measurementPoints.values())
|
|
.find(mp => mp.sensorId === sensorId);
|
|
|
|
if (!measurementPoint) {
|
|
console.warn(`No measurement point found for sensor: ${sensorId}`);
|
|
return;
|
|
}
|
|
|
|
this.checkAlerts(measurementPoint, value);
|
|
}
|
|
|
|
private checkAlerts(measurementPoint: MeasurementPointState, value: number): void {
|
|
const { id: pointId, warningThreshold, alarmThreshold, warningDelayMs, label, zone } = measurementPoint;
|
|
|
|
// Check if value exceeds alarm threshold (immediate alarm)
|
|
if (value >= alarmThreshold) {
|
|
this.alarmStore.clearWarningTimer(pointId);
|
|
this.alarmStore.createAlert(
|
|
pointId,
|
|
measurementPoint.sensorId,
|
|
'ALARM',
|
|
value,
|
|
alarmThreshold,
|
|
label,
|
|
zone
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Check if value exceeds warning threshold
|
|
if (value >= warningThreshold) {
|
|
const existingAlert = this.alarmStore.getAlertByMeasurementPointId(pointId);
|
|
|
|
if (!existingAlert) {
|
|
// Create warning alert
|
|
this.alarmStore.createAlert(
|
|
pointId,
|
|
measurementPoint.sensorId,
|
|
'WARNING',
|
|
value,
|
|
warningThreshold,
|
|
label,
|
|
zone
|
|
);
|
|
|
|
// Set timer for warning to escalate to alarm
|
|
const timer = setTimeout(() => {
|
|
this.alarmStore.createAlert(
|
|
pointId,
|
|
measurementPoint.sensorId,
|
|
'ALARM',
|
|
value,
|
|
warningThreshold,
|
|
label,
|
|
zone
|
|
);
|
|
}, warningDelayMs);
|
|
|
|
this.alarmStore.setWarningTimer(pointId, timer);
|
|
}
|
|
} else {
|
|
// Value is below warning threshold, clear any alerts for this point
|
|
this.alarmStore.clearWarningTimer(pointId);
|
|
this.alarmStore.removeAlertsByMeasurementPointId(pointId);
|
|
}
|
|
}
|
|
|
|
// Get all active alerts
|
|
getActiveAlerts(): VolatileAlert[] {
|
|
return this.alarmStore.getAllAlerts();
|
|
}
|
|
|
|
// Get alerts in frontend state format
|
|
getAlertStates(): Record<string, import('../types/FrontendState').AlertState> {
|
|
return this.alarmStore.toAlertStates();
|
|
}
|
|
|
|
// Acknowledge alert
|
|
acknowledgeAlert(alertId: string): boolean {
|
|
return this.alarmStore.acknowledgeAlert(alertId);
|
|
}
|
|
|
|
// Silence alert
|
|
silenceAlert(alertId: string): boolean {
|
|
return this.alarmStore.silenceAlert(alertId);
|
|
}
|
|
|
|
// Get alert by ID
|
|
getAlert(alertId: string): VolatileAlert | undefined {
|
|
return this.alarmStore.getAlert(alertId);
|
|
}
|
|
|
|
// Get statistics
|
|
getStats() {
|
|
return this.alarmStore.getStats();
|
|
}
|
|
|
|
// Clear all alerts (for testing/reset)
|
|
clearAllAlerts(): void {
|
|
this.alarmStore.clearAll();
|
|
}
|
|
|
|
// Cleanup
|
|
cleanup(): void {
|
|
this.alarmStore.clearAll();
|
|
this.removeAllListeners();
|
|
}
|
|
} |