mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-07 15:35:10 +00:00
Adapt to new scheduler.
This commit is contained in:
@@ -54,7 +54,7 @@ class JobAddReq(BaseModel):
|
|||||||
action_type: str = Field(
|
action_type: str = Field(
|
||||||
examples=["unilabos_msgs.action._str_single_input.StrSingleInput"], description="action type", default=""
|
examples=["unilabos_msgs.action._str_single_input.StrSingleInput"], description="action type", default=""
|
||||||
)
|
)
|
||||||
sample_material: dict = Field(examples=[{"string": "string"}], description="sample uuid to material uuid", default_factory=dict)
|
sample_material: dict = Field(examples=[{"string": "string"}], description="sample uuid to material uuid")
|
||||||
action_args: dict = Field(examples=[{"string": "string"}], description="action arguments", default_factory=dict)
|
action_args: dict = Field(examples=[{"string": "string"}], description="action arguments", default_factory=dict)
|
||||||
task_id: str = Field(examples=["task_id"], description="task uuid (auto-generated if empty)", default="")
|
task_id: str = Field(examples=["task_id"], description="task uuid (auto-generated if empty)", default="")
|
||||||
job_id: str = Field(examples=["job_id"], description="goal uuid (auto-generated if empty)", default="")
|
job_id: str = Field(examples=["job_id"], description="goal uuid (auto-generated if empty)", default="")
|
||||||
|
|||||||
@@ -657,6 +657,8 @@ class MessageProcessor:
|
|||||||
async def _handle_job_start(self, data: Dict[str, Any]):
|
async def _handle_job_start(self, data: Dict[str, Any]):
|
||||||
"""处理job_start消息"""
|
"""处理job_start消息"""
|
||||||
try:
|
try:
|
||||||
|
if not data.get("sample_material"):
|
||||||
|
data["sample_material"] = {}
|
||||||
req = JobAddReq(**data)
|
req = JobAddReq(**data)
|
||||||
|
|
||||||
job_log = format_job_log(req.job_id, req.task_id, req.device_id, req.action)
|
job_log = format_job_log(req.job_id, req.task_id, req.device_id, req.action)
|
||||||
|
|||||||
@@ -690,16 +690,14 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def set_liquid_from_plate(
|
def set_liquid_from_plate(
|
||||||
self, plate: List[ResourceSlot], well_names: list[str], liquid_names: list[str], volumes: list[float]
|
self, plate: ResourceSlot, well_names: list[str], liquid_names: list[str], volumes: list[float]
|
||||||
) -> SetLiquidFromPlateReturn:
|
) -> SetLiquidFromPlateReturn:
|
||||||
"""Set the liquid in wells of a plate by well names (e.g., A1, A2, B3).
|
"""Set the liquid in wells of a plate by well names (e.g., A1, A2, B3).
|
||||||
|
|
||||||
如果 liquid_names 和 volumes 为空,但 plate 和 well_names 不为空,直接返回 plate 和 wells。
|
如果 liquid_names 和 volumes 为空,但 plate 和 well_names 不为空,直接返回 plate 和 wells。
|
||||||
"""
|
"""
|
||||||
if isinstance(plate, list): # 未来移除
|
|
||||||
plate = plate[0]
|
|
||||||
assert issubclass(plate.__class__, Plate), "plate must be a Plate"
|
assert issubclass(plate.__class__, Plate), "plate must be a Plate"
|
||||||
plate: Plate = cast(Plate, plate)
|
plate: Plate = cast(Plate, cast(Resource, plate))
|
||||||
# 根据 well_names 获取对应的 Well 对象
|
# 根据 well_names 获取对应的 Well 对象
|
||||||
wells = [plate.get_well(name) for name in well_names]
|
wells = [plate.get_well(name) for name in well_names]
|
||||||
res_volumes = []
|
res_volumes = []
|
||||||
|
|||||||
@@ -595,7 +595,7 @@ class PRCXI9300Handler(LiquidHandlerAbstract):
|
|||||||
return super().set_liquid(wells, liquid_names, volumes)
|
return super().set_liquid(wells, liquid_names, volumes)
|
||||||
|
|
||||||
def set_liquid_from_plate(
|
def set_liquid_from_plate(
|
||||||
self, plate: List[ResourceSlot], well_names: list[str], liquid_names: list[str], volumes: list[float]
|
self, plate: ResourceSlot, well_names: list[str], liquid_names: list[str], volumes: list[float]
|
||||||
) -> SetLiquidFromPlateReturn:
|
) -> SetLiquidFromPlateReturn:
|
||||||
return super().set_liquid_from_plate(plate, well_names, liquid_names, volumes)
|
return super().set_liquid_from_plate(plate, well_names, liquid_names, volumes)
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Virtual Workbench Device - 模拟工作台设备
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional, List
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from threading import Lock, RLock
|
from threading import Lock, RLock
|
||||||
@@ -23,7 +23,7 @@ from typing_extensions import TypedDict
|
|||||||
|
|
||||||
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
|
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
|
||||||
from unilabos.utils.decorator import not_action
|
from unilabos.utils.decorator import not_action
|
||||||
from unilabos.resources.resource_tracker import SampleUUIDsType
|
from unilabos.resources.resource_tracker import SampleUUIDsType, LabSample, RETURN_UNILABOS_SAMPLES
|
||||||
|
|
||||||
|
|
||||||
# ============ TypedDict 返回类型定义 ============
|
# ============ TypedDict 返回类型定义 ============
|
||||||
@@ -37,6 +37,7 @@ class MoveToHeatingStationResult(TypedDict):
|
|||||||
material_id: str
|
material_id: str
|
||||||
material_number: int
|
material_number: int
|
||||||
message: str
|
message: str
|
||||||
|
unilabos_samples: List[LabSample]
|
||||||
|
|
||||||
|
|
||||||
class StartHeatingResult(TypedDict):
|
class StartHeatingResult(TypedDict):
|
||||||
@@ -47,6 +48,7 @@ class StartHeatingResult(TypedDict):
|
|||||||
material_id: str
|
material_id: str
|
||||||
material_number: int
|
material_number: int
|
||||||
message: str
|
message: str
|
||||||
|
unilabos_samples: List[LabSample]
|
||||||
|
|
||||||
|
|
||||||
class MoveToOutputResult(TypedDict):
|
class MoveToOutputResult(TypedDict):
|
||||||
@@ -55,6 +57,7 @@ class MoveToOutputResult(TypedDict):
|
|||||||
success: bool
|
success: bool
|
||||||
station_id: int
|
station_id: int
|
||||||
material_id: str
|
material_id: str
|
||||||
|
unilabos_samples: List[LabSample]
|
||||||
|
|
||||||
|
|
||||||
class PrepareMaterialsResult(TypedDict):
|
class PrepareMaterialsResult(TypedDict):
|
||||||
@@ -68,6 +71,7 @@ class PrepareMaterialsResult(TypedDict):
|
|||||||
material_4: int # 物料编号4
|
material_4: int # 物料编号4
|
||||||
material_5: int # 物料编号5
|
material_5: int # 物料编号5
|
||||||
message: str
|
message: str
|
||||||
|
unilabos_samples: List[LabSample]
|
||||||
|
|
||||||
|
|
||||||
# ============ 状态枚举 ============
|
# ============ 状态枚举 ============
|
||||||
@@ -325,6 +329,7 @@ class VirtualWorkbench:
|
|||||||
"material_4": materials[3] if len(materials) > 3 else 0,
|
"material_4": materials[3] if len(materials) > 3 else 0,
|
||||||
"material_5": materials[4] if len(materials) > 4 else 0,
|
"material_5": materials[4] if len(materials) > 4 else 0,
|
||||||
"message": f"已准备 {count} 个物料: A1-A{count}",
|
"message": f"已准备 {count} 个物料: A1-A{count}",
|
||||||
|
"unilabos_samples": [LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
def move_to_heating_station(
|
def move_to_heating_station(
|
||||||
@@ -406,6 +411,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": material_id,
|
"material_id": material_id,
|
||||||
"material_number": material_number,
|
"material_number": material_number,
|
||||||
"message": f"{material_id}已成功移动到加热台{station_id}",
|
"message": f"{material_id}已成功移动到加热台{station_id}",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -418,6 +426,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": material_id,
|
"material_id": material_id,
|
||||||
"material_number": material_number,
|
"material_number": material_number,
|
||||||
"message": f"移动失败: {str(e)}",
|
"message": f"移动失败: {str(e)}",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
def start_heating(
|
def start_heating(
|
||||||
@@ -445,6 +456,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": "",
|
"material_id": "",
|
||||||
"material_number": material_number,
|
"material_number": material_number,
|
||||||
"message": f"无效的加热台ID: {station_id}",
|
"message": f"无效的加热台ID: {station_id}",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
with self._stations_lock:
|
with self._stations_lock:
|
||||||
@@ -457,6 +471,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": "",
|
"material_id": "",
|
||||||
"material_number": material_number,
|
"material_number": material_number,
|
||||||
"message": f"加热台{station_id}上没有物料",
|
"message": f"加热台{station_id}上没有物料",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
if station.state == HeatingStationState.HEATING:
|
if station.state == HeatingStationState.HEATING:
|
||||||
@@ -466,6 +483,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": station.current_material,
|
"material_id": station.current_material,
|
||||||
"material_number": material_number,
|
"material_number": material_number,
|
||||||
"message": f"加热台{station_id}已经在加热中",
|
"message": f"加热台{station_id}已经在加热中",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
material_id = station.current_material
|
material_id = station.current_material
|
||||||
@@ -515,6 +535,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": material_id,
|
"material_id": material_id,
|
||||||
"material_number": material_number,
|
"material_number": material_number,
|
||||||
"message": f"加热台{station_id}加热完成",
|
"message": f"加热台{station_id}加热完成",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
def move_to_output(
|
def move_to_output(
|
||||||
@@ -542,6 +565,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": "",
|
"material_id": "",
|
||||||
"output_position": f"C{output_number}",
|
"output_position": f"C{output_number}",
|
||||||
"message": f"无效的加热台ID: {station_id}",
|
"message": f"无效的加热台ID: {station_id}",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
with self._stations_lock:
|
with self._stations_lock:
|
||||||
@@ -555,6 +581,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": "",
|
"material_id": "",
|
||||||
"output_position": f"C{output_number}",
|
"output_position": f"C{output_number}",
|
||||||
"message": f"加热台{station_id}上没有物料",
|
"message": f"加热台{station_id}上没有物料",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
if station.state != HeatingStationState.COMPLETED:
|
if station.state != HeatingStationState.COMPLETED:
|
||||||
@@ -564,6 +593,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": material_id,
|
"material_id": material_id,
|
||||||
"output_position": f"C{output_number}",
|
"output_position": f"C{output_number}",
|
||||||
"message": f"加热台{station_id}尚未完成加热 (当前状态: {station.state.value})",
|
"message": f"加热台{station_id}尚未完成加热 (当前状态: {station.state.value})",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
output_position = f"C{output_number}"
|
output_position = f"C{output_number}"
|
||||||
@@ -612,6 +644,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": material_id,
|
"material_id": material_id,
|
||||||
"output_position": output_position,
|
"output_position": output_position,
|
||||||
"message": f"{material_id}已成功移动到{output_position}",
|
"message": f"{material_id}已成功移动到{output_position}",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -624,6 +659,9 @@ class VirtualWorkbench:
|
|||||||
"material_id": "",
|
"material_id": "",
|
||||||
"output_position": output_position,
|
"output_position": output_position,
|
||||||
"message": f"移动失败: {str(e)}",
|
"message": f"移动失败: {str(e)}",
|
||||||
|
"unilabos_samples": [
|
||||||
|
LabSample(sample_uuid=sample_uuid, oss_path="", extra={"material_uuid": content} if isinstance(content, str) else content.serialize()) for
|
||||||
|
sample_uuid, content in sample_uuids.items()]
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 状态属性 ============
|
# ============ 状态属性 ============
|
||||||
|
|||||||
@@ -9468,7 +9468,7 @@ liquid_handler.prcxi:
|
|||||||
well_names: null
|
well_names: null
|
||||||
handles:
|
handles:
|
||||||
input:
|
input:
|
||||||
- data_key: plate
|
- data_key: '@this.0@@@plate'
|
||||||
data_source: handle
|
data_source: handle
|
||||||
data_type: resource
|
data_type: resource
|
||||||
handler_key: input_plate
|
handler_key: input_plate
|
||||||
@@ -9503,81 +9503,78 @@ liquid_handler.prcxi:
|
|||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
plate:
|
plate:
|
||||||
items:
|
properties:
|
||||||
properties:
|
category:
|
||||||
category:
|
type: string
|
||||||
|
children:
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
children:
|
type: array
|
||||||
items:
|
config:
|
||||||
type: string
|
type: string
|
||||||
type: array
|
data:
|
||||||
config:
|
type: string
|
||||||
type: string
|
id:
|
||||||
data:
|
type: string
|
||||||
type: string
|
name:
|
||||||
id:
|
type: string
|
||||||
type: string
|
parent:
|
||||||
name:
|
type: string
|
||||||
type: string
|
pose:
|
||||||
parent:
|
properties:
|
||||||
type: string
|
orientation:
|
||||||
pose:
|
properties:
|
||||||
properties:
|
w:
|
||||||
orientation:
|
type: number
|
||||||
properties:
|
x:
|
||||||
w:
|
type: number
|
||||||
type: number
|
y:
|
||||||
x:
|
type: number
|
||||||
type: number
|
z:
|
||||||
y:
|
type: number
|
||||||
type: number
|
required:
|
||||||
z:
|
- x
|
||||||
type: number
|
- y
|
||||||
required:
|
- z
|
||||||
- x
|
- w
|
||||||
- y
|
title: orientation
|
||||||
- z
|
type: object
|
||||||
- w
|
position:
|
||||||
title: orientation
|
properties:
|
||||||
type: object
|
x:
|
||||||
position:
|
type: number
|
||||||
properties:
|
y:
|
||||||
x:
|
type: number
|
||||||
type: number
|
z:
|
||||||
y:
|
type: number
|
||||||
type: number
|
required:
|
||||||
z:
|
- x
|
||||||
type: number
|
- y
|
||||||
required:
|
- z
|
||||||
- x
|
title: position
|
||||||
- y
|
type: object
|
||||||
- z
|
required:
|
||||||
title: position
|
- position
|
||||||
type: object
|
- orientation
|
||||||
required:
|
title: pose
|
||||||
- position
|
type: object
|
||||||
- orientation
|
sample_id:
|
||||||
title: pose
|
type: string
|
||||||
type: object
|
type:
|
||||||
sample_id:
|
type: string
|
||||||
type: string
|
required:
|
||||||
type:
|
- id
|
||||||
type: string
|
- name
|
||||||
required:
|
- sample_id
|
||||||
- id
|
- children
|
||||||
- name
|
- parent
|
||||||
- sample_id
|
- type
|
||||||
- children
|
- category
|
||||||
- parent
|
- pose
|
||||||
- type
|
- config
|
||||||
- category
|
- data
|
||||||
- pose
|
|
||||||
- config
|
|
||||||
- data
|
|
||||||
title: plate
|
|
||||||
type: object
|
|
||||||
title: plate
|
title: plate
|
||||||
type: array
|
type: object
|
||||||
volumes:
|
volumes:
|
||||||
items:
|
items:
|
||||||
type: number
|
type: number
|
||||||
@@ -9593,17 +9590,207 @@ liquid_handler.prcxi:
|
|||||||
- volumes
|
- volumes
|
||||||
type: object
|
type: object
|
||||||
result:
|
result:
|
||||||
|
$defs:
|
||||||
|
ResourceDict:
|
||||||
|
properties:
|
||||||
|
class:
|
||||||
|
description: Resource class name
|
||||||
|
title: Class
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
additionalProperties: true
|
||||||
|
description: Resource configuration
|
||||||
|
title: Config
|
||||||
|
type: object
|
||||||
|
data:
|
||||||
|
additionalProperties: true
|
||||||
|
description: 'Resource data, eg: container liquid data'
|
||||||
|
title: Data
|
||||||
|
type: object
|
||||||
|
description:
|
||||||
|
default: ''
|
||||||
|
description: Resource description
|
||||||
|
title: Description
|
||||||
|
type: string
|
||||||
|
extra:
|
||||||
|
additionalProperties: true
|
||||||
|
description: 'Extra data, eg: slot index'
|
||||||
|
title: Extra
|
||||||
|
type: object
|
||||||
|
icon:
|
||||||
|
default: ''
|
||||||
|
description: Resource icon
|
||||||
|
title: Icon
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
description: Resource ID
|
||||||
|
title: Id
|
||||||
|
type: string
|
||||||
|
model:
|
||||||
|
additionalProperties: true
|
||||||
|
description: Resource model
|
||||||
|
title: Model
|
||||||
|
type: object
|
||||||
|
name:
|
||||||
|
description: Resource name
|
||||||
|
title: Name
|
||||||
|
type: string
|
||||||
|
parent:
|
||||||
|
anyOf:
|
||||||
|
- $ref: '#/$defs/ResourceDict'
|
||||||
|
- type: 'null'
|
||||||
|
default: null
|
||||||
|
description: Parent resource object
|
||||||
|
parent_uuid:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
default: null
|
||||||
|
description: Parent resource uuid
|
||||||
|
title: Parent Uuid
|
||||||
|
pose:
|
||||||
|
$ref: '#/$defs/ResourceDictPosition'
|
||||||
|
description: Resource position
|
||||||
|
schema:
|
||||||
|
additionalProperties: true
|
||||||
|
description: Resource schema
|
||||||
|
title: Schema
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
anyOf:
|
||||||
|
- const: device
|
||||||
|
type: string
|
||||||
|
- type: string
|
||||||
|
description: Resource type
|
||||||
|
title: Type
|
||||||
|
uuid:
|
||||||
|
description: Resource UUID
|
||||||
|
title: Uuid
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- uuid
|
||||||
|
- name
|
||||||
|
- type
|
||||||
|
- class
|
||||||
|
- config
|
||||||
|
- data
|
||||||
|
- extra
|
||||||
|
title: ResourceDict
|
||||||
|
type: object
|
||||||
|
ResourceDictPosition:
|
||||||
|
properties:
|
||||||
|
cross_section_type:
|
||||||
|
default: rectangle
|
||||||
|
description: Cross section type
|
||||||
|
enum:
|
||||||
|
- rectangle
|
||||||
|
- circle
|
||||||
|
- rounded_rectangle
|
||||||
|
title: Cross Section Type
|
||||||
|
type: string
|
||||||
|
layout:
|
||||||
|
default: x-y
|
||||||
|
description: Resource layout
|
||||||
|
enum:
|
||||||
|
- 2d
|
||||||
|
- x-y
|
||||||
|
- z-y
|
||||||
|
- x-z
|
||||||
|
title: Layout
|
||||||
|
type: string
|
||||||
|
position:
|
||||||
|
$ref: '#/$defs/ResourceDictPositionObject'
|
||||||
|
description: Resource position
|
||||||
|
position3d:
|
||||||
|
$ref: '#/$defs/ResourceDictPositionObject'
|
||||||
|
description: Resource position in 3D space
|
||||||
|
rotation:
|
||||||
|
$ref: '#/$defs/ResourceDictPositionObject'
|
||||||
|
description: Resource rotation
|
||||||
|
scale:
|
||||||
|
$ref: '#/$defs/ResourceDictPositionScale'
|
||||||
|
description: Resource scale
|
||||||
|
size:
|
||||||
|
$ref: '#/$defs/ResourceDictPositionSize'
|
||||||
|
description: Resource size
|
||||||
|
title: ResourceDictPosition
|
||||||
|
type: object
|
||||||
|
ResourceDictPositionObject:
|
||||||
|
properties:
|
||||||
|
x:
|
||||||
|
default: 0.0
|
||||||
|
description: X coordinate
|
||||||
|
title: X
|
||||||
|
type: number
|
||||||
|
y:
|
||||||
|
default: 0.0
|
||||||
|
description: Y coordinate
|
||||||
|
title: Y
|
||||||
|
type: number
|
||||||
|
z:
|
||||||
|
default: 0.0
|
||||||
|
description: Z coordinate
|
||||||
|
title: Z
|
||||||
|
type: number
|
||||||
|
title: ResourceDictPositionObject
|
||||||
|
type: object
|
||||||
|
ResourceDictPositionScale:
|
||||||
|
properties:
|
||||||
|
x:
|
||||||
|
default: 0.0
|
||||||
|
description: x scale
|
||||||
|
title: X
|
||||||
|
type: number
|
||||||
|
y:
|
||||||
|
default: 0.0
|
||||||
|
description: y scale
|
||||||
|
title: Y
|
||||||
|
type: number
|
||||||
|
z:
|
||||||
|
default: 0.0
|
||||||
|
description: z scale
|
||||||
|
title: Z
|
||||||
|
type: number
|
||||||
|
title: ResourceDictPositionScale
|
||||||
|
type: object
|
||||||
|
ResourceDictPositionSize:
|
||||||
|
properties:
|
||||||
|
depth:
|
||||||
|
default: 0.0
|
||||||
|
description: Depth
|
||||||
|
title: Depth
|
||||||
|
type: number
|
||||||
|
height:
|
||||||
|
default: 0.0
|
||||||
|
description: Height
|
||||||
|
title: Height
|
||||||
|
type: number
|
||||||
|
width:
|
||||||
|
default: 0.0
|
||||||
|
description: Width
|
||||||
|
title: Width
|
||||||
|
type: number
|
||||||
|
title: ResourceDictPositionSize
|
||||||
|
type: object
|
||||||
properties:
|
properties:
|
||||||
plate:
|
plate:
|
||||||
items: {}
|
items:
|
||||||
|
items:
|
||||||
|
$ref: '#/$defs/ResourceDict'
|
||||||
|
type: array
|
||||||
title: Plate
|
title: Plate
|
||||||
type: array
|
type: array
|
||||||
volumes:
|
volumes:
|
||||||
items: {}
|
items:
|
||||||
|
type: number
|
||||||
title: Volumes
|
title: Volumes
|
||||||
type: array
|
type: array
|
||||||
wells:
|
wells:
|
||||||
items: {}
|
items:
|
||||||
|
items:
|
||||||
|
$ref: '#/$defs/ResourceDict'
|
||||||
|
type: array
|
||||||
title: Wells
|
title: Wells
|
||||||
type: array
|
type: array
|
||||||
required:
|
required:
|
||||||
|
|||||||
@@ -5835,6 +5835,25 @@ virtual_workbench:
|
|||||||
- material_number
|
- material_number
|
||||||
type: object
|
type: object
|
||||||
result:
|
result:
|
||||||
|
$defs:
|
||||||
|
LabSample:
|
||||||
|
properties:
|
||||||
|
extra:
|
||||||
|
additionalProperties: true
|
||||||
|
title: Extra
|
||||||
|
type: object
|
||||||
|
oss_path:
|
||||||
|
title: Oss Path
|
||||||
|
type: string
|
||||||
|
sample_uuid:
|
||||||
|
title: Sample Uuid
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- sample_uuid
|
||||||
|
- oss_path
|
||||||
|
- extra
|
||||||
|
title: LabSample
|
||||||
|
type: object
|
||||||
description: move_to_heating_station 返回类型
|
description: move_to_heating_station 返回类型
|
||||||
properties:
|
properties:
|
||||||
material_id:
|
material_id:
|
||||||
@@ -5853,12 +5872,18 @@ virtual_workbench:
|
|||||||
success:
|
success:
|
||||||
title: Success
|
title: Success
|
||||||
type: boolean
|
type: boolean
|
||||||
|
unilabos_samples:
|
||||||
|
items:
|
||||||
|
$ref: '#/$defs/LabSample'
|
||||||
|
title: Unilabos Samples
|
||||||
|
type: array
|
||||||
required:
|
required:
|
||||||
- success
|
- success
|
||||||
- station_id
|
- station_id
|
||||||
- material_id
|
- material_id
|
||||||
- material_number
|
- material_number
|
||||||
- message
|
- message
|
||||||
|
- unilabos_samples
|
||||||
title: MoveToHeatingStationResult
|
title: MoveToHeatingStationResult
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
@@ -5903,6 +5928,25 @@ virtual_workbench:
|
|||||||
- material_number
|
- material_number
|
||||||
type: object
|
type: object
|
||||||
result:
|
result:
|
||||||
|
$defs:
|
||||||
|
LabSample:
|
||||||
|
properties:
|
||||||
|
extra:
|
||||||
|
additionalProperties: true
|
||||||
|
title: Extra
|
||||||
|
type: object
|
||||||
|
oss_path:
|
||||||
|
title: Oss Path
|
||||||
|
type: string
|
||||||
|
sample_uuid:
|
||||||
|
title: Sample Uuid
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- sample_uuid
|
||||||
|
- oss_path
|
||||||
|
- extra
|
||||||
|
title: LabSample
|
||||||
|
type: object
|
||||||
description: move_to_output 返回类型
|
description: move_to_output 返回类型
|
||||||
properties:
|
properties:
|
||||||
material_id:
|
material_id:
|
||||||
@@ -5914,10 +5958,16 @@ virtual_workbench:
|
|||||||
success:
|
success:
|
||||||
title: Success
|
title: Success
|
||||||
type: boolean
|
type: boolean
|
||||||
|
unilabos_samples:
|
||||||
|
items:
|
||||||
|
$ref: '#/$defs/LabSample'
|
||||||
|
title: Unilabos Samples
|
||||||
|
type: array
|
||||||
required:
|
required:
|
||||||
- success
|
- success
|
||||||
- station_id
|
- station_id
|
||||||
- material_id
|
- material_id
|
||||||
|
- unilabos_samples
|
||||||
title: MoveToOutputResult
|
title: MoveToOutputResult
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
@@ -5972,6 +6022,25 @@ virtual_workbench:
|
|||||||
required: []
|
required: []
|
||||||
type: object
|
type: object
|
||||||
result:
|
result:
|
||||||
|
$defs:
|
||||||
|
LabSample:
|
||||||
|
properties:
|
||||||
|
extra:
|
||||||
|
additionalProperties: true
|
||||||
|
title: Extra
|
||||||
|
type: object
|
||||||
|
oss_path:
|
||||||
|
title: Oss Path
|
||||||
|
type: string
|
||||||
|
sample_uuid:
|
||||||
|
title: Sample Uuid
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- sample_uuid
|
||||||
|
- oss_path
|
||||||
|
- extra
|
||||||
|
title: LabSample
|
||||||
|
type: object
|
||||||
description: prepare_materials 返回类型 - 批量准备物料
|
description: prepare_materials 返回类型 - 批量准备物料
|
||||||
properties:
|
properties:
|
||||||
count:
|
count:
|
||||||
@@ -5998,6 +6067,11 @@ virtual_workbench:
|
|||||||
success:
|
success:
|
||||||
title: Success
|
title: Success
|
||||||
type: boolean
|
type: boolean
|
||||||
|
unilabos_samples:
|
||||||
|
items:
|
||||||
|
$ref: '#/$defs/LabSample'
|
||||||
|
title: Unilabos Samples
|
||||||
|
type: array
|
||||||
required:
|
required:
|
||||||
- success
|
- success
|
||||||
- count
|
- count
|
||||||
@@ -6007,6 +6081,7 @@ virtual_workbench:
|
|||||||
- material_4
|
- material_4
|
||||||
- material_5
|
- material_5
|
||||||
- message
|
- message
|
||||||
|
- unilabos_samples
|
||||||
title: PrepareMaterialsResult
|
title: PrepareMaterialsResult
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
@@ -6062,6 +6137,25 @@ virtual_workbench:
|
|||||||
- material_number
|
- material_number
|
||||||
type: object
|
type: object
|
||||||
result:
|
result:
|
||||||
|
$defs:
|
||||||
|
LabSample:
|
||||||
|
properties:
|
||||||
|
extra:
|
||||||
|
additionalProperties: true
|
||||||
|
title: Extra
|
||||||
|
type: object
|
||||||
|
oss_path:
|
||||||
|
title: Oss Path
|
||||||
|
type: string
|
||||||
|
sample_uuid:
|
||||||
|
title: Sample Uuid
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- sample_uuid
|
||||||
|
- oss_path
|
||||||
|
- extra
|
||||||
|
title: LabSample
|
||||||
|
type: object
|
||||||
description: start_heating 返回类型
|
description: start_heating 返回类型
|
||||||
properties:
|
properties:
|
||||||
material_id:
|
material_id:
|
||||||
@@ -6079,12 +6173,18 @@ virtual_workbench:
|
|||||||
success:
|
success:
|
||||||
title: Success
|
title: Success
|
||||||
type: boolean
|
type: boolean
|
||||||
|
unilabos_samples:
|
||||||
|
items:
|
||||||
|
$ref: '#/$defs/LabSample'
|
||||||
|
title: Unilabos Samples
|
||||||
|
type: array
|
||||||
required:
|
required:
|
||||||
- success
|
- success
|
||||||
- station_id
|
- station_id
|
||||||
- material_id
|
- material_id
|
||||||
- material_number
|
- material_number
|
||||||
- message
|
- message
|
||||||
|
- unilabos_samples
|
||||||
title: StartHeatingResult
|
title: StartHeatingResult
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ from pydantic import BaseModel, field_serializer, field_validator, ValidationErr
|
|||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from typing import List, Tuple, Any, Dict, Literal, Optional, cast, TYPE_CHECKING, Union
|
from typing import List, Tuple, Any, Dict, Literal, Optional, cast, TYPE_CHECKING, Union
|
||||||
|
|
||||||
|
from typing_extensions import TypedDict
|
||||||
|
|
||||||
from unilabos.resources.plr_additional_res_reg import register
|
from unilabos.resources.plr_additional_res_reg import register
|
||||||
from unilabos.utils.log import logger
|
from unilabos.utils.log import logger
|
||||||
|
|
||||||
@@ -30,6 +32,12 @@ RETURN_UNILABOS_SAMPLES = "unilabos_samples"
|
|||||||
SampleUUIDsType = Dict[str, Optional["PLRResource"]]
|
SampleUUIDsType = Dict[str, Optional["PLRResource"]]
|
||||||
|
|
||||||
|
|
||||||
|
class LabSample(TypedDict):
|
||||||
|
sample_uuid: str
|
||||||
|
oss_path: str
|
||||||
|
extra: Dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
class ResourceDictPositionSize(BaseModel):
|
class ResourceDictPositionSize(BaseModel):
|
||||||
depth: float = Field(description="Depth", default=0.0) # z
|
depth: float = Field(description="Depth", default=0.0) # z
|
||||||
width: float = Field(description="Width", default=0.0) # x
|
width: float = Field(description="Width", default=0.0) # x
|
||||||
|
|||||||
@@ -863,7 +863,7 @@ class HostNode(BaseROS2DeviceNode):
|
|||||||
f"{[s.get('name', s.get('id', 'unknown')) if isinstance(s, dict) else str(s)[:20] for s in unilabos_samples[:5]]}"
|
f"{[s.get('name', s.get('id', 'unknown')) if isinstance(s, dict) else str(s)[:20] for s in unilabos_samples[:5]]}"
|
||||||
f"{'...' if len(unilabos_samples) > 5 else ''}"
|
f"{'...' if len(unilabos_samples) > 5 else ''}"
|
||||||
)
|
)
|
||||||
return_info[RETURN_UNILABOS_SAMPLES] = unilabos_samples
|
return_info["samples"] = unilabos_samples
|
||||||
suc = return_info.get("suc", False)
|
suc = return_info.get("suc", False)
|
||||||
if not suc:
|
if not suc:
|
||||||
status = "failed"
|
status = "failed"
|
||||||
|
|||||||
Reference in New Issue
Block a user