from dataclasses import dataclass, field from typing import List, Optional from enum import Enum class ModuleType(Enum): HD3200 = "HD3200" RFID = "RFID" class CameraPosition(Enum): LEFT = "left" RIGHT = "right" class CameraState(Enum): ONLINE = "online" OFFLINE = "offline" class SwitchMode(Enum): AUTO = "auto" HAND = "hand" @dataclass class CameraModel: position: CameraPosition rtsp_url: str topic: Optional[str] = None state: CameraState = CameraState.OFFLINE class HookState(Enum): IDLE = "idle" RELEASING = "releasing" # 放包中 HOOKING = "hooking" # 挂包中 READY = "ready" # 挂包成功 @dataclass class BucketModel: id: int description: str code_x: str # 大车标识(RFID卡号或Modbus点号) code_y: str = "" # 小车标识(垂直工位) ai_module_id: Optional[int] = None # 关联AI模块索引 cameras: List[CameraModel] = field(default_factory=list) is_active: bool = False ready_x: bool = False ready_y: bool = True # 无垂直工位时为True # 可以起吊判定:hook/lug 归一化偏移标定值(X 用中心点、Y 用框底边,每工位每侧,空=未标定) hook_lug_x_offset_ratio_left: Optional[float] = None hook_lug_y_offset_ratio_left: Optional[float] = None hook_lug_x_offset_ratio_right: Optional[float] = None hook_lug_y_offset_ratio_right: Optional[float] = None @dataclass class AIModuleModel: id: int broker: str = "127.0.0.1" port: int = 1883 topics: List[str] = field(default_factory=list) @dataclass class AIConfig: enabled: bool = False tts_enabled: bool = False debug_trace: bool = True # 可以起吊:hook/lug 中心归一化偏移容差(x/y 共用)与防抖帧数 offset_ratio_tolerance: float = 0.25 ready_debounce: int = 3 # 自动标定参数:窗口内出现 N 帧 ready 触发(不要求连续)/ 窗口时长(秒)/ 最少有效样本数 auto_calib_ready_frames: int = 3 auto_calib_duration_secs: float = 1.0 auto_calib_min_samples: int = 2 @dataclass class ModbusConfig: ip: str port: int = 502 frequency: int = 100 stability_count: int = 3 @dataclass class SocketConfig: ip: str port: int = 6000 stability_time: int = 20 stability_count: int = 3 class RestartInterval(Enum): DAY = "day" WEEK = "week" MONTH = "month" class RestartTarget(Enum): APP = "app" DEVICE = "device" @dataclass class AutoRestartConfig: enabled: bool = False interval: RestartInterval = RestartInterval.DAY hour: int = 3 minute: int = 0 target: RestartTarget = RestartTarget.APP weekdays: int = 0 day_of_month: int = 1 countdown: int = 60 @dataclass class VideoConfig: rtsp_timeout: float = 5.0 # 默认 5 秒 ratio_16_9: bool = True # 画面比例 16:9 / 4:3 @dataclass class Config: app_name: str = "钢包工位视频监测系统" copyright: str = "恒莱达" screen: int = 0 module_type: ModuleType = ModuleType.RFID rfid: Optional[SocketConfig] = None modbus: Optional[ModbusConfig] = None ai: AIConfig = field(default_factory=AIConfig) ai_modules: List[AIModuleModel] = field(default_factory=list) buckets: List[BucketModel] = field(default_factory=list) video: VideoConfig = field(default_factory=VideoConfig) auto_restart: AutoRestartConfig = field(default_factory=AutoRestartConfig)