mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-14 13:14:39 +00:00
Compare commits
4 Commits
f5446c6480
...
a061bc2942
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a061bc2942 | ||
|
|
8c9e11c04f | ||
|
|
e4e3ec805a | ||
|
|
d634316bce |
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from cgi import print_arguments
|
||||
from doctest import debug
|
||||
from typing import Dict, Any, List, Optional
|
||||
from typing import Dict, Any, List, Optional, Tuple
|
||||
import requests
|
||||
from pylabrobot.resources.resource import Resource as ResourcePLR
|
||||
from pathlib import Path
|
||||
@@ -22,6 +22,7 @@ from unilabos.resources.bioyond.decks import BIOYOND_YB_Deck
|
||||
from unilabos.resources.graphio import resource_bioyond_to_plr
|
||||
from unilabos.utils.log import logger
|
||||
from unilabos.registry.registry import lab_registry
|
||||
from unilabos.ros.nodes.base_device_node import ROS2DeviceNode
|
||||
|
||||
def _iso_local_now_ms() -> str:
|
||||
# 文档要求:到毫秒 + Z,例如 2025-08-15T05:43:22.814Z
|
||||
@@ -41,12 +42,14 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
def __init__(self, config: dict = None, deck=None, protocol_type=None, **kwargs):
|
||||
|
||||
# 使用统一配置,支持自定义覆盖, 从 config.py 加载完整配置
|
||||
self.bioyond_config ={
|
||||
self.bioyond_config = {
|
||||
**API_CONFIG,
|
||||
"material_type_mappings": MATERIAL_TYPE_MAPPINGS,
|
||||
"warehouse_mapping": WAREHOUSE_MAPPING,
|
||||
"debug_mode": False
|
||||
}
|
||||
"debug_mode": False,
|
||||
}
|
||||
if config:
|
||||
self.bioyond_config.update(config)
|
||||
|
||||
# "material_type_mappings": MATERIAL_TYPE_MAPPINGS
|
||||
# "warehouse_mapping": WAREHOUSE_MAPPING
|
||||
@@ -57,6 +60,12 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
self.http_service_started = self.debug_mode
|
||||
self._device_id = "bioyond_cell_workstation" # 默认值,后续会从_ros_node获取
|
||||
super().__init__(bioyond_config=config, deck=deck)
|
||||
self.transfer_target_device_id = self.bioyond_config.get("transfer_target_device_id", "BatteryStation")
|
||||
self.transfer_target_parent = self.bioyond_config.get("transfer_target_parent", "YB_YH_Deck")
|
||||
self.transfer_timeout = float(self.bioyond_config.get("transfer_timeout", 180.0))
|
||||
self.coin_cell_workflow_config = self.bioyond_config.get("coin_cell_workflow_config", {})
|
||||
self.pending_transfer_materials: List[Dict[str, Any]] = []
|
||||
self.pending_transfer_plr: List[ResourcePLR] = []
|
||||
self.update_push_ip() #直接修改奔耀端的报送ip地址
|
||||
logger.info("已更新奔耀端推送 IP 地址")
|
||||
|
||||
@@ -472,7 +481,7 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
return response
|
||||
|
||||
# 2.14 新建实验
|
||||
def create_orders(self, xlsx_path: str) -> Dict[str, Any]:
|
||||
def create_orders(self, xlsx_path: str, *, material_filter: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
从 Excel 解析并创建实验(2.14)
|
||||
约定:
|
||||
@@ -629,7 +638,34 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
return response
|
||||
# 等待完成报送
|
||||
result = self.wait_for_order_finish(order_code)
|
||||
return result
|
||||
report_data = result.get("report") if isinstance(result, dict) else None
|
||||
materials_from_report = (
|
||||
report_data.get("usedMaterials") if isinstance(report_data, dict) else None
|
||||
)
|
||||
if materials_from_report:
|
||||
materials = materials_from_report
|
||||
logger.info(
|
||||
"[create_orders] 使用订单完成报送中的物料信息: "
|
||||
f"{len(materials)} 条"
|
||||
)
|
||||
else:
|
||||
materials = self._fetch_bioyond_materials(filter_keyword=material_filter)
|
||||
logger.info(
|
||||
"[create_orders] 未收到订单报送物料信息,回退到实时查询"
|
||||
)
|
||||
print("materials_from_report:", materials_from_report)
|
||||
# TODO: 需要将 materials 字典转换为 ResourceSlot 对象后才能转运
|
||||
# self.transfer_resource_to_another(
|
||||
# resource=[materials],
|
||||
# mount_resource=["YB_YH_Deck"],
|
||||
# sites=[None],
|
||||
# mount_device_id="BatteryStation"
|
||||
# )
|
||||
return {
|
||||
"api_response": response,
|
||||
"order_finish": result,
|
||||
"materials": materials,
|
||||
}
|
||||
|
||||
# 2.7 启动调度
|
||||
def scheduler_start(self) -> Dict[str, Any]:
|
||||
@@ -701,6 +737,7 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
return response
|
||||
# 等待完成报送
|
||||
result = self.wait_for_order_finish(order_code)
|
||||
|
||||
return result
|
||||
|
||||
# 2.5 批量查询实验报告(post过滤关键字查询)
|
||||
@@ -1198,6 +1235,108 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
|
||||
return raw_materials
|
||||
|
||||
def _convert_materials_to_plr(self, materials: List[Dict[str, Any]]) -> List[ResourcePLR]:
|
||||
try:
|
||||
return resource_bioyond_to_plr(
|
||||
deepcopy(materials),
|
||||
type_mapping=self.bioyond_config.get("material_type_mappings", MATERIAL_TYPE_MAPPINGS),
|
||||
deck=self.deck,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.error(f"物料转换为 PLR 失败: {exc}", exc_info=True)
|
||||
return []
|
||||
|
||||
def _wait_for_future(self, future, stage: str, timeout: Optional[float] = None):
|
||||
if future is None:
|
||||
return None
|
||||
timeout = timeout or self.transfer_timeout
|
||||
start = time.time()
|
||||
while not future.done():
|
||||
if (time.time() - start) > timeout:
|
||||
raise TimeoutError(f"{stage} 超时 {timeout}s")
|
||||
time.sleep(0.05)
|
||||
return future.result()
|
||||
|
||||
def _register_plr_resources(self, resources: List[ResourcePLR]) -> None:
|
||||
if not resources or not hasattr(self, "_ros_node") or self._ros_node is None:
|
||||
return
|
||||
future = ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, resources=resources)
|
||||
self._wait_for_future(future, "update_resource")
|
||||
|
||||
def _get_target_resource(self, name: str) -> ResourcePLR:
|
||||
if not hasattr(self, "_ros_node") or self._ros_node is None:
|
||||
raise RuntimeError("ROS 节点未初始化,无法获取资源")
|
||||
resource = self._ros_node.resource_tracker.figure_resource({"name": name}, try_mode=False) # type: ignore
|
||||
if resource is None:
|
||||
raise ValueError(f"未找到目标资源: {name}")
|
||||
return resource
|
||||
|
||||
def _allocate_sites(self, parent_resource: ResourcePLR, count: int) -> List[str]:
|
||||
if not hasattr(parent_resource, "get_free_sites"):
|
||||
raise ValueError(f"资源 {parent_resource} 不支持自动分配站位")
|
||||
free_indices = list(parent_resource.get_free_sites())
|
||||
if len(free_indices) < count:
|
||||
raise ValueError(f"{parent_resource.name} 可用站位不足 (need {count}, have {len(free_indices)})")
|
||||
ordering = list(getattr(parent_resource, "_ordering", {}).keys())
|
||||
sites: List[str] = []
|
||||
for idx in free_indices[:count]:
|
||||
if ordering and idx < len(ordering):
|
||||
sites.append(ordering[idx])
|
||||
else:
|
||||
sites.append(str(idx))
|
||||
return sites
|
||||
|
||||
def _invoke_coin_cell_workflow(self, material_payload: List[Dict[str, Any]]) -> Any:
|
||||
timeout = float(self.bioyond_config.get("coin_cell_workflow_timeout", 300.0))
|
||||
workflow_payload: Dict[str, Any] = {}
|
||||
if isinstance(self.coin_cell_workflow_config, dict):
|
||||
workflow_payload.update(deepcopy(self.coin_cell_workflow_config))
|
||||
workflow_payload["materials"] = deepcopy(material_payload)
|
||||
return self._call_remote_device_method(
|
||||
self.transfer_target_device_id,
|
||||
"run_coin_cell_assembly_workflow",
|
||||
timeout=timeout,
|
||||
workflow_config=workflow_payload,
|
||||
)
|
||||
|
||||
def _call_remote_device_method(
|
||||
self,
|
||||
device_id: str,
|
||||
method: str,
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
**kwargs,
|
||||
) -> Any:
|
||||
if not hasattr(self, "_ros_node") or self._ros_node is None:
|
||||
raise RuntimeError("ROS 节点未初始化,无法调用远程设备")
|
||||
if not device_id:
|
||||
raise ValueError("device_id 不能为空")
|
||||
if not method:
|
||||
raise ValueError("method 不能为空")
|
||||
|
||||
timeout = timeout or self.transfer_timeout
|
||||
payload = json.dumps(
|
||||
{
|
||||
"function_name": method,
|
||||
"function_args": kwargs,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
future = ROS2DeviceNode.run_async_func(
|
||||
self._ros_node.execute_single_action,
|
||||
True,
|
||||
device_id=device_id,
|
||||
action_name="_execute_driver_command_async",
|
||||
action_kwargs={"string": payload},
|
||||
)
|
||||
result = self._wait_for_future(future, f"{device_id}.{method}", timeout)
|
||||
if hasattr(result, "return_info"):
|
||||
try:
|
||||
return json.loads(result.return_info)
|
||||
except Exception:
|
||||
return result.return_info
|
||||
return result
|
||||
|
||||
def run_feeding_stage(self) -> Dict[str, List[Dict[str, Any]]]:
|
||||
self.create_sample(
|
||||
board_type="配液瓶(小)板",
|
||||
@@ -1239,17 +1378,38 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
def run_transfer_stage(
|
||||
self,
|
||||
liquid_materials: Optional[List[Dict[str, Any]]] = None,
|
||||
) -> Dict[str, List[Dict[str, Any]]]:
|
||||
self.transfer_3_to_2_to_1(
|
||||
source_wh_id="3a19debc-84b4-0359-e2d4-b3beea49348b",
|
||||
source_x=1,
|
||||
source_y=1,
|
||||
source_z=1,
|
||||
source_wh_id: Optional[str] = '3a19debc-84b4-0359-e2d4-b3beea49348b',
|
||||
source_x: int = 1,
|
||||
source_y: int = 1,
|
||||
source_z: int = 1
|
||||
) -> Dict[str, Any]:
|
||||
"""转运阶段:调用transfer_3_to_2_to_1执行3到2到1转运"""
|
||||
logger.info("开始执行转运阶段 (run_transfer_stage)")
|
||||
|
||||
# 暂时注释掉物料转换和跨工站转运逻辑
|
||||
# transfer_summary: Dict[str, Any] = {}
|
||||
# try:
|
||||
# source_materials = liquid_materials or self._fetch_bioyond_materials()
|
||||
# transfer_plr = self._convert_materials_to_plr(source_materials)
|
||||
# transfer_summary["plr_count"] = len(transfer_plr)
|
||||
# ...
|
||||
# except Exception as exc:
|
||||
# transfer_summary["error"] = str(exc)
|
||||
# logger.error(f"跨工站转运失败: {exc}", exc_info=True)
|
||||
|
||||
# 只执行核心的3到2到1转运
|
||||
transfer_result = self.transfer_3_to_2_to_1(
|
||||
source_wh_id=source_wh_id,
|
||||
source_x=source_x,
|
||||
source_y=source_y,
|
||||
source_z=source_z
|
||||
)
|
||||
transfer_materials = self._fetch_bioyond_materials()
|
||||
|
||||
logger.info("转运阶段执行完成")
|
||||
return {
|
||||
"liquid_materials": liquid_materials or [],
|
||||
"transfer_materials": transfer_materials,
|
||||
"success": True,
|
||||
"stage": "transfer",
|
||||
"transfer_result": transfer_result
|
||||
}
|
||||
if __name__ == "__main__":
|
||||
deck = BIOYOND_YB_Deck(setup=True)
|
||||
|
||||
Binary file not shown.
@@ -159,6 +159,27 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
|
||||
"resources": [self.deck]
|
||||
})
|
||||
|
||||
def sync_transfer_resources(self) -> Dict[str, Any]:
|
||||
"""
|
||||
供跨工站转运完成后调用,强制将当前台面资源同步到云端/前端。
|
||||
"""
|
||||
if not hasattr(self, "_ros_node") or self._ros_node is None:
|
||||
return {"status": "failed", "error": "ros_node_not_ready"}
|
||||
if self.deck is None:
|
||||
return {"status": "failed", "error": "deck_not_initialized"}
|
||||
try:
|
||||
future = ROS2DeviceNode.run_async_func(
|
||||
self._ros_node.update_resource,
|
||||
True,
|
||||
resources=[self.deck],
|
||||
)
|
||||
if future:
|
||||
future.result()
|
||||
return {"status": "success"}
|
||||
except Exception as exc:
|
||||
logger.error(f"同步转运资源失败: {exc}", exc_info=True)
|
||||
return {"status": "failed", "error": str(exc)}
|
||||
|
||||
# 批量操作在这里写
|
||||
async def change_hole_sheet_to_2(self, hole: MaterialHole):
|
||||
hole._unilabos_state["max_sheets"] = 2
|
||||
@@ -1225,26 +1246,87 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
|
||||
|
||||
'''
|
||||
|
||||
def run_coin_cell_assembly_workflow(self):
|
||||
self.qiming_coin_cell_code(
|
||||
fujipian_panshu=1,
|
||||
fujipian_juzhendianwei=0,
|
||||
gemopanshu=0,
|
||||
gemo_juzhendianwei=0,
|
||||
lvbodian=True,
|
||||
battery_pressure_mode=True,
|
||||
battery_pressure=4200,
|
||||
battery_clean_ignore=False,
|
||||
)
|
||||
self.func_pack_device_init()
|
||||
self.func_pack_device_auto()
|
||||
self.func_pack_device_start()
|
||||
self.func_pack_send_bottle_num(1)
|
||||
self.func_allpack_cmd(elec_num = 1, elec_use_num = 1, elec_vol=50, assembly_type=7, assembly_pressure=4200, file_path="/Users/sml/work")
|
||||
self.func_pack_send_finished_cmd()
|
||||
self.func_pack_device_stop()
|
||||
# 物料转换
|
||||
return self
|
||||
def run_coin_cell_assembly_workflow(
|
||||
self,
|
||||
workflow_config: Optional[Dict[str, Any]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
config: Dict[str, Any]
|
||||
if workflow_config is None:
|
||||
config = {}
|
||||
elif isinstance(workflow_config, list):
|
||||
config = {"materials": workflow_config}
|
||||
else:
|
||||
config = workflow_config
|
||||
qiming_defaults = {
|
||||
"fujipian_panshu": 1,
|
||||
"fujipian_juzhendianwei": 0,
|
||||
"gemopanshu": 1,
|
||||
"gemo_juzhendianwei": 0,
|
||||
"lvbodian": True,
|
||||
"battery_pressure_mode": True,
|
||||
"battery_pressure": 4200,
|
||||
"battery_clean_ignore": False,
|
||||
}
|
||||
qiming_params = {**qiming_defaults, **(config.get("qiming") or {})}
|
||||
qiming_success = self.qiming_coin_cell_code(**qiming_params)
|
||||
|
||||
step_results: Dict[str, Any] = {}
|
||||
try:
|
||||
self.func_pack_device_init()
|
||||
step_results["init"] = True
|
||||
except Exception as exc:
|
||||
step_results["init"] = f"error: {exc}"
|
||||
|
||||
try:
|
||||
self.func_pack_device_auto()
|
||||
step_results["auto"] = True
|
||||
except Exception as exc:
|
||||
step_results["auto"] = f"error: {exc}"
|
||||
|
||||
try:
|
||||
self.func_pack_device_start()
|
||||
step_results["start"] = True
|
||||
except Exception as exc:
|
||||
step_results["start"] = f"error: {exc}"
|
||||
|
||||
packaging_cfg = config.get("packaging") or {}
|
||||
bottle_num = packaging_cfg.get("bottle_num", 1)
|
||||
try:
|
||||
self.func_pack_send_bottle_num(bottle_num)
|
||||
step_results["send_bottle_num"] = True
|
||||
except Exception as exc:
|
||||
step_results["send_bottle_num"] = f"error: {exc}"
|
||||
|
||||
command_defaults = {
|
||||
"elec_num": 1,
|
||||
"elec_use_num": 1,
|
||||
"elec_vol": 50,
|
||||
"assembly_type": 7,
|
||||
"assembly_pressure": 4200,
|
||||
"file_path": "/Users/sml/work",
|
||||
}
|
||||
command_params = {**command_defaults, **(packaging_cfg.get("command") or {})}
|
||||
packaging_result = self.func_allpack_cmd(**command_params)
|
||||
|
||||
finished_result = self.func_pack_send_finished_cmd()
|
||||
stop_result = self.func_pack_device_stop()
|
||||
|
||||
return {
|
||||
"qiming": {
|
||||
"params": qiming_params,
|
||||
"success": qiming_success,
|
||||
},
|
||||
"workflow_steps": step_results,
|
||||
"packaging": {
|
||||
"bottle_num": bottle_num,
|
||||
"command": command_params,
|
||||
"result": packaging_result,
|
||||
},
|
||||
"finish": {
|
||||
"send_finished": finished_result,
|
||||
"stop": stop_result,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -837,6 +837,8 @@ bioyond_cell:
|
||||
result:
|
||||
properties:
|
||||
feeding_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- feeding_materials
|
||||
@@ -876,8 +878,12 @@ bioyond_cell:
|
||||
result:
|
||||
properties:
|
||||
feeding_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
liquid_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- liquid_materials
|
||||
@@ -889,6 +895,8 @@ bioyond_cell:
|
||||
goal:
|
||||
properties:
|
||||
feeding_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
required: []
|
||||
type: object
|
||||
@@ -919,9 +927,15 @@ bioyond_cell:
|
||||
result:
|
||||
properties:
|
||||
liquid_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
transfer_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
transfer_summary:
|
||||
type: object
|
||||
required:
|
||||
- transfer_materials
|
||||
type: object
|
||||
@@ -932,10 +946,24 @@ bioyond_cell:
|
||||
goal:
|
||||
properties:
|
||||
liquid_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
required: []
|
||||
type: object
|
||||
result: {}
|
||||
result:
|
||||
properties:
|
||||
liquid_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
transfer_materials:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
transfer_summary:
|
||||
type: object
|
||||
type: object
|
||||
required:
|
||||
- goal
|
||||
title: run_transfer_stage参数
|
||||
@@ -1234,7 +1262,7 @@ bioyond_cell:
|
||||
config_info: []
|
||||
description: 配液工站
|
||||
handles: []
|
||||
icon: ''
|
||||
icon: benyao2.webp
|
||||
init_param_schema:
|
||||
config:
|
||||
properties:
|
||||
|
||||
@@ -479,20 +479,139 @@ coincellassemblyworkstation_device:
|
||||
type: UniLabJsonCommand
|
||||
auto-run_coin_cell_assembly_workflow:
|
||||
feedback: {}
|
||||
goal: {}
|
||||
goal_default: {}
|
||||
handles: {}
|
||||
goal:
|
||||
properties:
|
||||
workflow_config:
|
||||
type: object
|
||||
required: []
|
||||
type: object
|
||||
goal_default:
|
||||
workflow_config: {}
|
||||
handles:
|
||||
input:
|
||||
- data_key: workflow_config
|
||||
data_source: handle
|
||||
data_type: resource
|
||||
handler_key: WorkflowConfig
|
||||
label: Workflow Config
|
||||
output:
|
||||
- data_key: qiming
|
||||
data_source: executor
|
||||
data_type: resource
|
||||
handler_key: QimingResult
|
||||
label: Qiming Result
|
||||
- data_key: workflow_steps
|
||||
data_source: executor
|
||||
data_type: resource
|
||||
handler_key: WorkflowSteps
|
||||
label: Workflow Steps
|
||||
- data_key: packaging
|
||||
data_source: executor
|
||||
data_type: resource
|
||||
handler_key: PackagingResult
|
||||
label: Packaging Result
|
||||
- data_key: finish
|
||||
data_source: executor
|
||||
data_type: resource
|
||||
handler_key: FinishResult
|
||||
label: Finish Result
|
||||
placeholder_keys: {}
|
||||
result: {}
|
||||
result:
|
||||
properties:
|
||||
finish:
|
||||
properties:
|
||||
send_finished:
|
||||
type: object
|
||||
stop:
|
||||
type: object
|
||||
required:
|
||||
- send_finished
|
||||
- stop
|
||||
type: object
|
||||
packaging:
|
||||
properties:
|
||||
bottle_num:
|
||||
type: integer
|
||||
command:
|
||||
type: object
|
||||
result:
|
||||
type: object
|
||||
required:
|
||||
- bottle_num
|
||||
- command
|
||||
- result
|
||||
type: object
|
||||
qiming:
|
||||
properties:
|
||||
params:
|
||||
type: object
|
||||
success:
|
||||
type: boolean
|
||||
required:
|
||||
- params
|
||||
- success
|
||||
type: object
|
||||
workflow_steps:
|
||||
type: object
|
||||
required:
|
||||
- qiming
|
||||
- workflow_steps
|
||||
- packaging
|
||||
- finish
|
||||
type: object
|
||||
schema:
|
||||
description: ''
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties: {}
|
||||
properties:
|
||||
workflow_config:
|
||||
type: object
|
||||
required: []
|
||||
type: object
|
||||
result: {}
|
||||
result:
|
||||
properties:
|
||||
finish:
|
||||
properties:
|
||||
send_finished:
|
||||
type: object
|
||||
stop:
|
||||
type: object
|
||||
required:
|
||||
- send_finished
|
||||
- stop
|
||||
type: object
|
||||
packaging:
|
||||
properties:
|
||||
bottle_num:
|
||||
type: integer
|
||||
command:
|
||||
type: object
|
||||
result:
|
||||
type: object
|
||||
required:
|
||||
- bottle_num
|
||||
- command
|
||||
- result
|
||||
type: object
|
||||
qiming:
|
||||
properties:
|
||||
params:
|
||||
type: object
|
||||
success:
|
||||
type: boolean
|
||||
required:
|
||||
- params
|
||||
- success
|
||||
type: object
|
||||
workflow_steps:
|
||||
type: object
|
||||
required:
|
||||
- qiming
|
||||
- workflow_steps
|
||||
- packaging
|
||||
- finish
|
||||
type: object
|
||||
required:
|
||||
- goal
|
||||
title: run_coin_cell_assembly_workflow参数
|
||||
@@ -548,7 +667,7 @@ coincellassemblyworkstation_device:
|
||||
config_info: []
|
||||
description: 扣电工站
|
||||
handles: []
|
||||
icon: ''
|
||||
icon: koudian.webp
|
||||
init_param_schema:
|
||||
config:
|
||||
properties:
|
||||
|
||||
@@ -402,7 +402,6 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
|
||||
|
||||
return result_future.result
|
||||
|
||||
"""还没有改过的部分"""
|
||||
|
||||
def _setup_hardware_proxy(
|
||||
self, device: ROS2DeviceNode, communication_device: ROS2DeviceNode, read_method, write_method
|
||||
|
||||
Reference in New Issue
Block a user