mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 13:01:12 +00:00
refactor: workstation_base 重构为仅含业务逻辑,通信和子设备管理交给 ProtocolNode
This commit is contained in:
@@ -947,6 +947,12 @@ class ROS2DeviceNode:
|
||||
|
||||
# TODO: 要在创建之前预先请求服务器是否有当前id的物料,放到resource_tracker中,让pylabrobot进行创建
|
||||
# 创建设备类实例
|
||||
# 判断是否包含设备子节点,决定是否使用ROS2ProtocolNode
|
||||
has_device_children = any(
|
||||
child_config.get("type", "device") == "device"
|
||||
for child_config in children.values()
|
||||
)
|
||||
|
||||
if use_pylabrobot_creator:
|
||||
# 先对pylabrobot的子资源进行加载,不然subclass无法认出
|
||||
# 在下方对于加载Deck等Resource要手动import
|
||||
@@ -956,10 +962,18 @@ class ROS2DeviceNode:
|
||||
)
|
||||
else:
|
||||
from unilabos.ros.nodes.presets.protocol_node import ROS2ProtocolNode
|
||||
from unilabos.device_comms.workstation_base import WorkstationBase
|
||||
|
||||
if issubclass(self._driver_class, ROS2ProtocolNode): # 是ProtocolNode的子节点,就要调用ProtocolNodeCreator
|
||||
# 检查是否是WorkstationBase的子类且包含设备子节点
|
||||
if issubclass(self._driver_class, WorkstationBase) and has_device_children:
|
||||
# WorkstationBase + 设备子节点 -> 使用ProtocolNode作为ros_instance
|
||||
self._use_protocol_node_ros = True
|
||||
self._driver_creator = DeviceClassCreator(driver_class, children=children, resource_tracker=self.resource_tracker)
|
||||
elif issubclass(self._driver_class, ROS2ProtocolNode): # 是ProtocolNode的子节点,就要调用ProtocolNodeCreator
|
||||
self._use_protocol_node_ros = False
|
||||
self._driver_creator = ProtocolNodeCreator(driver_class, children=children, resource_tracker=self.resource_tracker)
|
||||
else:
|
||||
self._use_protocol_node_ros = False
|
||||
self._driver_creator = DeviceClassCreator(driver_class, children=children, resource_tracker=self.resource_tracker)
|
||||
|
||||
if driver_is_ros:
|
||||
@@ -973,6 +987,35 @@ class ROS2DeviceNode:
|
||||
# 创建ROS2节点
|
||||
if driver_is_ros:
|
||||
self._ros_node = self._driver_instance # type: ignore
|
||||
elif hasattr(self, '_use_protocol_node_ros') and self._use_protocol_node_ros:
|
||||
# WorkstationBase + 设备子节点 -> 创建ROS2ProtocolNode作为ros_instance
|
||||
from unilabos.ros.nodes.presets.protocol_node import ROS2ProtocolNode
|
||||
|
||||
# 从children提取设备协议类型
|
||||
protocol_types = set()
|
||||
for child_id, child_config in children.items():
|
||||
if child_config.get("type", "device") == "device":
|
||||
# 检查设备配置中的协议类型
|
||||
if "protocol_type" in child_config:
|
||||
if isinstance(child_config["protocol_type"], list):
|
||||
protocol_types.update(child_config["protocol_type"])
|
||||
else:
|
||||
protocol_types.add(child_config["protocol_type"])
|
||||
|
||||
# 如果没有明确的协议类型,使用默认值
|
||||
if not protocol_types:
|
||||
protocol_types = ["default_protocol"]
|
||||
|
||||
self._ros_node = ROS2ProtocolNode(
|
||||
device_id=device_id,
|
||||
children=children,
|
||||
protocol_type=list(protocol_types),
|
||||
resource_tracker=self.resource_tracker,
|
||||
workstation_config={
|
||||
'workstation_instance': self._driver_instance,
|
||||
'deck_config': getattr(self._driver_instance, 'deck_config', {}),
|
||||
}
|
||||
)
|
||||
else:
|
||||
self._ros_node = BaseROS2DeviceNode(
|
||||
driver_instance=self._driver_instance,
|
||||
|
||||
@@ -2,7 +2,7 @@ import json
|
||||
import time
|
||||
import traceback
|
||||
from pprint import pprint, saferepr, pformat
|
||||
from typing import Union
|
||||
from typing import Union, Dict, Any
|
||||
|
||||
import rclpy
|
||||
from rosidl_runtime_py import message_to_ordereddict
|
||||
@@ -53,6 +53,10 @@ class ROS2ProtocolNode(BaseROS2DeviceNode):
|
||||
self.children = children
|
||||
self.workstation_config = workstation_config or {} # 新增:保存工作站配置
|
||||
self.communication_interfaces = self.workstation_config.get('communication_interfaces', {}) # 从工作站配置获取通信接口
|
||||
|
||||
# 新增:获取工作站实例(如果存在)
|
||||
self.workstation_instance = self.workstation_config.get('workstation_instance')
|
||||
|
||||
self._busy = False
|
||||
self.sub_devices = {}
|
||||
self._goals = {}
|
||||
@@ -60,8 +64,11 @@ class ROS2ProtocolNode(BaseROS2DeviceNode):
|
||||
self._action_clients = {}
|
||||
|
||||
# 初始化基类,让基类处理常规动作
|
||||
# 如果有工作站实例,使用工作站实例作为driver_instance
|
||||
driver_instance = self.workstation_instance if self.workstation_instance else self
|
||||
|
||||
super().__init__(
|
||||
driver_instance=self,
|
||||
driver_instance=driver_instance,
|
||||
device_id=device_id,
|
||||
status_types={},
|
||||
action_value_mappings=self.protocol_action_mappings,
|
||||
@@ -77,8 +84,56 @@ class ROS2ProtocolNode(BaseROS2DeviceNode):
|
||||
# 设置硬件接口代理
|
||||
self._setup_hardware_proxies()
|
||||
|
||||
# 新增:如果有工作站实例,建立双向引用
|
||||
if self.workstation_instance:
|
||||
self.workstation_instance._protocol_node = self
|
||||
self._setup_workstation_method_proxies()
|
||||
self.lab_logger().info(f"ROS2ProtocolNode {device_id} 与工作站实例 {type(self.workstation_instance).__name__} 关联")
|
||||
|
||||
self.lab_logger().info(f"ROS2ProtocolNode {device_id} initialized with protocols: {self.protocol_names}")
|
||||
|
||||
def _setup_workstation_method_proxies(self):
|
||||
"""设置工作站方法代理"""
|
||||
if not self.workstation_instance:
|
||||
return
|
||||
|
||||
# 代理工作站的核心方法
|
||||
workstation_methods = [
|
||||
'start_workflow', 'stop_workflow', 'workflow_status', 'is_busy',
|
||||
'process_material_change_report', 'process_step_finish_report',
|
||||
'process_sample_finish_report', 'process_order_finish_report',
|
||||
'handle_external_error'
|
||||
]
|
||||
|
||||
for method_name in workstation_methods:
|
||||
if hasattr(self.workstation_instance, method_name):
|
||||
# 创建代理方法
|
||||
setattr(self, method_name, getattr(self.workstation_instance, method_name))
|
||||
self.lab_logger().debug(f"代理工作站方法: {method_name}")
|
||||
|
||||
# ============ 工作站方法代理 ============
|
||||
|
||||
def get_workstation_status(self) -> Dict[str, Any]:
|
||||
"""获取工作站状态"""
|
||||
if self.workstation_instance:
|
||||
return {
|
||||
'workflow_status': str(self.workstation_instance.workflow_status.value),
|
||||
'is_busy': self.workstation_instance.is_busy,
|
||||
'workflow_runtime': self.workstation_instance.workflow_runtime,
|
||||
'error_count': self.workstation_instance.error_count,
|
||||
'last_error': self.workstation_instance.last_error
|
||||
}
|
||||
return {'status': 'no_workstation_instance'}
|
||||
|
||||
def delegate_to_workstation(self, method_name: str, *args, **kwargs):
|
||||
"""委托方法调用给工作站实例"""
|
||||
if self.workstation_instance and hasattr(self.workstation_instance, method_name):
|
||||
method = getattr(self.workstation_instance, method_name)
|
||||
return method(*args, **kwargs)
|
||||
else:
|
||||
self.lab_logger().warning(f"工作站实例不存在或没有方法: {method_name}")
|
||||
return None
|
||||
|
||||
def _initialize_child_devices(self):
|
||||
"""初始化子设备 - 重构为更清晰的方法"""
|
||||
# 设备分类字典 - 统一管理
|
||||
|
||||
Reference in New Issue
Block a user