TestLatency Return Value Example & gitignore update

This commit is contained in:
Xuwznln
2026-01-26 00:20:15 +08:00
parent ec7ca6a1fe
commit 98e706ad8f
5 changed files with 55 additions and 54 deletions

View File

@@ -1,9 +0,0 @@
@echo off
setlocal enabledelayedexpansion
REM upgrade pip
"%PREFIX%\python.exe" -m pip install --upgrade pip
REM install extra deps
"%PREFIX%\python.exe" -m pip install paho-mqtt opentrons_shared_data
"%PREFIX%\python.exe" -m pip install git+https://github.com/Xuwznln/pylabrobot.git

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -euxo pipefail
# make sure pip is available
"$PREFIX/bin/python" -m pip install --upgrade pip
# install extra deps
"$PREFIX/bin/python" -m pip install paho-mqtt opentrons_shared_data
"$PREFIX/bin/python" -m pip install git+https://github.com/Xuwznln/pylabrobot.git

View File

@@ -1,26 +0,0 @@
.conda
# .github
.idea
# .vscode
output
pylabrobot_repo
recipes
scripts
service
temp
# unilabos/test
# unilabos/app/web
unilabos/device_mesh
unilabos_data
unilabos_msgs
unilabos.egg-info
CONTRIBUTORS
# LICENSE
MANIFEST.in
pyrightconfig.json
# README.md
# README_zh.md
setup.py
setup.cfg
.gitattrubutes
**/__pycache__

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@ temp/
output/ output/
unilabos_data/ unilabos_data/
pyrightconfig.json pyrightconfig.json
.cursorignore
## Python ## Python
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files

View File

