#!/usr/bin/env python3 """pCCU 集成测试:验证真实 UDP 链路上的完整数据流。 拓扑: 测试脚本(FC模拟) --16000--> pCCU(fc_local) [FC状态 0x0002] 测试脚本(PM模拟) --16002--> pCCU(pm_local) [PM操控 0x0001, PM参数设定 0x0002] pCCU --16001--> 测试脚本 [FC控制 0x0001 转发] pCCU --16003--> 测试脚本 [PM状态 0x0004, PM参数反馈 0x0003] 校验: 1. FC 状态收到并整合,pCCU 周期发送 PM 状态(0x0004, 248B)到 16003 2. PM 操控(0x0001)转发为 FC 控制(0x0001, 24B)到 16001 3. PM 参数设定(0x0002)触发参数反馈(0x0003, 12B)到 16003 4. SQLite 记录了收/发原始帧 5. Web 页面可访问 """ import socket import struct import threading import time import subprocess import os import signal import sys import urllib.request # ---- 配置 ---- FC_STATUS_PORT = 16000 FC_CTRL_RECV_PORT = 16001 PM_CTRL_PORT = 16002 PM_STATUS_RECV_PORT = 16003 WEB_PORT = 18081 DB_PATH = "/tmp/pccu_it_test.db" MOOSDB_EXE = "/usr/local/bin/MOOSDB" PCCU_EXE = "/home/zjk/project/H100PowerManger/bin/pCCU" MISSION = os.path.join(os.path.dirname(os.path.abspath(__file__)), "pccu_it.moos") # 帧头 START = bytes([0x40, 0x40]) def frame(msg_id, payload, checksum=True): total = 6 + len(payload) + (4 if checksum else 0) hdr = START + struct.pack("=1, 每帧248B)") if len(pm_status) >= 1: d = pm_status[0] total = struct.unpack_from(" length={total}, mode={mode}, status={status}, size={len(d)}") ok = ok and (total == 248) and (mode == 2) and (status == 6) else: ok = False # 校验 2:PM 操控转发为 FC 控制(24B,0827协议:姿态数据1转发,数据2字节预留恒0) fc_ctl = [d for d in fc_ctl_results if len(d) == 24] print(f"[FC 控制转发] 收到 {len(fc_ctl)} 帧 (期望>=1, 每帧24B)") if fc_ctl: d = fc_ctl[0] cmd = d[7]; power = d[8]; hb = d[23] pitch = struct.unpack_from(" cmd={cmd}, outputPower={power}, pitch={pitch}, roll={roll}, " f"resv1={resv1}, resv2={resv2}, heartbeat={hb}") ok = ok and (cmd == 2) and (power == 120) and (hb == 7) ok = ok and (pitch == 123) and (roll == -45) ok = ok and (resv1 == 0) and (resv2 == 0) else: ok = False # 校验 3:PM 参数反馈(12B) fb = [d for d in pm_status_results if len(d) == 12] print(f"[PM 参数反馈] 收到 {len(fb)} 帧 (期望>=1, 每帧12B)") if fb: flag = fb[0][6] print(f" -> flag=0x{flag:02X}") ok = ok and (flag == 0x10) else: ok = False # 校验 4:数据库有记录 time.sleep(1.0) db_count = -1 if os.path.exists(DB_PATH): import sqlite3 conn = sqlite3.connect(DB_PATH) db_count = conn.execute("SELECT COUNT(*) FROM comm_log").fetchone()[0] conn.close() print(f"[数据库] comm_log 记录数 = {db_count}") ok = ok and (db_count >= 6) # 3条FC状态 + 1条PM操控 + 1条PM参数 + 周期PM状态(至少1) # 校验 5:Web 页面 web_ok = False try: resp = urllib.request.urlopen(f"http://127.0.0.1:{WEB_PORT}/", timeout=3) html = resp.read().decode() web_ok = ("pCCU" in html) print(f"[Web] 页面可访问, 长度={len(html)}") except Exception as e: print(f"[Web] 访问失败: {e}") ok = ok and web_ok print("\n==== 集成测试 " + ("PASSED" if ok else "FAILED") + " ====") return 0 if ok else 1 finally: for p in reversed(procs): try: p.terminate() except Exception: pass time.sleep(0.5) for p in procs: try: p.kill() except Exception: pass if __name__ == "__main__": sys.exit(main())