mirror of
https://github.com/deepmodeling/Uni-Lab-OS
synced 2026-05-24 21:09:56 +00:00
feat: RNA simplify station action signatures and add order query
- Add explicit reset_operations default; keep hidden plumbing kwargs-only. - Add read-only get_order_list manual_confirm action that calls order_query with latest_only and exposes order_id/order_ids handles. - Collapse start_experiment visible signature to (order_id, materials_loaded, timeout_seconds, assignee_user_ids); legacy params consumed from kwargs to preserve runtime contract. - Reduce submit_experiment_1 graph handles to order_id, resource, coin_cell_code, mount_resource; result dict gains order_id while keeping existing keys.
This commit is contained in:
@@ -377,7 +377,11 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
always_free=True,
|
always_free=True,
|
||||||
node_type=NodeType.MANUAL_CONFIRM,
|
node_type=NodeType.MANUAL_CONFIRM,
|
||||||
placeholder_keys={"assignee_user_ids": "unilabos_manual_confirm"},
|
placeholder_keys={"assignee_user_ids": "unilabos_manual_confirm"},
|
||||||
goal_default={"timeout_seconds": 3600, "assignee_user_ids": []},
|
goal_default={
|
||||||
|
"reset_operations": ["scheduler_reset", "reset_order_status", "reset_location"],
|
||||||
|
"timeout_seconds": 3600,
|
||||||
|
"assignee_user_ids": [],
|
||||||
|
},
|
||||||
feedback_interval=300,
|
feedback_interval=300,
|
||||||
description="复位小核酸实验前状态",
|
description="复位小核酸实验前状态",
|
||||||
)
|
)
|
||||||
@@ -423,35 +427,14 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
description="提交小核酸实验1(报告基因检测)",
|
description="提交小核酸实验1(报告基因检测)",
|
||||||
handles=[
|
handles=[
|
||||||
ActionOutputHandle(
|
ActionOutputHandle(
|
||||||
key="order_ids",
|
key="order_id",
|
||||||
data_type="bioyond_order_ids",
|
data_type="bioyond_order_id",
|
||||||
label="实验ID",
|
label="实验ID",
|
||||||
data_key="order_ids",
|
data_key="order_id",
|
||||||
data_source=DataSource.EXECUTOR,
|
data_source=DataSource.EXECUTOR,
|
||||||
),
|
),
|
||||||
ActionOutputHandle(
|
ActionOutputHandle(
|
||||||
key="order_code",
|
# TEMP frontend-compat key: material/resource name display (renderer compat).
|
||||||
data_type="bioyond_order_code",
|
|
||||||
label="订单编号",
|
|
||||||
data_key="order_code",
|
|
||||||
data_source=DataSource.EXECUTOR,
|
|
||||||
),
|
|
||||||
ActionOutputHandle(
|
|
||||||
key="order_name",
|
|
||||||
data_type="bioyond_order_name",
|
|
||||||
label="订单名称",
|
|
||||||
data_key="order_name",
|
|
||||||
data_source=DataSource.EXECUTOR,
|
|
||||||
),
|
|
||||||
ActionOutputHandle(
|
|
||||||
key="target_device",
|
|
||||||
data_type="device_id",
|
|
||||||
label="目标设备",
|
|
||||||
data_key="target_device",
|
|
||||||
data_source=DataSource.EXECUTOR,
|
|
||||||
),
|
|
||||||
ActionOutputHandle(
|
|
||||||
# TEMP frontend-compat key: material/resource name.
|
|
||||||
key="resource",
|
key="resource",
|
||||||
data_type="resource",
|
data_type="resource",
|
||||||
label="待装载物料",
|
label="待装载物料",
|
||||||
@@ -592,6 +575,7 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
"success": self._create_result_success(parsed_result, order_ids, material_records),
|
"success": self._create_result_success(parsed_result, order_ids, material_records),
|
||||||
"order_code": resolved_order_code,
|
"order_code": resolved_order_code,
|
||||||
"order_name": resolved_order_name,
|
"order_name": resolved_order_name,
|
||||||
|
"order_id": order_ids[0] if order_ids else "",
|
||||||
"order_ids": order_ids,
|
"order_ids": order_ids,
|
||||||
"target_device": target_device,
|
"target_device": target_device,
|
||||||
"workflow": workflow,
|
"workflow": workflow,
|
||||||
@@ -657,7 +641,6 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
node_type=NodeType.MANUAL_CONFIRM,
|
node_type=NodeType.MANUAL_CONFIRM,
|
||||||
placeholder_keys={
|
placeholder_keys={
|
||||||
"resource": "unilabos_resources",
|
"resource": "unilabos_resources",
|
||||||
"target_device": "unilabos_devices",
|
|
||||||
"mount_resource": "unilabos_resources",
|
"mount_resource": "unilabos_resources",
|
||||||
"assignee_user_ids": "unilabos_manual_confirm",
|
"assignee_user_ids": "unilabos_manual_confirm",
|
||||||
},
|
},
|
||||||
@@ -670,14 +653,7 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
description="请核对并装载实验物料;勾选装载确认后方可启动调度",
|
description="请核对并装载实验物料;勾选装载确认后方可启动调度",
|
||||||
handles=[
|
handles=[
|
||||||
ActionInputHandle(
|
ActionInputHandle(
|
||||||
key="target_device",
|
# TEMP frontend-compat key: material/resource name (renderer compat).
|
||||||
data_type="device_id",
|
|
||||||
label="目标设备",
|
|
||||||
data_key="target_device",
|
|
||||||
data_source=DataSource.HANDLE,
|
|
||||||
io_type="source",
|
|
||||||
),
|
|
||||||
ActionInputHandle(
|
|
||||||
key="resource",
|
key="resource",
|
||||||
data_type="resource",
|
data_type="resource",
|
||||||
label="待装载物料",
|
label="待装载物料",
|
||||||
@@ -705,8 +681,8 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
),
|
),
|
||||||
# Order metadata for scheduler start.
|
# Order metadata for scheduler start.
|
||||||
ActionInputHandle(
|
ActionInputHandle(
|
||||||
key="order_ids", data_type="bioyond_order_ids",
|
key="order_id", data_type="bioyond_order_id",
|
||||||
label="实验ID", data_key="order_ids",
|
label="实验ID", data_key="order_id",
|
||||||
data_source=DataSource.HANDLE,
|
data_source=DataSource.HANDLE,
|
||||||
io_type="source",
|
io_type="source",
|
||||||
),
|
),
|
||||||
@@ -714,23 +690,29 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
)
|
)
|
||||||
def start_experiment(
|
def start_experiment(
|
||||||
self,
|
self,
|
||||||
target_device: DeviceSlot = "",
|
|
||||||
resource: Optional[List[ResourceSlot]] = None,
|
|
||||||
coin_cell_code: Optional[List[str]] = None,
|
|
||||||
mount_resource: Optional[List[ResourceSlot]] = None,
|
|
||||||
submit_experiment_result: Optional[Dict[str, Any]] = None,
|
|
||||||
order_id: str = "",
|
order_id: str = "",
|
||||||
order_ids: Optional[List[str]] = None,
|
|
||||||
materials_loaded: bool = False,
|
materials_loaded: bool = False,
|
||||||
api_host: str = "",
|
|
||||||
api_key: str = "",
|
|
||||||
ready_signal: str = "READY",
|
|
||||||
timeout_seconds: int = 3600,
|
timeout_seconds: int = 3600,
|
||||||
assignee_user_ids: Optional[List[str]] = None,
|
assignee_user_ids: Optional[List[str]] = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Guided manual-load checkpoint that gates ``rpc.scheduler_start()``."""
|
"""Guided manual-load checkpoint that gates ``rpc.scheduler_start()``.
|
||||||
del target_device, timeout_seconds, assignee_user_ids, kwargs
|
|
||||||
|
Args:
|
||||||
|
order_id: 上游 ``submit_experiment_1`` 创建的订单 ID(可选;若上游连接则自动传入)。
|
||||||
|
materials_loaded: 操作员勾选确认物料已装载。未勾选且存在物料显示则阻断启动。
|
||||||
|
timeout_seconds: 超时时间(秒,框架参数)。
|
||||||
|
assignee_user_ids: 分配用户 ID 列表(框架参数)。
|
||||||
|
"""
|
||||||
|
resource = kwargs.get("resource")
|
||||||
|
coin_cell_code = kwargs.get("coin_cell_code")
|
||||||
|
mount_resource = kwargs.get("mount_resource")
|
||||||
|
order_ids = kwargs.get("order_ids")
|
||||||
|
submit_experiment_result = kwargs.get("submit_experiment_result")
|
||||||
|
api_host = self._kwarg_text(kwargs, "api_host")
|
||||||
|
api_key = self._kwarg_text(kwargs, "api_key")
|
||||||
|
ready_signal = self._kwarg_text(kwargs, "ready_signal") or DEFAULT_READY_SIGNAL
|
||||||
|
del timeout_seconds, assignee_user_ids
|
||||||
self._update_runtime_api_config(api_host=api_host, api_key=api_key)
|
self._update_runtime_api_config(api_host=api_host, api_key=api_key)
|
||||||
self._require_ready_signal(ready_signal)
|
self._require_ready_signal(ready_signal)
|
||||||
|
|
||||||
@@ -768,6 +750,120 @@ class BioyondSirnaStation(BioyondWorkstation):
|
|||||||
"confirmation_message": "调度器启动成功" if result == 1 else "调度器启动失败,请检查 LIMS 状态",
|
"confirmation_message": "调度器启动成功" if result == 1 else "调度器启动失败,请检查 LIMS 状态",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@action(
|
||||||
|
always_free=True,
|
||||||
|
node_type=NodeType.MANUAL_CONFIRM,
|
||||||
|
placeholder_keys={"assignee_user_ids": "unilabos_manual_confirm"},
|
||||||
|
goal_default={
|
||||||
|
"filter_text": "",
|
||||||
|
"status": "",
|
||||||
|
"latest_only": True,
|
||||||
|
"max_results": 20,
|
||||||
|
"timeout_seconds": 3600,
|
||||||
|
"assignee_user_ids": [],
|
||||||
|
},
|
||||||
|
feedback_interval=300,
|
||||||
|
description="只读查询 Bioyond LIMS 订单列表,可作为下游节点的 order_id 来源",
|
||||||
|
handles=[
|
||||||
|
ActionOutputHandle(
|
||||||
|
key="order_id",
|
||||||
|
data_type="bioyond_order_id",
|
||||||
|
label="实验ID",
|
||||||
|
data_key="order_id",
|
||||||
|
data_source=DataSource.EXECUTOR,
|
||||||
|
),
|
||||||
|
ActionOutputHandle(
|
||||||
|
key="order_ids",
|
||||||
|
data_type="bioyond_order_ids",
|
||||||
|
label="实验ID列表",
|
||||||
|
data_key="order_ids",
|
||||||
|
data_source=DataSource.EXECUTOR,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def get_order_list(
|
||||||
|
self,
|
||||||
|
filter_text: str = "",
|
||||||
|
status: str = "",
|
||||||
|
latest_only: bool = True,
|
||||||
|
max_results: int = 20,
|
||||||
|
timeout_seconds: int = 3600,
|
||||||
|
assignee_user_ids: Optional[List[str]] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""只读查询 Bioyond LIMS 订单列表。
|
||||||
|
|
||||||
|
``api_host`` / ``api_key`` 隐藏不再作为前端可见参数;缺失会沿用现有 RPC 配置错误。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filter_text: 订单编号 / 名称模糊匹配字符串,对应 LIMS ``order_query.filter``。
|
||||||
|
status: 订单状态字段过滤值(透传给 ``order_query.status``,留空表示不过滤)。
|
||||||
|
latest_only: 默认 ``True``,仅返回最新(创建时间最大)的一条订单作为 ``order_id``。
|
||||||
|
max_results: 一次返回的最大订单条数(透传给 ``pageCount``,默认 20)。
|
||||||
|
timeout_seconds: 超时时间(秒,框架参数)。
|
||||||
|
assignee_user_ids: 分配用户 ID 列表(框架参数)。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``{"success": bool, "orders": [...], "order_id": str, "order_ids": [...], "query": {...}}``。
|
||||||
|
"""
|
||||||
|
del timeout_seconds, assignee_user_ids, kwargs
|
||||||
|
try:
|
||||||
|
normalized_max = int(max_results)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
normalized_max = 20
|
||||||
|
if normalized_max <= 0:
|
||||||
|
normalized_max = 20
|
||||||
|
rpc = self._require_hardware_interface("order_query")
|
||||||
|
query_payload = {
|
||||||
|
"timeType": "",
|
||||||
|
"beginTime": None,
|
||||||
|
"endTime": None,
|
||||||
|
"status": str(status or ""),
|
||||||
|
"filter": str(filter_text or ""),
|
||||||
|
"skipCount": 0,
|
||||||
|
"pageCount": normalized_max,
|
||||||
|
"sorting": "creationTime desc",
|
||||||
|
}
|
||||||
|
logger.info(
|
||||||
|
"正在查询 Bioyond LIMS 订单列表 filter=%r status=%r latest_only=%s",
|
||||||
|
filter_text,
|
||||||
|
status,
|
||||||
|
latest_only,
|
||||||
|
)
|
||||||
|
raw_result = rpc.order_query(json.dumps(query_payload, ensure_ascii=False))
|
||||||
|
items = self._order_items(raw_result)
|
||||||
|
|
||||||
|
orders: List[Dict[str, Any]] = []
|
||||||
|
for item in items:
|
||||||
|
order_id = str(item.get("id") or "")
|
||||||
|
if not order_id:
|
||||||
|
continue
|
||||||
|
orders.append({
|
||||||
|
"order_id": order_id,
|
||||||
|
"order_code": str(item.get("orderCode") or ""),
|
||||||
|
"order_name": str(item.get("name") or item.get("orderName") or ""),
|
||||||
|
"status": str(item.get("status") or item.get("statusName") or ""),
|
||||||
|
"created_at": str(item.get("creationTime") or item.get("createTime") or ""),
|
||||||
|
"raw": item,
|
||||||
|
})
|
||||||
|
|
||||||
|
order_ids = [order["order_id"] for order in orders]
|
||||||
|
if latest_only and orders:
|
||||||
|
chosen = orders[0]
|
||||||
|
order_id_value = chosen["order_id"]
|
||||||
|
elif len(order_ids) == 1:
|
||||||
|
order_id_value = order_ids[0]
|
||||||
|
else:
|
||||||
|
order_id_value = ""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"success": bool(orders),
|
||||||
|
"orders": orders,
|
||||||
|
"order_id": order_id_value,
|
||||||
|
"order_ids": order_ids,
|
||||||
|
"query": query_payload,
|
||||||
|
}
|
||||||
|
|
||||||
def _require_hardware_interface(self, method_name: str) -> Any:
|
def _require_hardware_interface(self, method_name: str) -> Any:
|
||||||
rpc = getattr(self, "hardware_interface", None)
|
rpc = getattr(self, "hardware_interface", None)
|
||||||
if rpc is None:
|
if rpc is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user