@@ -5,7 +5,8 @@ import threading
import time import time
import traceback import traceback
import uuid import uuid
from typing import TYPE_CHECKING, Optional, Dict, Any, List, ClassVar, Set, TypedDict, Union from typing import TYPE_CHECKING, Optional, Dict, Any, List, ClassVar, Set, Union
from typing_extensions import TypedDict
from action_msgs.msg import GoalStatus from action_msgs.msg import GoalStatus
from geometry_msgs.msg import Point from geometry_msgs.msg import Point
@@ -62,6 +63,17 @@ class TestResourceReturn(TypedDict):
devices: List[DeviceSlot] devices: List[DeviceSlot]
class TestLatencyReturn(TypedDict):
"""test_latency方法的返回值类型"""
avg_rtt_ms: float
avg_time_diff_ms: float
max_time_error_ms: float
task_delay_ms: float
raw_delay_ms: float
test_count: int
status: str
class HostNode(BaseROS2DeviceNode): class HostNode(BaseROS2DeviceNode):
""" """
主机节点类,负责管理设备、资源和控制器 主机节点类,负责管理设备、资源和控制器
@@ -853,8 +865,13 @@ class HostNode(BaseROS2DeviceNode):
# 适配后端的一些额外处理 # 适配后端的一些额外处理
return_value = return_info.get("return_value") return_value = return_info.get("return_value")
if isinstance(return_value, dict): if isinstance(return_value, dict):
unilabos_samples = return_info.get("unilabos_samples") unilabos_samples = return_value.pop("unilabos_samples", None)
if isinstance(unilabos_samples, list): if isinstance(unilabos_samples, list) and unilabos_samples:
self.lab_logger().info(
f"[Host Node] Job {job_id[:8]} returned {len(unilabos_samples)} sample(s): "
f"{[s.get('name', s.get('id', 'unknown')) if isinstance(s, dict) else str(s)[:20] for s in unilabos_samples[:5]]}"
f"{'...' if len(unilabos_samples) > 5 else ''}"
)
return_info["unilabos_samples"] = unilabos_samples return_info["unilabos_samples"] = unilabos_samples
suc = return_info.get("suc", False) suc = return_info.get("suc", False)
if not suc: if not suc:
@@ -1326,10 +1343,20 @@ class HostNode(BaseROS2DeviceNode):
self.lab_logger().debug(f"[Host Node-Resource] List parameters: {request}") self.lab_logger().debug(f"[Host Node-Resource] List parameters: {request}")
return response return response
def test_latency(self): def test_latency(self) -> TestLatencyReturn:
""" """
测试网络延迟的action实现 测试网络延迟的action实现
通过5次ping-pong机制校对时间误差并计算实际延迟 通过5次ping-pong机制校对时间误差并计算实际延迟
Returns:
TestLatencyReturn: 包含延迟测试结果的字典,包括:
- avg_rtt_ms: 平均往返时间(毫秒)
- avg_time_diff_ms: 平均时间差(毫秒)
- max_time_error_ms: 最大时间误差(毫秒)
- task_delay_ms: 实际任务延迟(毫秒),-1表示无法计算
- raw_delay_ms: 原始时间差(毫秒),-1表示无法计算
- test_count: 有效测试次数
- status: 测试状态,"success"表示成功,"all_timeout"表示全部超时
""" """
import uuid as uuid_module import uuid as uuid_module
@@ -1392,7 +1419,15 @@ class HostNode(BaseROS2DeviceNode):
if not ping_results: if not ping_results:
self.lab_logger().error("❌ 所有ping-pong测试都失败了") self.lab_logger().error("❌ 所有ping-pong测试都失败了")
return {"status": "all_timeout"} return {
"avg_rtt_ms": -1.0,
"avg_time_diff_ms": -1.0,
"max_time_error_ms": -1.0,
"task_delay_ms": -1.0,
"raw_delay_ms": -1.0,
"test_count": 0,
"status": "all_timeout",
}
# 统计分析 # 统计分析
rtts = [r["rtt_ms"] for r in ping_results] rtts = [r["rtt_ms"] for r in ping_results]
@@ -1400,7 +1435,7 @@ class HostNode(BaseROS2DeviceNode):
avg_rtt_ms = sum(rtts) / len(rtts) avg_rtt_ms = sum(rtts) / len(rtts)
avg_time_diff_ms = sum(time_diffs) / len(time_diffs) avg_time_diff_ms = sum(time_diffs) / len(time_diffs)
max_time_diff_error_ms = max(abs(min(time_diffs)), abs(max(time_diffs))) max_time_diff_error_ms: float = max(abs(min(time_diffs)), abs(max(time_diffs)))
self.lab_logger().info("-" * 50) self.lab_logger().info("-" * 50)
self.lab_logger().info("[测试统计]") self.lab_logger().info("[测试统计]")
@@ -1440,7 +1475,7 @@ class HostNode(BaseROS2DeviceNode):
self.lab_logger().info("=" * 60) self.lab_logger().info("=" * 60)
return { res: TestLatencyReturn = {
"avg_rtt_ms": avg_rtt_ms, "avg_rtt_ms": avg_rtt_ms,
"avg_time_diff_ms": avg_time_diff_ms, "avg_time_diff_ms": avg_time_diff_ms,
"max_time_error_ms": max_time_diff_error_ms, "max_time_error_ms": max_time_diff_error_ms,
@@ -1451,9 +1486,14 @@ class HostNode(BaseROS2DeviceNode):
"test_count": len(ping_results), "test_count": len(ping_results),
"status": "success", "status": "success",
} }
return res
def test_resource( def test_resource(
self, resource: ResourceSlot = None, resources: List[ResourceSlot] = None, device: DeviceSlot = None, devices: List[DeviceSlot] = None self,
resource: ResourceSlot = None,
resources: List[ResourceSlot] = None,
device: DeviceSlot = None,
devices: List[DeviceSlot] = None,
) -> TestResourceReturn: ) -> TestResourceReturn:
if resources is None: if resources is None:
resources = [] resources = []
@@ -1514,7 +1554,9 @@ class HostNode(BaseROS2DeviceNode):
# 构建服务地址 # 构建服务地址
srv_address = f"/srv{namespace}/s2c_resource_tree" srv_address = f"/srv{namespace}/s2c_resource_tree"
self.lab_logger().trace(f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation started -------") self.lab_logger().trace(
f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation started -------"
)
# 创建服务客户端 # 创建服务客户端
sclient = self.create_client(SerialCommand, srv_address) sclient = self.create_client(SerialCommand, srv_address)
@@ -1549,7 +1591,9 @@ class HostNode(BaseROS2DeviceNode):
time.sleep(0.05) time.sleep(0.05)
response = future.result() response = future.result()
self.lab_logger().trace(f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation completed -------") self.lab_logger().trace(
f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation completed -------"
)
return True return True
except Exception as e: except Exception as e: