Squash merge from dev

Update recipe.yaml

fix: figure_resource

use call_async in all service to avoid deadlock

fix: prcxi import error

临时兼容错误的driver写法

fix protocol node

fix filter protocol

bugfixes on organic protocols

fix and remove redundant info

feat: 新增use_remote_resource参数

fix all protocol_compilers and remove deprecated devices

feat: 优化protocol node节点运行日志

fix pumps and liquid_handler handle

feat: workstation example

add: prcxi res
fix: startup slow

fix: prcxi_res

fix: discard_tips

fix: discard_tips error

fix: drop_tips not using auto resource select

feat: 添加ChinWe设备控制类,支持串口通信和电机控制功能 (#79)

feat: add trace log level

modify default discovery_interval to 15s

fix: working dir error when input config path
feat: report publish topic when error

fix: workstation handlers and vessel_id parsing

Cleanup registry to be easy-understanding (#76)

* delete deprecated mock devices

* rename categories

* combine chromatographic devices

* rename rviz simulation nodes

* organic virtual devices

* parse vessel_id

* run registry completion before merge

---------

Co-authored-by: Xuwznln <18435084+Xuwznln@users.noreply.github.com>
This commit is contained in:
Junhan Chang
2025-08-03 11:21:37 +08:00
committed by Xuwznln
parent a555c59dc2
commit 0bfb52df00
97 changed files with 5033 additions and 164837 deletions

View File

@@ -138,6 +138,8 @@ class LiquidHandlerMiddleware(LiquidHandler):
offsets: Optional[List[Coordinate]] = None,
**backend_kwargs,
):
if not offsets or (isinstance(offsets, list) and len(offsets) != len(use_channels)):
offsets = [Coordinate.zero()] * len(use_channels)
if self._simulator:
return await self._simulate_handler.discard_tips(use_channels, allow_nonzero_volume, offsets, **backend_kwargs)
return await super().discard_tips(use_channels, allow_nonzero_volume, offsets, **backend_kwargs)

View File

@@ -67,7 +67,7 @@ class PRCXI9300Deck(Deck):
class PRCXI9300Container(Plate, TipRack):
"""PRCXI 9300 的专用 Deck 类,继承自 Deck。
"""PRCXI 9300 的专用 Container 类,继承自 Plate和TipRack。
该类定义了 PRCXI 9300 的工作台布局和槽位信息。
"""

View File

@@ -0,0 +1,44 @@
import collections
from pylabrobot.resources import opentrons_96_tiprack_10ul
from pylabrobot.resources.opentrons.plates import corning_96_wellplate_360ul_flat, nest_96_wellplate_2ml_deep
from unilabos.devices.liquid_handling.prcxi.prcxi import PRCXI9300Container, PRCXI9300Trash
def get_well_container(name: str) -> PRCXI9300Container:
well_containers = corning_96_wellplate_360ul_flat(name).serialize()
plate = PRCXI9300Container(name=name, size_x=50, size_y=50, size_z=10, category="plate",
ordering=collections.OrderedDict())
plate_serialized = plate.serialize()
well_containers.update({k: v for k, v in plate_serialized.items() if k not in ["children"]})
new_plate: PRCXI9300Container = PRCXI9300Container.deserialize(well_containers)
return new_plate
def get_tip_rack(name: str) -> PRCXI9300Container:
tip_racks = opentrons_96_tiprack_10ul("name").serialize()
tip_rack = PRCXI9300Container(name=name, size_x=50, size_y=50, size_z=10, category="tip_rack",
ordering=collections.OrderedDict())
tip_rack_serialized = tip_rack.serialize()
tip_racks.update({k: v for k, v in tip_rack_serialized.items() if k not in ["children"]})
new_tip_rack: PRCXI9300Container = PRCXI9300Container.deserialize(tip_racks)
return new_tip_rack
def prcxi_96_wellplate_360ul_flat(name: str):
return get_well_container(name)
def prcxi_opentrons_96_tiprack_10ul(name: str):
return get_tip_rack(name)
def prcxi_trash(name: str = None):
return PRCXI9300Trash(name="trash", size_x=50, size_y=50, size_z=10, category="trash")
if __name__ == "__main__":
# Example usage
test_plate = prcxi_96_wellplate_360ul_flat("test_plate")
test_rack = prcxi_opentrons_96_tiprack_10ul("test_rack")
tash = prcxi_trash("trash")
print(test_plate)
print(test_rack)
print(tash)
# Output will be a dictionary representation of the PRCXI9300Container with well details