Skip to content

Workstation dev yb 260410 - #262

Draft
Xuwznln wants to merge 116 commits into
devfrom
workstation_dev_YB_260410
Draft

Workstation dev yb 260410#262
Xuwznln wants to merge 116 commits into
devfrom
workstation_dev_YB_260410

Conversation

@Xuwznln

@Xuwznln Xuwznln commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

Andy6M and others added 30 commits March 19, 2026 00:41
- MagazineHolder: klasses=None,解耦极片子节点初始化
- Magazine: 重写 serialize/deserialize,截断旧极片脏数据
- bottle_carriers: 移除 YIHUA_Electrolyte_12VialCarrier 初始化填瓶
- decks.py: BIOYOND_YB_Deck→BioyondElectrolyteDeck,移除 setup 参数
- YB_YH_materials.py: CoincellDeck→YihuaCoinCellDeck,新增 electrolyte_buffer 槽位
- resource_tracker.py: Container 状态键预填 + 重复 UUID 自动修复 + 树级名称去重
- itemized_carrier.py: XY 近似坐标匹配,修复 Z 偏移问题
- bioyond_cell_workstation.py: 跨站转运改用真实资源 + 类型映射双模式查找
- station.py: sync_to_external 属性访问路径修复
- coin_cell_assembly.py: 新增 10 个 Modbus 余量属性
- CSV/JSON/YAML 配置同步更新(类名重命名 + 移除 setup)
- 新增 changelog_2026-03-12.md
- 更新 neware_battery_test_system 驱动及设备配置
- 新增 generate_xml_content.py 工具脚本
- 更新 bioyond_cell_workstation 工作站实现
- 更新 coin_cell_assembly 扣式电池组装逻辑
- 更新相关注册表 YAML 配置:neware_battery_test_system、coin_cell_workstation、bioyond_cell
- add CSV export for order data in bioyond_cell
- extract prep and vial bottles from order_finish report
- update bioyond_cell registry with csv_export_path
- update coin_cell_assembly to export new bottle barcodes and mass ratios
- add 260415csv_export_walkthrough.md
bioyond_cell: Ensure order_name is cast to str and fix mix_time handling for single int/float values. YB_bottles: Fix max_volume capacity for 15mL and 60mL prep bottles to match their names.
Support unit in pylabrobot
- Expand neware_battery_test_system.py with new actions and logic
- Update generate_xml_content.py with additional XML generation support
- Extend neware_battery_test_system.yaml registry with new action schemas
- Update OSS upload READMEs and device.json
- Add electrode_sheet.py resource fields

Made-with: Cursor
…V export

- coin_cell_assembly: align battery_info to 9 fields (Time/open_circuit_voltage/pole_weight/assembly_time/assembly_pressure/electrolyte_volume/data_coin_type/electrolyte_code/coin_cell_code); expose assembly_data single array; rename CSV column coin_num -> data_coin_type
- coin_cell_workstation.yaml: add assembly_data_output handle for auto-func_sendbottle_allpack_multi
- neware manual_confirm: accept formulations + assembly_data + csv_export_dir, unpack to parallel lists, export merged CSV to {csv_export_dir}/{date}/date_{date}.csv, output pole_weight for downstream
- neware transfer -> battery_transfer_confirm with manual_confirm node_type, timeout_seconds, assignee_user_ids
- neware test -> submit_auto_export_excel, accept pole_weight input; relabel battery_system as xml工步

Made-with: Cursor
- neware manual_confirm: drop formulations/assembly_data from result and output handles (they only feed internal CSV export and should not be passed downstream); return dict no longer carries those two keys
- base_device_node.loop_find_with_uuid consumer: iterate all figured_resources instead of breaking after first attempt; raise explicit error when uuid cannot be resolved

Made-with: Cursor
- neware_driver: default backup filetype="1" so Neware BTS produces Excel
  backups out of the box (matches submit_*_export_excel semantics).
- submit_auto_export_excel: pass filetype=1 to align with function name
  and the newly default Excel backup.
