""" 验证工程满足1553B 6-12us 响应、同时支持 10 个单机接入、CAN/1553B 消息顺序发送的性能需求,在test/下创建test_udp_performance.py 2026/2/26 Tan Mingyan """ import socket import binascii import time import threading from midware.config.base_config import DEVICE_CONFIG_DICT, UDP_CONFIG # 全局配置 LOCAL_IP = UDP_CONFIG["LOCAL_IP"] FAULT_PORT = UDP_CONFIG["FAULT_INJECT_PORT"] BUFFER_SIZE = 4096 # 测试用1553B外设端口(取CSV中的1553B0/1553B1,如8882/8886) B1553B_PORTS = [dev_info["udp_port"] for dev_name, dev_info in DEVICE_CONFIG_DICT.items() if dev_info["protocol"] == "1553B"] # CAN外设端口 CAN_PORTS = [dev_info["udp_port"] for dev_name, dev_info in DEVICE_CONFIG_DICT.items() if dev_info["protocol"] == "CAN"] # 10个测试端口(覆盖所有协议) TEST_PORTS = [dev_info["udp_port"] for dev_name, dev_info in DEVICE_CONFIG_DICT.items()][:10] # 测试数据(小数据包,模拟星务平台实时数据) TEST_DATA = b"PERF_TEST" + b'\x9c\x47' # 含校验位 class UDPPerformanceTest: def __init__(self): self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.send_sock.setblocking(False) # 接收套接字(统计回传时延) self.recv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.recv_sock.bind((LOCAL_IP, FAULT_PORT)) self.recv_sock.setblocking(False) # 时延统计 self.latency_list = [] # 并发计数 self.send_count = 0 self.recv_count = 0 def _calc_latency(self, port, send_ts): """计算单包时延:发送时间→接收回传时间""" try: data, _ = self.recv_sock.recvfrom(BUFFER_SIZE) recv_ts = time.time() latency = (recv_ts - send_ts) * 1000000 # 转换为微秒(us) self.latency_list.append(latency) self.recv_count += 1 print(f"1553B端口{port} | 响应时延:{latency:.2f}us | 累计接收:{self.recv_count}") except: pass def test_1553b_latency(self, test_times=1000): """测试1553B响应时延(要求6-12us),发送test_times次数据包""" if not B1553B_PORTS: print("❌ 未配置1553B外设,跳过时延测试") return test_port = B1553B_PORTS[0] print(f"===== 1553B时延测试(端口{test_port},发送{test_times}次) =====") self.latency_list.clear() self.recv_count = 0 for i in range(test_times): send_ts = time.time() # 发送数据 hex_data = binascii.hexlify(TEST_DATA).decode("utf-8") self.send_sock.sendto(hex_data.encode("utf-8"), (LOCAL_IP, test_port)) # 立即统计时延(模拟中间层实时回传) self._calc_latency(test_port, send_ts) # 微秒级间隔,模拟星务平台请求频率 time.sleep(0.000001) # 统计结果 if self.latency_list: avg_latency = sum(self.latency_list) / len(self.latency_list) min_latency = min(self.latency_list) max_latency = max(self.latency_list) print(f"\n1553B时延统计 | 平均:{avg_latency:.2f}us | 最小:{min_latency:.2f}us | 最大:{max_latency:.2f}us") if avg_latency >=6 and avg_latency <=12: print("✅ 1553B时延满足要求(6-12us)") else: print("❌ 1553B时延不满足要求") def test_10_device_concurrent(self, test_times=500): """测试10个单机并发接入(同时发送,验证无丢包)""" if len(TEST_PORTS) <10: print("❌ 未配置10个外设,跳过多机并发测试") return print(f"===== 10机并发测试(发送{test_times}次/机) =====") self.send_count = 0 self.recv_count = 0 def send_task(port): for _ in range(test_times): hex_data = binascii.hexlify(TEST_DATA).decode("utf-8") self.send_sock.sendto(hex_data.encode("utf-8"), (LOCAL_IP, port)) self.send_count +=1 time.sleep(0.0001) # 启动10个线程,对应10个外设 threads = [threading.Thread(target=send_task, args=(p,), daemon=True) for p in TEST_PORTS] for t in threads: t.start() for t in threads: t.join() # 等待接收完成 time.sleep(2) loss_rate = (self.send_count - self.recv_count) / self.send_count * 100 print(f"总发送:{self.send_count} | 总接收:{self.recv_count} | 丢包率:{loss_rate:.2f}%") if loss_rate == 0: print("✅ 10机并发测试通过,无丢包") else: print("❌ 10机并发测试失败,存在丢包") def test_can_b1553b_order(self): """测试CAN/1553B消息顺序发送(要求一个节点发完再发下一个)""" print("===== CAN/1553B消息顺序测试 =====") # 按顺序发送多个节点数据,查看中间层日志 test_ports = CAN_PORTS[:2] + B1553B_PORTS[:2] for port in test_ports: hex_data = binascii.hexlify(TEST_DATA + str(port).encode()).decode("utf-8") self.send_sock.sendto(hex_data.encode("utf-8"), (LOCAL_IP, port)) print(f"按顺序发送:端口{port} 数据标识:{port}") time.sleep(0.001) print("✅ 请查看工程logs/run_*.log,验证日志中节点数据是否按发送顺序打印(无乱序)") def close(self): self.send_sock.close() self.recv_sock.close() if __name__ == "__main__": perf_test = UDPPerformanceTest() try: # 1. 1553B时延测试(发送1000次) perf_test.test_1553b_latency(test_times=1000) time.sleep(3) # 2. 10机并发测试(每机发送500次) perf_test.test_10_device_concurrent(test_times=500) time.sleep(3) # 3. CAN/1553B消息顺序测试 perf_test.test_can_b1553b_order() except KeyboardInterrupt: print("\n用户终止性能测试") finally: perf_test.close()