From 609b6006e86165348a8e074bdc9e68dd5a94b60e Mon Sep 17 00:00:00 2001 From: Xuwznln <18435084+Xuwznln@users.noreply.github.com> Date: Sat, 11 Oct 2025 00:57:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=89=E6=8B=A9=E5=99=A8?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E8=A1=A8=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90?= =?UTF-8?q?=20=E6=94=AF=E6=8C=81=E8=BD=AC=E8=BF=90=E7=89=A9=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unilabos/app/main.py | 13 +- unilabos/app/web/client.py | 6 +- .../workstation/bioyond_studio/config.py | 129 ++ .../workstation/bioyond_studio/station.py | 9 + .../device_comms/communication_devices.yaml | 3 + unilabos/registry/devices/camera.yaml | 2 + .../devices/characterization_chromatic.yaml | 7 + .../devices/characterization_optic.yaml | 4 + .../devices/dispensing_station_bioyond.yaml | 1156 ++++++++++++++- unilabos/registry/devices/gas_handler.yaml | 4 + unilabos/registry/devices/liquid_handler.yaml | 85 ++ .../devices/neware_battery_test_system.yaml | 3 + .../devices/organic_miscellaneous.yaml | 7 + unilabos/registry/devices/pump_and_valve.yaml | 43 + .../devices/reaction_station_bioyond.yaml | 1150 ++++++++++++++- unilabos/registry/devices/robot_agv.yaml | 1 + unilabos/registry/devices/robot_arm.yaml | 17 + unilabos/registry/devices/robot_gripper.yaml | 15 + .../registry/devices/robot_linear_motion.yaml | 13 + .../registry/devices/solid_dispenser.yaml | 2 + unilabos/registry/devices/temperature.yaml | 11 + unilabos/registry/devices/virtual_device.yaml | 53 + unilabos/registry/devices/work_station.yaml | 1243 ++++++++++++++++- unilabos/registry/devices/zhida_gcms.yaml | 3 + unilabos/registry/placeholder_type.py | 9 + unilabos/registry/registry.py | 16 +- unilabos/registry/resources/bioyond/deck.yaml | 26 +- unilabos/resources/graphio.py | 80 +- unilabos/ros/nodes/base_device_node.py | 260 ++-- unilabos/ros/nodes/presets/host_node.py | 3 +- unilabos/ros/nodes/resource_tracker.py | 173 +++ 31 files changed, 4268 insertions(+), 278 deletions(-) create mode 100644 unilabos/devices/workstation/bioyond_studio/config.py create mode 100644 unilabos/registry/placeholder_type.py diff --git a/unilabos/app/main.py b/unilabos/app/main.py index 1844fe77..7fab0588 100644 --- a/unilabos/app/main.py +++ b/unilabos/app/main.py @@ -6,7 +6,6 @@ import signal import sys import threading import time -from copy import deepcopy from typing import Dict, Any, List import networkx as nx @@ -262,8 +261,6 @@ def main(): read_node_link_json, read_graphml, dict_from_graph, - dict_to_nested_dict, - initialize_resources, ) from unilabos.app.communication import get_communication_client from unilabos.registry.registry import build_registry @@ -286,9 +283,8 @@ def main(): graph: nx.Graph resource_tree_set: ResourceTreeSet resource_links: List[Dict[str, Any]] - + request_startup_json = http_client.request_startup_json() if args_dict["graph"] is None: - request_startup_json = http_client.request_startup_json() if not request_startup_json: print_status( "未指定设备加载文件路径,尝试从HTTP获取失败,请检查网络或者使用-g参数指定设备加载文件路径", "error" @@ -339,6 +335,13 @@ def main(): resource_edge_info.pop(edge_info - ind - 1) continue + # 如果从远端获取了物料信息,则与本地物料进行同步 + if request_startup_json and "nodes" in request_startup_json: + print_status("开始同步远端物料到本地...", "info") + remote_tree_set = ResourceTreeSet.from_raw_list(request_startup_json["nodes"]) + resource_tree_set.merge_remote_resources(remote_tree_set) + print_status("远端物料同步完成", "info") + # 使用 ResourceTreeSet 代替 list args_dict["resources_config"] = resource_tree_set args_dict["devices_config"] = resource_tree_set diff --git a/unilabos/app/web/client.py b/unilabos/app/web/client.py index 401858b0..62ed8808 100644 --- a/unilabos/app/web/client.py +++ b/unilabos/app/web/client.py @@ -80,7 +80,7 @@ class HTTPClient: info(f"首次添加资源,当前远程地址: {self.remote_addr}") response = requests.post( f"{self.remote_addr}/edge/material", - json={"nodes": [x for xs in resources.dump() for x in xs], "mount_uuid": mount_uuid}, + json={"nodes": resources.dump()[0], "mount_uuid": mount_uuid}, headers={"Authorization": f"Lab {self.auth}"}, timeout=100, ) @@ -102,6 +102,8 @@ class HTTPClient: data = res["data"] for i in data: uuid_mapping[i["uuid"]] = i["cloud_uuid"] + if i["cloud_uuid"] == i["uuid"]: + print(i["cloud_uuid"], i["uuid"]) else: logger.error(f"添加物料失败: {response.text}") for u, n in old_uuids.items(): @@ -298,7 +300,7 @@ class HTTPClient: Response: API响应对象 """ response = requests.get( - f"{self.remote_addr}/lab/resource/graph_info/", + f"{self.remote_addr}/edge/material/download", headers={"Authorization": f"Lab {self.auth}"}, timeout=(3, 30), ) diff --git a/unilabos/devices/workstation/bioyond_studio/config.py b/unilabos/devices/workstation/bioyond_studio/config.py new file mode 100644 index 00000000..36bf00bb --- /dev/null +++ b/unilabos/devices/workstation/bioyond_studio/config.py @@ -0,0 +1,129 @@ +# config.py +""" +配置文件 - 包含所有配置信息和映射关系 +""" + +# API配置 +API_CONFIG = { + "api_key": "", + "api_host": "" +} + +# 站点类型配置 +STATION_TYPES = { + "REACTION": "reaction_station", # 仅反应站 + "DISPENSING": "dispensing_station", # 仅配液站 + "HYBRID": "hybrid_station" # 混合模式 +} + +# 默认站点配置 +DEFAULT_STATION_CONFIG = { + "station_type": STATION_TYPES["REACTION"], # 默认反应站模式 + "enable_reaction_station": True, # 是否启用反应站功能 + "enable_dispensing_station": False, # 是否启用配液站功能 + "station_name": "BioyondReactionStation", # 站点名称 + "description": "Bioyond反应工作站" # 站点描述 +} + +# 工作流映射配置 +WORKFLOW_MAPPINGS = { + "reactor_taken_out": "", + "reactor_taken_in": "", + "Solid_feeding_vials": "", + "Liquid_feeding_vials(non-titration)": "", + "Liquid_feeding_solvents": "", + "Liquid_feeding(titration)": "", + "liquid_feeding_beaker": "", + "Drip_back": "", +} + +# 工作流名称到DisplaySectionName的映射 +WORKFLOW_TO_SECTION_MAP = { + 'reactor_taken_in': '反应器放入', + 'liquid_feeding_beaker': '液体投料-烧杯', + 'Liquid_feeding_vials(non-titration)': '液体投料-小瓶(非滴定)', + 'Liquid_feeding_solvents': '液体投料-溶剂', + 'Solid_feeding_vials': '固体投料-小瓶', + 'Liquid_feeding(titration)': '液体投料-滴定', + 'reactor_taken_out': '反应器取出' +} + +# 库位映射配置 +LOCATION_MAPPING = { + 'A01': '', + 'A02': '', + 'A03': '', + 'A04': '', + 'A05': '', + 'A06': '', + 'A07': '', + 'A08': '', + 'B01': '', + 'B02': '', + 'B03': '', + 'B04': '', + 'B05': '', + 'B06': '', + 'B07': '', + 'B08': '', + 'C01': '', + 'C02': '', + 'C03': '', + 'C04': '', + 'C05': '', + 'C06': '', + 'C07': '', + 'C08': '', + 'D01': '', + 'D02': '', + 'D03': '', + 'D04': '', + 'D05': '', + 'D06': '', + 'D07': '', + 'D08': '', +} + +# 物料类型配置 +MATERIAL_TYPE_IDS = { + "样品板": "", + "样品": "", + "烧杯": "" +} + +MATERIAL_TYPE_MAPPINGS = { + "烧杯": "BIOYOND_PolymerStation_1FlaskCarrier", + "试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier", + "样品板": "BIOYOND_PolymerStation_6VialCarrier", +} + +# 步骤参数配置(各工作流的步骤UUID) +WORKFLOW_STEP_IDS = { + "reactor_taken_in": { + "config": "" + }, + "liquid_feeding_beaker": { + "liquid": "", + "observe": "" + }, + "liquid_feeding_vials_non_titration": { + "liquid": "", + "observe": "" + }, + "liquid_feeding_solvents": { + "liquid": "", + "observe": "" + }, + "solid_feeding_vials": { + "feeding": "", + "observe": "" + }, + "liquid_feeding_titration": { + "liquid": "", + "observe": "" + }, + "drip_back": { + "liquid": "", + "observe": "" + } +} diff --git a/unilabos/devices/workstation/bioyond_studio/station.py b/unilabos/devices/workstation/bioyond_studio/station.py index d09a8a3e..a57840ff 100644 --- a/unilabos/devices/workstation/bioyond_studio/station.py +++ b/unilabos/devices/workstation/bioyond_studio/station.py @@ -10,12 +10,14 @@ import json from unilabos.devices.workstation.workstation_base import WorkstationBase, ResourceSynchronizer from unilabos.devices.workstation.bioyond_studio.bioyond_rpc import BioyondV1RPC +from unilabos.registry.placeholder_type import ResourceSlot, DeviceSlot from unilabos.resources.warehouse import WareHouse from unilabos.utils.log import logger from unilabos.resources.graphio import resource_bioyond_to_plr from unilabos.ros.nodes.base_device_node import ROS2DeviceNode, BaseROS2DeviceNode from unilabos.ros.nodes.presets.workstation import ROS2WorkstationNode +from pylabrobot.resources.resource import Resource as ResourcePLR from unilabos.devices.workstation.bioyond_studio.config import ( API_CONFIG, WORKFLOW_MAPPINGS, MATERIAL_TYPE_MAPPINGS, @@ -153,6 +155,13 @@ class BioyondWorkstation(WorkstationBase): "resources": [self.deck] }) + def transfer_resource_to_another(self, resource_a: ResourceSlot, device_id: DeviceSlot, resource_b: ResourceSlot): + ROS2DeviceNode.run_async_func(self._ros_node.transfer_resource_to_another, True, **{ + "plr_resources": [resource_a], + "target_device_id": device_id, + "target_resource_uuid": getattr(resource_b, "unilabos_uuid", None), + }) + def _configure_station_type(self, station_config: Optional[Dict[str, Any]] = None) -> None: """配置站点类型和功能模块 diff --git a/unilabos/registry/device_comms/communication_devices.yaml b/unilabos/registry/device_comms/communication_devices.yaml index a35e0556..ea3f1b61 100644 --- a/unilabos/registry/device_comms/communication_devices.yaml +++ b/unilabos/registry/device_comms/communication_devices.yaml @@ -10,6 +10,7 @@ serial: request: null response: null handles: {} + placeholder_keys: {} result: {} schema: description: handle_serial_request的参数schema @@ -36,6 +37,7 @@ serial: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: read_data的参数schema @@ -57,6 +59,7 @@ serial: goal_default: command: null handles: {} + placeholder_keys: {} result: {} schema: description: send_command的参数schema diff --git a/unilabos/registry/devices/camera.yaml b/unilabos/registry/devices/camera.yaml index 3e50be0e..08c809cf 100644 --- a/unilabos/registry/devices/camera.yaml +++ b/unilabos/registry/devices/camera.yaml @@ -8,6 +8,7 @@ camera.USB: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 用于安全地关闭摄像头设备,释放摄像头资源,停止视频采集和发布服务。调用此函数将清理OpenCV摄像头连接并销毁ROS2节点。 @@ -28,6 +29,7 @@ camera.USB: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 定时器回调函数的参数schema。此函数负责定期采集摄像头视频帧,将OpenCV格式的图像转换为ROS Image消息格式,并发布到指定的视频话题。默认以10Hz频率执行,确保视频流的连续性和实时性。 diff --git a/unilabos/registry/devices/characterization_chromatic.yaml b/unilabos/registry/devices/characterization_chromatic.yaml index e22deb1b..f3059b58 100644 --- a/unilabos/registry/devices/characterization_chromatic.yaml +++ b/unilabos/registry/devices/characterization_chromatic.yaml @@ -8,6 +8,7 @@ hplc.agilent: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 检查安捷伦HPLC设备状态的函数。用于监控设备的运行状态、连接状态、错误信息等关键指标。该函数定期查询设备状态,确保系统稳定运行,及时发现和报告设备异常。适用于自动化流程中的设备监控、故障诊断、系统维护等场景。 @@ -29,6 +30,7 @@ hplc.agilent: goal_default: file_path: null handles: {} + placeholder_keys: {} result: {} schema: description: 从文本文件中提取分析数据的函数。用于解析安捷伦HPLC生成的结果文件,提取峰面积、保留时间、浓度等关键分析数据。支持多种文件格式的自动识别和数据结构化处理,为后续数据分析和报告生成提供标准化的数据格式。适用于批量数据处理、结果验证、质量控制等分析工作流程。 @@ -55,6 +57,7 @@ hplc.agilent: resource: null wf_name: null handles: {} + placeholder_keys: {} result: {} schema: description: 启动安捷伦HPLC分析序列的函数。用于执行预定义的分析方法序列,包括样品进样、色谱分离、检测等完整的分析流程。支持参数配置、资源分配、工作流程管理等功能,实现全自动的样品分析。适用于批量样品处理、标准化分析、质量检测等需要连续自动分析的应用场景。 @@ -83,6 +86,7 @@ hplc.agilent: goal_default: device_name: null handles: {} + placeholder_keys: {} result: {} schema: description: 尝试关闭HPLC子设备的函数。用于安全地关闭泵、检测器、进样器等各个子模块,确保设备正常断开连接并保护硬件安全。该函数提供错误处理和状态确认机制,避免强制关闭可能造成的设备损坏。适用于设备维护、系统重启、紧急停机等需要安全关闭设备的场景。 @@ -106,6 +110,7 @@ hplc.agilent: goal_default: device_name: null handles: {} + placeholder_keys: {} result: {} schema: description: 尝试打开HPLC子设备的函数。用于初始化和连接泵、检测器、进样器等各个子模块,建立设备通信并进行自检。该函数提供连接验证和错误恢复机制,确保子设备正常启动并准备就绪。适用于设备初始化、系统启动、设备重连等需要建立设备连接的场景。 @@ -263,6 +268,7 @@ hplc.agilent-zhida: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: HPLC设备连接关闭函数。安全地断开与智达HPLC设备的TCP socket连接,释放网络资源。该函数确保连接的正确关闭,避免网络资源泄露。通常在设备使用完毕或系统关闭时调用。 @@ -283,6 +289,7 @@ hplc.agilent-zhida: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: HPLC设备连接建立函数。与智达HPLC设备建立TCP socket通信连接,配置通信超时参数。该函数是设备使用前的必要步骤,建立成功后可进行状态查询、方法获取、任务启动等操作。连接失败时会抛出异常。 diff --git a/unilabos/registry/devices/characterization_optic.yaml b/unilabos/registry/devices/characterization_optic.yaml index f8a3105a..80dcf93d 100644 --- a/unilabos/registry/devices/characterization_optic.yaml +++ b/unilabos/registry/devices/characterization_optic.yaml @@ -9,6 +9,7 @@ raman.home_made: goal_default: int_time: null handles: {} + placeholder_keys: {} result: {} schema: description: 设置CCD检测器积分时间的函数。用于配置拉曼光谱仪的信号采集时间,控制光谱数据的质量和信噪比。较长的积分时间可获得更高的信号强度和更好的光谱质量,但会增加测量时间。该函数允许根据样品特性和测量要求动态调整检测参数,优化测量效果。 @@ -33,6 +34,7 @@ raman.home_made: goal_default: output_voltage_laser: null handles: {} + placeholder_keys: {} result: {} schema: description: 设置激光器输出功率的函数。用于控制拉曼光谱仪激光器的功率输出,调节激光强度以适应不同样品的测量需求。适当的激光功率能够获得良好的拉曼信号同时避免样品损伤。该函数支持精确的功率控制,确保测量结果的稳定性和重现性。 @@ -58,6 +60,7 @@ raman.home_made: int_time: null laser_power: null handles: {} + placeholder_keys: {} result: {} schema: description: 执行无背景扣除的拉曼光谱测量函数。用于直接采集样品的拉曼光谱信号,不进行背景校正处理。该函数配置积分时间和激光功率参数,获取原始光谱数据用于后续的数据处理分析。适用于对光谱数据质量要求较高或需要自定义背景处理流程的测量场景。 @@ -88,6 +91,7 @@ raman.home_made: laser_power: null sample_name: null handles: {} + placeholder_keys: {} result: {} schema: description: 执行多次平均的无背景拉曼光谱测量函数。通过多次测量取平均值来提高光谱数据的信噪比和测量精度,减少随机噪声影响。该函数支持自定义平均次数、积分时间、激光功率等参数,并可为样品指定名称便于数据管理。适用于对测量精度要求较高的定量分析和研究应用。 diff --git a/unilabos/registry/devices/dispensing_station_bioyond.yaml b/unilabos/registry/devices/dispensing_station_bioyond.yaml index 4c87e962..877f00f0 100644 --- a/unilabos/registry/devices/dispensing_station_bioyond.yaml +++ b/unilabos/registry/devices/dispensing_station_bioyond.yaml @@ -4,6 +4,1089 @@ dispensing_station.bioyond: - dispensing_station_bioyond class: action_value_mappings: + auto-add_material: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: object + required: + - material_data + type: object + result: {} + required: + - goal + title: add_material参数 + type: object + type: UniLabJsonCommand + auto-create_order: + feedback: {} + goal: {} + goal_default: + parameters: null + task_name: null + workflow_name: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + task_name: + type: string + workflow_name: + type: string + required: + - workflow_name + - task_name + type: object + result: {} + required: + - goal + title: create_order参数 + type: object + type: UniLabJsonCommand + auto-delete_material: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: delete_material参数 + type: object + type: UniLabJsonCommand + auto-device_operation: + feedback: {} + goal: {} + goal_default: + device_id: null + operation: null + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + device_id: + type: string + operation: + type: string + parameters: + type: object + required: + - device_id + - operation + type: object + result: {} + required: + - goal + title: device_operation参数 + type: object + type: UniLabJsonCommand + auto-drip_back: + feedback: {} + goal: {} + goal_default: + assign_material_name: Reactor + temperature: 25.0 + time: '0' + torque_variation: '1' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + default: Reactor + type: string + temperature: + default: 25.0 + type: number + time: + default: '0' + type: string + torque_variation: + default: '1' + type: string + required: [] + type: object + result: {} + required: + - goal + title: drip_back参数 + type: object + type: UniLabJsonCommand + auto-execute_bioyond_sync_workflow: + feedback: {} + goal: {} + goal_default: + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + required: + - parameters + type: object + result: {} + required: + - goal + title: execute_bioyond_sync_workflow参数 + type: object + type: UniLabJsonCommandAsync + auto-execute_bioyond_update_workflow: + feedback: {} + goal: {} + goal_default: + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + required: + - parameters + type: object + result: {} + required: + - goal + title: execute_bioyond_update_workflow参数 + type: object + type: UniLabJsonCommandAsync + auto-liquid_feeding_beaker: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_beaker参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_solvents: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_solvents参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_titration: + feedback: {} + goal: {} + goal_default: + material_name: '' + time: '120' + titration_type: '1' + torque_variation: '2' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + time: + default: '120' + type: string + titration_type: + default: '1' + type: string + torque_variation: + default: '2' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_titration参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_vials_non_titration: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_vials_non_titration参数 + type: object + type: UniLabJsonCommand + auto-load_bioyond_data_from_file: + feedback: {} + goal: {} + goal_default: + file_path: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + file_path: + type: string + required: + - file_path + type: object + result: {} + required: + - goal + title: load_bioyond_data_from_file参数 + type: object + type: UniLabJsonCommand + auto-material_inbound: + feedback: {} + goal: {} + goal_default: + location_name: null + material_id: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location_name: + type: string + material_id: + type: string + required: + - material_id + - location_name + type: object + result: {} + required: + - goal + title: material_inbound参数 + type: object + type: UniLabJsonCommand + auto-material_outbound: + feedback: {} + goal: {} + goal_default: + location_name: null + material_id: null + quantity: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location_name: + type: string + material_id: + type: string + quantity: + type: integer + required: + - material_id + - location_name + - quantity + type: object + result: {} + required: + - goal + title: material_outbound参数 + type: object + type: UniLabJsonCommand + auto-merge_workflow_with_parameters: + feedback: {} + goal: {} + goal_default: + name: null + workflows: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + name: + type: string + workflows: + items: + type: object + type: array + required: + - name + - workflows + type: object + result: {} + required: + - goal + title: merge_workflow_with_parameters参数 + type: object + type: UniLabJsonCommand + auto-order_query: + feedback: {} + goal: {} + goal_default: + query_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + query_data: + type: string + required: + - query_data + type: object + result: {} + required: + - goal + title: order_query参数 + type: object + type: UniLabJsonCommand + auto-post_init: + feedback: {} + goal: {} + goal_default: + ros_node: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + ros_node: + type: object + required: + - ros_node + type: object + result: {} + required: + - goal + title: post_init参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_drip_back: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + time: null + torque_variation: null + volume: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + time: + type: string + torque_variation: + type: string + volume: + type: string + required: + - volume + - assign_material_name + - time + - torque_variation + type: object + result: {} + required: + - goal + title: reaction_station_drip_back参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_liquid_feed: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + time: null + titration_type: null + torque_variation: null + volume: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + time: + type: string + titration_type: + type: string + torque_variation: + type: string + volume: + type: string + required: + - titration_type + - volume + - assign_material_name + - time + - torque_variation + type: object + result: {} + required: + - goal + title: reaction_station_liquid_feed参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_process_execute: + feedback: {} + goal: {} + goal_default: + task_name: null + workflow_name: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + task_name: + type: string + workflow_name: + type: string + required: + - workflow_name + - task_name + type: object + result: {} + required: + - goal + title: reaction_station_process_execute参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_reactor_taken_out: + feedback: {} + goal: {} + goal_default: + order_id: '' + preintake_id: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + order_id: + default: '' + type: string + preintake_id: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: reaction_station_reactor_taken_out参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_solid_feed_vial: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + material_id: null + time: null + torque_variation: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + material_id: + type: string + time: + type: string + torque_variation: + type: string + required: + - assign_material_name + - material_id + - time + - torque_variation + type: object + result: {} + required: + - goal + title: reaction_station_solid_feed_vial参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_take_in: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + cutoff: null + temperature: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + cutoff: + type: string + temperature: + type: string + required: + - cutoff + - temperature + - assign_material_name + type: object + result: {} + required: + - goal + title: reaction_station_take_in参数 + type: object + type: UniLabJsonCommand + auto-reactor_taken_in: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: reactor_taken_in参数 + type: object + type: UniLabJsonCommand + auto-reactor_taken_out: + feedback: {} + goal: {} + goal_default: + order_id: '' + preintake_id: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + order_id: + default: '' + type: string + preintake_id: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: reactor_taken_out参数 + type: object + type: UniLabJsonCommand + auto-reset_workstation: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: reset_workstation参数 + type: object + type: UniLabJsonCommand + auto-solid_feeding_vials: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: solid_feeding_vials参数 + type: object + type: UniLabJsonCommand + auto-start_scheduler: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: start_scheduler参数 + type: object + type: UniLabJsonCommand + auto-stock_material: + feedback: {} + goal: {} + goal_default: + location: null + material_id: null + quantity: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location: + type: string + material_id: + type: string + quantity: + type: integer + required: + - material_id + - location + - quantity + type: object + result: {} + required: + - goal + title: stock_material参数 + type: object + type: UniLabJsonCommand + auto-stop_scheduler: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: stop_scheduler参数 + type: object + type: UniLabJsonCommand + auto-transfer_resource_to_another: + feedback: {} + goal: {} + goal_default: + device_id: null + resource_a: null + resource_b: null + handles: {} + placeholder_keys: + device_id: unilabos_devices + resource_a: unilabos_resources + resource_b: unilabos_resources + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + device_id: + type: object + resource_a: + properties: + category: + type: string + children: + items: + type: string + type: array + config: + type: string + data: + type: string + id: + type: string + name: + type: string + parent: + type: string + pose: + properties: + orientation: + properties: + w: + type: number + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + - w + title: orientation + type: object + position: + properties: + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + title: position + type: object + required: + - position + - orientation + title: pose + type: object + sample_id: + type: string + type: + type: string + required: + - id + - name + - sample_id + - children + - parent + - type + - category + - pose + - config + - data + title: resource_a + type: object + resource_b: + properties: + category: + type: string + children: + items: + type: string + type: array + config: + type: string + data: + type: string + id: + type: string + name: + type: string + parent: + type: string + pose: + properties: + orientation: + properties: + w: + type: number + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + - w + title: orientation + type: object + position: + properties: + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + title: position + type: object + required: + - position + - orientation + title: pose + type: object + sample_id: + type: string + type: + type: string + required: + - id + - name + - sample_id + - children + - parent + - type + - category + - pose + - config + - data + title: resource_b + type: object + required: + - resource_a + - device_id + - resource_b + type: object + result: {} + required: + - goal + title: transfer_resource_to_another参数 + type: object + type: UniLabJsonCommand + auto-validate_workflow_parameters: + feedback: {} + goal: {} + goal_default: + workflows: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + workflows: + items: + type: object + type: array + required: + - workflows + type: object + result: {} + required: + - goal + title: validate_workflow_parameters参数 + type: object + type: UniLabJsonCommand bioyond_sync: feedback: {} goal: @@ -443,9 +1526,11 @@ dispensing_station.bioyond: protocol_type: [] status_types: bioyond_status: dict - enable_dispensing_station: bool - enable_reaction_station: bool - station_type: str + device_list: dict + scheduler_status: dict + station_info: dict + workflow_parameter_template: dict + workstation_status: dict type: python config_info: [] description: Bioyond配液站 - 专门用于物料配制和管理的工作站 @@ -455,52 +1540,33 @@ dispensing_station.bioyond: config: properties: bioyond_config: - description: Bioyond API配置 - properties: - api_host: - description: Bioyond API主机地址 - type: string - api_key: - description: Bioyond API密钥 - type: string - material_type_mappings: - description: 物料类型映射配置 - type: object - workflow_mappings: - description: 工作流映射配置 - type: object - type: object + type: string deck: - description: Deck配置 - type: object + type: string station_config: - description: 配液站配置 - properties: - description: - description: 配液站描述 - type: string - enable_dispensing_station: - default: true - description: 启用配液站功能 - type: boolean - enable_reaction_station: - default: false - description: 禁用反应站功能 - type: boolean - station_name: - description: 配液站名称 - type: string - station_type: - default: dispensing_station - description: 站点类型 - 配液站 - enum: - - dispensing_station - type: string - type: object + type: string required: [] type: object data: - properties: {} - required: [] + properties: + bioyond_status: + type: object + device_list: + type: object + scheduler_status: + type: object + station_info: + type: object + workflow_parameter_template: + type: object + workstation_status: + type: object + required: + - station_info + - bioyond_status + - workflow_parameter_template + - scheduler_status + - device_list + - workstation_status type: object version: 1.0.0 diff --git a/unilabos/registry/devices/gas_handler.yaml b/unilabos/registry/devices/gas_handler.yaml index 644696a5..65218619 100644 --- a/unilabos/registry/devices/gas_handler.yaml +++ b/unilabos/registry/devices/gas_handler.yaml @@ -8,6 +8,7 @@ gas_source.mock: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -28,6 +29,7 @@ gas_source.mock: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_open的参数schema @@ -188,6 +190,7 @@ vacuum_pump.mock: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -208,6 +211,7 @@ vacuum_pump.mock: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_open的参数schema diff --git a/unilabos/registry/devices/liquid_handler.yaml b/unilabos/registry/devices/liquid_handler.yaml index 3d9b75f9..b21ccd7e 100644 --- a/unilabos/registry/devices/liquid_handler.yaml +++ b/unilabos/registry/devices/liquid_handler.yaml @@ -564,6 +564,7 @@ liquid_handler: protocol_type: null protocol_version: null handles: {} + placeholder_keys: {} result: {} schema: description: 创建实验协议函数。用于建立新的液体处理实验协议,定义协议名称、描述、版本、作者、日期等基本信息。该函数支持协议模板化管理,便于实验流程的标准化和重复性。适用于实验设计、方法开发、标准操作程序建立等需要协议管理的应用场景。 @@ -607,6 +608,7 @@ liquid_handler: msg: null seconds: 0 handles: {} + placeholder_keys: {} result: {} schema: description: 自定义延时函数。在实验流程中插入可配置的等待时间,用于满足特定的反应时间、孵育时间或设备稳定时间要求。支持自定义延时消息和秒数设置,提供流程控制和时间管理功能。适用于酶反应等待、温度平衡、样品孵育等需要时间控制的实验步骤。 @@ -633,6 +635,7 @@ liquid_handler: goal_default: tip_racks: null handles: {} + placeholder_keys: {} result: {} schema: description: 吸头迭代函数。用于自动管理和切换吸头架中的吸头,实现批量实验中的吸头自动分配和追踪。该函数监控吸头使用状态,自动切换到下一个可用吸头位置,确保实验流程的连续性。适用于高通量实验、批量处理、自动化流水线等需要大量吸头管理的应用场景。 @@ -659,6 +662,7 @@ liquid_handler: volumes: null wells: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -689,6 +693,7 @@ liquid_handler: goal_default: tip_racks: null handles: {} + placeholder_keys: {} result: {} schema: description: 吸头架设置函数。用于配置和初始化液体处理系统的吸头架信息,包括吸头架位置、类型、容量等参数。该函数建立吸头资源管理系统,为后续的吸头选择和使用提供基础配置。适用于系统初始化、吸头架更换、实验配置等需要吸头资源管理的操作场景。 @@ -713,6 +718,7 @@ liquid_handler: goal_default: targets: null handles: {} + placeholder_keys: {} result: {} schema: description: 吸头碰触函数。控制移液器吸头轻触容器边缘或底部,用于去除吸头外壁附着的液滴,提高移液精度和减少污染。该函数支持多目标位置操作,可配置碰触参数和位置偏移。适用于精密移液、减少液体残留、防止交叉污染等需要提高移液质量的实验操作。 @@ -739,6 +745,7 @@ liquid_handler: target_group_name: null unit_volume: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -4495,6 +4502,7 @@ liquid_handler.biomek: resources: null slot_on_deck: null handles: {} + placeholder_keys: {} result: {} schema: description: create_resource的参数schema @@ -4554,6 +4562,7 @@ liquid_handler.biomek: parent: null slot_on_deck: null handles: {} + placeholder_keys: {} result: {} schema: description: instrument_setup_biomek的参数schema @@ -6042,6 +6051,7 @@ liquid_handler.prcxi: protocol_type: '' protocol_version: '' handles: {} + placeholder_keys: {} result: {} schema: description: create_protocol的参数schema @@ -6087,6 +6097,7 @@ liquid_handler.prcxi: msg: null seconds: 0 handles: {} + placeholder_keys: {} result: {} schema: description: custom_delay的参数schema @@ -6113,6 +6124,7 @@ liquid_handler.prcxi: goal_default: tip_racks: null handles: {} + placeholder_keys: {} result: {} schema: description: iter_tips的参数schema @@ -6139,6 +6151,7 @@ liquid_handler.prcxi: dis_to_top: 0 well: null handles: {} + placeholder_keys: {} result: {} schema: description: move_to的参数schema @@ -6168,6 +6181,7 @@ liquid_handler.prcxi: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: run_protocol的参数schema @@ -6183,12 +6197,50 @@ liquid_handler.prcxi: title: run_protocol参数 type: object type: UniLabJsonCommandAsync + auto-set_group: + feedback: {} + goal: {} + goal_default: + group_name: null + volumes: null + wells: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + group_name: + type: string + volumes: + items: + type: number + type: array + wells: + items: + type: object + type: array + required: + - group_name + - wells + - volumes + type: object + result: {} + required: + - goal + title: set_group参数 + type: object + type: UniLabJsonCommand auto-touch_tip: feedback: {} goal: {} goal_default: targets: null handles: {} + placeholder_keys: {} result: {} schema: description: touch_tip的参数schema @@ -6207,6 +6259,39 @@ liquid_handler.prcxi: title: touch_tip参数 type: object type: UniLabJsonCommandAsync + auto-transfer_group: + feedback: {} + goal: {} + goal_default: + source_group_name: null + target_group_name: null + unit_volume: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + source_group_name: + type: string + target_group_name: + type: string + unit_volume: + type: number + required: + - source_group_name + - target_group_name + - unit_volume + type: object + result: {} + required: + - goal + title: transfer_group参数 + type: object + type: UniLabJsonCommandAsync discard_tips: feedback: {} goal: diff --git a/unilabos/registry/devices/neware_battery_test_system.yaml b/unilabos/registry/devices/neware_battery_test_system.yaml index 3dd7568d..bfcbc43d 100644 --- a/unilabos/registry/devices/neware_battery_test_system.yaml +++ b/unilabos/registry/devices/neware_battery_test_system.yaml @@ -9,6 +9,7 @@ neware_battery_test_system: goal_default: ros_node: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -32,6 +33,7 @@ neware_battery_test_system: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -52,6 +54,7 @@ neware_battery_test_system: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: '' diff --git a/unilabos/registry/devices/organic_miscellaneous.yaml b/unilabos/registry/devices/organic_miscellaneous.yaml index 025fad59..3085c823 100644 --- a/unilabos/registry/devices/organic_miscellaneous.yaml +++ b/unilabos/registry/devices/organic_miscellaneous.yaml @@ -9,6 +9,7 @@ rotavap.one: goal_default: cmd: null handles: {} + placeholder_keys: {} result: {} schema: description: cmd_write的参数schema @@ -32,6 +33,7 @@ rotavap.one: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: main_loop的参数schema @@ -53,6 +55,7 @@ rotavap.one: goal_default: time: null handles: {} + placeholder_keys: {} result: {} schema: description: set_pump_time的参数schema @@ -77,6 +80,7 @@ rotavap.one: goal_default: time: null handles: {} + placeholder_keys: {} result: {} schema: description: set_rotate_time的参数schema @@ -172,6 +176,7 @@ separator.homemade: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: read_sensor_loop的参数schema @@ -194,6 +199,7 @@ separator.homemade: condition: null value: null handles: {} + placeholder_keys: {} result: {} schema: description: valve_open的参数schema @@ -221,6 +227,7 @@ separator.homemade: goal_default: data: null handles: {} + placeholder_keys: {} result: {} schema: description: write的参数schema diff --git a/unilabos/registry/devices/pump_and_valve.yaml b/unilabos/registry/devices/pump_and_valve.yaml index 5a333a56..40fd9d3e 100644 --- a/unilabos/registry/devices/pump_and_valve.yaml +++ b/unilabos/registry/devices/pump_and_valve.yaml @@ -8,6 +8,7 @@ solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: close的参数schema @@ -28,6 +29,7 @@ solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -48,6 +50,7 @@ solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_open的参数schema @@ -68,6 +71,7 @@ solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -88,6 +92,7 @@ solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: read_data的参数schema @@ -109,6 +114,7 @@ solenoid_valve: goal_default: command: null handles: {} + placeholder_keys: {} result: {} schema: description: send_command的参数schema @@ -205,6 +211,7 @@ solenoid_valve.mock: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -225,6 +232,7 @@ solenoid_valve.mock: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_open的参数schema @@ -246,6 +254,7 @@ solenoid_valve.mock: goal_default: position: null handles: {} + placeholder_keys: {} result: {} schema: description: set_valve_position的参数schema @@ -376,6 +385,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: close的参数schema @@ -396,6 +406,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -417,6 +428,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: volume: null handles: {} + placeholder_keys: {} result: {} schema: description: pull_plunger的参数schema @@ -441,6 +453,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: volume: null handles: {} + placeholder_keys: {} result: {} schema: description: push_plunger的参数schema @@ -464,6 +477,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_aux_input_status_1的参数schema @@ -484,6 +498,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_aux_input_status_2的参数schema @@ -504,6 +519,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_backlash_position的参数schema @@ -524,6 +540,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_command_buffer_status的参数schema @@ -544,6 +561,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_software_version的参数schema @@ -565,6 +583,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: full_command: null handles: {} + placeholder_keys: {} result: {} schema: description: send_command的参数schema @@ -589,6 +608,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: baudrate: null handles: {} + placeholder_keys: {} result: {} schema: description: set_baudrate的参数schema @@ -613,6 +633,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: set_max_velocity的参数schema @@ -638,6 +659,7 @@ syringe_pump_with_valve.runze.SY03B-T06: max_velocity: null position: null handles: {} + placeholder_keys: {} result: {} schema: description: set_position的参数schema @@ -664,6 +686,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: position: null handles: {} + placeholder_keys: {} result: {} schema: description: set_valve_position的参数schema @@ -688,6 +711,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: set_velocity_grade的参数schema @@ -711,6 +735,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: stop_operation的参数schema @@ -731,6 +756,7 @@ syringe_pump_with_valve.runze.SY03B-T06: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_error的参数schema @@ -880,6 +906,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: close的参数schema @@ -900,6 +927,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -921,6 +949,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: volume: null handles: {} + placeholder_keys: {} result: {} schema: description: pull_plunger的参数schema @@ -945,6 +974,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: volume: null handles: {} + placeholder_keys: {} result: {} schema: description: push_plunger的参数schema @@ -968,6 +998,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_aux_input_status_1的参数schema @@ -988,6 +1019,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_aux_input_status_2的参数schema @@ -1008,6 +1040,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_backlash_position的参数schema @@ -1028,6 +1061,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_command_buffer_status的参数schema @@ -1048,6 +1082,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: query_software_version的参数schema @@ -1069,6 +1104,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: full_command: null handles: {} + placeholder_keys: {} result: {} schema: description: send_command的参数schema @@ -1093,6 +1129,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: baudrate: null handles: {} + placeholder_keys: {} result: {} schema: description: set_baudrate的参数schema @@ -1117,6 +1154,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: set_max_velocity的参数schema @@ -1142,6 +1180,7 @@ syringe_pump_with_valve.runze.SY03B-T08: max_velocity: null position: null handles: {} + placeholder_keys: {} result: {} schema: description: set_position的参数schema @@ -1168,6 +1207,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: position: null handles: {} + placeholder_keys: {} result: {} schema: description: set_valve_position的参数schema @@ -1192,6 +1232,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: set_velocity_grade的参数schema @@ -1215,6 +1256,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: stop_operation的参数schema @@ -1235,6 +1277,7 @@ syringe_pump_with_valve.runze.SY03B-T08: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_error的参数schema diff --git a/unilabos/registry/devices/reaction_station_bioyond.yaml b/unilabos/registry/devices/reaction_station_bioyond.yaml index 2dc341a6..675b4a0a 100644 --- a/unilabos/registry/devices/reaction_station_bioyond.yaml +++ b/unilabos/registry/devices/reaction_station_bioyond.yaml @@ -4,6 +4,1083 @@ reaction_station.bioyond: - reaction_station_bioyond class: action_value_mappings: + auto-add_material: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: object + required: + - material_data + type: object + result: {} + required: + - goal + title: add_material参数 + type: object + type: UniLabJsonCommand + auto-create_90_10_vial_feeding_task: + feedback: {} + goal: {} + goal_default: + task_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + task_data: + type: string + required: + - task_data + type: object + result: {} + required: + - goal + title: create_90_10_vial_feeding_task参数 + type: object + type: UniLabJsonCommand + auto-create_batch_90_10_vial_feeding_task: + feedback: {} + goal: {} + goal_default: + batch_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + batch_data: + type: string + required: + - batch_data + type: object + result: {} + required: + - goal + title: create_batch_90_10_vial_feeding_task参数 + type: object + type: UniLabJsonCommand + auto-create_batch_diamine_solution_task: + feedback: {} + goal: {} + goal_default: + batch_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + batch_data: + type: string + required: + - batch_data + type: object + result: {} + required: + - goal + title: create_batch_diamine_solution_task参数 + type: object + type: UniLabJsonCommand + auto-create_diamine_solution_task: + feedback: {} + goal: {} + goal_default: + solution_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + solution_data: + type: string + required: + - solution_data + type: object + result: {} + required: + - goal + title: create_diamine_solution_task参数 + type: object + type: UniLabJsonCommand + auto-create_order: + feedback: {} + goal: {} + goal_default: + parameters: null + task_name: null + workflow_name: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + task_name: + type: string + workflow_name: + type: string + required: + - workflow_name + - task_name + type: object + result: {} + required: + - goal + title: create_order参数 + type: object + type: UniLabJsonCommand + auto-create_resource: + feedback: {} + goal: {} + goal_default: + resource_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + resource_data: + type: string + required: + - resource_data + type: object + result: {} + required: + - goal + title: create_resource参数 + type: object + type: UniLabJsonCommand + auto-delete_material: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: delete_material参数 + type: object + type: UniLabJsonCommand + auto-device_operation: + feedback: {} + goal: {} + goal_default: + device_id: null + operation: null + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + device_id: + type: string + operation: + type: string + parameters: + type: object + required: + - device_id + - operation + type: object + result: {} + required: + - goal + title: device_operation参数 + type: object + type: UniLabJsonCommand + auto-dispensing_material_inbound: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: dispensing_material_inbound参数 + type: object + type: UniLabJsonCommand + auto-dispensing_material_outbound: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: dispensing_material_outbound参数 + type: object + type: UniLabJsonCommand + auto-drip_back: + feedback: {} + goal: {} + goal_default: + assign_material_name: Reactor + temperature: 25.0 + time: '0' + torque_variation: '1' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + default: Reactor + type: string + temperature: + default: 25.0 + type: number + time: + default: '0' + type: string + torque_variation: + default: '1' + type: string + required: [] + type: object + result: {} + required: + - goal + title: drip_back参数 + type: object + type: UniLabJsonCommand + auto-execute_bioyond_sync_workflow: + feedback: {} + goal: {} + goal_default: + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + required: + - parameters + type: object + result: {} + required: + - goal + title: execute_bioyond_sync_workflow参数 + type: object + type: UniLabJsonCommandAsync + auto-execute_bioyond_update_workflow: + feedback: {} + goal: {} + goal_default: + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + required: + - parameters + type: object + result: {} + required: + - goal + title: execute_bioyond_update_workflow参数 + type: object + type: UniLabJsonCommandAsync + auto-liquid_feeding_beaker: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_beaker参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_solvents: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_solvents参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_titration: + feedback: {} + goal: {} + goal_default: + material_name: '' + time: '120' + titration_type: '1' + torque_variation: '2' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + time: + default: '120' + type: string + titration_type: + default: '1' + type: string + torque_variation: + default: '2' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_titration参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_vials_non_titration: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_vials_non_titration参数 + type: object + type: UniLabJsonCommand + auto-load_bioyond_data_from_file: + feedback: {} + goal: {} + goal_default: + file_path: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + file_path: + type: string + required: + - file_path + type: object + result: {} + required: + - goal + title: load_bioyond_data_from_file参数 + type: object + type: UniLabJsonCommand + auto-material_inbound: + feedback: {} + goal: {} + goal_default: + location_name: null + material_id: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location_name: + type: string + material_id: + type: string + required: + - material_id + - location_name + type: object + result: {} + required: + - goal + title: material_inbound参数 + type: object + type: UniLabJsonCommand + auto-material_outbound: + feedback: {} + goal: {} + goal_default: + location_name: null + material_id: null + quantity: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location_name: + type: string + material_id: + type: string + quantity: + type: integer + required: + - material_id + - location_name + - quantity + type: object + result: {} + required: + - goal + title: material_outbound参数 + type: object + type: UniLabJsonCommand + auto-merge_workflow_with_parameters: + feedback: {} + goal: {} + goal_default: + name: null + workflows: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + name: + type: string + workflows: + items: + type: object + type: array + required: + - name + - workflows + type: object + result: {} + required: + - goal + title: merge_workflow_with_parameters参数 + type: object + type: UniLabJsonCommand + auto-order_query: + feedback: {} + goal: {} + goal_default: + query_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + query_data: + type: string + required: + - query_data + type: object + result: {} + required: + - goal + title: order_query参数 + type: object + type: UniLabJsonCommand + auto-post_init: + feedback: {} + goal: {} + goal_default: + ros_node: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + ros_node: + type: object + required: + - ros_node + type: object + result: {} + required: + - goal + title: post_init参数 + type: object + type: UniLabJsonCommand + auto-reactor_taken_in: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: reactor_taken_in参数 + type: object + type: UniLabJsonCommand + auto-reactor_taken_out: + feedback: {} + goal: {} + goal_default: + order_id: '' + preintake_id: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + order_id: + default: '' + type: string + preintake_id: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: reactor_taken_out参数 + type: object + type: UniLabJsonCommand + auto-reset_workstation: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: reset_workstation参数 + type: object + type: UniLabJsonCommand + auto-sample_waste_removal: + feedback: {} + goal: {} + goal_default: + waste_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + waste_data: + type: string + required: + - waste_data + type: object + result: {} + required: + - goal + title: sample_waste_removal参数 + type: object + type: UniLabJsonCommand + auto-solid_feeding_vials: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: solid_feeding_vials参数 + type: object + type: UniLabJsonCommand + auto-start_scheduler: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: start_scheduler参数 + type: object + type: UniLabJsonCommand + auto-stock_material: + feedback: {} + goal: {} + goal_default: + location: null + material_id: null + quantity: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location: + type: string + material_id: + type: string + quantity: + type: integer + required: + - material_id + - location + - quantity + type: object + result: {} + required: + - goal + title: stock_material参数 + type: object + type: UniLabJsonCommand + auto-stop_scheduler: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: stop_scheduler参数 + type: object + type: UniLabJsonCommand + auto-transfer_resource_to_another: + feedback: {} + goal: {} + goal_default: + device_id: null + resource_a: null + resource_b: null + handles: {} + placeholder_keys: + device_id: unilabos_devices + resource_a: unilabos_resources + resource_b: unilabos_resources + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + device_id: + type: object + resource_a: + properties: + category: + type: string + children: + items: + type: string + type: array + config: + type: string + data: + type: string + id: + type: string + name: + type: string + parent: + type: string + pose: + properties: + orientation: + properties: + w: + type: number + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + - w + title: orientation + type: object + position: + properties: + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + title: position + type: object + required: + - position + - orientation + title: pose + type: object + sample_id: + type: string + type: + type: string + required: + - id + - name + - sample_id + - children + - parent + - type + - category + - pose + - config + - data + title: resource_a + type: object + resource_b: + properties: + category: + type: string + children: + items: + type: string + type: array + config: + type: string + data: + type: string + id: + type: string + name: + type: string + parent: + type: string + pose: + properties: + orientation: + properties: + w: + type: number + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + - w + title: orientation + type: object + position: + properties: + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + title: position + type: object + required: + - position + - orientation + title: pose + type: object + sample_id: + type: string + type: + type: string + required: + - id + - name + - sample_id + - children + - parent + - type + - category + - pose + - config + - data + title: resource_b + type: object + required: + - resource_a + - device_id + - resource_b + type: object + result: {} + required: + - goal + title: transfer_resource_to_another参数 + type: object + type: UniLabJsonCommand + auto-validate_workflow_parameters: + feedback: {} + goal: {} + goal_default: + workflows: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + workflows: + items: + type: object + type: array + required: + - workflows + type: object + result: {} + required: + - goal + title: validate_workflow_parameters参数 + type: object + type: UniLabJsonCommand bioyond_sync: feedback: {} goal: @@ -321,9 +1398,11 @@ reaction_station.bioyond: protocol_type: [] status_types: bioyond_status: dict - enable_dispensing_station: bool - enable_reaction_station: bool - station_type: str + device_list: dict + scheduler_status: dict + station_info: dict + workflow_parameter_template: dict + workstation_status: dict type: python config_info: [] description: Bioyond反应站 - 专门用于化学反应操作的工作站 @@ -333,52 +1412,33 @@ reaction_station.bioyond: config: properties: bioyond_config: - description: Bioyond API配置 - properties: - api_host: - description: Bioyond API主机地址 - type: string - api_key: - description: Bioyond API密钥 - type: string - material_type_mappings: - description: 物料类型映射配置 - type: object - workflow_mappings: - description: 工作流映射配置 - type: object - type: object + type: string deck: - description: Deck配置 - type: object + type: string station_config: - description: 反应站配置 - properties: - description: - description: 反应站描述 - type: string - enable_dispensing_station: - default: false - description: 禁用配液站功能 - type: boolean - enable_reaction_station: - default: true - description: 启用反应站功能 - type: boolean - station_name: - description: 反应站名称 - type: string - station_type: - default: reaction_station - description: 站点类型 - 反应站 - enum: - - reaction_station - type: string - type: object + type: string required: [] type: object data: - properties: {} - required: [] + properties: + bioyond_status: + type: object + device_list: + type: object + scheduler_status: + type: object + station_info: + type: object + workflow_parameter_template: + type: object + workstation_status: + type: object + required: + - station_info + - bioyond_status + - workflow_parameter_template + - scheduler_status + - device_list + - workstation_status type: object version: 1.0.0 diff --git a/unilabos/registry/devices/robot_agv.yaml b/unilabos/registry/devices/robot_agv.yaml index 74085b1f..9f45bd5e 100644 --- a/unilabos/registry/devices/robot_agv.yaml +++ b/unilabos/registry/devices/robot_agv.yaml @@ -11,6 +11,7 @@ agv.SEER: ex_data: '' obj: receive_socket handles: {} + placeholder_keys: {} result: {} schema: description: AGV底层通信命令发送函数。通过TCP socket连接向AGV发送底层控制命令,支持pose(位置)、status(状态)、nav(导航)等命令类型。用于获取AGV当前位置坐标、运行状态或发送导航指令。该函数封装了AGV的通信协议,将命令转换为十六进制数据包并处理响应解析。 diff --git a/unilabos/registry/devices/robot_arm.yaml b/unilabos/registry/devices/robot_arm.yaml index b4a48b00..7c049ff7 100644 --- a/unilabos/registry/devices/robot_arm.yaml +++ b/unilabos/registry/devices/robot_arm.yaml @@ -8,6 +8,7 @@ robotic_arm.SCARA_with_slider.virtual: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: check_tf_update_actions的参数schema @@ -33,6 +34,7 @@ robotic_arm.SCARA_with_slider.virtual: retry: 10 speed: 1 handles: {} + placeholder_keys: {} result: {} schema: description: moveit_joint_task的参数schema @@ -78,6 +80,7 @@ robotic_arm.SCARA_with_slider.virtual: speed: 1 target_link: null handles: {} + placeholder_keys: {} result: {} schema: description: moveit_task的参数schema @@ -125,6 +128,7 @@ robotic_arm.SCARA_with_slider.virtual: goal_default: ros_node: null handles: {} + placeholder_keys: {} result: {} schema: description: post_init的参数schema @@ -150,6 +154,7 @@ robotic_arm.SCARA_with_slider.virtual: parent_link: null resource: null handles: {} + placeholder_keys: {} result: {} schema: description: resource_manager的参数schema @@ -176,6 +181,7 @@ robotic_arm.SCARA_with_slider.virtual: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_for_resource_action的参数schema @@ -360,6 +366,7 @@ robotic_arm.UR: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 机械臂初始化函数。执行UR机械臂的完整初始化流程,包括上电、释放制动器、解除保护停止状态等。该函数确保机械臂从安全停止状态恢复到可操作状态,是机械臂使用前的必要步骤。初始化完成后机械臂将处于就绪状态,可以接收后续的运动指令。 @@ -381,6 +388,7 @@ robotic_arm.UR: goal_default: data: null handles: {} + placeholder_keys: {} result: {} schema: description: 从JSON字符串加载位置数据函数。接收包含机械臂位置信息的JSON格式字符串,解析并存储位置数据供后续运动任务使用。位置数据通常包含多个预定义的工作位置坐标,用于实现精确的多点运动控制。适用于动态配置机械臂工作位置的场景。 @@ -405,6 +413,7 @@ robotic_arm.UR: goal_default: file: null handles: {} + placeholder_keys: {} result: {} schema: description: 从文件加载位置数据函数。读取指定的JSON文件并加载其中的机械臂位置信息。该函数支持从外部配置文件中获取预设的工作位置,便于位置数据的管理和重用。适用于需要从固定配置文件中读取复杂位置序列的应用场景。 @@ -428,6 +437,7 @@ robotic_arm.UR: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 重新加载位置数据函数。重新读取并解析之前设置的位置文件,更新内存中的位置数据。该函数用于在位置文件被修改后刷新机械臂的位置配置,无需重新初始化整个系统。适用于动态更新机械臂工作位置的场景。 @@ -536,6 +546,7 @@ robotic_arm.elite: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -556,6 +567,7 @@ robotic_arm.elite: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -579,6 +591,7 @@ robotic_arm.elite: start_addr: null unit_id: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -609,6 +622,7 @@ robotic_arm.elite: goal_default: job_id: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -635,6 +649,7 @@ robotic_arm.elite: unit_id: null value: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -665,6 +680,7 @@ robotic_arm.elite: goal_default: response: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -689,6 +705,7 @@ robotic_arm.elite: goal_default: command: null handles: {} + placeholder_keys: {} result: {} schema: description: '' diff --git a/unilabos/registry/devices/robot_gripper.yaml b/unilabos/registry/devices/robot_gripper.yaml index 0e79395f..295c48a0 100644 --- a/unilabos/registry/devices/robot_gripper.yaml +++ b/unilabos/registry/devices/robot_gripper.yaml @@ -8,6 +8,7 @@ gripper.misumi_rz: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: data_loop的参数schema @@ -28,6 +29,7 @@ gripper.misumi_rz: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: data_reader的参数schema @@ -51,6 +53,7 @@ gripper.misumi_rz: pos: null speed: null handles: {} + placeholder_keys: {} result: {} schema: description: 夹爪抓取运动控制函数。控制夹爪的开合运动,支持位置、速度、力矩的精确设定。位置参数控制夹爪开合程度,速度参数控制运动快慢,力矩参数控制夹持强度。该函数提供安全的力控制,避免损坏被抓取物体,适用于各种形状和材质的物品抓取。 @@ -80,6 +83,7 @@ gripper.misumi_rz: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 夹爪初始化函数。执行Misumi RZ夹爪的完整初始化流程,包括Modbus通信建立、电机参数配置、传感器校准等。该函数确保夹爪系统从安全状态恢复到可操作状态,是夹爪使用前的必要步骤。初始化完成后夹爪将处于就绪状态,可接收抓取和旋转指令。 @@ -101,6 +105,7 @@ gripper.misumi_rz: goal_default: data: null handles: {} + placeholder_keys: {} result: {} schema: description: modbus_crc的参数schema @@ -130,6 +135,7 @@ gripper.misumi_rz: spin_pos: null spin_v: null handles: {} + placeholder_keys: {} result: {} schema: description: move_and_rotate的参数schema @@ -169,6 +175,7 @@ gripper.misumi_rz: goal_default: cmd: null handles: {} + placeholder_keys: {} result: {} schema: description: 节点夹爪移动任务函数。接收逗号分隔的命令字符串,解析位置、速度、力矩参数并执行夹爪抓取动作。该函数等待运动完成并返回执行结果,提供同步的运动控制接口。适用于需要可靠完成确认的精密抓取操作。 @@ -193,6 +200,7 @@ gripper.misumi_rz: goal_default: cmd: null handles: {} + placeholder_keys: {} result: {} schema: description: 节点旋转移动任务函数。接收逗号分隔的命令字符串,解析角度、速度、力矩参数并执行夹爪旋转动作。该函数等待旋转完成并返回执行结果,提供同步的旋转控制接口。适用于需要精确角度定位和完成确认的旋转操作。 @@ -219,6 +227,7 @@ gripper.misumi_rz: data_len: null id: null handles: {} + placeholder_keys: {} result: {} schema: description: read_address的参数schema @@ -251,6 +260,7 @@ gripper.misumi_rz: pos: null speed: null handles: {} + placeholder_keys: {} result: {} schema: description: 夹爪绝对位置旋转控制函数。控制夹爪主轴旋转到指定的绝对角度位置,支持360度连续旋转。位置参数指定目标角度,速度参数控制旋转速率,力矩参数设定旋转阻力限制。该函数提供高精度的角度定位,适用于需要精确方向控制的操作场景。 @@ -284,6 +294,7 @@ gripper.misumi_rz: fun: null id: null handles: {} + placeholder_keys: {} result: {} schema: description: send_cmd的参数schema @@ -316,6 +327,7 @@ gripper.misumi_rz: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_for_gripper的参数schema @@ -336,6 +348,7 @@ gripper.misumi_rz: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_for_gripper_init的参数schema @@ -356,6 +369,7 @@ gripper.misumi_rz: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_for_rotate的参数schema @@ -462,6 +476,7 @@ gripper.mock: Gripper1: {} wf_name: gripper_run handles: {} + placeholder_keys: {} result: {} schema: description: 模拟夹爪资源ID编辑函数。用于测试和演示资源管理功能,模拟修改夹爪资源的标识信息。该函数接收工作流名称、参数和资源对象,模拟真实的资源更新过程并返回修改后的资源信息。适用于系统测试和开发调试场景。 diff --git a/unilabos/registry/devices/robot_linear_motion.yaml b/unilabos/registry/devices/robot_linear_motion.yaml index c789259c..0f8506e9 100644 --- a/unilabos/registry/devices/robot_linear_motion.yaml +++ b/unilabos/registry/devices/robot_linear_motion.yaml @@ -8,6 +8,7 @@ linear_motion.grbl: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: CNC设备初始化函数。执行Grbl CNC的完整初始化流程,包括归零操作、轴校准和状态复位。该函数将所有轴移动到原点位置(0,0,0),确保设备处于已知的参考状态。初始化完成后设备进入空闲状态,可接收后续的运动指令。 @@ -29,6 +30,7 @@ linear_motion.grbl: goal_default: position: null handles: {} + placeholder_keys: {} result: {} schema: description: CNC绝对位置设定函数。控制CNC设备移动到指定的三维坐标位置(x,y,z)。该函数支持安全限位检查,防止超出设备工作范围。移动过程中会监控设备状态,确保安全到达目标位置。适用于精确定位和轨迹控制操作。 @@ -52,6 +54,7 @@ linear_motion.grbl: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: CNC操作停止函数。立即停止当前正在执行的所有CNC运动,包括轴移动和主轴旋转。该函数用于紧急停止或任务中断,确保设备和工件的安全。停止后设备将保持当前位置,等待新的指令。 @@ -72,6 +75,7 @@ linear_motion.grbl: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_error的参数schema @@ -482,6 +486,7 @@ linear_motion.toyo_xyz.sim: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: check_tf_update_actions的参数schema @@ -507,6 +512,7 @@ linear_motion.toyo_xyz.sim: retry: 10 speed: 1 handles: {} + placeholder_keys: {} result: {} schema: description: moveit_joint_task的参数schema @@ -552,6 +558,7 @@ linear_motion.toyo_xyz.sim: speed: 1 target_link: null handles: {} + placeholder_keys: {} result: {} schema: description: moveit_task的参数schema @@ -599,6 +606,7 @@ linear_motion.toyo_xyz.sim: goal_default: ros_node: null handles: {} + placeholder_keys: {} result: {} schema: description: post_init的参数schema @@ -624,6 +632,7 @@ linear_motion.toyo_xyz.sim: parent_link: null resource: null handles: {} + placeholder_keys: {} result: {} schema: description: resource_manager的参数schema @@ -650,6 +659,7 @@ linear_motion.toyo_xyz.sim: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: wait_for_resource_action的参数schema @@ -837,6 +847,7 @@ motor.iCL42: position: null velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: 步进电机执行运动函数。直接执行电机运动命令,包括位置设定、速度控制和路径规划。该函数处理底层的电机控制协议,消除警告信息,设置运动参数并启动电机运行。适用于需要直接控制电机运动的应用场景。 @@ -866,6 +877,7 @@ motor.iCL42: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: iCL42电机设备初始化函数。建立与iCL42步进电机驱动器的串口通信连接,配置通信参数包括波特率、数据位、校验位等。该函数是电机使用前的必要步骤,确保驱动器处于可控状态并准备接收运动指令。 @@ -889,6 +901,7 @@ motor.iCL42: position: null velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: 步进电机运动控制函数。根据指定的运动模式、目标位置和速度参数控制电机运动。支持多种运动模式和精确的位置控制,自动处理运动轨迹规划和执行。该函数提供异步执行和状态反馈,确保运动的准确性和可靠性。 diff --git a/unilabos/registry/devices/solid_dispenser.yaml b/unilabos/registry/devices/solid_dispenser.yaml index 42cabec1..9bceb54b 100644 --- a/unilabos/registry/devices/solid_dispenser.yaml +++ b/unilabos/registry/devices/solid_dispenser.yaml @@ -65,6 +65,7 @@ solid_dispenser.laiyu: goal_default: data: null handles: {} + placeholder_keys: {} result: {} schema: description: Modbus CRC-16校验码计算函数。计算Modbus RTU通信协议所需的CRC-16校验码,确保数据传输的完整性和可靠性。该函数实现标准的CRC-16算法,用于构造完整的Modbus指令帧。 @@ -89,6 +90,7 @@ solid_dispenser.laiyu: goal_default: command: null handles: {} + placeholder_keys: {} result: {} schema: description: Modbus指令发送函数。构造完整的Modbus RTU指令帧(包含CRC校验),发送给分装设备并等待响应。该函数处理底层通信协议,确保指令的正确传输和响应接收,支持最长3分钟的响应等待时间。 diff --git a/unilabos/registry/devices/temperature.yaml b/unilabos/registry/devices/temperature.yaml index bb717b56..874fe517 100644 --- a/unilabos/registry/devices/temperature.yaml +++ b/unilabos/registry/devices/temperature.yaml @@ -12,6 +12,7 @@ chiller: register_address: null value: null handles: {} + placeholder_keys: {} result: {} schema: description: build_modbus_frame的参数schema @@ -46,6 +47,7 @@ chiller: decimal_points: 1 temperature: null handles: {} + placeholder_keys: {} result: {} schema: description: convert_temperature_to_modbus_value的参数schema @@ -73,6 +75,7 @@ chiller: goal_default: data: null handles: {} + placeholder_keys: {} result: {} schema: description: modbus_crc的参数schema @@ -96,6 +99,7 @@ chiller: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: stop的参数schema @@ -188,6 +192,7 @@ heaterstirrer.dalong: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: close的参数schema @@ -209,6 +214,7 @@ heaterstirrer.dalong: goal_default: speed: null handles: {} + placeholder_keys: {} result: {} schema: description: set_stir_speed的参数schema @@ -234,6 +240,7 @@ heaterstirrer.dalong: temp: null type: warning handles: {} + placeholder_keys: {} result: {} schema: description: set_temp_inner的参数schema @@ -580,6 +587,7 @@ tempsensor: register_address: null register_count: null handles: {} + placeholder_keys: {} result: {} schema: description: build_modbus_request的参数schema @@ -613,6 +621,7 @@ tempsensor: goal_default: data: null handles: {} + placeholder_keys: {} result: {} schema: description: calculate_crc的参数schema @@ -637,6 +646,7 @@ tempsensor: goal_default: response: null handles: {} + placeholder_keys: {} result: {} schema: description: read_modbus_response的参数schema @@ -661,6 +671,7 @@ tempsensor: goal_default: command: null handles: {} + placeholder_keys: {} result: {} schema: description: send_prototype_command的参数schema diff --git a/unilabos/registry/devices/virtual_device.yaml b/unilabos/registry/devices/virtual_device.yaml index f94bdad5..18575821 100644 --- a/unilabos/registry/devices/virtual_device.yaml +++ b/unilabos/registry/devices/virtual_device.yaml @@ -8,6 +8,7 @@ virtual_centrifuge: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -28,6 +29,7 @@ virtual_centrifuge: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -296,6 +298,7 @@ virtual_column: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -316,6 +319,7 @@ virtual_column: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -691,6 +695,7 @@ virtual_filter: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -711,6 +716,7 @@ virtual_filter: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -1089,6 +1095,7 @@ virtual_gas_source: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -1109,6 +1116,7 @@ virtual_gas_source: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -1129,6 +1137,7 @@ virtual_gas_source: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -1149,6 +1158,7 @@ virtual_gas_source: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_open的参数schema @@ -1311,6 +1321,7 @@ virtual_heatchill: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -1331,6 +1342,7 @@ virtual_heatchill: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -1880,6 +1892,7 @@ virtual_multiway_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: close的参数schema @@ -1901,6 +1914,7 @@ virtual_multiway_valve: goal_default: port_number: null handles: {} + placeholder_keys: {} result: {} schema: description: is_at_port的参数schema @@ -1925,6 +1939,7 @@ virtual_multiway_valve: goal_default: position: null handles: {} + placeholder_keys: {} result: {} schema: description: is_at_position的参数schema @@ -1948,6 +1963,7 @@ virtual_multiway_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_at_pump_position的参数schema @@ -1968,6 +1984,7 @@ virtual_multiway_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -1988,6 +2005,7 @@ virtual_multiway_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: reset的参数schema @@ -2009,6 +2027,7 @@ virtual_multiway_valve: goal_default: port_number: null handles: {} + placeholder_keys: {} result: {} schema: description: set_to_port的参数schema @@ -2032,6 +2051,7 @@ virtual_multiway_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: set_to_pump_position的参数schema @@ -2053,6 +2073,7 @@ virtual_multiway_valve: goal_default: port_number: null handles: {} + placeholder_keys: {} result: {} schema: description: switch_between_pump_and_port的参数schema @@ -2300,6 +2321,7 @@ virtual_rotavap: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -2320,6 +2342,7 @@ virtual_rotavap: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -2630,6 +2653,7 @@ virtual_separator: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -2650,6 +2674,7 @@ virtual_separator: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -3517,6 +3542,7 @@ virtual_solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -3537,6 +3563,7 @@ virtual_solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -3557,6 +3584,7 @@ virtual_solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -3577,6 +3605,7 @@ virtual_solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: reset的参数schema @@ -3597,6 +3626,7 @@ virtual_solenoid_valve: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: toggle的参数schema @@ -4035,6 +4065,7 @@ virtual_solid_dispenser: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -4056,6 +4087,7 @@ virtual_solid_dispenser: goal_default: reagent_name: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -4079,6 +4111,7 @@ virtual_solid_dispenser: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -4100,6 +4133,7 @@ virtual_solid_dispenser: goal_default: mass_str: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -4124,6 +4158,7 @@ virtual_solid_dispenser: goal_default: mol_str: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -4206,6 +4241,7 @@ virtual_stirrer: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -4226,6 +4262,7 @@ virtual_stirrer: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -4777,6 +4814,7 @@ virtual_transfer_pump: velocity: null volume: null handles: {} + placeholder_keys: {} result: {} schema: description: aspirate的参数schema @@ -4802,6 +4840,7 @@ virtual_transfer_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -4824,6 +4863,7 @@ virtual_transfer_pump: velocity: null volume: null handles: {} + placeholder_keys: {} result: {} schema: description: dispense的参数schema @@ -4850,6 +4890,7 @@ virtual_transfer_pump: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: empty_syringe的参数schema @@ -4873,6 +4914,7 @@ virtual_transfer_pump: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: fill_syringe的参数schema @@ -4895,6 +4937,7 @@ virtual_transfer_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -4915,6 +4958,7 @@ virtual_transfer_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_empty的参数schema @@ -4935,6 +4979,7 @@ virtual_transfer_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_full的参数schema @@ -4957,6 +5002,7 @@ virtual_transfer_pump: velocity: null volume: null handles: {} + placeholder_keys: {} result: {} schema: description: pull_plunger的参数schema @@ -4984,6 +5030,7 @@ virtual_transfer_pump: velocity: null volume: null handles: {} + placeholder_keys: {} result: {} schema: description: push_plunger的参数schema @@ -5010,6 +5057,7 @@ virtual_transfer_pump: goal_default: velocity: null handles: {} + placeholder_keys: {} result: {} schema: description: set_max_velocity的参数schema @@ -5033,6 +5081,7 @@ virtual_transfer_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: stop_operation的参数schema @@ -5277,6 +5326,7 @@ virtual_vacuum_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: cleanup的参数schema @@ -5297,6 +5347,7 @@ virtual_vacuum_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: initialize的参数schema @@ -5317,6 +5368,7 @@ virtual_vacuum_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_closed的参数schema @@ -5337,6 +5389,7 @@ virtual_vacuum_pump: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: is_open的参数schema diff --git a/unilabos/registry/devices/work_station.yaml b/unilabos/registry/devices/work_station.yaml index 48054810..640824b9 100644 --- a/unilabos/registry/devices/work_station.yaml +++ b/unilabos/registry/devices/work_station.yaml @@ -6049,12 +6049,339 @@ workstation.bioyond: - work_station class: action_value_mappings: + auto-add_material: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: object + required: + - material_data + type: object + result: {} + required: + - goal + title: add_material参数 + type: object + type: UniLabJsonCommand + auto-create_90_10_vial_feeding_task: + feedback: {} + goal: {} + goal_default: + task_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + task_data: + type: string + required: + - task_data + type: object + result: {} + required: + - goal + title: create_90_10_vial_feeding_task参数 + type: object + type: UniLabJsonCommand + auto-create_batch_90_10_vial_feeding_task: + feedback: {} + goal: {} + goal_default: + batch_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + batch_data: + type: string + required: + - batch_data + type: object + result: {} + required: + - goal + title: create_batch_90_10_vial_feeding_task参数 + type: object + type: UniLabJsonCommand + auto-create_batch_diamine_solution_task: + feedback: {} + goal: {} + goal_default: + batch_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + batch_data: + type: string + required: + - batch_data + type: object + result: {} + required: + - goal + title: create_batch_diamine_solution_task参数 + type: object + type: UniLabJsonCommand + auto-create_diamine_solution_task: + feedback: {} + goal: {} + goal_default: + solution_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + solution_data: + type: string + required: + - solution_data + type: object + result: {} + required: + - goal + title: create_diamine_solution_task参数 + type: object + type: UniLabJsonCommand + auto-create_order: + feedback: {} + goal: {} + goal_default: + parameters: null + task_name: null + workflow_name: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + parameters: + type: object + task_name: + type: string + workflow_name: + type: string + required: + - workflow_name + - task_name + type: object + result: {} + required: + - goal + title: create_order参数 + type: object + type: UniLabJsonCommand + auto-create_resource: + feedback: {} + goal: {} + goal_default: + resource_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + resource_data: + type: string + required: + - resource_data + type: object + result: {} + required: + - goal + title: create_resource参数 + type: object + type: UniLabJsonCommand + auto-delete_material: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: delete_material参数 + type: object + type: UniLabJsonCommand + auto-device_operation: + feedback: {} + goal: {} + goal_default: + device_id: null + operation: null + parameters: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + device_id: + type: string + operation: + type: string + parameters: + type: object + required: + - device_id + - operation + type: object + result: {} + required: + - goal + title: device_operation参数 + type: object + type: UniLabJsonCommand + auto-dispensing_material_inbound: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: dispensing_material_inbound参数 + type: object + type: UniLabJsonCommand + auto-dispensing_material_outbound: + feedback: {} + goal: {} + goal_default: + material_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_data: + type: string + required: + - material_data + type: object + result: {} + required: + - goal + title: dispensing_material_outbound参数 + type: object + type: UniLabJsonCommand + auto-drip_back: + feedback: {} + goal: {} + goal_default: + assign_material_name: Reactor + temperature: 25.0 + time: '0' + torque_variation: '1' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + default: Reactor + type: string + temperature: + default: 25.0 + type: number + time: + default: '0' + type: string + torque_variation: + default: '1' + type: string + required: [] + type: object + result: {} + required: + - goal + title: drip_back参数 + type: object + type: UniLabJsonCommand auto-execute_bioyond_sync_workflow: feedback: {} goal: {} goal_default: parameters: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -6079,6 +6406,7 @@ workstation.bioyond: goal_default: parameters: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -6097,12 +6425,141 @@ workstation.bioyond: title: execute_bioyond_update_workflow参数 type: object type: UniLabJsonCommandAsync + auto-liquid_feeding_beaker: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_beaker参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_solvents: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_solvents参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_titration: + feedback: {} + goal: {} + goal_default: + material_name: '' + time: '120' + titration_type: '1' + torque_variation: '2' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + time: + default: '120' + type: string + titration_type: + default: '1' + type: string + torque_variation: + default: '2' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_titration参数 + type: object + type: UniLabJsonCommand + auto-liquid_feeding_vials_non_titration: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: liquid_feeding_vials_non_titration参数 + type: object + type: UniLabJsonCommand auto-load_bioyond_data_from_file: feedback: {} goal: {} goal_default: file_path: null handles: {} + placeholder_keys: {} result: {} schema: description: '' @@ -6121,8 +6578,768 @@ workstation.bioyond: title: load_bioyond_data_from_file参数 type: object type: UniLabJsonCommand + auto-material_inbound: + feedback: {} + goal: {} + goal_default: + location_name: null + material_id: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location_name: + type: string + material_id: + type: string + required: + - material_id + - location_name + type: object + result: {} + required: + - goal + title: material_inbound参数 + type: object + type: UniLabJsonCommand + auto-material_outbound: + feedback: {} + goal: {} + goal_default: + location_name: null + material_id: null + quantity: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location_name: + type: string + material_id: + type: string + quantity: + type: integer + required: + - material_id + - location_name + - quantity + type: object + result: {} + required: + - goal + title: material_outbound参数 + type: object + type: UniLabJsonCommand + auto-merge_workflow_with_parameters: + feedback: {} + goal: {} + goal_default: + name: null + workflows: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + name: + type: string + workflows: + items: + type: object + type: array + required: + - name + - workflows + type: object + result: {} + required: + - goal + title: merge_workflow_with_parameters参数 + type: object + type: UniLabJsonCommand + auto-order_query: + feedback: {} + goal: {} + goal_default: + query_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + query_data: + type: string + required: + - query_data + type: object + result: {} + required: + - goal + title: order_query参数 + type: object + type: UniLabJsonCommand + auto-post_init: + feedback: {} + goal: {} + goal_default: + ros_node: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + ros_node: + type: object + required: + - ros_node + type: object + result: {} + required: + - goal + title: post_init参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_drip_back: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + time: null + torque_variation: null + volume: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + time: + type: string + torque_variation: + type: string + volume: + type: string + required: + - volume + - assign_material_name + - time + - torque_variation + type: object + result: {} + required: + - goal + title: reaction_station_drip_back参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_liquid_feed: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + time: null + titration_type: null + torque_variation: null + volume: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + time: + type: string + titration_type: + type: string + torque_variation: + type: string + volume: + type: string + required: + - titration_type + - volume + - assign_material_name + - time + - torque_variation + type: object + result: {} + required: + - goal + title: reaction_station_liquid_feed参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_process_execute: + feedback: {} + goal: {} + goal_default: + task_name: null + workflow_name: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + task_name: + type: string + workflow_name: + type: string + required: + - workflow_name + - task_name + type: object + result: {} + required: + - goal + title: reaction_station_process_execute参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_reactor_taken_out: + feedback: {} + goal: {} + goal_default: + order_id: '' + preintake_id: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + order_id: + default: '' + type: string + preintake_id: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: reaction_station_reactor_taken_out参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_solid_feed_vial: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + material_id: null + time: null + torque_variation: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + material_id: + type: string + time: + type: string + torque_variation: + type: string + required: + - assign_material_name + - material_id + - time + - torque_variation + type: object + result: {} + required: + - goal + title: reaction_station_solid_feed_vial参数 + type: object + type: UniLabJsonCommand + auto-reaction_station_take_in: + feedback: {} + goal: {} + goal_default: + assign_material_name: null + cutoff: null + temperature: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + assign_material_name: + type: string + cutoff: + type: string + temperature: + type: string + required: + - cutoff + - temperature + - assign_material_name + type: object + result: {} + required: + - goal + title: reaction_station_take_in参数 + type: object + type: UniLabJsonCommand + auto-reactor_taken_in: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: reactor_taken_in参数 + type: object + type: UniLabJsonCommand + auto-reactor_taken_out: + feedback: {} + goal: {} + goal_default: + order_id: '' + preintake_id: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + order_id: + default: '' + type: string + preintake_id: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: reactor_taken_out参数 + type: object + type: UniLabJsonCommand + auto-reset_workstation: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: reset_workstation参数 + type: object + type: UniLabJsonCommand + auto-sample_waste_removal: + feedback: {} + goal: {} + goal_default: + waste_data: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + waste_data: + type: string + required: + - waste_data + type: object + result: {} + required: + - goal + title: sample_waste_removal参数 + type: object + type: UniLabJsonCommand + auto-solid_feeding_vials: + feedback: {} + goal: {} + goal_default: + material_name: '' + volume: '' + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + material_name: + default: '' + type: string + volume: + default: '' + type: string + required: [] + type: object + result: {} + required: + - goal + title: solid_feeding_vials参数 + type: object + type: UniLabJsonCommand + auto-start_scheduler: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: start_scheduler参数 + type: object + type: UniLabJsonCommand + auto-stock_material: + feedback: {} + goal: {} + goal_default: + location: null + material_id: null + quantity: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + location: + type: string + material_id: + type: string + quantity: + type: integer + required: + - material_id + - location + - quantity + type: object + result: {} + required: + - goal + title: stock_material参数 + type: object + type: UniLabJsonCommand + auto-stop_scheduler: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: stop_scheduler参数 + type: object + type: UniLabJsonCommand + auto-transfer_resource_to_another: + feedback: {} + goal: {} + goal_default: + device_id: null + resource_a: null + resource_b: null + handles: {} + placeholder_keys: + device_id: unilabos_devices + resource_a: unilabos_resources + resource_b: unilabos_resources + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + device_id: + type: object + resource_a: + properties: + category: + type: string + children: + items: + type: string + type: array + config: + type: string + data: + type: string + id: + type: string + name: + type: string + parent: + type: string + pose: + properties: + orientation: + properties: + w: + type: number + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + - w + title: orientation + type: object + position: + properties: + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + title: position + type: object + required: + - position + - orientation + title: pose + type: object + sample_id: + type: string + type: + type: string + required: + - id + - name + - sample_id + - children + - parent + - type + - category + - pose + - config + - data + title: resource_a + type: object + resource_b: + properties: + category: + type: string + children: + items: + type: string + type: array + config: + type: string + data: + type: string + id: + type: string + name: + type: string + parent: + type: string + pose: + properties: + orientation: + properties: + w: + type: number + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + - w + title: orientation + type: object + position: + properties: + x: + type: number + y: + type: number + z: + type: number + required: + - x + - y + - z + title: position + type: object + required: + - position + - orientation + title: pose + type: object + sample_id: + type: string + type: + type: string + required: + - id + - name + - sample_id + - children + - parent + - type + - category + - pose + - config + - data + title: resource_b + type: object + required: + - resource_a + - device_id + - resource_b + type: object + result: {} + required: + - goal + title: transfer_resource_to_another参数 + type: object + type: UniLabJsonCommand + auto-validate_workflow_parameters: + feedback: {} + goal: {} + goal_default: + workflows: null + handles: {} + placeholder_keys: {} + result: {} + schema: + description: '' + properties: + feedback: {} + goal: + properties: + workflows: + items: + type: object + type: array + required: + - workflows + type: object + result: {} + required: + - goal + title: validate_workflow_parameters参数 + type: object + type: UniLabJsonCommand module: unilabos.devices.workstation.bioyond_studio.station:BioyondWorkstation - status_types: {} + status_types: + bioyond_status: dict + device_list: dict + scheduler_status: dict + station_info: dict + workflow_parameter_template: dict + workstation_status: dict type: python config_info: [] description: '' @@ -6135,10 +7352,30 @@ workstation.bioyond: type: string deck: type: string + station_config: + type: string required: [] type: object data: - properties: {} - required: [] + properties: + bioyond_status: + type: object + device_list: + type: object + scheduler_status: + type: object + station_info: + type: object + workflow_parameter_template: + type: object + workstation_status: + type: object + required: + - station_info + - bioyond_status + - workflow_parameter_template + - scheduler_status + - device_list + - workstation_status type: object version: 1.0.0 diff --git a/unilabos/registry/devices/zhida_gcms.yaml b/unilabos/registry/devices/zhida_gcms.yaml index 66f53822..607af9b9 100644 --- a/unilabos/registry/devices/zhida_gcms.yaml +++ b/unilabos/registry/devices/zhida_gcms.yaml @@ -40,6 +40,7 @@ zhida_gcms: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 安全关闭与智达 GCMS 设备的 TCP 连接,释放网络资源。 @@ -60,6 +61,7 @@ zhida_gcms: goal: {} goal_default: {} handles: {} + placeholder_keys: {} result: {} schema: description: 与智达 GCMS 设备建立 TCP 连接,配置超时参数。 @@ -81,6 +83,7 @@ zhida_gcms: goal_default: ros_node: null handles: {} + placeholder_keys: {} result: {} schema: description: '' diff --git a/unilabos/registry/placeholder_type.py b/unilabos/registry/placeholder_type.py new file mode 100644 index 00000000..7a476dd0 --- /dev/null +++ b/unilabos/registry/placeholder_type.py @@ -0,0 +1,9 @@ +from pylabrobot.resources import Resource + + +class ResourceSlot(Resource): + pass + + +class DeviceSlot(str): + pass diff --git a/unilabos/registry/registry.py b/unilabos/registry/registry.py index adc9c5c4..fa18459b 100644 --- a/unilabos/registry/registry.py +++ b/unilabos/registry/registry.py @@ -7,11 +7,14 @@ import importlib from pathlib import Path from typing import Any, Dict, List, Union, Tuple +import msgcenterpy import yaml +from unilabos_msgs.msg import Resource from unilabos.config.config import BasicConfig from unilabos.resources.graphio import resource_plr_to_ulab, tree_to_list -from unilabos.ros.msgs.message_converter import msg_converter_manager, ros_action_to_json_schema, String +from unilabos.ros.msgs.message_converter import msg_converter_manager, ros_action_to_json_schema, String, \ + ros_message_to_json_schema from unilabos.utils import logger from unilabos.utils.decorator import singleton from unilabos.utils.import_manager import get_enhanced_class_info, get_class @@ -426,7 +429,10 @@ class Registry: param_type = arg_info.get("type", "") param_default = arg_info.get("default") param_required = arg_info.get("required", True) - schema["properties"][param_name] = self._generate_schema_from_info(param_name, param_type, param_default) + if param_type == "unilabos.registry.placeholder_type:ResourceSlot": + schema["properties"][param_name] = ros_message_to_json_schema(Resource, param_name) + else: + schema["properties"][param_name] = self._generate_schema_from_info(param_name, param_type, param_default) if param_required: schema["required"].append(param_name) @@ -536,13 +542,17 @@ class Registry: "schema": self._generate_unilab_json_command_schema(v["args"], k), "goal_default": {i["name"]: i["default"] for i in v["args"]}, "handles": [], + "placeholder_keys": { + i["name"]: "unilabos_resources" if i["type"] == "unilabos.registry.placeholder_type:ResourceSlot" else "unilabos_devices" + for i in v["args"] + if i.get("type", "") in ["unilabos.registry.placeholder_type:ResourceSlot", "unilabos.registry.placeholder_type:DeviceSlot"] + } } # 不生成已配置action的动作 for k, v in enhanced_info["action_methods"].items() if k not in device_config["class"]["action_value_mappings"] } ) - # 恢复原有的description信息(auto开头的不修改) for action_name, description in old_descriptions.items(): if action_name in device_config["class"]["action_value_mappings"]: # 有一些会被删除 diff --git a/unilabos/registry/resources/bioyond/deck.yaml b/unilabos/registry/resources/bioyond/deck.yaml index cb655126..d5a49b84 100644 --- a/unilabos/registry/resources/bioyond/deck.yaml +++ b/unilabos/registry/resources/bioyond/deck.yaml @@ -1,15 +1,3 @@ -BIOYOND_PolymerReactionStation_Deck: - category: - - deck - class: - module: unilabos.resources.bioyond.decks:BIOYOND_PolymerReactionStation_Deck - type: pylabrobot - description: BIOYOND PolymerReactionStation Deck - handles: [] - icon: '反应站.webp' - init_param_schema: {} - registry_type: resource - version: 1.0.0 BIOYOND_PolymerPreparationStation_Deck: category: - deck @@ -18,7 +6,19 @@ BIOYOND_PolymerPreparationStation_Deck: type: pylabrobot description: BIOYOND PolymerPreparationStation Deck handles: [] - icon: '配液站.webp' + icon: 配液站.webp + init_param_schema: {} + registry_type: resource + version: 1.0.0 +BIOYOND_PolymerReactionStation_Deck: + category: + - deck + class: + module: unilabos.resources.bioyond.decks:BIOYOND_PolymerReactionStation_Deck + type: pylabrobot + description: BIOYOND PolymerReactionStation Deck + handles: [] + icon: 反应站.webp init_param_schema: {} registry_type: resource version: 1.0.0 diff --git a/unilabos/resources/graphio.py b/unilabos/resources/graphio.py index cca2c9f2..797f6e17 100644 --- a/unilabos/resources/graphio.py +++ b/unilabos/resources/graphio.py @@ -9,10 +9,7 @@ from unilabos_msgs.msg import Resource from unilabos.resources.container import RegularContainer from unilabos.ros.msgs.message_converter import convert_to_ros_msg -from unilabos.ros.nodes.resource_tracker import ( - ResourceDictInstance, - ResourceTreeSet, -) +from unilabos.ros.nodes.resource_tracker import ResourceTreeSet from unilabos.utils.banner_print import print_status try: @@ -54,57 +51,24 @@ def canonicalize_nodes_data( if child in id2idx: nodes[id2idx[child]]["parent"] = parent - # 第三步:使用 ResourceInstanceDictFlatten 标准化每个节点 - standardized_instances = [] - known_nodes: Dict[str, ResourceDictInstance] = {} # {node_id: ResourceDictInstance} - uuid_to_instance: Dict[str, ResourceDictInstance] = {} # {uuid: ResourceDictInstance} - + # 第三步:打印节点信息(用于调试) for node in nodes: try: print_status(f"DeviceId: {node['id']}, Class: {node['class']}", "info") - # 使用标准化方法 - resource_instance = ResourceDictInstance.get_resource_instance_from_dict(node) - known_nodes[node["id"]] = resource_instance - uuid_to_instance[resource_instance.res_content.uuid] = resource_instance - standardized_instances.append(resource_instance) except Exception as e: - print_status(f"Failed to standardize node {node.get('id', 'unknown')}:\n{traceback.format_exc()}", "error") - continue + print_status(f"Failed to read node {node.get('id', 'unknown')}: {e}", "error") - # 第四步:建立 parent 和 children 关系 - for node in nodes: - node_id = node["id"] - if node_id not in known_nodes: - continue + # 第四步:使用 from_raw_list 创建 ResourceTreeSet(自动处理标准化、parent-children关系) + try: + resource_tree_set = ResourceTreeSet.from_raw_list(nodes) + except Exception as e: + print_status(f"Failed to create ResourceTreeSet:\n{traceback.format_exc()}", "error") + raise - current_instance = known_nodes[node_id] - - # 优先使用 parent_uuid 进行匹配,如果不存在则使用 parent - parent_uuid = node.get("parent_uuid") - parent_id = node.get("parent") - parent_instance = None - - # 优先用 parent_uuid 匹配 - if parent_uuid and parent_uuid in uuid_to_instance: - parent_instance = uuid_to_instance[parent_uuid] - # 否则用 parent_id 匹配 - elif parent_id and parent_id in known_nodes: - parent_instance = known_nodes[parent_id] - - # 设置 parent 引用 - if parent_instance: - current_instance.res_content.parent = parent_instance.res_content - # 将当前节点添加到父节点的 children 列表 - parent_instance.children.append(current_instance) - - # 第五步:创建 ResourceTreeSet - resource_tree_set = ResourceTreeSet.from_nested_list(standardized_instances) return resource_tree_set -def canonicalize_links_ports( - links: List[Dict[str, Any]], resource_tree_set: ResourceTreeSet -) -> List[Dict[str, Any]]: +def canonicalize_links_ports(links: List[Dict[str, Any]], resource_tree_set: ResourceTreeSet) -> List[Dict[str, Any]]: """ 标准化边/连接的端口信息 @@ -593,18 +557,24 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict = plr_materials = [] for material in bioyond_materials: - className = type_mapping.get(material.get("typeName"), "RegularContainer") if type_mapping else "RegularContainer" + className = ( + type_mapping.get(material.get("typeName"), "RegularContainer") if type_mapping else "RegularContainer" + ) - plr_material: ResourcePLR = initialize_resource({"name": material["name"], "class": className}, resource_type=ResourcePLR) + plr_material: ResourcePLR = initialize_resource( + {"name": material["name"], "class": className}, resource_type=ResourcePLR + ) plr_material.code = material.get("code", "") and material.get("barCode", "") or "" # 处理子物料(detail) if material.get("detail") and len(material["detail"]) > 0: child_ids = [] for detail in material["detail"]: - number = (detail.get("z", 0) - 1) * plr_material.num_items_x * plr_material.num_items_y + \ - (detail.get("x", 0) - 1) * plr_material.num_items_x + \ - (detail.get("y", 0) - 1) + number = ( + (detail.get("z", 0) - 1) * plr_material.num_items_x * plr_material.num_items_y + + (detail.get("x", 0) - 1) * plr_material.num_items_x + + (detail.get("y", 0) - 1) + ) bottle = plr_material[number] bottle.code = detail.get("code", "") bottle.tracker.liquids = [ @@ -617,9 +587,11 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict = for loc in material.get("locations", []): if hasattr(deck, "warehouses") and loc.get("whName") in deck.warehouses: warehouse = deck.warehouses[loc["whName"]] - idx = (loc.get("y", 0) - 1) * warehouse.num_items_x * warehouse.num_items_y + \ - (loc.get("x", 0) - 1) * warehouse.num_items_x + \ - (loc.get("z", 0) - 1) + idx = ( + (loc.get("y", 0) - 1) * warehouse.num_items_x * warehouse.num_items_y + + (loc.get("x", 0) - 1) * warehouse.num_items_x + + (loc.get("z", 0) - 1) + ) if 0 <= idx < warehouse.capacity: if warehouse[idx] is None or isinstance(warehouse[idx], ResourceHolder): warehouse[idx] = plr_material diff --git a/unilabos/ros/nodes/base_device_node.py b/unilabos/ros/nodes/base_device_node.py index d5c4a30d..c3b96065 100644 --- a/unilabos/ros/nodes/base_device_node.py +++ b/unilabos/ros/nodes/base_device_node.py @@ -345,111 +345,6 @@ class BaseROS2DeviceNode(Node, Generic[T]): res.response = "" return res - async def s2c_resource_tree(req: SerialCommand_Request, res: SerialCommand_Response): - """ - 处理资源树更新请求 - - 支持三种操作: - - add: 添加新资源到资源树 - - update: 更新现有资源 - - remove: 从资源树中移除资源 - """ - try: - data = json.loads(req.command) - results = [] - - for i in data: - action = i.get("action") # remove, add, update - resources_uuid: List[str] = i.get("data") # 资源数据 - self.lab_logger().info( - f"[Resource Tree Update] Processing {action} operation, " - f"resources count: {len(resources_uuid)}" - ) - tree_set = None - if action in ["add", "update"]: - response: SerialCommand.Response = await self._resource_clients[ - "c2s_update_resource_tree" - ].call_async( - SerialCommand.Request( - command=json.dumps( - {"data": {"data": resources_uuid, "with_children": False}, "action": "get"} - ) - ) - ) # type: ignore - raw_nodes = json.loads(response.response) - nodes = [ResourceDictInstance.get_resource_instance_from_dict(n) for n in raw_nodes] - uuids_to_nodes = {u["uuid"]: n for u, n in zip(raw_nodes, nodes)} - for u, n in zip(raw_nodes, nodes): - n.res_content.parent = uuids_to_nodes.get(u["parent_uuid"]).res_content if u["parent_uuid"] in uuids_to_nodes else None - print(n.res_content.parent) - tree_set = ResourceTreeSet.from_nested_list(nodes) - try: - if action == "add": - # 添加资源到资源跟踪器 - plr_resources = tree_set.to_plr_resources() - for plr_resource, tree in zip(plr_resources, tree_set.trees): - self.resource_tracker.add_resource(plr_resource) - parent_uuid = tree.root_node.res_content.parent_uuid - if parent_uuid: - parent_resource: ResourcePLR = self.resource_tracker.uuid_to_resources.get(parent_uuid) - if parent_resource is None: - self.lab_logger().warning(f"物料{plr_resource}请求挂载{tree.root_node.res_content.name}的父节点{parent_uuid}不存在") - else: - try: - parent_resource.assign_child_resource(plr_resource, location=None) - except Exception as e: - self.lab_logger().warning( - f"物料{plr_resource}请求挂载{tree.root_node.res_content.name}的父节点{parent_resource}[{parent_uuid}]失败!\n{traceback.format_exc()}") - func = getattr(self.driver_instance, "resource_tree_add", None) - if callable(func): - func(plr_resources) - results.append({"success": True, "action": "add"}) - elif action == "update": - # 更新资源 - plr_resources = tree_set.to_plr_resources() - for plr_resource, tree in zip(plr_resources, tree_set.trees): - states = plr_resource.serialize_all_state() - original_instance: ResourcePLR = self.resource_tracker.figure_resource({"uuid": tree.root_node.res_content.uuid}, try_mode=False) - original_instance.load_all_state(states) - self.lab_logger().info(f"更新了资源属性 {plr_resource}[{tree.root_node.res_content.uuid}] 及其子节点 {len(original_instance.get_all_children())} 个") - - func = getattr(self.driver_instance, "resource_tree_update", None) - if callable(func): - func(tree_set) - results.append({"success": True, "action": "update"}) - elif action == "remove": - # 移除资源 - func = getattr(self.driver_instance, "resource_tree_remove", None) - if callable(func): - resources_instances: List[ResourcePLR] = [self.resource_tracker.uuid_to_resources[i] for - i in resources_uuid] - self.resource_tracker.add_resource() - [r.parent.unassign_child_resource(r) for r in resources_instances if r is not None] - func(resources_instances) - [r.parent.unassign_child_resource(r) for r in resources_instances if r is not None] - results.append({"success": True, "action": "remove"}) - except Exception as e: - error_msg = f"Error processing {action} operation: {str(e)}" - self.lab_logger().error(f"[Resource Tree Update] {error_msg}") - self.lab_logger().error(traceback.format_exc()) - results.append({"success": False, "action": action, "error": error_msg}) - - # 返回处理结果 - result_json = {"results": results, "total": len(data)} - res.response = json.dumps(result_json, ensure_ascii=False) - self.lab_logger().info(f"[Resource Tree Update] Completed processing {len(data)} operations") - - except json.JSONDecodeError as e: - error_msg = f"Invalid JSON format: {str(e)}" - self.lab_logger().error(f"[Resource Tree Update] {error_msg}") - res.response = json.dumps({"success": False, "error": error_msg}, ensure_ascii=False) - except Exception as e: - error_msg = f"Unexpected error: {str(e)}" - self.lab_logger().error(f"[Resource Tree Update] {error_msg}") - self.lab_logger().error(traceback.format_exc()) - res.response = json.dumps({"success": False, "error": error_msg}, ensure_ascii=False) - - return res async def append_resource(req: SerialCommand_Request, res: SerialCommand_Response): # 物料传输到对应的node节点 @@ -644,7 +539,7 @@ class BaseROS2DeviceNode(Node, Generic[T]): "s2c_resource_tree": self.create_service( SerialCommand, f"/srv{self.namespace}/s2c_resource_tree", - s2c_resource_tree, # type: ignore + self.s2c_resource_tree, # type: ignore callback_group=self.callback_group, ), } @@ -667,6 +562,159 @@ class BaseROS2DeviceNode(Node, Generic[T]): self.lab_logger().error(traceback.format_exc()) self.lab_logger().debug(f"资源更新结果: {response}") + async def s2c_resource_tree(self, req: SerialCommand_Request, res: SerialCommand_Response): + """ + 处理资源树更新请求 + + 支持三种操作: + - add: 添加新资源到资源树 + - update: 更新现有资源 + - remove: 从资源树中移除资源 + """ + try: + data = json.loads(req.command) + results = [] + + for i in data: + action = i.get("action") # remove, add, update + resources_uuid: List[str] = i.get("data") # 资源数据 + self.lab_logger().info( + f"[Resource Tree Update] Processing {action} operation, " + f"resources count: {len(resources_uuid)}" + ) + tree_set = None + if action in ["add", "update"]: + response: SerialCommand.Response = await self._resource_clients[ + "c2s_update_resource_tree" + ].call_async( + SerialCommand.Request( + command=json.dumps( + {"data": {"data": resources_uuid, "with_children": False}, "action": "get"} + ) + ) + ) # type: ignore + raw_nodes = json.loads(response.response) + tree_set = ResourceTreeSet.from_raw_list(raw_nodes) + try: + if action == "add": + # 添加资源到资源跟踪器 + plr_resources = tree_set.to_plr_resources() + for plr_resource, tree in zip(plr_resources, tree_set.trees): + self.resource_tracker.add_resource(plr_resource) + parent_uuid = tree.root_node.res_content.parent_uuid + if parent_uuid: + parent_resource: ResourcePLR = self.resource_tracker.uuid_to_resources.get(parent_uuid) + if parent_resource is None: + self.lab_logger().warning( + f"物料{plr_resource}请求挂载{tree.root_node.res_content.name}的父节点{parent_uuid}不存在") + else: + try: + parent_resource.assign_child_resource(plr_resource, location=None) + except Exception as e: + self.lab_logger().warning( + f"物料{plr_resource}请求挂载{tree.root_node.res_content.name}的父节点{parent_resource}[{parent_uuid}]失败!\n{traceback.format_exc()}") + func = getattr(self.driver_instance, "resource_tree_add", None) + if callable(func): + func(plr_resources) + results.append({"success": True, "action": "add"}) + elif action == "update": + # 更新资源 + plr_resources = tree_set.to_plr_resources() + for plr_resource, tree in zip(plr_resources, tree_set.trees): + states = plr_resource.serialize_all_state() + original_instance: ResourcePLR = self.resource_tracker.figure_resource( + {"uuid": tree.root_node.res_content.uuid}, try_mode=False) + original_instance.load_all_state(states) + self.lab_logger().info( + f"更新了资源属性 {plr_resource}[{tree.root_node.res_content.uuid}] 及其子节点 {len(original_instance.get_all_children())} 个") + + func = getattr(self.driver_instance, "resource_tree_update", None) + if callable(func): + func(plr_resources) + results.append({"success": True, "action": "update"}) + elif action == "remove": + # 移除资源 + plr_resources: List[ResourcePLR] = [self.resource_tracker.uuid_to_resources[i] for + i in resources_uuid] + func = getattr(self.driver_instance, "resource_tree_remove", None) + if callable(func): + func(plr_resources) + for plr_resource in plr_resources: + plr_resource.parent.unassign_child_resource(plr_resource) + self.resource_tracker.remove_resource(plr_resource) + results.append({"success": True, "action": "remove"}) + except Exception as e: + error_msg = f"Error processing {action} operation: {str(e)}" + self.lab_logger().error(f"[Resource Tree Update] {error_msg}") + self.lab_logger().error(traceback.format_exc()) + results.append({"success": False, "action": action, "error": error_msg}) + + # 返回处理结果 + result_json = {"results": results, "total": len(data)} + res.response = json.dumps(result_json, ensure_ascii=False) + self.lab_logger().info(f"[Resource Tree Update] Completed processing {len(data)} operations") + + except json.JSONDecodeError as e: + error_msg = f"Invalid JSON format: {str(e)}" + self.lab_logger().error(f"[Resource Tree Update] {error_msg}") + res.response = json.dumps({"success": False, "error": error_msg}, ensure_ascii=False) + except Exception as e: + error_msg = f"Unexpected error: {str(e)}" + self.lab_logger().error(f"[Resource Tree Update] {error_msg}") + self.lab_logger().error(traceback.format_exc()) + res.response = json.dumps({"success": False, "error": error_msg}, ensure_ascii=False) + + return res + + async def transfer_resource_to_another(self, plr_resources: List["ResourcePLR"], target_device_id, target_resource_uuid: str): + # 准备工作 + uids = [] + for plr_resource in plr_resources: + uid = getattr(plr_resource, "unilabos_uuid", None) + if uid is None: + raise ValueError(f"物料{plr_resource}没有unilabos_uuid属性,无法转运") + uids.append(uid) + srv_address = f"/srv{target_device_id}/s2c_resource_tree" + sclient = self.create_client(SerialCommand, srv_address) + # 等待服务可用(设置超时) + if not sclient.wait_for_service(timeout_sec=5.0): + self.lab_logger().error(f"[{self.device_id} Node-Resource] Service {srv_address} not available") + raise ValueError(f"[{self.device_id} Node-Resource] Service {srv_address} not available") + + # 先从当前节点移除资源 + await self.s2c_resource_tree(SerialCommand_Request(command=json.dumps([{ + "action": "remove", + "data": uids # 只移除父节点 + }], ensure_ascii=False)), SerialCommand_Response()) + + # 通知云端转运资源 + tree_set = ResourceTreeSet.from_plr_resources(plr_resources) + for root_node in tree_set.root_nodes: + root_node.res_content.parent = None + root_node.res_content.parent_uuid = target_resource_uuid + r = SerialCommand.Request() + r.command = json.dumps({"data": {"data": tree_set.dump()}, "action": "update"}) # 和Update Resource一致 + response: SerialCommand_Response = await self._resource_clients["c2s_update_resource_tree"].call_async(r) # type: ignore + self.lab_logger().info(f"资源云端转运到{target_device_id}结果: {response.response}") + + # 创建请求 + request = SerialCommand.Request() + request.command = json.dumps([{ + "action": "add", + "data": tree_set.all_nodes_uuid # 只添加父节点,子节点会自动添加 + }], ensure_ascii=False) + + future = sclient.call_async(request) + timeout = 30.0 + start_time = time.time() + while not future.done(): + if time.time() - start_time > timeout: + self.lab_logger().error(f"[{self.device_id} Node-Resource] Timeout waiting for response from {target_device_id}") + return False + time.sleep(0.05) + self.lab_logger().info(f"资源本地增加到{target_device_id}结果: {response.response}") + return None + def register_device(self): """向注册表中注册设备信息""" topics_info = self._property_publishers.copy() diff --git a/unilabos/ros/nodes/presets/host_node.py b/unilabos/ros/nodes/presets/host_node.py index e9e5e38a..b07dc045 100644 --- a/unilabos/ros/nodes/presets/host_node.py +++ b/unilabos/ros/nodes/presets/host_node.py @@ -247,7 +247,6 @@ class HostNode(BaseROS2DeviceNode): else: resource_instance = self.resource_tracker.figure_resource({"name": node.res_content.name}) self._resource_tracker.loop_update_uuid(resource_instance, uuid_mapping) - except Exception as ex: self.lab_logger().error("[Host Node-Resource] 添加物料出错!") self.lab_logger().error(traceback.format_exc()) @@ -1323,7 +1322,7 @@ class HostNode(BaseROS2DeviceNode): if time.time() - start_time > timeout: self.lab_logger().error(f"[Host Node-Resource] Timeout waiting for response from {device_id}") return False - time.sleep(0.01) + time.sleep(0.05) response = future.result() self.lab_logger().info( diff --git a/unilabos/ros/nodes/resource_tracker.py b/unilabos/ros/nodes/resource_tracker.py index 5ae808ed..999ee254 100644 --- a/unilabos/ros/nodes/resource_tracker.py +++ b/unilabos/ros/nodes/resource_tracker.py @@ -454,6 +454,59 @@ class ResourceTreeSet(object): return plr_resources + @classmethod + def from_raw_list(cls, raw_list: List[Dict[str, Any]]) -> "ResourceTreeSet": + """ + 从原始字典列表创建 ResourceTreeSet,自动建立 parent-children 关系 + + Args: + raw_list: 原始字典列表,每个字典代表一个资源节点 + + Returns: + ResourceTreeSet 实例 + + Raises: + ValueError: 当建立关系时发现不一致 + """ + # 第一步:将字典列表转换为 ResourceDictInstance 列表 + instances = [ResourceDictInstance.get_resource_instance_from_dict(node_dict) for node_dict in raw_list] + + # 第二步:建立映射关系 + uuid_to_instance: Dict[str, ResourceDictInstance] = {} + id_to_instance: Dict[str, ResourceDictInstance] = {} + + for raw_node, instance in zip(raw_list, instances): + # 建立 uuid 映射 + if instance.res_content.uuid: + uuid_to_instance[instance.res_content.uuid] = instance + # 建立 id 映射 + if instance.res_content.id: + id_to_instance[instance.res_content.id] = instance + + # 第三步:建立 parent-children 关系 + for raw_node, instance in zip(raw_list, instances): + # 优先使用 parent_uuid 进行匹配,如果不存在则使用 parent (id) + parent_uuid = raw_node.get("parent_uuid") + parent_id = raw_node.get("parent") + parent_instance = None + + # 优先用 parent_uuid 匹配 + if parent_uuid and parent_uuid in uuid_to_instance: + parent_instance = uuid_to_instance[parent_uuid] + # 否则用 parent (id) 匹配 + elif parent_id and parent_id in id_to_instance: + parent_instance = id_to_instance[parent_id] + + # 设置 parent 引用并建立 children 关系 + if parent_instance: + instance.res_content.parent = parent_instance.res_content + # 将当前节点添加到父节点的 children 列表(避免重复添加) + if instance not in parent_instance.children: + parent_instance.children.append(instance) + + # 第四步:使用 from_nested_list 创建 ResourceTreeSet + return cls.from_nested_list(instances) + @classmethod def from_nested_list(cls, nested_list: List[ResourceDictInstance]) -> "ResourceTreeSet": """ @@ -497,6 +550,16 @@ class ResourceTreeSet(object): """ return [node for tree in self.trees for node in tree.get_all_nodes()] + @property + def all_nodes_uuid(self) -> List[str]: + """ + 获取所有树中的所有节点 + + Returns: + 所有节点的资源实例列表 + """ + return [node.res_content.uuid for tree in self.trees for node in tree.get_all_nodes()] + def find_by_uuid(self, target_uuid: str) -> Optional[ResourceDictInstance]: """ 在所有树中通过uuid查找节点 @@ -513,6 +576,116 @@ class ResourceTreeSet(object): return result return None + def merge_remote_resources(self, remote_tree_set: "ResourceTreeSet") -> "ResourceTreeSet": + """ + 将远端物料同步到本地物料中(以子树为单位) + + 同步规则: + 1. 一级节点(根节点):如果不存在的物料,引入整个子树 + 2. 一级设备下的二级物料:如果不存在,引入整个子树 + 3. 二级设备下的三级物料:如果不存在,引入整个子树 + 如果存在则跳过并提示 + + Args: + remote_tree_set: 远端的资源树集合 + + Returns: + 合并后的资源树集合(self) + """ + # 构建本地映射:一级 device id -> 根节点实例 + local_device_map: Dict[str, ResourceDictInstance] = {} + for root_node in self.root_nodes: + if root_node.res_content.type == "device": + local_device_map[root_node.res_content.id] = root_node + + # 记录需要添加的新根节点(不属于任何 device 的物料) + new_root_nodes: List[ResourceDictInstance] = [] + + # 遍历远端根节点 + for remote_root in remote_tree_set.root_nodes: + remote_root_id = remote_root.res_content.id + remote_root_type = remote_root.res_content.type + + if remote_root_type == "device": + # 情况1: 一级是 device + if remote_root_id not in local_device_map: + logger.warning(f"Device '{remote_root_id}' 在本地不存在,跳过该 device 下的物料同步") + continue + + local_device = local_device_map[remote_root_id] + + # 构建本地一级 device 下的子节点映射 + local_children_map = {child.res_content.name: child for child in local_device.children} + + # 遍历远端一级 device 的子节点 + for remote_child in remote_root.children: + remote_child_name = remote_child.res_content.name + remote_child_type = remote_child.res_content.type + + if remote_child_type == "device": + # 情况2: 二级是 device + if remote_child_name not in local_children_map: + logger.warning(f"Device '{remote_root_id}/{remote_child_name}' 在本地不存在,跳过") + continue + + local_sub_device = local_children_map[remote_child_name] + + # 构建本地二级 device 下的子节点映射 + local_sub_children_map = {child.res_content.name: child for child in local_sub_device.children} + + # 遍历远端二级 device 的子节点(三级物料) + added_count = 0 + for remote_material in remote_child.children: + remote_material_name = remote_material.res_content.name + + # 情况3: 三级物料 + if remote_material_name not in local_sub_children_map: + # 引入整个子树 + remote_material.res_content.parent = local_sub_device.res_content + local_sub_device.children.append(remote_material) + added_count += 1 + else: + logger.info( + f"物料 '{remote_root_id}/{remote_child_name}/{remote_material_name}' " + f"已存在,跳过" + ) + + if added_count > 0: + logger.info( + f"Device '{remote_root_id}/{remote_child_name}': " + f"从远端同步了 {added_count} 个物料子树" + ) + else: + # 情况2: 二级是物料(不是 device) + if remote_child_name not in local_children_map: + # 引入整个子树 + remote_child.res_content.parent = local_device.res_content + local_device.children.append(remote_child) + logger.info(f"Device '{remote_root_id}': 从远端同步物料子树 '{remote_child_name}'") + else: + logger.info(f"物料 '{remote_root_id}/{remote_child_name}' 已存在,跳过") + else: + # 情况1: 一级节点是物料(不是 device) + # 检查是否已存在 + existing = False + for local_root in self.root_nodes: + if local_root.res_content.name == remote_root.res_content.name: + existing = True + logger.info(f"根节点物料 '{remote_root.res_content.name}' 已存在,跳过") + break + + if not existing: + # 引入整个子树 + new_root_nodes.append(remote_root) + logger.info(f"添加远端独立物料根节点子树: '{remote_root_id}'") + + # 将新的根节点添加到本地树集合 + if new_root_nodes: + for new_root in new_root_nodes: + self.trees.append(ResourceTreeInstance(new_root)) + + return self + def dump(self) -> List[List[Dict[str, Any]]]: """ 将 ResourceTreeSet 序列化为嵌套列表格式