- manual_confirm: prefix Channel_Name with a single quote when writing
  the integrated CSV so Excel keeps it as text (e.g. "6-10-2") instead
  of auto-coercing to a date (e.g. "2006/10/2"). The on-disk value is
  archival only and submit_auto_export_excel never reads it, so the
  live workflow is unaffected either way.
- neware yaml: declare explicit item properties for manual_confirm's
  formulations and assembly_data arrays so the orchestrator schema
  projection keeps the 7/9 upstream fields intact.

Made-with: Cursor
…type kwarg

问题:
- 日志中 submit_auto_export_excel 收到 resource=[](工作流本身不传成品电池资源,
  电池由人工搬运),原代码 n = len(resource) = 0 → 整个循环跳过 →
  "共 0 颗电池,成功下发 0 颗"。
- neware_driver.start_test 原来不接收 filetype kwarg,导致 TypeError 阻塞下发。

修复:
1. submit_auto_export_excel 改为由 mount_resource 驱动循环长度:
   - 新签名以 mount_resource 为主,resource/pole_weight/coin_cell_code 均可选
   - 新增 coin_cell_code 入参,coin_id 优先级 coin_cell_code > resource.name > fallback
   - n==0 时提前返回并给出明确错误信息
2. manual_confirm 的返回值与 YAML handles/output 新增 coin_cell_code
   (从已解包的 assembly_data 直接取)
3. submit_auto_export_excel YAML goal/schema/goal_default/handles.input
   新增 coin_cell_code;required 中移除 resource(不再强制)
4. neware_driver.build_start_command / start_test 增加 filetype:int=1 参数,
   动态嵌入 XML backup 配置,消除 TypeError

Made-with: Cursor
…ctrolyte_code

- Add output_dir param, backup dir derived from user input (xml_dir/backup_dir auto-created)
- Add electrolyte_code param, backup file name format: coin_cell_code-electrolyte_code-devid-subdevid-chlid
- manual_confirm return value adds electrolyte_code field for downstream passthrough
- YAML: manual_confirm output handles add electrolyte_code
- YAML: submit_auto_export_excel goal/schema/goal_default/handles add output_dir and electrolyte_code
- YAML: battery_transfer_confirm output changed to empty list

Made-with: Cursor
Andy6M and others added 30 commits June 5, 2026 11:09
冲突解决:_extract_vial_plate_from_report
- 上游 851b923 给单板 Optional[Dict] 版本加了 source_x/y/z(从 material_info.locations
  的"自动堆栈-左"仓库 whid 取坐标)。
- 本地 9661546 把该函数重构成 List[Dict],支持 1 个 order 多块 20ml 板(电导多温度)+
  跨 order 共用板时的 orderId(GUID) 反查。
- 合并方案:保留 List[Dict] 结构,把 source_x/y/z 注入到每块 plate_info 中。
  下游 _find_plate_xyz 仍能从 all_vial_plates 中按 typeName 关键字找出对应坐标。

自动合并的部分:
- _submit_and_wait_orders 末尾上游的 source_pos 提取逻辑无冲突落入;
  我们去重后的 all_vial_plates 每块板都带 source_x/y/z,_find_plate_xyz 直接可用。
- bioyond_cell.yaml:上游加的 vial_321_source_pos / vial_32_source_pos 输出(auto-create_orders
  / auto-create_orders_formulation)+ transfer 3-2-1/3-2 的 source_pos 输入 全部保留;
  我们删的 stop_scheduler_timeout / conductivity_auto_* 输出仍维持删除。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…bottle barCode extraction

Co-authored-by: Cursor <cursoragent@cursor.com>
- coin_cell_assembly: assembly_data 增加 target_assembly_pressure;导出目录不存在时跳过 CSV 记录且不中断组装任务

- neware: manual_confirm 解包/整合 CSV/schema 增加 target_assembly_pressure 列

- bioyond: 配液-电导相关调整

