import { EventEmitter } from 'events'; import { AlertState } from '../types/FrontendState'; export interface VolatileAlert { id: string; measurementPointId: string; sensorId: string; type: 'WARNING' | 'ALARM'; value: number; threshold: number; acknowledged: boolean; silenced: boolean; startTime: Date; sensorLabel: string; zone: string; } export class AlarmStateStore extends EventEmitter { private alerts: Map = new Map(); private warningTimers: Map = new Map(); private alertIdCounter = 0; // Generate unique alert ID private generateAlertId(): string { return `alert_${Date.now()}_${++this.alertIdCounter}`; } // Create a new alert createAlert( measurementPointId: string, sensorId: string, type: 'WARNING' | 'ALARM', value: number, threshold: number, sensorLabel: string, zone: string ): VolatileAlert { // Check if there's already an active alert for this measurement point const existingAlert = this.getAlertByMeasurementPointId(measurementPointId); if (existingAlert) { // If upgrading from WARNING to ALARM, update the existing alert if (existingAlert.type === 'WARNING' && type === 'ALARM') { existingAlert.type = 'ALARM'; existingAlert.value = value; existingAlert.threshold = threshold; this.emit('alertUpdated', existingAlert); return existingAlert; } // If it's the same type or downgrading, return existing return existingAlert; } const alert: VolatileAlert = { id: this.generateAlertId(), measurementPointId, sensorId, type, value, threshold, acknowledged: false, silenced: false, startTime: new Date(), sensorLabel, zone }; this.alerts.set(alert.id, alert); this.emit('alertCreated', alert); return alert; } // Get alert by measurement point ID getAlertByMeasurementPointId(measurementPointId: string): VolatileAlert | undefined { return Array.from(this.alerts.values()) .find(alert => alert.measurementPointId === measurementPointId); } // Remove alert removeAlert(alertId: string): boolean { const alert = this.alerts.get(alertId); if (alert) { this.alerts.delete(alertId); this.emit('alertRemoved', alert); return true; } return false; } // Remove alerts by measurement point ID removeAlertsByMeasurementPointId(measurementPointId: string): void { const alertsToRemove = Array.from(this.alerts.values()) .filter(alert => alert.measurementPointId === measurementPointId); alertsToRemove.forEach(alert => { this.alerts.delete(alert.id); this.emit('alertRemoved', alert); }); } // Acknowledge alert acknowledgeAlert(alertId: string): boolean { const alert = this.alerts.get(alertId); if (alert) { alert.acknowledged = true; this.emit('alertUpdated', alert); return true; } return false; } // Silence alert silenceAlert(alertId: string): boolean { const alert = this.alerts.get(alertId); if (alert) { alert.silenced = true; this.emit('alertUpdated', alert); return true; } return false; } // Set warning timer setWarningTimer(measurementPointId: string, timer: NodeJS.Timeout): void { // Clear existing timer if any this.clearWarningTimer(measurementPointId); this.warningTimers.set(measurementPointId, timer); } // Clear warning timer clearWarningTimer(measurementPointId: string): void { const timer = this.warningTimers.get(measurementPointId); if (timer) { clearTimeout(timer); this.warningTimers.delete(measurementPointId); } } // Get all active alerts getAllAlerts(): VolatileAlert[] { return Array.from(this.alerts.values()); } // Get alert by ID getAlert(alertId: string): VolatileAlert | undefined { return this.alerts.get(alertId); } // Convert to AlertState format for frontend toAlertState(alert: VolatileAlert): AlertState { return { id: alert.id, measurementPointId: alert.measurementPointId, type: alert.type, value: alert.value, threshold: alert.threshold, acknowledged: alert.acknowledged, silenced: alert.silenced, startTime: alert.startTime, endTime: undefined, // Volatile alerts don't have end times sensorLabel: alert.sensorLabel, zone: alert.zone }; } // Convert all alerts to AlertState format toAlertStates(): Record { const result: Record = {}; this.alerts.forEach((alert, id) => { result[id] = this.toAlertState(alert); }); return result; } // Clear all alerts clearAll(): void { // Clear all warning timers this.warningTimers.forEach(timer => clearTimeout(timer)); this.warningTimers.clear(); // Clear all alerts this.alerts.clear(); this.emit('allAlertsCleared'); } // Get statistics getStats() { const alerts = this.getAllAlerts(); return { total: alerts.length, warnings: alerts.filter(a => a.type === 'WARNING').length, alarms: alerts.filter(a => a.type === 'ALARM').length, acknowledged: alerts.filter(a => a.acknowledged).length, silenced: alerts.filter(a => a.silenced).length }; } }