mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-05 14:05:12 +00:00
Compare commits
7 Commits
35fc2f5ea6
...
e92d933968
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e92d933968 | ||
|
|
f0ebcc60bb | ||
|
|
e2097f0b22 | ||
|
|
fd73731130 | ||
|
|
ab7f2081c9 | ||
|
|
9e850d8a81 | ||
|
|
1af6ffafc6 |
@@ -14,7 +14,7 @@ import socket
|
||||
|
||||
from urllib3 import response
|
||||
from unilabos.devices.workstation.workstation_base import WorkstationBase
|
||||
from unilabos.devices.workstation.bioyond_studio.station import BioyondWorkstation
|
||||
from unilabos.devices.workstation.bioyond_studio.station import BioyondWorkstation, BioyondResourceSynchronizer
|
||||
from unilabos.devices.workstation.bioyond_studio.config import (
|
||||
BIOYOND_FULL_CONFIG, WORKFLOW_MAPPINGS, MATERIAL_TYPE_MAPPINGS, WAREHOUSE_MAPPING
|
||||
)
|
||||
@@ -825,12 +825,206 @@ class BioyondCellWorkstation(BioyondWorkstation):
|
||||
logger.warning("超时未找到成功的物料转移任务")
|
||||
return False
|
||||
|
||||
def create_solid_materials(self, material_names: List[str], type_id: str = "3a190ca0-b2f6-9aeb-8067-547e72c11469") -> List[Dict[str, Any]]:
|
||||
"""
|
||||
批量创建固体物料
|
||||
|
||||
Args:
|
||||
material_names: 物料名称列表
|
||||
type_id: 物料类型ID(默认为固体物料类型)
|
||||
|
||||
Returns:
|
||||
创建的物料列表,每个元素包含物料信息和ID
|
||||
"""
|
||||
created_materials = []
|
||||
total = len(material_names)
|
||||
|
||||
for i, name in enumerate(material_names, 1):
|
||||
# 根据接口文档构建完整的请求体
|
||||
material_data = {
|
||||
"typeId": type_id,
|
||||
"name": name,
|
||||
"unit": "g", # 添加单位
|
||||
"quantity": 1, # 添加数量(默认1)
|
||||
"parameters": "" # 参数字段(空字符串表示无参数)
|
||||
}
|
||||
|
||||
logger.info(f"正在创建第 {i}/{total} 个固体物料: {name}")
|
||||
result = self._post_lims("/api/lims/storage/material", material_data)
|
||||
|
||||
if result and result.get("code") == 1:
|
||||
# data 字段可能是字符串(物料ID)或字典(包含id字段)
|
||||
data = result.get("data")
|
||||
if isinstance(data, str):
|
||||
# data 直接是物料ID字符串
|
||||
material_id = data
|
||||
elif isinstance(data, dict):
|
||||
# data 是字典,包含id字段
|
||||
material_id = data.get("id")
|
||||
else:
|
||||
material_id = None
|
||||
|
||||
if material_id:
|
||||
created_materials.append({
|
||||
"name": name,
|
||||
"materialId": material_id,
|
||||
"typeId": type_id
|
||||
})
|
||||
logger.info(f"✓ 成功创建物料: {name}, ID: {material_id}")
|
||||
else:
|
||||
logger.error(f"✗ 创建物料失败: {name}, 未返回ID")
|
||||
logger.error(f" 响应数据: {result}")
|
||||
else:
|
||||
error_msg = result.get("error") or result.get("message", "未知错误")
|
||||
logger.error(f"✗ 创建物料失败: {name}")
|
||||
logger.error(f" 错误信息: {error_msg}")
|
||||
logger.error(f" 完整响应: {result}")
|
||||
|
||||
# 避免请求过快
|
||||
time.sleep(0.3)
|
||||
|
||||
logger.info(f"物料创建完成,成功创建 {len(created_materials)}/{total} 个固体物料")
|
||||
return created_materials
|
||||
|
||||
def _sync_materials_safe(self) -> bool:
|
||||
"""仅使用 BioyondResourceSynchronizer 执行同步(与 station.py 保持一致)。"""
|
||||
if hasattr(self, 'resource_synchronizer') and self.resource_synchronizer:
|
||||
try:
|
||||
return bool(self.resource_synchronizer.sync_from_external())
|
||||
except Exception as e:
|
||||
logger.error(f"同步失败: {e}")
|
||||
return False
|
||||
logger.warning("资源同步器未初始化")
|
||||
return False
|
||||
|
||||
def _load_warehouse_locations(self, warehouse_name: str) -> tuple[List[str], List[str]]:
|
||||
"""从配置加载仓库位置信息
|
||||
|
||||
Args:
|
||||
warehouse_name: 仓库名称
|
||||
|
||||
Returns:
|
||||
(location_ids, position_names) 元组
|
||||
"""
|
||||
warehouse_mapping = self.bioyond_config.get("warehouse_mapping", WAREHOUSE_MAPPING)
|
||||
|
||||
if warehouse_name not in warehouse_mapping:
|
||||
raise ValueError(f"配置中未找到仓库: {warehouse_name}。可用: {list(warehouse_mapping.keys())}")
|
||||
|
||||
site_uuids = warehouse_mapping[warehouse_name].get("site_uuids", {})
|
||||
if not site_uuids:
|
||||
raise ValueError(f"仓库 {warehouse_name} 没有配置位置")
|
||||
|
||||
# 按顺序获取位置ID和名称
|
||||
location_ids = []
|
||||
position_names = []
|
||||
for key in sorted(site_uuids.keys()):
|
||||
location_ids.append(site_uuids[key])
|
||||
position_names.append(key)
|
||||
|
||||
return location_ids, position_names
|
||||
|
||||
|
||||
def create_and_inbound_materials(
|
||||
self,
|
||||
material_names: Optional[List[str]] = None,
|
||||
type_id: str = "3a190ca0-b2f6-9aeb-8067-547e72c11469",
|
||||
warehouse_name: str = "粉末加样头堆栈"
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
传参与默认列表方式创建物料并入库(不使用CSV)。
|
||||
|
||||
Args:
|
||||
material_names: 物料名称列表;默认使用 [LiPF6, LiDFOB, DTD, LiFSI, LiPO2F2]
|
||||
type_id: 物料类型ID
|
||||
warehouse_name: 目标仓库名(用于取位置信息)
|
||||
|
||||
Returns:
|
||||
执行结果字典
|
||||
"""
|
||||
logger.info("=" * 60)
|
||||
logger.info(f"开始执行:从参数创建物料并批量入库到 {warehouse_name}")
|
||||
logger.info("=" * 60)
|
||||
|
||||
try:
|
||||
# 1) 准备物料名称(默认值)
|
||||
default_materials = ["LiPF6", "LiDFOB", "DTD", "LiFSI", "LiPO2F2"]
|
||||
mat_names = [m.strip() for m in (material_names or default_materials) if str(m).strip()]
|
||||
if not mat_names:
|
||||
return {"success": False, "error": "物料名称列表为空"}
|
||||
|
||||
# 2) 加载仓库位置信息
|
||||
all_location_ids, position_names = self._load_warehouse_locations(warehouse_name)
|
||||
logger.info(f"✓ 加载 {len(all_location_ids)} 个位置 ({position_names[0]} ~ {position_names[-1]})")
|
||||
|
||||
# 限制数量不超过可用位置
|
||||
if len(mat_names) > len(all_location_ids):
|
||||
logger.warning(f"物料数量超出位置数量,仅处理前 {len(all_location_ids)} 个")
|
||||
mat_names = mat_names[:len(all_location_ids)]
|
||||
|
||||
# 3) 创建物料
|
||||
logger.info(f"\n【步骤1/3】创建 {len(mat_names)} 个固体物料...")
|
||||
created_materials = self.create_solid_materials(mat_names, type_id)
|
||||
if not created_materials:
|
||||
return {"success": False, "error": "没有成功创建任何物料"}
|
||||
|
||||
# 4) 批量入库
|
||||
logger.info(f"\n【步骤2/3】批量入库物料...")
|
||||
location_ids = all_location_ids[:len(created_materials)]
|
||||
selected_positions = position_names[:len(created_materials)]
|
||||
|
||||
inbound_items = [
|
||||
{"materialId": mat["materialId"], "locationId": loc_id}
|
||||
for mat, loc_id in zip(created_materials, location_ids)
|
||||
]
|
||||
|
||||
for material, position in zip(created_materials, selected_positions):
|
||||
logger.info(f" - {material['name']} → {position}")
|
||||
|
||||
result = self.storage_batch_inbound(inbound_items)
|
||||
if result.get("code") != 1:
|
||||
logger.error(f"✗ 批量入库失败: {result}")
|
||||
return {"success": False, "error": "批量入库失败", "created_materials": created_materials, "inbound_result": result}
|
||||
|
||||
logger.info("✓ 批量入库成功")
|
||||
|
||||
# 5) 同步
|
||||
logger.info(f"\n【步骤3/3】同步物料数据...")
|
||||
if self._sync_materials_safe():
|
||||
logger.info("✓ 物料数据同步完成")
|
||||
else:
|
||||
logger.warning("⚠ 物料数据同步未完成(可忽略,不影响已创建与入库的数据)")
|
||||
|
||||
logger.info("\n" + "=" * 60)
|
||||
logger.info("流程完成")
|
||||
logger.info("=" * 60 + "\n")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"created_materials": created_materials,
|
||||
"inbound_result": result,
|
||||
"total_created": len(created_materials),
|
||||
"total_inbound": len(inbound_items),
|
||||
"warehouse": warehouse_name,
|
||||
"positions": selected_positions
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"✗ 执行失败: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
|
||||
# --------------------------------
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ws = BioyondCellWorkstation()
|
||||
logger.info(ws.scheduler_start())
|
||||
#TODO:新建入库
|
||||
|
||||
# 从CSV文件读取物料列表并批量创建入库
|
||||
result = ws.create_and_inbound_materials()
|
||||
|
||||
# 继续后续流程
|
||||
logger.info(ws.auto_feeding4to3()) #搬运物料到3号箱
|
||||
# 使用正斜杠或 Path 对象来指定文件路径
|
||||
excel_path = Path("unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
material_name
|
||||
LiPF6
|
||||
LiDFOB
|
||||
DTD
|
||||
LiFSI
|
||||
LiPO2F2
|
||||
|
||||
|
@@ -25,8 +25,7 @@ BIOYOND_FULL_CONFIG = {
|
||||
# HTTP 服务配置
|
||||
"HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "0.0.0.0"), # HTTP服务监听地址(0.0.0.0 表示监听所有网络接口)
|
||||
"HTTP_port": int(os.getenv("BIOYOND_HTTP_PORT", "8080")),
|
||||
"report_ip": os.getenv("BIOYOND_REPORT_IP", "172.21.32.57"), # 报送给 Bioyond 的本机IP地址(留空则自动检测)
|
||||
|
||||
"report_ip": os.getenv("BIOYOND_REPORT_IP", "172.21.32.172"), # 报送给 Bioyond 的本机IP地址(留空则自动检测)
|
||||
# 调试模式
|
||||
"debug_mode": os.getenv("BIOYOND_DEBUG_MODE", "False").lower() == "true",
|
||||
}
|
||||
@@ -112,6 +111,31 @@ WAREHOUSE_MAPPING = {
|
||||
"B3": "3a14198c-c2d0-725e-523d-34c037ac2440",
|
||||
"B4": "3a14198c-c2d0-efce-0939-69ca5a7dfd39"
|
||||
}
|
||||
},
|
||||
"粉末加样头堆栈": {
|
||||
"uuid": "",
|
||||
"site_uuids": {
|
||||
"A01": "3a19da56-1379-20c8-5886-f7c4fbcb5733",
|
||||
"B01": "3a19da56-1379-2424-d751-fe6e94cef938",
|
||||
"C01": "3a19da56-1379-271c-03e3-6bdb590e395e",
|
||||
"D01": "3a19da56-1379-277f-2b1b-0d11f7cf92c6",
|
||||
"E01": "3a19da56-1379-2f1c-a15b-e01db90eb39a",
|
||||
"F01": "3a19da56-1379-3fa1-846b-088158ac0b3d",
|
||||
"G01": "3a19da56-1379-5aeb-d0cd-d3b4609d66e1",
|
||||
"H01": "3a19da56-1379-6077-8258-bdc036870b78",
|
||||
"I01": "3a19da56-1379-863b-a120-f606baf04617",
|
||||
"J01": "3a19da56-1379-8a74-74e5-35a9b41d4fd5",
|
||||
"K01": "3a19da56-1379-b270-b7af-f18773918abe",
|
||||
"L01": "3a19da56-1379-ba54-6d78-fd770a671ffc",
|
||||
"M01": "3a19da56-1379-c22d-c96f-0ceb5eb54a04",
|
||||
"N01": "3a19da56-1379-d64e-c6c5-c72ea4829888",
|
||||
"O01": "3a19da56-1379-d887-1a3c-6f9cce90f90e",
|
||||
"P01": "3a19da56-1379-e77d-0e65-7463b238a3b9",
|
||||
"Q01": "3a19da56-1379-edf6-1472-802ddb628774",
|
||||
"R01": "3a19da56-1379-f281-0273-e0ef78f0fd97",
|
||||
"S01": "3a19da56-1379-f924-7f68-df1fa51489f4",
|
||||
"T01": "3a19da56-1379-ff7c-1745-07e200b44ce2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +148,22 @@ MATERIAL_TYPE_MAPPINGS = {
|
||||
"样品瓶": ("BIOYOND_PolymerStation_Solid_Stock", "3a14196a-cf7d-8aea-48d8-b9662c7dba94"),
|
||||
"90%分装小瓶": ("BIOYOND_PolymerStation_Solid_Vial", "3a14196c-cdcf-088d-dc7d-5cf38f0ad9ea"),
|
||||
"10%分装小瓶": ("BIOYOND_PolymerStation_Liquid_Vial", "3a14196c-76be-2279-4e22-7310d69aed68"),
|
||||
"20ml分液瓶": ("BIOYOND_PolymerStation_6x20ml_DispensingVialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"),
|
||||
"100ml液体": ("BIOYOND_PolymerStation_100ml_Liquid_Bottle", "d37166b3-ecaa-481e-bd84-3032b795ba07"),
|
||||
"液": ("BIOYOND_PolymerStation_Liquid_Bottle", "3a190ca1-2add-2b23-f8e1-bbd348b7f790"),
|
||||
"高粘液": ("BIOYOND_PolymerStation_High_Viscosity_Liquid_Bottle", "abe8df30-563d-43d2-85e0-cabec59ddc16"),
|
||||
"加样头(大)": ("BIOYOND_PolymerStation_Large_Dispense_Head", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
|
||||
"5ml分液瓶板": ("BIOYOND_PolymerStation_6x5ml_DispensingVialCarrier", "3a192fa4-007d-ec7b-456e-2a8be7a13f23"),
|
||||
"5ml分液瓶": ("BIOYOND_PolymerStation_5ml_Dispensing_Vial", "3a192c2a-ebb7-58a1-480d-8b3863bf74f4"),
|
||||
"20ml分液瓶板": ("BIOYOND_PolymerStation_6x20ml_DispensingVialCarrier", "3a192fa4-47db-3449-162a-eaf8aba57e27"),
|
||||
"配液瓶(小)板": ("BIOYOND_PolymerStation_6x_SmallSolutionBottleCarrier", "3a190c8b-3284-af78-d29f-9a69463ad047"),
|
||||
"配液瓶(小)": ("BIOYOND_PolymerStation_Small_Solution_Bottle", "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"),
|
||||
"配液瓶(大)板": ("BIOYOND_PolymerStation_4x_LargeSolutionBottleCarrier", "53e50377-32dc-4781-b3c0-5ce45bc7dc27"),
|
||||
"配液瓶(大)": ("BIOYOND_PolymerStation_Large_Solution_Bottle", "19c52ad1-51c5-494f-8854-576f4ca9c6ca"),
|
||||
"加样头(大)板": ("BIOYOND_PolymerStation_6x_LargeDispenseHeadCarrier", "a8e714ae-2a4e-4eb9-9614-e4c140ec3f16"),
|
||||
"适配器块": ("BIOYOND_PolymerStation_AdapterBlock", "efc3bb32-d504-4890-91c0-b64ed3ac80cf"),
|
||||
"枪头盒": ("BIOYOND_PolymerStation_TipBox", "3a192c2e-20f3-a44a-0334-c8301839d0b3"),
|
||||
"枪头": ("BIOYOND_PolymerStation_Pipette_Tip", "b6196971-1050-46da-9927-333e8dea062d"),
|
||||
}
|
||||
|
||||
# 步骤参数配置(各工作流的步骤UUID)
|
||||
|
||||
@@ -283,7 +283,7 @@ def BIOYOND_PolymerStation_1FlaskCarrier(name: str) -> BottleCarrier:
|
||||
|
||||
|
||||
def BIOYOND_PolymerStation_6x5ml_DispensingVialCarrier(name: str) -> BottleCarrier:
|
||||
"""5ml分液瓶板 - 2x3布局,6个位置"""
|
||||
"""5ml分液瓶板 - 4x2布局,8个位置"""
|
||||
|
||||
# 载架尺寸 (mm)
|
||||
carrier_size_x = 127.8
|
||||
@@ -296,12 +296,12 @@ def BIOYOND_PolymerStation_6x5ml_DispensingVialCarrier(name: str) -> BottleCarri
|
||||
bottle_spacing_y = 35.0 # Y方向间距
|
||||
|
||||
# 计算起始位置 (居中排列)
|
||||
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_x = (carrier_size_x - (4 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
|
||||
|
||||
sites = create_ordered_items_2d(
|
||||
klass=ResourceHolder,
|
||||
num_items_x=3,
|
||||
num_items_x=4,
|
||||
num_items_y=2,
|
||||
dx=start_x,
|
||||
dy=start_y,
|
||||
@@ -323,17 +323,17 @@ def BIOYOND_PolymerStation_6x5ml_DispensingVialCarrier(name: str) -> BottleCarri
|
||||
sites=sites,
|
||||
model="6x5ml_DispensingVialCarrier",
|
||||
)
|
||||
carrier.num_items_x = 3
|
||||
carrier.num_items_x = 4
|
||||
carrier.num_items_y = 2
|
||||
carrier.num_items_z = 1
|
||||
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"]
|
||||
for i in range(6):
|
||||
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
|
||||
for i in range(8):
|
||||
carrier[i] = BIOYOND_PolymerStation_5ml_Dispensing_Vial(f"{name}_vial_{ordering[i]}")
|
||||
return carrier
|
||||
|
||||
|
||||
def BIOYOND_PolymerStation_6x20ml_DispensingVialCarrier(name: str) -> BottleCarrier:
|
||||
"""20ml分液瓶板 - 2x3布局,6个位置"""
|
||||
"""20ml分液瓶板 - 4x2布局,8个位置"""
|
||||
|
||||
# 载架尺寸 (mm)
|
||||
carrier_size_x = 127.8
|
||||
@@ -346,12 +346,12 @@ def BIOYOND_PolymerStation_6x20ml_DispensingVialCarrier(name: str) -> BottleCarr
|
||||
bottle_spacing_y = 35.0 # Y方向间距
|
||||
|
||||
# 计算起始位置 (居中排列)
|
||||
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_x = (carrier_size_x - (4 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
|
||||
|
||||
sites = create_ordered_items_2d(
|
||||
klass=ResourceHolder,
|
||||
num_items_x=3,
|
||||
num_items_x=4,
|
||||
num_items_y=2,
|
||||
dx=start_x,
|
||||
dy=start_y,
|
||||
@@ -373,17 +373,17 @@ def BIOYOND_PolymerStation_6x20ml_DispensingVialCarrier(name: str) -> BottleCarr
|
||||
sites=sites,
|
||||
model="6x20ml_DispensingVialCarrier",
|
||||
)
|
||||
carrier.num_items_x = 3
|
||||
carrier.num_items_x = 4
|
||||
carrier.num_items_y = 2
|
||||
carrier.num_items_z = 1
|
||||
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"]
|
||||
for i in range(6):
|
||||
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
|
||||
for i in range(8):
|
||||
carrier[i] = BIOYOND_PolymerStation_20ml_Dispensing_Vial(f"{name}_vial_{ordering[i]}")
|
||||
return carrier
|
||||
|
||||
|
||||
def BIOYOND_PolymerStation_6x_SmallSolutionBottleCarrier(name: str) -> BottleCarrier:
|
||||
"""配液瓶(小)板 - 2x3布局,6个位置"""
|
||||
"""配液瓶(小)板 - 4x2布局,8个位置"""
|
||||
|
||||
# 载架尺寸 (mm)
|
||||
carrier_size_x = 127.8
|
||||
@@ -396,12 +396,12 @@ def BIOYOND_PolymerStation_6x_SmallSolutionBottleCarrier(name: str) -> BottleCar
|
||||
bottle_spacing_y = 35.0 # Y方向间距
|
||||
|
||||
# 计算起始位置 (居中排列)
|
||||
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_x = (carrier_size_x - (4 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
|
||||
|
||||
sites = create_ordered_items_2d(
|
||||
klass=ResourceHolder,
|
||||
num_items_x=3,
|
||||
num_items_x=4,
|
||||
num_items_y=2,
|
||||
dx=start_x,
|
||||
dy=start_y,
|
||||
@@ -423,11 +423,11 @@ def BIOYOND_PolymerStation_6x_SmallSolutionBottleCarrier(name: str) -> BottleCar
|
||||
sites=sites,
|
||||
model="6x_SmallSolutionBottleCarrier",
|
||||
)
|
||||
carrier.num_items_x = 3
|
||||
carrier.num_items_x = 4
|
||||
carrier.num_items_y = 2
|
||||
carrier.num_items_z = 1
|
||||
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"]
|
||||
for i in range(6):
|
||||
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
|
||||
for i in range(8):
|
||||
carrier[i] = BIOYOND_PolymerStation_Small_Solution_Bottle(f"{name}_bottle_{ordering[i]}")
|
||||
return carrier
|
||||
|
||||
@@ -483,7 +483,7 @@ def BIOYOND_PolymerStation_4x_LargeSolutionBottleCarrier(name: str) -> BottleCar
|
||||
|
||||
|
||||
def BIOYOND_PolymerStation_6x_LargeDispenseHeadCarrier(name: str) -> BottleCarrier:
|
||||
"""加样头(大)板 - 2x3布局,6个位置"""
|
||||
"""加样头(大)板 - 1x1布局,1个位置"""
|
||||
|
||||
# 载架尺寸 (mm)
|
||||
carrier_size_x = 127.8
|
||||
@@ -496,13 +496,13 @@ def BIOYOND_PolymerStation_6x_LargeDispenseHeadCarrier(name: str) -> BottleCarri
|
||||
bottle_spacing_y = 35.0 # Y方向间距
|
||||
|
||||
# 计算起始位置 (居中排列)
|
||||
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
|
||||
start_x = (carrier_size_x - (1 - 1) * bottle_spacing_x - bottle_diameter) / 2
|
||||
start_y = (carrier_size_y - (1 - 1) * bottle_spacing_y - bottle_diameter) / 2
|
||||
|
||||
sites = create_ordered_items_2d(
|
||||
klass=ResourceHolder,
|
||||
num_items_x=3,
|
||||
num_items_y=2,
|
||||
num_items_x=1,
|
||||
num_items_y=1,
|
||||
dx=start_x,
|
||||
dy=start_y,
|
||||
dz=5.0,
|
||||
@@ -523,12 +523,10 @@ def BIOYOND_PolymerStation_6x_LargeDispenseHeadCarrier(name: str) -> BottleCarri
|
||||
sites=sites,
|
||||
model="6x_LargeDispenseHeadCarrier",
|
||||
)
|
||||
carrier.num_items_x = 3
|
||||
carrier.num_items_y = 2
|
||||
carrier.num_items_x = 1
|
||||
carrier.num_items_y = 1
|
||||
carrier.num_items_z = 1
|
||||
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"]
|
||||
for i in range(6):
|
||||
carrier[i] = BIOYOND_PolymerStation_Large_Dispense_Head(f"{name}_head_{ordering[i]}")
|
||||
carrier[0] = BIOYOND_PolymerStation_Large_Dispense_Head(f"{name}_head_1")
|
||||
return carrier
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user