Co-authored-by: Cursor <cursoragent@cursor.com>
- coin_cell_init(原 func_pack_device_init_auto_start_combined):工站初始化
- coin_cell_start(原 func_sendbottle_allpack_multi):发瓶数 + 批量组装
- 物料参数拼音改英文简称:ne_plate_num / ne_plate_matrix / sep_plate_num /
  sep_plate_matrix / tip_box_matrix / aluminum_foil(coin_cell_start 与
  func_allpack_cmd_simp 同步)
- 删除冗余函数 qiming_coin_cell_code、func_allpack_cmd(逻辑已内联到
  func_allpack_cmd_simp),并修正 __main__ 测试块
- 同步 coin_cell_workstation.yaml:动作与参数改名,移除 auto-qiming_coin_cell_code
- 更新 yibin-electrolyte-submit 技能文档(SKILL.md / action-index.md)及两份历史
  md 文档中的动作名与参数说明
- bioyond_cell: 纳入既有未提交改动(CSV 导出相关)

Co-authored-by: Cursor <cursoragent@cursor.com>
 Optimization for bioyond, neware and coin_cell_assembly
- 新增模块级函数 push_csv_to_datacore(),通过 HTTP Basic Auth + multipart 上传把 CSV 推送到 DataCore 接入接口(设备号 unilab01)
- 支持凭据通过环境变量 DATACORE_INGEST_URL / DATACORE_DEVICE_ID / DATACORE_DEVICE_KEY 覆盖
- 内置失败重试:total_timeout=60s 总预算内自动重试,单次请求超时动态收紧到剩余预算
- manual_confirm 在整合 CSV 写入成功后自动调用推送(尽力而为,失败只记日志不影响节点返回)

Co-authored-by: Cursor <cursoragent@cursor.com>
- 删除 unilabos/devices/donghua_ec/ 目录及全部驱动文件
- 删除 unilabos/registry/devices/donghua_ec.yaml
- 删除 unilabos/devices/sse_auto_synthesis/ 目录及全部驱动文件
- 删除 unilabos/registry/devices/sse_auto_synthesis.yaml

Co-authored-by: Cursor <cursoragent@cursor.com>
Added datacore , removed solid-state synthesis workstation and Donghua workstation
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- manual_confirm goal 移除平铺的 collector_mass 等字段,改为 A/B/C 三组
- A(标量默认),B(逐颗数组),C(CSV 路径)
- resource 和 mount_resource 补充前端 title/description
- 覆盖 manual_confirm / submit_auto_export_excel / battery_transfer_confirm
- timeout_seconds 默认值从 3600 调整为 86400

Co-authored-by: Cursor <cursoragent@cursor.com>
…on loading support, and station fixes

- Add result export for conductivity test bottle-plate barcode entry (20ml dispensing bottle plate)
- Add adsorption loading support
- Other bug fixes (Bioyond dispensing station function naming conventions, etc.)

Co-authored-by: Cursor <cursoragent@cursor.com>
_get_xml_builder 原先一次性构建映射字典,引用了未实现的 xml_LFP_Li/xml_LP_LFP,导致每次调用均抛 AttributeError、全部电池下发失败。改为存函数名字符串并按需 getattr 惰性解析,同时移除 LFP_LI/LP_LFP 两个坏映射,未知体系给出清晰报错。

Co-authored-by: Cursor <cursoragent@cursor.com>
- coin_cell_assembly: 新增正极片取料模式、负极片厚度模式及吹气时间参数,同步写入PLC寄存器
- coin_cell_workstation.yaml: 补充上述4个新参数的schema定义及默认值
- bioyond_cell_workstation: 新增conductivityUnit字段,CSV列同步更新
- YB_warehouses: 新增bioyond_warehouse_4x2x1仓库工厂函数(5号右侧手动堆栈)
- decks: 注册5号右侧手动堆栈并配置坐标
- 新增coin_cell_assembly_b.csv及coin_cell_assembly_b_old.csv配置文件

