Update workstation code for YB4 0107

This commit is contained in:
Andy6M
2026-01-07 11:59:32 +08:00
parent 915a6a04c3
commit 936834f8c3
36 changed files with 3860 additions and 26826 deletions

View File

@@ -257,7 +257,7 @@ class BioyondCellWorkstation(BioyondWorkstation):
def auto_feeding4to3(
self,
# ★ 修改点:默认模板路径
xlsx_path: Optional[str] = "/Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx",
xlsx_path: Optional[str] = "D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\material_template.xlsx",
# ---------------- WH4 - 加样头面 (Z=1, 12个点位) ----------------
WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0,
WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0,
@@ -394,9 +394,13 @@ class BioyondCellWorkstation(BioyondWorkstation):
return response
# 等待完成报送
result = self.wait_for_order_finish(order_code)
print("\n" + "="*60)
print("实验记录本结果auto_feeding4to3")
print("="*60)
print(json.dumps(result, indent=2, ensure_ascii=False))
print("="*60 + "\n")
return result
def auto_batch_outbound_from_xlsx(self, xlsx_path: str) -> Dict[str, Any]:
"""
3.31 自动化下料Excel -> JSON -> POST /api/lims/storage/auto-batch-out-bound
@@ -474,7 +478,7 @@ class BioyondCellWorkstation(BioyondWorkstation):
- totalMass 自动计算为所有物料质量之和
- createTime 缺失或为空时自动填充为当前日期YYYY/M/D
"""
default_path = Path("/Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx")
default_path = Path("D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\2025122301.xlsx")
path = Path(xlsx_path) if xlsx_path else default_path
print(f"[create_orders] 使用 Excel 路径: {path}")
if path != default_path:
@@ -610,19 +614,63 @@ class BioyondCellWorkstation(BioyondWorkstation):
print(f"[create_orders] 即将提交订单数量: {len(orders)}")
response = self._post_lims("/api/lims/order/orders", orders)
print(f"[create_orders] 接口返回: {response}")
# 等待任务报送成功
# 提取所有返回的 orderCode
data_list = response.get("data", [])
if data_list:
order_code = data_list[0].get("orderCode")
else:
order_code = None
if not order_code:
logger.error("上料任务未返回有效 orderCode")
if not data_list:
logger.error("创建订单未返回有效数据!")
return response
# 等待完成报送
result = self.wait_for_order_finish(order_code)
return result
# 收集所有 orderCode
order_codes = []
for order_item in data_list:
code = order_item.get("orderCode")
if code:
order_codes.append(code)
if not order_codes:
logger.error("未找到任何有效的 orderCode")
return response
print(f"[create_orders] 等待 {len(order_codes)} 个订单完成: {order_codes}")
# 等待所有订单完成并收集报文
all_reports = []
for idx, order_code in enumerate(order_codes, 1):
print(f"[create_orders] 正在等待第 {idx}/{len(order_codes)} 个订单: {order_code}")
result = self.wait_for_order_finish(order_code)
# 提取报文数据
if result.get("status") == "success":
report = result.get("report", {})
all_reports.append(report)
print(f"[create_orders] ✓ 订单 {order_code} 完成")
else:
logger.warning(f"订单 {order_code} 状态异常: {result.get('status')}")
# 即使订单失败,也记录下这个结果
all_reports.append({
"orderCode": order_code,
"status": result.get("status"),
"error": result.get("message", "未知错误")
})
print(f"[create_orders] 所有订单已完成,共收集 {len(all_reports)} 个报文")
print("实验记录本========================create_orders========================")
# 返回所有订单的完成报文
final_result = {
"status": "all_completed",
"total_orders": len(order_codes),
"reports": all_reports,
"original_response": response
}
print(f"返回报文数量: {len(all_reports)}")
for i, report in enumerate(all_reports, 1):
print(f"报文 {i}: orderCode={report.get('orderCode', 'N/A')}, status={report.get('status', 'N/A')}")
print("========================")
return final_result
# 2.7 启动调度
def scheduler_start(self) -> Dict[str, Any]:
@@ -650,6 +698,146 @@ class BioyondCellWorkstation(BioyondWorkstation):
"""
return self._post_lims("/api/lims/scheduler/reset")
def scheduler_start_and_auto_feeding(
self,
# ★ Excel路径参数
xlsx_path: Optional[str] = "D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\material_template.xlsx",
# ---------------- WH4 - 加样头面 (Z=1, 12个点位) ----------------
WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0,
WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0,
WH4_x3_y1_z1_3_materialName: str = "", WH4_x3_y1_z1_3_quantity: float = 0.0,
WH4_x4_y1_z1_4_materialName: str = "", WH4_x4_y1_z1_4_quantity: float = 0.0,
WH4_x5_y1_z1_5_materialName: str = "", WH4_x5_y1_z1_5_quantity: float = 0.0,
WH4_x1_y2_z1_6_materialName: str = "", WH4_x1_y2_z1_6_quantity: float = 0.0,
WH4_x2_y2_z1_7_materialName: str = "", WH4_x2_y2_z1_7_quantity: float = 0.0,
WH4_x3_y2_z1_8_materialName: str = "", WH4_x3_y2_z1_8_quantity: float = 0.0,
WH4_x4_y2_z1_9_materialName: str = "", WH4_x4_y2_z1_9_quantity: float = 0.0,
WH4_x5_y2_z1_10_materialName: str = "", WH4_x5_y2_z1_10_quantity: float = 0.0,
WH4_x1_y3_z1_11_materialName: str = "", WH4_x1_y3_z1_11_quantity: float = 0.0,
WH4_x2_y3_z1_12_materialName: str = "", WH4_x2_y3_z1_12_quantity: float = 0.0,
# ---------------- WH4 - 原液瓶面 (Z=2, 9个点位) ----------------
WH4_x1_y1_z2_1_materialName: str = "", WH4_x1_y1_z2_1_quantity: float = 0.0, WH4_x1_y1_z2_1_materialType: str = "", WH4_x1_y1_z2_1_targetWH: str = "",
WH4_x2_y1_z2_2_materialName: str = "", WH4_x2_y1_z2_2_quantity: float = 0.0, WH4_x2_y1_z2_2_materialType: str = "", WH4_x2_y1_z2_2_targetWH: str = "",
WH4_x3_y1_z2_3_materialName: str = "", WH4_x3_y1_z2_3_quantity: float = 0.0, WH4_x3_y1_z2_3_materialType: str = "", WH4_x3_y1_z2_3_targetWH: str = "",
WH4_x1_y2_z2_4_materialName: str = "", WH4_x1_y2_z2_4_quantity: float = 0.0, WH4_x1_y2_z2_4_materialType: str = "", WH4_x1_y2_z2_4_targetWH: str = "",
WH4_x2_y2_z2_5_materialName: str = "", WH4_x2_y2_z2_5_quantity: float = 0.0, WH4_x2_y2_z2_5_materialType: str = "", WH4_x2_y2_z2_5_targetWH: str = "",
WH4_x3_y2_z2_6_materialName: str = "", WH4_x3_y2_z2_6_quantity: float = 0.0, WH4_x3_y2_z2_6_materialType: str = "", WH4_x3_y2_z2_6_targetWH: str = "",
WH4_x1_y3_z2_7_materialName: str = "", WH4_x1_y3_z2_7_quantity: float = 0.0, WH4_x1_y3_z2_7_materialType: str = "", WH4_x1_y3_z2_7_targetWH: str = "",
WH4_x2_y3_z2_8_materialName: str = "", WH4_x2_y3_z2_8_quantity: float = 0.0, WH4_x2_y3_z2_8_materialType: str = "", WH4_x2_y3_z2_8_targetWH: str = "",
WH4_x3_y3_z2_9_materialName: str = "", WH4_x3_y3_z2_9_quantity: float = 0.0, WH4_x3_y3_z2_9_materialType: str = "", WH4_x3_y3_z2_9_targetWH: str = "",
# ---------------- WH3 - 人工堆栈 (Z=3, 15个点位) ----------------
WH3_x1_y1_z3_1_materialType: str = "", WH3_x1_y1_z3_1_materialId: str = "", WH3_x1_y1_z3_1_quantity: float = 0,
WH3_x2_y1_z3_2_materialType: str = "", WH3_x2_y1_z3_2_materialId: str = "", WH3_x2_y1_z3_2_quantity: float = 0,
WH3_x3_y1_z3_3_materialType: str = "", WH3_x3_y1_z3_3_materialId: str = "", WH3_x3_y1_z3_3_quantity: float = 0,
WH3_x1_y2_z3_4_materialType: str = "", WH3_x1_y2_z3_4_materialId: str = "", WH3_x1_y2_z3_4_quantity: float = 0,
WH3_x2_y2_z3_5_materialType: str = "", WH3_x2_y2_z3_5_materialId: str = "", WH3_x2_y2_z3_5_quantity: float = 0,
WH3_x3_y2_z3_6_materialType: str = "", WH3_x3_y2_z3_6_materialId: str = "", WH3_x3_y2_z3_6_quantity: float = 0,
WH3_x1_y3_z3_7_materialType: str = "", WH3_x1_y3_z3_7_materialId: str = "", WH3_x1_y3_z3_7_quantity: float = 0,
WH3_x2_y3_z3_8_materialType: str = "", WH3_x2_y3_z3_8_materialId: str = "", WH3_x2_y3_z3_8_quantity: float = 0,
WH3_x3_y3_z3_9_materialType: str = "", WH3_x3_y3_z3_9_materialId: str = "", WH3_x3_y3_z3_9_quantity: float = 0,
WH3_x1_y4_z3_10_materialType: str = "", WH3_x1_y4_z3_10_materialId: str = "", WH3_x1_y4_z3_10_quantity: float = 0,
WH3_x2_y4_z3_11_materialType: str = "", WH3_x2_y4_z3_11_materialId: str = "", WH3_x2_y4_z3_11_quantity: float = 0,
WH3_x3_y4_z3_12_materialType: str = "", WH3_x3_y4_z3_12_materialId: str = "", WH3_x3_y4_z3_12_quantity: float = 0,
WH3_x1_y5_z3_13_materialType: str = "", WH3_x1_y5_z3_13_materialId: str = "", WH3_x1_y5_z3_13_quantity: float = 0,
WH3_x2_y5_z3_14_materialType: str = "", WH3_x2_y5_z3_14_materialId: str = "", WH3_x2_y5_z3_14_quantity: float = 0,
WH3_x3_y5_z3_15_materialType: str = "", WH3_x3_y5_z3_15_materialId: str = "", WH3_x3_y5_z3_15_quantity: float = 0,
) -> Dict[str, Any]:
"""
组合函数:先启动调度,然后执行自动化上料
此函数简化了工作流操作,将两个有顺序依赖的操作组合在一起:
1. 启动调度scheduler_start
2. 自动化上料auto_feeding4to3
参数与 auto_feeding4to3 完全相同,支持 Excel 和手动参数两种模式
Returns:
包含调度启动结果和上料结果的字典
"""
logger.info("=" * 60)
logger.info("开始执行组合操作:启动调度 + 自动化上料")
logger.info("=" * 60)
# 步骤1: 启动调度
logger.info("【步骤 1/2】启动调度...")
scheduler_result = self.scheduler_start()
logger.info(f"调度启动结果: {scheduler_result}")
# 检查调度是否启动成功
if scheduler_result.get("code") != 1:
logger.error(f"调度启动失败: {scheduler_result}")
return {
"success": False,
"step": "scheduler_start",
"scheduler_result": scheduler_result,
"error": "调度启动失败"
}
logger.info("✓ 调度启动成功")
# 步骤2: 执行自动化上料
logger.info("【步骤 2/2】执行自动化上料...")
feeding_result = self.auto_feeding4to3(
xlsx_path=xlsx_path,
WH4_x1_y1_z1_1_materialName=WH4_x1_y1_z1_1_materialName, WH4_x1_y1_z1_1_quantity=WH4_x1_y1_z1_1_quantity,
WH4_x2_y1_z1_2_materialName=WH4_x2_y1_z1_2_materialName, WH4_x2_y1_z1_2_quantity=WH4_x2_y1_z1_2_quantity,
WH4_x3_y1_z1_3_materialName=WH4_x3_y1_z1_3_materialName, WH4_x3_y1_z1_3_quantity=WH4_x3_y1_z1_3_quantity,
WH4_x4_y1_z1_4_materialName=WH4_x4_y1_z1_4_materialName, WH4_x4_y1_z1_4_quantity=WH4_x4_y1_z1_4_quantity,
WH4_x5_y1_z1_5_materialName=WH4_x5_y1_z1_5_materialName, WH4_x5_y1_z1_5_quantity=WH4_x5_y1_z1_5_quantity,
WH4_x1_y2_z1_6_materialName=WH4_x1_y2_z1_6_materialName, WH4_x1_y2_z1_6_quantity=WH4_x1_y2_z1_6_quantity,
WH4_x2_y2_z1_7_materialName=WH4_x2_y2_z1_7_materialName, WH4_x2_y2_z1_7_quantity=WH4_x2_y2_z1_7_quantity,
WH4_x3_y2_z1_8_materialName=WH4_x3_y2_z1_8_materialName, WH4_x3_y2_z1_8_quantity=WH4_x3_y2_z1_8_quantity,
WH4_x4_y2_z1_9_materialName=WH4_x4_y2_z1_9_materialName, WH4_x4_y2_z1_9_quantity=WH4_x4_y2_z1_9_quantity,
WH4_x5_y2_z1_10_materialName=WH4_x5_y2_z1_10_materialName, WH4_x5_y2_z1_10_quantity=WH4_x5_y2_z1_10_quantity,
WH4_x1_y3_z1_11_materialName=WH4_x1_y3_z1_11_materialName, WH4_x1_y3_z1_11_quantity=WH4_x1_y3_z1_11_quantity,
WH4_x2_y3_z1_12_materialName=WH4_x2_y3_z1_12_materialName, WH4_x2_y3_z1_12_quantity=WH4_x2_y3_z1_12_quantity,
WH4_x1_y1_z2_1_materialName=WH4_x1_y1_z2_1_materialName, WH4_x1_y1_z2_1_quantity=WH4_x1_y1_z2_1_quantity,
WH4_x1_y1_z2_1_materialType=WH4_x1_y1_z2_1_materialType, WH4_x1_y1_z2_1_targetWH=WH4_x1_y1_z2_1_targetWH,
WH4_x2_y1_z2_2_materialName=WH4_x2_y1_z2_2_materialName, WH4_x2_y1_z2_2_quantity=WH4_x2_y1_z2_2_quantity,
WH4_x2_y1_z2_2_materialType=WH4_x2_y1_z2_2_materialType, WH4_x2_y1_z2_2_targetWH=WH4_x2_y1_z2_2_targetWH,
WH4_x3_y1_z2_3_materialName=WH4_x3_y1_z2_3_materialName, WH4_x3_y1_z2_3_quantity=WH4_x3_y1_z2_3_quantity,
WH4_x3_y1_z2_3_materialType=WH4_x3_y1_z2_3_materialType, WH4_x3_y1_z2_3_targetWH=WH4_x3_y1_z2_3_targetWH,
WH4_x1_y2_z2_4_materialName=WH4_x1_y2_z2_4_materialName, WH4_x1_y2_z2_4_quantity=WH4_x1_y2_z2_4_quantity,
WH4_x1_y2_z2_4_materialType=WH4_x1_y2_z2_4_materialType, WH4_x1_y2_z2_4_targetWH=WH4_x1_y2_z2_4_targetWH,
WH4_x2_y2_z2_5_materialName=WH4_x2_y2_z2_5_materialName, WH4_x2_y2_z2_5_quantity=WH4_x2_y2_z2_5_quantity,
WH4_x2_y2_z2_5_materialType=WH4_x2_y2_z2_5_materialType, WH4_x2_y2_z2_5_targetWH=WH4_x2_y2_z2_5_targetWH,
WH4_x3_y2_z2_6_materialName=WH4_x3_y2_z2_6_materialName, WH4_x3_y2_z2_6_quantity=WH4_x3_y2_z2_6_quantity,
WH4_x3_y2_z2_6_materialType=WH4_x3_y2_z2_6_materialType, WH4_x3_y2_z2_6_targetWH=WH4_x3_y2_z2_6_targetWH,
WH4_x1_y3_z2_7_materialName=WH4_x1_y3_z2_7_materialName, WH4_x1_y3_z2_7_quantity=WH4_x1_y3_z2_7_quantity,
WH4_x1_y3_z2_7_materialType=WH4_x1_y3_z2_7_materialType, WH4_x1_y3_z2_7_targetWH=WH4_x1_y3_z2_7_targetWH,
WH4_x2_y3_z2_8_materialName=WH4_x2_y3_z2_8_materialName, WH4_x2_y3_z2_8_quantity=WH4_x2_y3_z2_8_quantity,
WH4_x2_y3_z2_8_materialType=WH4_x2_y3_z2_8_materialType, WH4_x2_y3_z2_8_targetWH=WH4_x2_y3_z2_8_targetWH,
WH4_x3_y3_z2_9_materialName=WH4_x3_y3_z2_9_materialName, WH4_x3_y3_z2_9_quantity=WH4_x3_y3_z2_9_quantity,
WH4_x3_y3_z2_9_materialType=WH4_x3_y3_z2_9_materialType, WH4_x3_y3_z2_9_targetWH=WH4_x3_y3_z2_9_targetWH,
WH3_x1_y1_z3_1_materialType=WH3_x1_y1_z3_1_materialType, WH3_x1_y1_z3_1_materialId=WH3_x1_y1_z3_1_materialId, WH3_x1_y1_z3_1_quantity=WH3_x1_y1_z3_1_quantity,
WH3_x2_y1_z3_2_materialType=WH3_x2_y1_z3_2_materialType, WH3_x2_y1_z3_2_materialId=WH3_x2_y1_z3_2_materialId, WH3_x2_y1_z3_2_quantity=WH3_x2_y1_z3_2_quantity,
WH3_x3_y1_z3_3_materialType=WH3_x3_y1_z3_3_materialType, WH3_x3_y1_z3_3_materialId=WH3_x3_y1_z3_3_materialId, WH3_x3_y1_z3_3_quantity=WH3_x3_y1_z3_3_quantity,
WH3_x1_y2_z3_4_materialType=WH3_x1_y2_z3_4_materialType, WH3_x1_y2_z3_4_materialId=WH3_x1_y2_z3_4_materialId, WH3_x1_y2_z3_4_quantity=WH3_x1_y2_z3_4_quantity,
WH3_x2_y2_z3_5_materialType=WH3_x2_y2_z3_5_materialType, WH3_x2_y2_z3_5_materialId=WH3_x2_y2_z3_5_materialId, WH3_x2_y2_z3_5_quantity=WH3_x2_y2_z3_5_quantity,
WH3_x3_y2_z3_6_materialType=WH3_x3_y2_z3_6_materialType, WH3_x3_y2_z3_6_materialId=WH3_x3_y2_z3_6_materialId, WH3_x3_y2_z3_6_quantity=WH3_x3_y2_z3_6_quantity,
WH3_x1_y3_z3_7_materialType=WH3_x1_y3_z3_7_materialType, WH3_x1_y3_z3_7_materialId=WH3_x1_y3_z3_7_materialId, WH3_x1_y3_z3_7_quantity=WH3_x1_y3_z3_7_quantity,
WH3_x2_y3_z3_8_materialType=WH3_x2_y3_z3_8_materialType, WH3_x2_y3_z3_8_materialId=WH3_x2_y3_z3_8_materialId, WH3_x2_y3_z3_8_quantity=WH3_x2_y3_z3_8_quantity,
WH3_x3_y3_z3_9_materialType=WH3_x3_y3_z3_9_materialType, WH3_x3_y3_z3_9_materialId=WH3_x3_y3_z3_9_materialId, WH3_x3_y3_z3_9_quantity=WH3_x3_y3_z3_9_quantity,
WH3_x1_y4_z3_10_materialType=WH3_x1_y4_z3_10_materialType, WH3_x1_y4_z3_10_materialId=WH3_x1_y4_z3_10_materialId, WH3_x1_y4_z3_10_quantity=WH3_x1_y4_z3_10_quantity,
WH3_x2_y4_z3_11_materialType=WH3_x2_y4_z3_11_materialType, WH3_x2_y4_z3_11_materialId=WH3_x2_y4_z3_11_materialId, WH3_x2_y4_z3_11_quantity=WH3_x2_y4_z3_11_quantity,
WH3_x3_y4_z3_12_materialType=WH3_x3_y4_z3_12_materialType, WH3_x3_y4_z3_12_materialId=WH3_x3_y4_z3_12_materialId, WH3_x3_y4_z3_12_quantity=WH3_x3_y4_z3_12_quantity,
WH3_x1_y5_z3_13_materialType=WH3_x1_y5_z3_13_materialType, WH3_x1_y5_z3_13_materialId=WH3_x1_y5_z3_13_materialId, WH3_x1_y5_z3_13_quantity=WH3_x1_y5_z3_13_quantity,
WH3_x2_y5_z3_14_materialType=WH3_x2_y5_z3_14_materialType, WH3_x2_y5_z3_14_materialId=WH3_x2_y5_z3_14_materialId, WH3_x2_y5_z3_14_quantity=WH3_x2_y5_z3_14_quantity,
WH3_x3_y5_z3_15_materialType=WH3_x3_y5_z3_15_materialType, WH3_x3_y5_z3_15_materialId=WH3_x3_y5_z3_15_materialId, WH3_x3_y5_z3_15_quantity=WH3_x3_y5_z3_15_quantity,
)
logger.info("=" * 60)
logger.info("组合操作完成")
logger.info("=" * 60)
return {
"success": True,
"scheduler_result": scheduler_result,
"feeding_result": feeding_result
}
# 2.24 物料变更推送
def report_material_change(self, material_obj: Dict[str, Any]) -> Dict[str, Any]:

View File

@@ -0,0 +1,197 @@
{
"token": "",
"request_time": "2025-12-24T15:32:09.2148671+08:00",
"data": {
"orderId": "3a1e614d-a082-c44a-60be-68647a35e6f1",
"orderCode": "BSO2025122400024",
"orderName": "DP20251224001",
"startTime": "2025-12-24T14:51:50.549848",
"endTime": "2025-12-24T15:32:09.000765",
"status": "30",
"workflowStatus": "completed",
"completionTime": "2025-12-24T15:32:09.000765",
"usedMaterials": [
{
"materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-4da7-cf62-3a40-7e5879255c0c",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-53a7-2850-42c8-a7a2de8ff4bf",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f",
"locationId": "3a1abd46-18fe-1f56-6ced-a1f7fe08e36c",
"typemode": "0",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829",
"locationId": "3a19da43-57b5-294f-d663-154a1cc32270",
"typemode": "2",
"usedQuantity": 3.51,
"realQuantity": 3.5155000000000000000000000000
},
{
"materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d",
"locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"typemode": "2",
"usedQuantity": 0.33,
"realQuantity": 0.3336000000000000000000000000
}
]
}
}
{
"token": "",
"request_time": "2025-12-24T15:32:09.9999039+08:00",
"data": {
"orderId": "3a1e614d-a0a2-f7a9-9360-610021c9479d",
"orderCode": "BSO2025122400025",
"orderName": "DP20251224002",
"startTime": "2025-12-24T14:53:03.44259",
"endTime": "2025-12-24T15:32:09.828261",
"status": "30",
"workflowStatus": "completed",
"completionTime": "2025-12-24T15:32:09.828261",
"usedMaterials": [
{
"materialId": "3a1e614b-4da7-6527-9f1c-b39e3de8ff2b",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2",
"locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-53a8-8474-cac8-0fd7d349e4b2",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f",
"locationId": null,
"typemode": "0",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829",
"locationId": "3a19da43-57b5-294f-d663-154a1cc32270",
"typemode": "2",
"usedQuantity": 0.7,
"realQuantity": 0
},
{
"materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d",
"locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"typemode": "2",
"usedQuantity": 1.15,
"realQuantity": 1.1627000000000000000000000000
}
]
}
}
{
"token": "",
"request_time": "2025-12-24T15:34:00.4139986+08:00",
"data": {
"orderId": "3a1e614d-a0cd-81ca-9f7f-2f4e93af01cd",
"orderCode": "BSO2025122400026",
"orderName": "DP20251224003",
"startTime": "2025-12-24T14:54:24.443344",
"endTime": "2025-12-24T15:34:00.26321",
"status": "30",
"workflowStatus": "completed",
"completionTime": "2025-12-24T15:34:00.26321",
"usedMaterials": [
{
"materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2",
"locationId": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-4da8-b678-f204-207076f09c83",
"locationId": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 2,
"realQuantity": 2
},
{
"materialId": "3a1e614b-53a8-e3f2-dee0-fa97b600b652",
"locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"typemode": "1",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f",
"locationId": null,
"typemode": "0",
"usedQuantity": 1,
"realQuantity": 1
},
{
"materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829",
"locationId": "3a19da43-57b5-294f-d663-154a1cc32270",
"typemode": "2",
"usedQuantity": 2.0,
"realQuantity": 2.0075000000000000000000000000
},
{
"materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d",
"locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"typemode": "2",
"usedQuantity": 1.2,
"realQuantity": 1.2126000000000000000000000000
}
]
}
}

View File

@@ -0,0 +1,113 @@
# Bioyond Cell 工作站 - 多订单返回示例
本文档说明了 `create_orders` 函数如何收集并返回所有订单的完成报文。
## 问题描述
之前的实现只会等待并返回第一个订单的完成报文,如果有多个订单(例如从 Excel 解析出 3 个订单),只能得到第一个订单的推送信息。
## 解决方案
修改后的 `create_orders` 函数现在会:
1. **提取所有 orderCode**:从 LIMS 接口返回的 `data` 列表中提取所有订单编号
2. **逐个等待完成**:遍历所有 orderCode调用 `wait_for_order_finish` 等待每个订单完成
3. **收集所有报文**:将每个订单的完成报文存入 `all_reports` 列表
4. **统一返回**:返回包含所有订单报文的 JSON 格式数据
## 返回格式
```json
{
"status": "all_completed",
"total_orders": 3,
"reports": [
{
"token": "",
"request_time": "2025-12-24T15:32:09.2148671+08:00",
"data": {
"orderId": "3a1e614d-a082-c44a-60be-68647a35e6f1",
"orderCode": "BSO2025122400024",
"orderName": "DP20251224001",
"status": "30",
"workflowStatus": "completed",
"usedMaterials": [...]
}
},
{
"token": "",
"request_time": "2025-12-24T15:32:09.9999039+08:00",
"data": {
"orderId": "3a1e614d-a0a2-f7a9-9360-610021c9479d",
"orderCode": "BSO2025122400025",
"orderName": "DP20251224002",
"status": "30",
"workflowStatus": "completed",
"usedMaterials": [...]
}
},
{
"token": "",
"request_time": "2025-12-24T15:34:00.4139986+08:00",
"data": {
"orderId": "3a1e614d-a0cd-81ca-9f7f-2f4e93af01cd",
"orderCode": "BSO2025122400026",
"orderName": "DP20251224003",
"status": "30",
"workflowStatus": "completed",
"usedMaterials": [...]
}
}
],
"original_response": {...}
}
```
## 使用示例
```python
# 调用 create_orders
result = workstation.create_orders("20251224.xlsx")
# 访问返回数据
print(f"总订单数: {result['total_orders']}")
print(f"状态: {result['status']}")
# 遍历所有订单的报文
for i, report in enumerate(result['reports'], 1):
order_data = report.get('data', {})
print(f"\n订单 {i}:")
print(f" orderCode: {order_data.get('orderCode')}")
print(f" orderName: {order_data.get('orderName')}")
print(f" status: {order_data.get('status')}")
print(f" 使用物料数: {len(order_data.get('usedMaterials', []))}")
```
## 控制台输出示例
```
[create_orders] 即将提交订单数量: 3
[create_orders] 接口返回: {...}
[create_orders] 等待 3 个订单完成: ['BSO2025122400024', 'BSO2025122400025', 'BSO2025122400026']
[create_orders] 正在等待第 1/3 个订单: BSO2025122400024
[create_orders] ✓ 订单 BSO2025122400024 完成
[create_orders] 正在等待第 2/3 个订单: BSO2025122400025
[create_orders] ✓ 订单 BSO2025122400025 完成
[create_orders] 正在等待第 3/3 个订单: BSO2025122400026
[create_orders] ✓ 订单 BSO2025122400026 完成
[create_orders] 所有订单已完成,共收集 3 个报文
实验记录本========================create_orders========================
返回报文数量: 3
报文 1: orderCode=BSO2025122400024, status=30
报文 2: orderCode=BSO2025122400025, status=30
报文 3: orderCode=BSO2025122400026, status=30
========================
```
## 关键改进
1.**等待所有订单**:不再只等待第一个订单,而是遍历所有 orderCode
2.**收集完整报文**:每个订单的完整推送报文都被保存在 `reports` 数组中
3.**详细日志**:清晰显示正在等待哪个订单,以及完成情况
4.**错误处理**:即使某个订单失败,也会记录其状态信息
5.**统一格式**:返回的 JSON 格式便于后续处理和分析

View File

@@ -8,8 +8,10 @@ import os
# BioyondCellWorkstation 默认配置(包含所有必需参数)
API_CONFIG = {
# API 连接配置
# "api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.1.143:44389"),#实机
"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.219:44388"),# 仿真机
# 实机
#"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.118:44389"),
# 仿真机
"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.219:44388"),
"api_key": os.getenv("BIOYOND_API_KEY", "8A819E5C"),
"timeout": int(os.getenv("BIOYOND_TIMEOUT", "30")),
@@ -17,7 +19,7 @@ API_CONFIG = {
"report_token": os.getenv("BIOYOND_REPORT_TOKEN", "CHANGE_ME_TOKEN"),
# HTTP 服务配置
"HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.16.11.2"), # HTTP服务监听地址监听计算机飞连ip地址
"HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.16.11.206"), # HTTP服务监听地址监听计算机飞连ip地址
"HTTP_port": int(os.getenv("BIOYOND_HTTP_PORT", "8080")),
"debug_mode": False,# 调试模式
}