mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-18 05:21:19 +00:00
Compare commits
2 Commits
5551fbf360
...
0b896870ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b896870ba | ||
|
|
ee609e4aa2 |
@@ -1314,3 +1314,19 @@ class WebSocketClient(BaseCommunicationClient):
|
|||||||
logger.info(f"[WebSocketClient] Job {job_log} cancelled successfully")
|
logger.info(f"[WebSocketClient] Job {job_log} cancelled successfully")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"[WebSocketClient] Failed to cancel job {job_log}")
|
logger.warning(f"[WebSocketClient] Failed to cancel job {job_log}")
|
||||||
|
|
||||||
|
def publish_host_ready(self) -> None:
|
||||||
|
"""发布host_node ready信号"""
|
||||||
|
if self.is_disabled or not self.is_connected():
|
||||||
|
logger.debug("[WebSocketClient] Not connected, cannot publish host ready signal")
|
||||||
|
return
|
||||||
|
|
||||||
|
message = {
|
||||||
|
"action": "host_node_ready",
|
||||||
|
"data": {
|
||||||
|
"status": "ready",
|
||||||
|
"timestamp": time.time(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
self.message_processor.send_message(message)
|
||||||
|
logger.info("[WebSocketClient] Host node ready signal published")
|
||||||
|
|||||||
@@ -45,10 +45,13 @@ def canonicalize_nodes_data(
|
|||||||
print_status(f"{len(nodes)} Resources loaded:", "info")
|
print_status(f"{len(nodes)} Resources loaded:", "info")
|
||||||
|
|
||||||
# 第一步:基本预处理(处理graphml的label字段)
|
# 第一步:基本预处理(处理graphml的label字段)
|
||||||
for node in nodes:
|
outer_host_node_id = None
|
||||||
|
for idx, node in enumerate(nodes):
|
||||||
if node.get("label") is not None:
|
if node.get("label") is not None:
|
||||||
node_id = node.pop("label")
|
node_id = node.pop("label")
|
||||||
node["id"] = node["name"] = node_id
|
node["id"] = node["name"] = node_id
|
||||||
|
if node["id"] == "host_node":
|
||||||
|
outer_host_node_id = idx
|
||||||
if not isinstance(node.get("config"), dict):
|
if not isinstance(node.get("config"), dict):
|
||||||
node["config"] = {}
|
node["config"] = {}
|
||||||
if not node.get("type"):
|
if not node.get("type"):
|
||||||
@@ -76,7 +79,8 @@ def canonicalize_nodes_data(
|
|||||||
if k not in ["id", "uuid", "name", "description", "schema", "model", "icon", "parent_uuid", "parent", "type", "class", "position", "config", "data", "children", "pose"]:
|
if k not in ["id", "uuid", "name", "description", "schema", "model", "icon", "parent_uuid", "parent", "type", "class", "position", "config", "data", "children", "pose"]:
|
||||||
v = node.pop(k)
|
v = node.pop(k)
|
||||||
node["config"][k] = v
|
node["config"][k] = v
|
||||||
|
if outer_host_node_id is not None:
|
||||||
|
nodes.pop(outer_host_node_id)
|
||||||
# 第二步:处理parent_relation
|
# 第二步:处理parent_relation
|
||||||
id2idx = {node["id"]: idx for idx, node in enumerate(nodes)}
|
id2idx = {node["id"]: idx for idx, node in enumerate(nodes)}
|
||||||
for parent, children in parent_relation.items():
|
for parent, children in parent_relation.items():
|
||||||
|
|||||||
@@ -289,6 +289,12 @@ class HostNode(BaseROS2DeviceNode):
|
|||||||
self.lab_logger().info("[Host Node] Host node initialized.")
|
self.lab_logger().info("[Host Node] Host node initialized.")
|
||||||
HostNode._ready_event.set()
|
HostNode._ready_event.set()
|
||||||
|
|
||||||
|
# 发送host_node ready信号到所有桥接器
|
||||||
|
for bridge in self.bridges:
|
||||||
|
if hasattr(bridge, "publish_host_ready"):
|
||||||
|
bridge.publish_host_ready()
|
||||||
|
self.lab_logger().debug(f"Host ready signal sent via {bridge.__class__.__name__}")
|
||||||
|
|
||||||
def _send_re_register(self, sclient):
|
def _send_re_register(self, sclient):
|
||||||
sclient.wait_for_service()
|
sclient.wait_for_service()
|
||||||
request = SerialCommand.Request()
|
request = SerialCommand.Request()
|
||||||
@@ -794,6 +800,7 @@ class HostNode(BaseROS2DeviceNode):
|
|||||||
# 存储结果供 HTTP API 查询
|
# 存储结果供 HTTP API 查询
|
||||||
try:
|
try:
|
||||||
from unilabos.app.web.controller import store_job_result
|
from unilabos.app.web.controller import store_job_result
|
||||||
|
|
||||||
if goal_status == GoalStatus.STATUS_CANCELED:
|
if goal_status == GoalStatus.STATUS_CANCELED:
|
||||||
store_job_result(job_id, status, return_info, {})
|
store_job_result(job_id, status, return_info, {})
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import inspect
|
||||||
import traceback
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
from pydantic import BaseModel, field_serializer, field_validator
|
from pydantic import BaseModel, field_serializer, field_validator
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from typing import List, Tuple, Any, Dict, Literal, Optional, cast, TYPE_CHECKING, Union
|
from typing import List, Tuple, Any, Dict, Literal, Optional, cast, TYPE_CHECKING, Union
|
||||||
|
|
||||||
|
from unilabos.resources.plr_additional_res_reg import register
|
||||||
from unilabos.utils.log import logger
|
from unilabos.utils.log import logger
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -429,9 +431,9 @@ class ResourceTreeSet(object):
|
|||||||
Returns:
|
Returns:
|
||||||
List[PLRResource]: PLR 资源实例列表
|
List[PLRResource]: PLR 资源实例列表
|
||||||
"""
|
"""
|
||||||
|
register()
|
||||||
from pylabrobot.resources import Resource as PLRResource
|
from pylabrobot.resources import Resource as PLRResource
|
||||||
from pylabrobot.utils.object_parsing import find_subclass
|
from pylabrobot.utils.object_parsing import find_subclass
|
||||||
import inspect
|
|
||||||
|
|
||||||
# 类型映射
|
# 类型映射
|
||||||
TYPE_MAP = {"plate": "Plate", "well": "Well", "deck": "Deck", "container": "RegularContainer"}
|
TYPE_MAP = {"plate": "Plate", "well": "Well", "deck": "Deck", "container": "RegularContainer"}
|
||||||
@@ -459,9 +461,9 @@ class ResourceTreeSet(object):
|
|||||||
"size_y": res.config.get("size_y", 0),
|
"size_y": res.config.get("size_y", 0),
|
||||||
"size_z": res.config.get("size_z", 0),
|
"size_z": res.config.get("size_z", 0),
|
||||||
"location": {
|
"location": {
|
||||||
"x": res.position.position.x,
|
"x": res.pose.position.x,
|
||||||
"y": res.position.position.y,
|
"y": res.pose.position.y,
|
||||||
"z": res.position.position.z,
|
"z": res.pose.position.z,
|
||||||
"type": "Coordinate",
|
"type": "Coordinate",
|
||||||
},
|
},
|
||||||
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
||||||
|
|||||||
Reference in New Issue
Block a user