Co-authored-by: Cursor <cursoragent@cursor.com>
- 新增 data_order_completion_percentage 属性,按 完成数/(瓶数×每瓶电池数) 计算订单进度
- coin_cell_start 记录电解液瓶数 _elec_bottle_num 作为分母
- data_electrolyte_volume 读取失败时容错返回 0
- registry 暴露 data_order_completion_percentage 状态字段

Co-authored-by: Cursor <cursoragent@cursor.com>
- decks.py: BioyondElectrolyteDeck.setup() 新增 大分液瓶堆栈/小分液瓶堆栈
  仓库节点(复用 bioyond_warehouse_3x3x1,A01-C03)及对应坐标,修复配液分液
  完成后登记 20ml 分液瓶板时报 Resource '大分液瓶堆栈' not found 的问题
- bioyond_cell_workstation.py: _extract_prep_bottle_from_report 配液瓶类型
  判断由子串匹配改为精确匹配,避免把托板 配液瓶(大)板/配液瓶(小)板
  误判为配液瓶导致 CSV 导出错误

Co-authored-by: Cursor <cursoragent@cursor.com>
一、进度百分比(本次主要开发)
背景:原先直接数 step_finish 报文(如「电导分液」出现 34 次)无法反映真实进度——
同一订单每瓶/每步会重复报送,且会串入其他批次订单(本批 8 单实际应为 32 瓶电导分液,
多出的 2 条来自 BSO20260715… 无关订单)。改为按本批 orderCode 集合归组统计,暴露两个
像扣电站 data_order_completion_percentage 一样的只读属性。

- __init__ 新增进度统计状态(带 _progress_lock 线程锁):本批订单集合 _batch_order_codes、
  每单分液瓶数 _batch_order_dispense,以及配液/分液的分母与完成集合。
- 新增 _reset_progress_tracking(orders, order_codes, data_list):提交批次时按 orderName
  关联响应(含 orderCode)与入参 orders(含分液配置),索引兜底;计算每单分液瓶数 =
  (loadSheddingInfo>0?1:0) + (pouchCellInfo>0?1:0) + (conductivityInfo>0?conductivityBottleCount:0),
  得到配液分母(订单数)与分液分母(瓶数之和)。
- _submit_and_wait_orders 拿到 order_codes 后调用重置(try 包裹,异常不影响下单)。
- 改写 process_step_finish_report:保留原日志与返回值;仅统计本批 orderCode;「开始混匀」
  记该单已混匀,「三轴取」且该单已混匀→配液完成+1(按订单去重),「电导分液/扣电分液/
  软包分液」→按 (orderCode, stepId) 去重计一瓶;每次更新打 INFO 进度日志。
- 新增 6 个 @Property(对齐扣电站写法:异常兜底 0.0、round(...,2)、分液做上限截断防溢出):
  data_formulation_completion_percentage、data_dispense_completion_percentage、
  data_formulation_total_count、data_formulation_completed_count、
  data_dispense_total_bottles、data_dispense_completed_bottles。

判定规则:
- 配液完成(按订单):同一订单先收到「开始混匀」再收到「三轴取」即计为完成;
  百分比 = 已完成订单数 / 本批订单数。
- 分液完成(按瓶):三类分液步骤 step_finish(电导/扣电/软包分液)按 (orderCode, stepId)
  去重计瓶;百分比 = 已完成瓶数 / 本批分液瓶总数。
- 全部限定在本批 orderCode 集合内,天然排除跨批次/其他订单串入。

registry/devices/bioyond_cell.yaml:status_types 追加上述 6 个字段(int/float),供前端轮询;
init_param_schema.data.properties 同步加入 6 个字段(integer/number)。

二、配液/电导报告导出修复
- 电导 finish 报文与配液分库缓存(_cond_finish_events/_cond_finish_reports),
  process_order_finish_report 双写、两库互不 pop,避免跨阶段串扰。
- _wait_conductivity_and_resolve_ids 进 wait 前按本批 orderCode 清电导缓存残留;
  _wait_conductivity_finish 命中缓存时校验 orderId 非空且非全 0 GUID,否则丢弃转阻塞等待。
