""" 数据模型定义 定义水务管理系统的各种数据结构 """ from dataclasses import dataclass, field from typing import Dict, List, Optional, Any from datetime import datetime from enum import Enum class DataType(Enum): """数据类型枚举""" LL = "LL" # 流量 YL = "YL" # 压力 SW = "SW" # 水位 ZD = "ZD" # 浊度 PH = "PH" # pH值 WD = "WD" # 温度 DD = "DD" # 电导率 YD = "YD" # 硬度 class AlertLevel(Enum): """警报级别枚举""" INFO = "info" WARNING = "warning" ERROR = "error" CRITICAL = "critical" @dataclass class Device: """设备模型""" id: str name: str device_type: str location: str description: Optional[str] = None install_date: Optional[datetime] = None status: str = "active" # active, inactive, maintenance metadata: Dict[str, Any] = field(default_factory=dict) @dataclass class SensorData: """传感器数据模型""" id: str device_id: str data_type: DataType value: float unit: str timestamp: datetime location: str quality_score: float = 1.0 metadata: Dict[str, Any] = field(default_factory=dict) def to_dict(self) -> Dict[str, Any]: """转换为字典""" return { "id": self.id, "device_id": self.device_id, "data_type": self.data_type.value, "value": self.value, "unit": self.unit, "timestamp": self.timestamp.isoformat(), "location": self.location, "quality_score": self.quality_score, "metadata": self.metadata } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'SensorData': """从字典创建对象""" return cls( id=data["id"], device_id=data["device_id"], data_type=DataType(data["data_type"]), value=float(data["value"]), unit=data.get("unit", ""), timestamp=datetime.fromisoformat(data["timestamp"]), location=data.get("location", ""), quality_score=float(data.get("quality_score", 1.0)), metadata=data.get("metadata", {}) ) @dataclass class Alert: """警报模型""" id: str device_id: str alert_type: str level: AlertLevel message: str timestamp: datetime resolved: bool = False resolved_by: Optional[str] = None resolved_at: Optional[datetime] = None metadata: Dict[str, Any] = field(default_factory=dict) def to_dict(self) -> Dict[str, Any]: """转换为字典""" return { "id": self.id, "device_id": self.device_id, "alert_type": self.alert_type, "level": self.level.value, "message": self.message, "timestamp": self.timestamp.isoformat(), "resolved": self.resolved, "resolved_by": self.resolved_by, "resolved_at": self.resolved_at.isoformat() if self.resolved_at else None, "metadata": self.metadata } @dataclass class BatchImport: """批量导入记录模型""" id: str batch_id: str data_source: str total_records: int successful_records: int failed_records: int status: str # pending, processing, completed, failed file_name: Optional[str] = None import_time: Optional[datetime] = None completed_time: Optional[datetime] = None error_messages: List[str] = field(default_factory=list) metadata: Dict[str, Any] = field(default_factory=dict) def to_dict(self) -> Dict[str, Any]: """转换为字典""" return { "id": self.id, "batch_id": self.batch_id, "data_source": self.data_source, "total_records": self.total_records, "successful_records": self.successful_records, "failed_records": self.failed_records, "status": self.status, "file_name": self.file_name, "import_time": self.import_time.isoformat() if self.import_time else None, "completed_time": self.completed_time.isoformat() if self.completed_time else None, "error_messages": self.error_messages, "metadata": self.metadata } @dataclass class APIRequest: """API请求模型""" id: str method: str endpoint: str params: Dict[str, Any] headers: Dict[str, Any] body: Optional[Any] = None timestamp: datetime = field(default_factory=datetime.now) response_code: Optional[int] = None response_time_ms: Optional[float] = None response_body: Optional[Any] = None def to_dict(self) -> Dict[str, Any]: """转换为字典""" return { "id": self.id, "method": self.method, "endpoint": self.endpoint, "params": self.params, "headers": self.headers, "body": self.body, "timestamp": self.timestamp.isoformat(), "response_code": self.response_code, "response_time_ms": self.response_time_ms, "response_body": self.response_body } @dataclass class WebSocketConnection: """WebSocket连接模型""" id: str client_ip: str connected_at: datetime disconnected_at: Optional[datetime] = None subscriptions: List[str] = field(default_factory=list) message_count: int = 0 last_message_at: Optional[datetime] = None metadata: Dict[str, Any] = field(default_factory=dict) def to_dict(self) -> Dict[str, Any]: """转换为字典""" return { "id": self.id, "client_ip": self.client_ip, "connected_at": self.connected_at.isoformat(), "disconnected_at": self.disconnected_at.isoformat() if self.disconnected_at else None, "subscriptions": self.subscriptions, "message_count": self.message_count, "last_message_at": self.last_message_at.isoformat() if self.last_message_at else None, "metadata": self.metadata } @dataclass class SystemStats: """系统统计模型""" timestamp: datetime total_records: int total_devices: int active_connections: int api_requests_count: int alerts_count: int data_quality_score: float memory_usage_mb: float cpu_usage_percent: float def to_dict(self) -> Dict[str, Any]: """转换为字典""" return { "timestamp": self.timestamp.isoformat(), "total_records": self.total_records, "total_devices": self.total_devices, "active_connections": self.active_connections, "api_requests_count": self.api_requests_count, "alerts_count": self.alerts_count, "data_quality_score": self.data_quality_score, "memory_usage_mb": self.memory_usage_mb, "cpu_usage_percent": self.cpu_usage_percent } class DataValidator: """数据验证器""" @staticmethod def validate_sensor_data(data: Dict[str, Any]) -> List[str]: """验证传感器数据""" errors = [] # 必需字段检查 required_fields = ["device_id", "data_type", "value", "location"] for field in required_fields: if field not in data: errors.append(f"缺少必需字段: {field}") # 数据类型验证 if "data_type" in data: try: DataType(data["data_type"]) except ValueError: errors.append(f"无效的数据类型: {data['data_type']}") # 数值验证 if "value" in data: try: value = float(data["value"]) # 根据数据类型进行数值范围检查 data_type = data.get("data_type") if data_type == "LL" and value < 0: errors.append("流量不能为负数") elif data_type == "YL" and value < 0: errors.append("压力不能为负数") elif data_type == "SW" and value < 0: errors.append("水位不能为负数") except (ValueError, TypeError): errors.append(f"无效的数值: {data['value']}") # 时间戳验证 if "timestamp" in data: try: if isinstance(data["timestamp"], str): datetime.fromisoformat(data["timestamp"]) except (ValueError, TypeError): errors.append(f"无效的时间戳格式: {data['timestamp']}") return errors @staticmethod def validate_device_data(data: Dict[str, Any]) -> List[str]: """验证设备数据""" errors = [] # 必需字段检查 required_fields = ["id", "name", "device_type", "location"] for field in required_fields: if field not in data: errors.append(f"缺少必需字段: {field}") # 设备ID格式验证 if "id" in data: device_id = data["id"] if not isinstance(device_id, str) or not device_id.strip(): errors.append("设备ID不能为空") elif len(device_id) > 50: errors.append("设备ID长度不能超过50个字符") # 状态验证 if "status" in data and data["status"] not in ["active", "inactive", "maintenance"]: errors.append("设备状态必须是: active, inactive, maintenance") return errors @staticmethod def validate_alert_data(data: Dict[str, Any]) -> List[str]: """验证警报数据""" errors = [] # 必需字段检查 required_fields = ["device_id", "alert_type", "level", "message"] for field in required_fields: if field not in data: errors.append(f"缺少必需字段: {field}") # 警报级别验证 if "level" in data: try: AlertLevel(data["level"]) except ValueError: errors.append(f"无效的警报级别: {data['level']}") return errors # 全局验证器实例 validator = DataValidator()