/// Event received from bridge WebSocket class BridgeEvent { final String serverId; final DateTime timestamp; final String action; final Map params; BridgeEvent({ required this.serverId, required this.timestamp, required this.action, required this.params, }); factory BridgeEvent.fromJson(Map json, String serverId) { return BridgeEvent( serverId: serverId, timestamp: json['timestamp'] != null ? DateTime.parse(json['timestamp'] as String) : DateTime.now(), action: json['action'] as String? ?? '', params: json['params'] as Map? ?? {}, ); } // Specific event type checks bool get isViewerConnected => action == 'ViewerConnected'; bool get isViewerCleared => action == 'ViewerCleared'; bool get isViewerSelectionChanged => action == 'ViewerSelectionChanged'; bool get isEventStarted => action == 'EventStarted'; bool get isEventStopped => action == 'EventStopped'; bool get isDigitalInput => action == 'DigitalInput'; bool get isAlarmQueueNotification => action == 'VCAlarmQueueNotification'; bool get isConnectionLost => action == 'ConnectionLost'; // Viewer events int? get viewer => params['Viewer'] as int?; int? get channel => params['Channel'] as int?; int? get playMode => params['PlayMode'] as int?; // Alarm events int? get eventId => params['EventID'] as int?; String? get eventName => params['EventName'] as String?; int? get typeId => params['TypeID'] as int?; int? get foreignKey { final fk = params['ForeignKey']; if (fk is int) return fk; if (fk is String) return int.tryParse(fk); return null; } // Digital input int? get contact => params['Contact'] as int?; int? get state => params['State'] as int?; // Alarm queue notification int? get notification => params['Notification'] as int?; int? get alarmId => params['AlarmID'] as int?; @override String toString() { return 'BridgeEvent($action from $serverId at $timestamp)'; } }