223 lines
6.7 KiB
Python
223 lines
6.7 KiB
Python
"""
|
|
测试客户端程序
|
|
用于测试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()
|