""" UDP交互程序数据结构定义 根据文档表格定义所有数据结构 """ import struct from enum import IntEnum from dataclasses import dataclass from typing import Optional # ==================== 常量定义 ==================== # 帧头尾标志 FRAME_HEAD_SYMBOL = 0x7EFFDC01 FRAME_TAIL_SYMBOL = 0x7EFFDC02 # 端口定义 CONTROL_RX_PORT = 38101 # 模块1:接收控制指令 CONTROL_TX_PORT = 37001 # 模块2:发送控制响应 DATA_TX_PORT = 37004 # 模块3:发送数据包 # 工作模式(dWorkMode) class WorkMode(IntEnum): NORMAL = 0 # 正常模式 AUTO = 4 # 自动模式 # 工作指令(dWorkInstruction) class WorkInstruction(IntEnum): UPLOAD_ROUTE = 0 # 上传航线 START_CALC = 1 # 开始计算 MANUAL_BOOT = 2 # 手动开机 END_TASK = 3 # 结束当前任务 CONNECT = 4 # 连接 DISCONNECT = 5 # 断开连接 # 成像模式 class ImagingMode(IntEnum): STRIP = 0 # 条带 FOCUS = 1 # 聚束 # 成像模式分辨率 class ImagingResolution(IntEnum): RES_0_1M = 0 # 0.1m RES_0_2M = 1 # 0.2m RES_0_3M = 2 # 0.3m RES_0_5M = 3 # 0.5m RES_1M = 4 # 1m # 状态包类型 class StatusPacketType(IntEnum): CONTROL_RESULT = 0 # 控制命令执行结果 IMAGING_READY = 1 # 成像准备完成 DEVICE_FAULT = 2 # 单机工作故障 # 执行状态 class ExecutionStatus(IntEnum): SUCCESS = 0 # 成功 ERROR = 1 # 错误 # ==================== 数据结构定义 ==================== @dataclass class ControlData: """表3:雷达控制数据格式(192字节)""" work_mode: int = 0 # Uint8 work_instruction: int = 0 # Uint8 imaging_mode: int = 0 # Uint8 imaging_resolution: int = 0 # Uint8 reserved1: bytes = b'\x00\x00\x00\x00' # Uint8*4 route_number: int = 0 # Uint16 route_count: int = 0 # Uint16 # 航线开机点 boot_longitude: int = 0 # Uint32 (1e-7量化) boot_latitude: int = 0 # Uint32 (1e-7量化) boot_altitude: int = 0 # Int16 # 地面开机点 ground_boot_longitude: int = 0 # Uint32 ground_boot_latitude: int = 0 # Uint32 ground_boot_altitude: int = 0 # Int16 # 航线关机点 shutdown_longitude: int = 0 # Uint32 shutdown_latitude: int = 0 # Uint32 shutdown_altitude: int = 0 # Int16 # 成像区域中心 imaging_center_longitude: int = 0 # Uint32 imaging_center_latitude: int = 0 # Uint32 imaging_center_altitude: int = 0 # Int16 # 成像区域参数 imaging_width: int = 0 # Uint16 imaging_length: int = 0 # Uint16 imaging_angle: int = 0 # Uint16 # 飞行参数 flight_speed: float = 0.0 # double64 flight_altitude: float = 0.0 # double64 grazing_angle: float = 0.0 # double64 slant_angle: float = 0.0 # double64 # 其他参数 route_type: int = 0 # Uint8 side_direction: int = 0 # Int8 polarization: int = 0 # Uint8 auto_focus: int = 0 # Uint8 motion_compensation: int = 0 # Uint8 image_format: int = 0 # Uint8 echo_disable: int = 0 # Uint8 installation_angle: float = 35.0 # Float image_bit: int = 0 # Uint8 prf: float = 0.0 # Float reserved2: bytes = b'\x00' * 86 # 86字节补齐192B def to_bytes(self) -> bytes: """将控制数据序列化为字节流(小端模式)""" data = struct.pack(' 'ControlData': """从字节流反序列化控制数据""" if len(data) < 192: raise ValueError(f"Control data must be 192 bytes, got {len(data)}") # 解析前4个字节 work_mode, work_instruction, imaging_mode, imaging_resolution = struct.unpack(' int: """计算校验和(无符号int32累加)""" checksum = 0 for i in range(0, len(data), 4): if i + 4 <= len(data): val = struct.unpack(' bytes: """将控制包序列化为字节流""" # 构建帧头到校验和之前的数据 data = struct.pack(' 'ControlPacket': """从字节流反序列化控制包""" if len(data) < 208: # 4+1+3+192+4+4 raise ValueError(f"Control packet must be at least 208 bytes, got {len(data)}") frame_head = struct.unpack(' bytes: """序列化为字节流""" return struct.pack(' 'ErrorPacket': """从字节流反序列化""" if len(data) < 8: raise ValueError(f"Error packet must be at least 8 bytes, got {len(data)}") status_packet_type, execution_status = struct.unpack(' bytes: """序列化为字节流""" data = struct.pack(' 'DeviceStatus': """从字节流反序列化""" if len(data) < 64: raise ValueError(f"Device status must be 64 bytes, got {len(data)}") values = struct.unpack(' int: """计算校验和(无符号int32累加)""" checksum = 0 for i in range(0, len(data), 4): if i + 4 <= len(data): val = struct.unpack(' bytes: """将响应包序列化为字节流""" data = struct.pack(' 'ResponsePacket': """从字节流反序列化响应包""" if len(data) < 88: # 4+8+1+3+4+8+64+4+4 raise ValueError(f"Response packet must be at least 88 bytes, got {len(data)}") frame_head = struct.unpack('