""" 测试客户端程序 用于测试UDP交互系统 """ import socket import struct import logging import time from data_structures import ( ControlPacket, ControlData, WorkMode, WorkInstruction, CONTROL_RX_PORT, CONTROL_TX_PORT, DATA_TX_PORT ) class TestClient: """测试客户端""" def __init__(self, server_host: str = '127.0.0.1'): """ 初始化测试客户端 Args: server_host: 服务器地址 """ self.server_host = server_host self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.rx_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.rx_socket.bind(('0.0.0.0', CONTROL_TX_PORT)) # 绑定到随机端口 self.local_port = self.rx_socket.getsockname()[1] # 配置日志 self.logger = logging.getLogger('TestClient') self.logger.setLevel(logging.DEBUG) if not self.logger.handlers: handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) self.logger.addHandler(handler) self.logger.info(f"Test client initialized on port {self.local_port}") def send_control_packet(self, work_mode: int, work_instruction: int, route_number: int = 0, route_count: int = 0) -> bool: """ 发送控制包 Args: work_mode: 工作模式 work_instruction: 工作指令 route_number: 航线编号 route_count: 航线个数 Returns: 是否发送成功 """ try: # 创建控制数据 control_data = ControlData( work_mode=work_mode, work_instruction=work_instruction, route_number=route_number, route_count=route_count ) # 创建控制包 packet = ControlPacket(control_data=control_data) # 序列化 data = packet.to_bytes() # Debug logging self.logger.info(f"DEBUG: Preparing to send packet - Mode: {work_mode}, Instr: {work_instruction}, Route#: {route_number}, Count: {route_count}") self.logger.info(f"DEBUG: Raw packet data ({len(data)} bytes): {data.hex()}") # 发送 self.socket.sendto(data, (self.server_host, CONTROL_RX_PORT)) self.logger.info(f"Control packet sent: mode={work_mode}, instruction={work_instruction}") return True except Exception as e: self.logger.error(f"Failed to send control packet: {e}") return False def receive_response(self, timeout: float = 2.0) -> bool: """ 接收响应包 Args: timeout: 接收超时时间(秒) Returns: 是否接收成功 """ try: self.rx_socket.settimeout(timeout) data, addr = self.rx_socket.recvfrom(2048) self.logger.info(f"Response received from {addr} ({len(data)} bytes)") self.logger.debug(f"Response data (hex): {data.hex()}") return True except socket.timeout: self.logger.warning("Response receive timeout") return False except Exception as e: self.logger.error(f"Failed to receive response: {e}") return False def test_connect(self): """测试连接指令""" self.logger.info("=== Testing CONNECT ===") self.send_control_packet(WorkMode.NORMAL, WorkInstruction.CONNECT) time.sleep(0.5) self.receive_response() def test_disconnect(self): """测试断开连接指令""" self.logger.info("=== Testing DISCONNECT ===") self.send_control_packet(WorkMode.NORMAL, WorkInstruction.DISCONNECT) time.sleep(0.5) self.receive_response() def test_upload_route(self): """测试上传航线指令""" self.logger.info("=== Testing UPLOAD_ROUTE ===") self.send_control_packet( WorkMode.AUTO, WorkInstruction.UPLOAD_ROUTE, route_number=0, route_count=1 ) time.sleep(0.5) self.receive_response() def test_start_calc(self): """测试开始计算指令""" self.logger.info("=== Testing START_CALC ===") self.send_control_packet(WorkMode.AUTO, WorkInstruction.START_CALC) time.sleep(0.5) self.receive_response() def test_manual_boot(self): """测试手动开机指令""" self.logger.info("=== Testing MANUAL_BOOT ===") self.send_control_packet(WorkMode.AUTO, WorkInstruction.MANUAL_BOOT) time.sleep(0.5) self.receive_response() def test_end_task(self): """测试结束当前任务指令""" self.logger.info("=== Testing END_TASK ===") self.send_control_packet(WorkMode.AUTO, WorkInstruction.END_TASK) time.sleep(0.5) self.receive_response() def test_end_all_tasks(self): """测试结束所有任务指令""" self.logger.info("=== Testing END_ALL_TASKS ===") self.send_control_packet(WorkMode.NORMAL, WorkInstruction.END_TASK) time.sleep(0.5) self.receive_response() def run_full_test(self): """运行完整测试""" self.logger.info("Starting full test sequence...") # 测试连接 self.test_connect() time.sleep(1) # 测试上传航线 self.test_upload_route() time.sleep(1) # 测试开始计算 self.test_start_calc() time.sleep(1) # 测试手动开机 self.test_manual_boot() time.sleep(1) # 测试结束任务 self.test_end_task() time.sleep(1) # 测试断开连接 self.test_disconnect() self.logger.info("Full test sequence completed") def close(self): """关闭客户端""" self.socket.close() self.rx_socket.close() self.logger.info("Test client closed") def main(): """主函数""" logging.basicConfig(level=logging.INFO) # 创建测试客户端 client = TestClient('127.0.0.1') try: # 运行完整测试 client.run_full_test() except KeyboardInterrupt: logging.info("Test interrupted") finally: client.close() if __name__ == '__main__': main()