- _collect_conductivity_results 用 resolved_oid 查空时,自动改用 creation_oid 兜底重试。
- 报告导出补齐各试剂允差/总质量允差列,新增配液+电导按分液瓶二维码合并导出
  Formulation_Conductivity_*.csv(瓶码为空时按 板码+X+Y 位置回退匹配)。

三、host_node.py
- manual_confirm 补充 docstring:说明确认对话框数据只读、人工修改不生效,补充参数说明。

说明与注意:
- 软包分液 step 名按「软包分液」处理(本批无软包样本,未从日志验证;若真实名不同,
  仅需改 _DISPENSE_STEP_NAMES 常量)。
- 未改动 wait_for_order_finish / order_finish 完成判定及分液、电导、转运执行逻辑;仅新增只读统计。

Co-authored-by: Cursor <cursoragent@cursor.com>
create_orders 收尾产出 vial_bottle_positions handle;conductivity_test_inline 硬切依赖该映射,过滤空占位孔并修复多单共板串单。

Co-authored-by: Cursor <cursoragent@cursor.com>
…ig pop

Read barcode from elevated root field (and PLR fallback) so frontend init_param_data.barcode reaches Bioyond LIMS.

Co-authored-by: Cursor <cursoragent@cursor.com>
同 orderCode、异 orderId 的推送(如仿真机 pool-r3)将被拒绝并继续等待;进度统计与 material-info 降级同步加固。

Co-authored-by: Cursor <cursoragent@cursor.com>
按《参数翻译与解释》统一 bioyond_cell、coin_cell_workstation、
neware_battery_test_system 的前端展示文案,便于操作员识别参数含义。

附带改动:

1. fix(bioyond_cell): barCode 不再用 materialName 冒充
   - _resolve_material_type_info:commit 1cd3493 起,报文带 typeName 就早退,
     并用 materialName(占位名 999/888)当条码,导致导出条码错误。
   - 真实 barCode 只在 material-info;finish 推送 / 建单 usedMaterials 均无 barCode。
   - 现改为:typeName 仍可从报文快取;barCode 只认报文自带值,缺失且为瓶/板时
     回查 material-info 取真实条码;接口失败降级为空字符串(空优于错误占位名);
     消耗品(typeName 不含"瓶")不额外查接口。
   - 不影响 finish 报文 orderCode+orderId 双重确认与 _enrich_report_materials_from_create。

2. chore(bioyond_cell): 新增 multitask_probe 调度开发测试动作
   - 对同一动作提交多任务、各传不同 task_no,按返回 start_time_ms 判断
     UniLab 多任务从前往后还是从后往前启动执行;仅用于调度开发测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
- 提取分液瓶板改为返回全部板型:旧实现"有 20ml 就只返回 20ml",混合实验
  (20ml 测电导 + 5ml 供扣电)下 5ml 板整块被丢掉,321 转运找不到板
- 321 批量转运按 typeName 只取 5ml 板,非 5ml 记 skipped
- 321 来源仓库固定为自动堆栈-左(WH3),不再由报告 locationId 反查:后者常
  指向配液站内临时槽位(小分液瓶堆栈[C03]),配上按槽位标签硬算的坐标
  (3,3,1) 会指到不存在的库位,LIMS 直接不建单
- 新增 _locate_material_in_warehouse:转运前查 warehouse-info 按 holdMId
  实时定位板的真实坐标,作为源坐标的权威来源
- 去重合并保留 source_x/y/z 并新增 source_found 标记,区分实测坐标与
  (1,1,1) 占位默认值,避免拿占位值去搬 A01 上的另一块板
- 三个转运接口在 LIMS 未返回 orderCode 或 finish 非 success 时抛异常,批量
  转运有板失败也抛:物理没动就不会继续同步资源树、往下跑 1→2 转运
- 资源树取板兼容 ResourceHolder 空槽,不再把 holder 当瓶板转运
- 瓶板命名带完整 materialId:奔曜 materialId 顺序生成,同订单多块板截断到
  前 8 位仍会撞名触发 already assigned to deck
- _get_warehouse_id 去掉回退到自动堆栈-左 uuid 的降级逻辑

Co-authored-by: Cursor <cursoragent@cursor.com>
原先实验报告只能在 create_orders 结束时依赖 order_finish 推送导出,推送丢失或
要事后补历史批次时无从下手。新增 export_order_report,只输入订单号与导出目录,
全部现查 LIMS 生成同格式 CSV。

取数链路:order-list 按 orderCode 查摘要(orderName/completeTime/reportFile,
用 preIntakes.sampleCode 前缀确认命中,因为 filter 是模糊匹配)→ 新增 order_report_v2
按 orderId 查 sampleMaterials 取瓶子规范类型名 → 下载解析报告 Excel 取配液瓶二维码
与逐组分目标/真实加样质量,据此算质量比与允差(口径同 _process_order_reagents)。

订单号支持打印机页码式写法:单个、全码区间、尾号简写区间(BSO2026072800006-29)、
逗号跳选,可混写;区间倒置/跨批次/超 500 单直接报错,避免笔误刷接口。

真实加样质量以报告 Excel 为准:已核对它与瓶身 feedingHistory 逐位一致,而
order_finish 推送的粉末 realQuantity 在 0728 批有 6 单 LiPF6 归属错位。分液瓶
二维码只取报告 Excel 的时点快照,缺失时留空并告警——查接口拿到的是瓶位当前状态,
会被后续批次扫码覆盖、串到别单。

全部为新增方法,未改动任何现有取数与导出逻辑。已用 0728 批 24 单实跑校验,9 列
数据与既有报告完全一致(分液瓶二维码 16 单有值、8 单扫码失败留空)。

Co-authored-by: Cursor <cursoragent@cursor.com>
电导+软包混合单里两类分液瓶板的 typeName 同为 20ml分液瓶板,靠板型无法
判断谁该走 32 转运。改为转运前查一次自动堆栈-左的实时占用,只搬命中的板,
已搬到 5 号自动传递窗的电导板直接跳过而非报错,与电导侧按传递窗求交集的
过滤正好互补。落点在 2 号手套箱、当前无对应设备节点承接,故只做物理转运
不做资源树同步。

顺带把 warehouse-info 查询抽成 _snapshot_warehouse 以便批量复用,并在 deck
上补齐 5 号自动传递窗(LIMS code=0018),让电导板有库位可挂。
LIMS /order/orders 是逐单校验逐单建单:一批里某单试剂不足时只有该单
errorMessage 非空,其余单照常建出来并推进调度队列,留下需要人工暂停
调度、撤单善后的半批订单。

- 新增 _preflight_check_reagents:提交前把整批 materialInfos 按试剂名汇总,
  与 2.3 stock-material 的在库量比对(同名多瓶累加、只扣正的 lockQuantity),
  任一不足则整批不下发并抛出带需求/可用/缺口明细的异常;库存查询失败时
  降级放行,交回 LIMS 逐单校验兜底,避免预检自身变成新的故障点
- 建单结果改为按 errorMessage + orderCode 逐条判定,出现失败条目或条目数
  对不上请求数时暂停调度并抛异常,不再静默丢弃失败单后报 all_completed
- total_orders 改用请求单数,避免建成 4 单 / 请求 8 单时显示成 4/4
- 新增 scheduler_pause 封装 2.8 暂停调度
- 资源树跳过无编号的空瓶位,防止下游按 barCode 取到未分液的空瓶

Co-authored-by: Cursor <cursoragent@cursor.com>
新增 wait_orderlist_idle 互锁(放行凭证、批次缓存、调度与失败单检测)及 precheck_reagents_total;增强 stack_inquiry_2to1 与 stack_inquiry_window_5_free。按 LIMS 实测修正 order-list:timeType 用 requestTime、运行/失败只看响应 status,避免把「未取出」误判为执行中。扣电工站新增 coin_cell_sim_delay 长时延模拟,并同步 bioyond_cell 与 coin_cell 注册表。

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants