77 Commits

Author SHA1 Message Date
calvincao
f230028558 feat: Enhance CoincellDeck setup with new ClipMagazine and BottleRack configurations
- Refactored ClipMagazine class to inherit from ItemizedResource and updated hole dimensions.
- Introduced ClipMagazine_four class for a new 2x2 hole layout.
- Expanded CoincellDeck setup to include multiple ClipMagazines and MaterialPlates with ElectrodeSheets.
- Improved BottleRack initialization with dynamic item positioning and resource assignment.
- Added serialization methods for new classes to maintain state consistency.
2025-11-03 21:30:27 +08:00
Calvin Cao
1c1a6b16c8 Merge pull request #142 from lixinyu1011/workstation_dev_YB3
11103-2byxinyu
2025-11-03 19:51:56 +08:00
lixinyu1011
a2d6012080 Merge branch 'workstation_dev_YB3' of https://github.com/lixinyu1011/Uni-Lab-OS into workstation_dev_YB3 2025-11-03 19:50:04 +08:00
lixinyu1011
10adc853a5 1103-2byxinyu 2025-11-03 19:50:01 +08:00
Calvin Cao
69ec034623 Merge pull request #141 from lixinyu1011/workstation_dev_YB3
1103byxinyu
2025-11-03 19:47:13 +08:00
Calvin Cao
62d08aa954 Merge branch 'workstation_dev_YB3' into workstation_dev_YB3 2025-11-03 19:46:52 +08:00
lixinyu1011
4485907df8 1103byxinyu 2025-11-03 18:46:50 +08:00
calvincao
b5b2358967 fix: 更新HTTP服务配置和物料类型映射
- 修改BIOYOND_HTTP_HOST的默认值为新的IP地址172.21.32.91
- 调整物料类型映射中“加样头(大)”的UUID顺序,并注释掉“加样头(大)板”配置
2025-11-03 18:20:50 +08:00
lixinyu1011
11f4f44bf9 Update coin_cell_assembly.py 2025-11-03 16:51:28 +08:00
lixinyu1011
f52fbd650e Update bioyond_cell_workstation.py 2025-11-03 16:50:59 +08:00
calvincao
e561c818b8 feat: 添加多个新仓库配置到config.py
- 新增多个仓库配置,包括大分液瓶堆栈、小分液瓶堆栈、站内Tip头盒堆栈等
- 每个仓库配置包含UUID和站点UUID映射
2025-11-03 14:31:50 +08:00
Calvin Cao
5cbd880e5a Merge pull request #140 from sun7151887/fix/yb3-material-names-and-model
fix: 修正YB warehouse排列方式和物料类型映射
2025-11-01 11:16:00 +08:00
Calvin Cao
41e7251f62 Merge branch 'workstation_dev_YB3' into fix/yb3-material-names-and-model 2025-11-01 11:14:45 +08:00
dijkstra402
727d2c2595 fix: 修正YB warehouse排列方式和物料类型映射
- 修改warehouse_factory为YB_warehouse_factory
- 调整warehouse排列方式:左上角为A01,竖着排ABCD,横着排01、02、03
- 修正config.py中的物料名称拼写错误(YB_fen_ye_20ml_Bottle, YB_pei_ye_xiao_Bottle)
- 添加缺失的warehouse函数(bioyond_warehouse_2x2x1, bioyond_warehouse_3x5x1, bioyond_warehouse_20x1x1)
- 更新decks.py中的warehouse位置映射
- 删除废弃的bottles.py和warehouses.py文件
2025-11-01 10:42:31 +08:00
Calvin Cao
202a2667fd Merge pull request #139 from lixinyu1011/workstation_dev_YB3
byxinyu111
2025-11-01 10:41:13 +08:00
lixinyu1011
03745c5d08 byxinyu111 2025-11-01 10:37:45 +08:00
Calvin Cao
385a495e21 Merge pull request #138 from lixinyu1011/workstation_dev_YB3
新建入库物料系统
2025-10-31 19:04:28 +08:00
lixinyu1011
91513a5f4c Delete button_battery_station.py 2025-10-31 19:02:06 +08:00
lixinyu1011
a62896eda2 1031_byxinyu 2025-10-31 18:57:38 +08:00
lixinyu1011
a82d1b7bdb Merge remote-tracking branch 'upstream/workstation_dev_YB3' into workstation_dev_YB3 2025-10-31 15:30:28 +08:00
lixinyu1011
6d7c39da9e 1031 2025-10-31 15:29:59 +08:00
Calvin Cao
d8e9ad4413 Merge pull request #136 from sun7151887/fix/yb3-material-names-and-model
fix: 更新物料类型配置映射
2025-10-31 15:13:48 +08:00
dijkstra402
eb93b83415 fix: 更新物料类型配置映射 2025-10-31 15:05:47 +08:00
lixinyu1011
6df93a5db7 Merge remote-tracking branch 'upstream/workstation_dev_YB3' into workstation_dev_YB3 2025-10-31 14:02:45 +08:00
lixinyu1011
2eb9986edb 123 2025-10-31 13:54:58 +08:00
calvincao
fe4e49e56d feat(workstation): 更新 Bioyond 和 Coin Cell 组装工作站配置
- 修改 Bioyond Studio 配置文件中的 API 主机地址
- 更新 bioyond_cell_workstation.py 中的默认模板路径
- 新增物料模板文件 material_template.xlsx
- 扩展 func_pack_send_msg_cmd 函数以支持 assembly_pressure 参数
- 更新 coin_cell_workstation.yaml 文件以包含 assembly_pressure 的默认值和类型定义
2025-10-31 13:53:58 +08:00
calvincao
0fba4cf275 feat(unilabos): 更新设备配置和资源定义
- 修改了 bioyond_cell.yaml 中的 xlsx_path 路径分隔符为反斜杠- 在 bioyond_cell.yaml 中新增多个自动命令定义,包括创建物料、处理报告和调度重置等功能- 修改 coin_cell_assembly.py 中 func_pack_send_msg_cmd 函数签名并调整调用参数
- 新增 qiming_coin_cell_code 方法用于设置启明扣电配置参数
- 更新 coin_cell_assembly_a.csv 文件中的寄存器描述和新增压制模式及清洁忽略选项- 修改 bioyond_studio 配置文件中的默认 API 主机地址
- 更新 new_cellconfig3c.json 中的设备类名为 coincellassemblyworkstation_device- 删除 reaction_station_bioyond.yaml 的全部内容,仅保留空对象
-重新组织 YB_bottle.yaml 和 YB_bottle_carriers.yaml 中的资源分类和命名定义
2025-10-30 19:56:34 +08:00
Calvin Cao
ef9359776a Merge pull request #134 from sun7151887/fix/yb3-material-names-and-model
feat: 添加扣电工作站 setup() 方法并修复显示问题
2025-10-30 16:31:50 +08:00
Calvin Cao
954f1ee7b2 Merge branch 'workstation_dev_YB3' into fix/yb3-material-names-and-model 2025-10-30 16:31:27 +08:00
dijkstra402
f58921ef82 feat: 添加扣电工作站 setup() 方法并修复显示问题
主要改动:
-  在 CoincellDeck 实现 setup() 方法(模仿 decks.py 三步配置模式)
-  统一 Deck 默认尺寸为 1000x1000x900mm
-  优化料盘布局:横向排列,留50mm边距
-  简化工作站 deck 创建逻辑(从30行减至1行)
-  新增 create_coin_cell_deck() 便捷函数
-  修复 ClipMagazine 参数错误
-  删除约200行冗余代码
-  修复底座不显示问题

技术细节:
- MaterialPlate 位置: liaopan1(50,50), liaopan2(250,50), 电池料盘(450,50)
- 自动为 liaopan1 添加16个初始极片
- 支持3种 deck 创建方式
- 智能判断是否需要 setup
2025-10-30 16:18:43 +08:00
calvincao
95bdd39bf8 fix(workstation): 更新 coin_cell_assembly_a.csv 中的寄存器和线圈定义为中文描述
- 将寄存器和线圈定义中的英文描述替换为中文,提升可读性
- 确保所有定义格式一致,保持文件的整洁性和维护性
2025-10-30 14:25:33 +08:00
calvincao
b3e28196c6 feat(battery): 更新电池工位资源配置
- 将 coin_cell_deck 类型从 container 更改为 coin_cell_deck
- 将 material_plate 类型从 container 更改为 material_plate
- 将 material_hole 类型从 container 更改为 material_hole- 移除电极片容器结构,直接使用 electrode_sheet 类型
- 更新物料孔配置参数,包括直径、深度和最大片数
-重新组织料盘结构,明确父子节点关系
- 添加新的电极片定义并关联到对应的物料孔
- 调整所有物料孔坐标位置以匹配新布局
- 为 liaopan2 添加完整的子节点结构和排序规则
2025-10-30 11:22:17 +08:00
calvincao
9fe8f4f28f fix(workstation): 修复 coin_cell_assembly_a.csv 文件中的寄存器和线圈定义格式
- 重新排列并清理了 coin_cell_assembly_a.csv 中的寄存器和线圈定义
- 确保所有定义的格式一致,提升可读性和维护性
2025-10-29 21:36:52 +08:00
calvincao
39bc317bfc feat(workstation): 支持多种输入类型的 station_resource 并优化物料系统初始化
- 新增 `_coerce_station_resource_input` 函数以支持 dict、list 和其他类型转换为 Deck
- 添加对 Modbus 客户端方法的兼容性封装,确保 slave/unit 参数正确传递- 在初始化时根据 station_resource 动态创建或赋值 deck
- 自动构建默认物料台面及三个料盘,并分配初始电极片资源
- 移除旧有的硬编码物料系统注释代码
- 更新资源导出逻辑以使用工作站实例中的 deck 属性
2025-10-29 18:39:22 +08:00
calvincao
a130c03ebd feat(workstation): 移除旧版bioyond设备配置并优化扣电组装工作站- 删除bioyond.yaml和bioyond_dispensing_station.yaml旧设备配置文件- 优化扣电组装工作站配置,移除不必要的子资源引用- 更新Modbus通信地址和端口配置- 简化CoinCellAssemblyWorkstation类的初始化参数- 移除冗余的deck资源创建逻辑
- 更新反应站配置文件中drip_back命令的位置
- 添加新的Modbus寄存器和线圈定义
- 移除workstation_base.py基类文件
2025-10-29 10:44:30 +08:00
calvincao
a97781c4eb Merge remote-tracking branch 'origin/dev' into workstation_dev_YB3 2025-10-28 11:47:07 +08:00
calvincao
c35edcece1 重构 coin_cell_assembly 目录结构 2025-10-28 11:42:14 +08:00
Calvin Cao
524e0f3053 Merge pull request #132 from sun7151887/fix/yb3-material-names-and-model
feat: 添加YB瓶子和载架配置
2025-10-27 22:30:40 +08:00
Calvin Cao
66f483929d Merge branch 'workstation_dev_YB3' into fix/yb3-material-names-and-model 2025-10-27 22:30:16 +08:00
dijkstra402
2d58576937 feat: 添加YB瓶子和载架配置
- 在YB_bottles.py中添加8种瓶子类型(100ml液体、高粘液、5ml分液瓶、20ml分液瓶、配液瓶小、配液瓶大、枪头等)
- 在YB_bottle_carriers.py中添加12个载架函数(包括新增的高粘液载架和100ml液体载架)
- 更新config.py的MATERIAL_TYPE_MAPPINGS配置,添加16种物料类型映射
- 创建YB_bottle_carriers.yaml注册文件,包含所有载架和瓶子函数
- 创建YB_bottle.yaml注册文件,包含独立的瓶子函数配置
- 移除不存在的瓶子函数引用(YB_Solid_Vial等4个函数)
2025-10-27 22:23:09 +08:00
calvincao
ff25e814de feat: add new glove box internal stack configuration with site UUIDs 2025-10-27 22:08:02 +08:00
Calvin Cao
0163d16cbb Merge pull request #131 from lixinyu1011/workstation_dev_YB3
by_Xinyu1027
2025-10-27 20:15:43 +08:00
lixinyu1011
3231d60646 1027by_Xinyu 2025-10-27 20:08:19 +08:00
lixinyu1011
d0279f63f0 Merge remote-tracking branch 'upstream/workstation_dev_YB3' into workstation_dev_YB3 2025-10-27 19:33:45 +08:00
lixinyu1011
ceef342860 1027byxinyu 2025-10-27 18:16:26 +08:00
h840473807
42f7010134 提交扣电工站最新代码到YB3分支
提交扣电工站最新代码到YB3分支,更新注册表
2025-10-27 11:57:57 +08:00
calvincao
190b2d2518 清理扣电不必要代码 2025-10-27 11:43:03 +08:00
calvincao
2901d72b4b feat: add button battery assembly station resources and configuration files
- Introduced new Python modules for button battery assembly, including resource classes and configurations.
- Added JSON and CSV files for resource definitions and device configurations.
- Created initial setup for the coin cell assembly workstation, including material handling and resource management.
2025-10-25 13:50:41 +08:00
calvincao
6ad0157b50 feat: add new warehouse configurations and update site UUIDs in bioyond_studio config 2025-10-24 16:37:11 +08:00
calvincao
55b678cd37 fix: update report IP address in configuration and clean up parameters in SOLID_LIQUID_MAPPINGS 2025-10-24 14:22:39 +08:00
Calvin Cao
8101a22a0f Merge pull request #130 from sun7151887/workstation_dev_YB3
refactor: 将 BIOYOND_PolymerStation_ 前缀统一改为 YB_
2025-10-24 13:56:08 +08:00
Calvin Cao
667138baac Merge branch 'workstation_dev_YB3' into workstation_dev_YB3 2025-10-24 13:56:00 +08:00
dijkstra402
01adf7ca92 refactor: 将 BIOYOND_PolymerStation_ 前缀统一改为 YB_
- 重命名 bottles.py 中所有工厂函数:BIOYOND_PolymerStation_* -> YB_*
- 重命名 bottle_carriers.py 中所有载具工厂函数和导入
- 更新 registry YAML 文件中的 module 引用
- 更新 MATERIAL_TYPE_MAPPINGS 配置中的类型字符串
- 更新测试文件和样例 JSON 中的类型引用
- 添加 YB_* 别名条目到 registry 以支持双键访问
2025-10-24 13:49:48 +08:00
Calvin Cao
f606062696 Merge pull request #129 from lixinyu1011/workstation_dev_YB3
xinyu1024修改
2025-10-24 11:44:16 +08:00
Calvin Cao
67d1c4acce Merge branch 'workstation_dev_YB3' into workstation_dev_YB3 2025-10-24 11:44:04 +08:00
lixinyu1011
7206e42bf1 xinyu1024修改 2025-10-24 11:37:36 +08:00
calvincao
e92d933968 refactor(bioyond_cell_workstation): 重构物料创建与入库逻辑- 移除从CSV读取物料名称的功能
- 新增通过参数传递物料名称列表的方式- 抽离仓库位置加载逻辑至独立方法
- 简化物料创建与入库流程- 统一使用资源同步器进行数据同步
- 更新调用示例以适配新接口
2025-10-23 22:36:21 +08:00
Calvin Cao
f0ebcc60bb Merge pull request #126 from sun7151887/fix/yb3-material-names-and-model
添加新物料类型映射:包括100ml液体、液、高粘液、5ml/20ml分液瓶、配液瓶、加样头、适配器块、枪头盒等
2025-10-23 21:59:26 +08:00
dijkstra402
e2097f0b22 添加新物料类型映射:包括100ml液体、液、高粘液、5ml/20ml分液瓶、配液瓶、加样头、适配器块、枪头盒等 2025-10-23 21:56:54 +08:00
calvincao
fd73731130 增强批量入库功能,添加物料数据同步逻辑;优化日志记录以提供更详细的同步状态信息。 2025-10-23 18:02:49 +08:00
Calvin Cao
ab7f2081c9 Merge pull request #124 from sun7151887/fix/yb3-material-names-and-model
更新载架网格布局:5ml/20ml/配液瓶(小)板改为4x2,加样头(大)板改为1x1
2025-10-23 17:45:29 +08:00
dijkstra402
9e850d8a81 更新载架网格布局:5ml/20ml/配液瓶(小)板改为4x2,加样头(大)板改为1x1 2025-10-23 17:42:10 +08:00
calvincao
1af6ffafc6 新增批量创建固体物料和从CSV文件入库的功能;更新配置文件中的 report_ip 默认值;新增 solid_materials.csv 文件以支持物料名称导入。 2025-10-23 17:32:08 +08:00
Calvin Cao
35fc2f5ea6 Merge pull request #123 from sun7151887/fix/yb3-material-names-and-model
fix(yb3): 物料名称与模型对齐;YAML 去掉 BIOYOND_PolymerStation_ 前缀;修复 6StockCarri…
2025-10-23 15:43:40 +08:00
dijkstra402
d3d8ba6500 fix(yb3): 物料名称与模型对齐;YAML 去掉 BIOYOND_PolymerStation_ 前缀;修复 6StockCarrier model 2025-10-23 15:32:36 +08:00
calvincao
5a7845d8ca 更新配置文件中的 report_ip 默认值,优化 bioyond_cell_workstation.py 中的订单状态处理逻辑,新增多个瓶子和载架类型的定义,调整仓库结构以支持更灵活的物料管理。 2025-10-23 08:34:33 +08:00
calvincao
9c4d0256cf 增强配置文件,新增 report_ip 选项以支持本机 IP 地址的灵活配置;在 bioyond_cell_workstation.py 中优化推送地址更新逻辑,支持自动检测和配置优先级处理。 2025-10-22 16:38:32 +08:00
calvincao
de7c80c3c2 重构:完善配置加载机制与初始化逻辑
新增环境变量覆盖机制,增强配置灵活性

优化 bioyond_rpc.py 与 bioyond_cell_workstation.py 的初始化流程与结构

修正 station.py 工作流映射逻辑,确保正确性

提高代码可读性与模块间解耦程度
2025-10-22 16:13:36 +08:00
calvincao
e70c545ec8 修复 **bioyond_yihua_YB.json** 中的 JSON 合并冲突,清理不必要的标记。 2025-10-21 15:19:44 +08:00
calvincao
2c2d1e5569 在 **bioyond_cell_workstation.py** 中实现 update_push_ip 方法并增强错误处理;修复 **bioyond_yihua_YB.json** 中的 JSON 合并冲突。 2025-10-21 14:58:38 +08:00
Calvin Cao
4638611fe7 Merge pull request #119 from lixinyu1011/workstation_dev_YB3
Update station.py
2025-10-21 14:51:54 +08:00
lixinyu1011
37641c4389 xinyu1021推送代码 2025-10-21 14:48:55 +08:00
lixinyu1011
ab697ce973 Update station.py 2025-10-20 16:12:38 +08:00
Calvin Cao
d4724b8664 Merge pull request #117 from lixinyu1011/workstation_dev_YB3
Update bioyond_cell_workstation.py
2025-10-20 15:33:17 +08:00
lixinyu1011
2f25063bf1 Update bioyond_cell_workstation.py 2025-10-20 15:30:41 +08:00
Calvin Cao
00b4b9cd87 Merge pull request #116 from lixinyu1011/workstation_dev_YB3
1020_YB奔耀仿真机同步对齐dev_unilab可控
2025-10-20 12:56:36 +08:00
lixinyu1011
d2352cc514 1020_YB奔耀仿真机同步对齐dev_unilab可控
待修改unilab的http服务
2025-10-20 12:48:19 +08:00
48 changed files with 22634 additions and 9400 deletions

14473
bioyond_yihua_YB.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

68
new_cellconfig3c.json Normal file
View File

@@ -0,0 +1,68 @@
{
"nodes": [
{
"id": "bioyond_cell_workstation",
"name": "配液分液工站",
"parent": null,
"children": [
"YB_Bioyond_Deck"
],
"type": "device",
"class": "bioyond_cell",
"config": {
"deck": {
"data": {
"_resource_child_name": "YB_Bioyond_Deck",
"_resource_type": "unilabos.resources.bioyond.decks:BIOYOND_YB_Deck"
}
},
"protocol_type": []
},
"data": {}
},
{
"id": "YB_Bioyond_Deck",
"name": "YB_Bioyond_Deck",
"children": [],
"parent": "bioyond_cell_workstation",
"type": "deck",
"class": "BIOYOND_YB_Deck",
"position": {
"x": 0,
"y": 0,
"z": 0
},
"config": {
"type": "BIOYOND_YB_Deck",
"setup": true,
"rotation": {
"x": 0,
"y": 0,
"z": 0,
"type": "Rotation"
}
},
"data": {}
},
{
"id": "BatteryStation",
"name": "扣电工作站",
"children": [
"coin_cell_deck"
],
"parent": null,
"type": "device",
"class": "coincellassemblyworkstation_device",
"position": {
"x": 600,
"y": 400,
"z": 0
},
"config": {
"debug_mode": false,
"protocol_type": []
}
}
],
"links": []
}

View File

@@ -24,13 +24,13 @@
"Drip_back": "3a162cf9-6aac-565a-ddd7-682ba1796a4a"
},
"material_type_mappings": {
"烧杯": ["BIOYOND_PolymerStation_1FlaskCarrier", "3a14196b-24f2-ca49-9081-0cab8021bf1a"],
"试剂瓶": ["BIOYOND_PolymerStation_1BottleCarrier", ""],
"样品板": ["BIOYOND_PolymerStation_6StockCarrier", "3a14196e-b7a0-a5da-1931-35f3000281e9"],
"分装板": ["BIOYOND_PolymerStation_6VialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"],
"样品瓶": ["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"]
"烧杯": ["YB_1FlaskCarrier", "3a14196b-24f2-ca49-9081-0cab8021bf1a"],
"试剂瓶": ["YB_1BottleCarrier", ""],
"样品板": ["YB_6StockCarrier", "3a14196e-b7a0-a5da-1931-35f3000281e9"],
"分装板": ["YB_6VialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"],
"样品瓶": ["YB_Solid_Stock", "3a14196a-cf7d-8aea-48d8-b9662c7dba94"],
"90%分装小瓶": ["YB_Solid_Vial", "3a14196c-cdcf-088d-dc7d-5cf38f0ad9ea"],
"10%分装小瓶": ["YB_Liquid_Vial", "3a14196c-76be-2279-4e22-7310d69aed68"]
}
},
"deck": {

View File

@@ -24,9 +24,9 @@
"Drip_back": "3a162cf9-6aac-565a-ddd7-682ba1796a4a"
},
"material_type_mappings": {
"烧杯": "BIOYOND_PolymerStation_1FlaskCarrier",
"试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier",
"样品板": "BIOYOND_PolymerStation_6VialCarrier"
"烧杯": "YB_1FlaskCarrier",
"试剂瓶": "YB_1BottleCarrier",
"样品板": "YB_6VialCarrier"
}
},
"deck": {

View File

@@ -0,0 +1,52 @@
[
{
"id": "3a1d377b-299d-d0f2-ced9-48257f60dfad",
"typeName": "加样头(大)",
"code": "0005-00145",
"barCode": "",
"name": "LiDFOB",
"quantity": 9999.0,
"lockQuantity": 0.0,
"unit": "个",
"status": 1,
"isUse": false,
"locations": [
{
"id": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"whid": "3a19da56-1378-613b-29f2-871e1a287aa5",
"whName": "粉末加样头堆栈",
"code": "0005-0001",
"x": 1,
"y": 1,
"z": 1,
"quantity": 0
}
],
"detail": []
},
{
"id": "3a1d377b-6a81-6a7e-147c-f89f6463656d",
"typeName": "液",
"code": "0006-00141",
"barCode": "",
"name": "EMC",
"quantity": 99999.0,
"lockQuantity": 0.0,
"unit": "g",
"status": 1,
"isUse": false,
"locations": [
{
"id": "3a1baa20-a7b1-c665-8b9c-d8099d07d2f6",
"whid": "3a1baa20-a7b0-5c19-8844-5de8924d4e78",
"whName": "4号手套箱内部堆栈",
"code": "0015-0001",
"x": 1,
"y": 1,
"z": 1,
"quantity": 0
}
],
"detail": []
}
]

View File

@@ -0,0 +1,99 @@
{
"typeId": "3a190c8b-3284-af78-d29f-9a69463ad047",
"code": "",
"barCode": "",
"name": "test",
"unit": "",
"parameters": "{}",
"quantity": "",
"details": [
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)11",
"quantity": "1",
"x": 1,
"y": 1,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)21",
"quantity": "1",
"x": 2,
"y": 1,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)12",
"quantity": "1",
"x": 1,
"y": 2,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)22",
"quantity": "1",
"x": 2,
"y": 2,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)13",
"quantity": "1",
"x": 1,
"y": 3,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)23",
"quantity": "1",
"x": 2,
"y": 3,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)14",
"quantity": "1",
"x": 1,
"y": 4,
"z": 1,
"unit": "",
"parameters": "{}"
},
{
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb",
"code": "",
"name": "配液瓶(小)24",
"quantity": "1",
"x": 2,
"y": 4,
"z": 1,
"unit": "",
"parameters": "{}"
}
]
}

148
test/resources/test.json Normal file
View File

@@ -0,0 +1,148 @@
[
{
"id": "3a1d4c14-a9fb-d7dc-9e96-7a3ad6e50219",
"typeName": "配液瓶(小)板",
"code": "0001-00093",
"barCode": "",
"name": "test",
"quantity": 2.0,
"lockQuantity": 0.0,
"unit": "块",
"status": 1,
"isUse": false,
"locations": [
{
"id": "3a19deae-2c7a-36f5-5e41-02c5b66feaea",
"whid": "3a19deae-2c79-05a3-9c76-8e6760424841",
"whName": "手动堆栈",
"code": "1",
"x": 1,
"y": 1,
"z": 1,
"quantity": 0
}
],
"detail": [
{
"id": "3a1d4c14-a9fc-1daa-71fa-146cb1ccb930",
"detailMaterialId": "3a1d4c14-a9fc-4f38-4c48-68486c391c42",
"code": "0001-00093 - 05",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 1,
"y": 3,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-3659-ea61-cd587da9e131",
"detailMaterialId": "3a1d4c14-a9fc-018f-93e5-c49343d37758",
"code": "0001-00093 - 08",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 2,
"y": 4,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-3f94-de83-979d2646e313",
"detailMaterialId": "3a1d4c14-a9fc-9987-c0ef-4b7cbad49e6b",
"code": "0001-00093 - 01",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 1,
"y": 1,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-8c35-6b25-913b11dbaf4e",
"detailMaterialId": "3a1d4c14-a9fc-9a83-865b-0c26ea5e8cc4",
"code": "0001-00093 - 03",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 1,
"y": 2,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-b41f-e968-64953bfddccd",
"detailMaterialId": "3a1d4c14-a9fc-daf7-9d64-e5ec8d3ae0e2",
"code": "0001-00093 - 07",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 1,
"y": 4,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-c20f-c26e-b1bb2cdc3bca",
"detailMaterialId": "3a1d4c14-a9fc-673b-ac83-aaaf71287f1f",
"code": "0001-00093 - 06",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 2,
"y": 3,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-cf21-059c-fde361d82b6f",
"detailMaterialId": "3a1d4c14-a9fc-25b1-e736-6b0d8dac0fae",
"code": "0001-00093 - 02",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 2,
"y": 1,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
},
{
"id": "3a1d4c14-a9fc-d732-2b93-9b2bd2bf581b",
"detailMaterialId": "3a1d4c14-a9fc-7f5d-b6b6-8bcb2e15f320",
"code": "0001-00093 - 04",
"name": "配液瓶(小)",
"quantity": "1",
"lockQuantity": "0",
"unit": "个",
"x": 2,
"y": 2,
"z": 1,
"associateId": null,
"typeName": "配液瓶(小)",
"typeId": "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"
}
]
}
]

View File

@@ -1,7 +1,7 @@
import pytest
from unilabos.resources.bioyond.bottle_carriers import BIOYOND_Electrolyte_6VialCarrier, BIOYOND_Electrolyte_1BottleCarrier
from unilabos.resources.bioyond.bottles import BIOYOND_PolymerStation_Solid_Vial, BIOYOND_PolymerStation_Solution_Beaker, BIOYOND_PolymerStation_Reagent_Bottle
from unilabos.resources.bioyond.bottles import YB_Solid_Vial, YB_Solution_Beaker, YB_Reagent_Bottle
def test_bottle_carrier() -> "BottleCarrier":
@@ -16,9 +16,9 @@ def test_bottle_carrier() -> "BottleCarrier":
print(f"1烧杯载架: {beaker_carrier.name}, 位置数: {len(beaker_carrier.sites)}")
# 创建瓶子和烧杯
powder_bottle = BIOYOND_PolymerStation_Solid_Vial("powder_bottle_01")
solution_beaker = BIOYOND_PolymerStation_Solution_Beaker("solution_beaker_01")
reagent_bottle = BIOYOND_PolymerStation_Reagent_Bottle("reagent_bottle_01")
powder_bottle = YB_Solid_Vial("powder_bottle_01")
solution_beaker = YB_Solution_Beaker("solution_beaker_01")
reagent_bottle = YB_Reagent_Bottle("reagent_bottle_01")
print(f"\n创建的物料:")
print(f"粉末瓶: {powder_bottle.name} - {powder_bottle.diameter}mm x {powder_bottle.height}mm, {powder_bottle.max_volume}μL")

View File

@@ -12,13 +12,13 @@ lab_registry.setup()
type_mapping = {
"烧杯": ("BIOYOND_PolymerStation_1FlaskCarrier", "3a14196b-24f2-ca49-9081-0cab8021bf1a"),
"试剂瓶": ("BIOYOND_PolymerStation_1BottleCarrier", ""),
"样品板": ("BIOYOND_PolymerStation_6StockCarrier", "3a14196e-b7a0-a5da-1931-35f3000281e9"),
"分装板": ("BIOYOND_PolymerStation_6VialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"),
"样品瓶": ("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"),
"烧杯": ("YB_1FlaskCarrier", "3a14196b-24f2-ca49-9081-0cab8021bf1a"),
"试剂瓶": ("YB_1BottleCarrier", ""),
"样品板": ("YB_6StockCarrier", "3a14196e-b7a0-a5da-1931-35f3000281e9"),
"分装板": ("YB_6VialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"),
"样品瓶": ("YB_Solid_Stock", "3a14196a-cf7d-8aea-48d8-b9662c7dba94"),
"90%分装小瓶": ("YB_Solid_Vial", "3a14196c-cdcf-088d-dc7d-5cf38f0ad9ea"),
"10%分装小瓶": ("YB_Liquid_Vial", "3a14196c-76be-2279-4e22-7310d69aed68"),
}

View File

@@ -1,3 +1,4 @@
from ast import If
import pytest
import json
import os
@@ -8,18 +9,16 @@ from unilabos.ros.nodes.resource_tracker import ResourceTreeSet
from unilabos.registry.registry import lab_registry
from unilabos.resources.bioyond.decks import BIOYOND_PolymerReactionStation_Deck
from unilabos.resources.bioyond.decks import YB_Deck
lab_registry.setup()
type_mapping = {
"烧杯": ("BIOYOND_PolymerStation_1FlaskCarrier", "3a14196b-24f2-ca49-9081-0cab8021bf1a"),
"试剂瓶": ("BIOYOND_PolymerStation_1BottleCarrier", ""),
"样品": ("BIOYOND_PolymerStation_6StockCarrier", "3a14196e-b7a0-a5da-1931-35f3000281e9"),
"分装板": ("BIOYOND_PolymerStation_6VialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"),
"样品瓶": ("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"),
"加样头(大)": ("YB_jia_yang_tou_da_1X1_carrier", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
"": ("YB_1BottleCarrier", "3a190ca1-2add-2b23-f8e1-bbd348b7f790"),
"配液瓶(小)": ("YB_6x_SmallSolutionBottleCarrier", "3a190c8b-3284-af78-d29f-9a69463ad047"),
"配液瓶(小)": ("YB_pei_ye_xiao_Bottler", "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"),
}
@@ -57,12 +56,20 @@ def bioyond_materials_liquidhandling_2() -> list[dict]:
"bioyond_materials_reaction",
"bioyond_materials_liquidhandling_1",
])
def test_resourcetreeset_from_plr(materials_fixture, request) -> list[dict]:
materials = request.getfixturevalue(materials_fixture)
deck = BIOYOND_PolymerReactionStation_Deck("test_deck")
def test_resourcetreeset_from_plr() -> list[dict]:
# 直接加载 bioyond_materials_reaction.json 文件
current_dir = os.path.dirname(os.path.abspath(__file__))
json_path = os.path.join(current_dir, "test.json")
with open(json_path, "r", encoding="utf-8") as f:
materials = json.load(f)
deck = YB_Deck("test_deck")
output = resource_bioyond_to_plr(materials, type_mapping=type_mapping, deck=deck)
print(deck.summary())
print(output)
# print(deck.summary())
r = ResourceTreeSet.from_plr_resources([deck])
print(r.dump())
# json.dump(deck.serialize(), open("test.json", "w", encoding="utf-8"), indent=4)
if __name__ == "__main__":
test_resourcetreeset_from_plr()

View File

@@ -0,0 +1,296 @@
# -*- coding: utf-8 -*-
import serial
import time
import csv
import threading
import os
from collections import deque
from typing import Dict, Any, Optional
from pylabrobot.resources import Deck
from unilabos.devices.workstation.workstation_base import WorkstationBase
class ElectrolysisWaterPlatform(WorkstationBase):
"""
电解水平台工作站
基于 WorkstationBase 的电解水实验平台,支持串口通信和数据采集
"""
def __init__(
self,
deck: Deck,
port: str = "COM10",
baudrate: int = 115200,
csv_path: Optional[str] = None,
timeout: float = 0.2,
**kwargs
):
super().__init__(deck, **kwargs)
# ========== 配置 ==========
self.port = port
self.baudrate = baudrate
# 如果没有指定路径,默认保存在代码文件所在目录
if csv_path is None:
current_dir = os.path.dirname(os.path.abspath(__file__))
self.csv_path = os.path.join(current_dir, "stm32_data.csv")
else:
self.csv_path = csv_path
self.ser_timeout = timeout
self.chunk_read = 128
# 串口对象
self.ser: Optional[serial.Serial] = None
self.stop_flag = False
# 线程对象
self.rx_thread: Optional[threading.Thread] = None
self.tx_thread: Optional[threading.Thread] = None
# ==== 接收(下位机->上位机):固定 1+13+1 = 15 字节 ====
self.RX_HEAD = 0x3E
self.RX_TAIL = 0x3E
self.RX_FRAME_LEN = 1 + 13 + 1 # 15
# ==== 发送(上位机->下位机):固定 1+9+1 = 11 字节 ====
self.TX_HEAD = 0x3E
self.TX_TAIL = 0xE3 # 协议图中标注 E3 作为帧尾
self.TX_FRAME_LEN = 1 + 9 + 1 # 11
def open_serial(self, port: Optional[str] = None, baudrate: Optional[int] = None, timeout: Optional[float] = None) -> Optional[serial.Serial]:
"""打开串口"""
port = port or self.port
baudrate = baudrate or self.baudrate
timeout = timeout or self.ser_timeout
try:
ser = serial.Serial(port, baudrate, timeout=timeout)
print(f"[OK] 串口 {port} 已打开,波特率 {baudrate}")
ser.reset_input_buffer()
ser.reset_output_buffer()
self.ser = ser
return ser
except serial.SerialException as e:
print(f"[ERR] 无法打开串口 {port}: {e}")
return None
def close_serial(self):
"""关闭串口"""
if self.ser and self.ser.is_open:
self.ser.close()
print("[INFO] 串口已关闭")
@staticmethod
def u16_be(h: int, l: int) -> int:
"""将两个字节组合成16位无符号整数大端序"""
return ((h & 0xFF) << 8) | (l & 0xFF)
@staticmethod
def split_u16_be(val: int) -> tuple:
"""返回 (高字节, 低字节),输入会夹到 0..65535"""
v = int(max(0, min(65535, int(val))))
return (v >> 8) & 0xFF, v & 0xFF
# ================== 接收固定15字节 ==================
def parse_rx_payload(self, dat13: bytes) -> Optional[Dict[str, Any]]:
"""解析 13 字节数据区(下位机发送到上位机)"""
if len(dat13) != 13:
return None
current_mA = self.u16_be(dat13[0], dat13[1])
voltage_mV = self.u16_be(dat13[2], dat13[3])
temperature_raw = self.u16_be(dat13[4], dat13[5])
tds_ppm = self.u16_be(dat13[6], dat13[7])
gas_sccm = self.u16_be(dat13[8], dat13[9])
liquid_mL = self.u16_be(dat13[10], dat13[11])
ph_raw = dat13[12] & 0xFF
return {
"Current_mA": current_mA,
"Voltage_mV": voltage_mV,
"Temperature_C": round(temperature_raw / 100.0, 2),
"TDS_ppm": tds_ppm,
"GasFlow_sccm": gas_sccm,
"LiquidFlow_mL": liquid_mL,
"pH": round(ph_raw / 10.0, 2)
}
def try_parse_rx_frame(self, frame15: bytes) -> Optional[Dict[str, Any]]:
"""尝试解析接收帧"""
if len(frame15) != self.RX_FRAME_LEN:
return None
if frame15[0] != self.RX_HEAD or frame15[-1] != self.RX_TAIL:
return None
return self.parse_rx_payload(frame15[1:-1])
def rx_thread_fn(self):
"""接收线程函数"""
headers = ["Timestamp", "Current_mA", "Voltage_mV",
"Temperature_C", "TDS_ppm", "GasFlow_sccm", "LiquidFlow_mL", "pH"]
new_file = not os.path.exists(self.csv_path)
f = open(self.csv_path, mode='a', newline='', encoding='utf-8')
writer = csv.writer(f)
if new_file:
writer.writerow(headers)
f.flush()
buf = deque(maxlen=8192)
print(f"[RX] 开始接收(帧长 {self.RX_FRAME_LEN} 字节);写入:{self.csv_path}")
try:
while not self.stop_flag and self.ser and self.ser.is_open:
chunk = self.ser.read(self.chunk_read)
if chunk:
buf.extend(chunk)
while True:
# 找帧头
try:
start = next(i for i, b in enumerate(buf) if b == self.RX_HEAD)
except StopIteration:
buf.clear()
break
if start > 0:
for _ in range(start):
buf.popleft()
if len(buf) < self.RX_FRAME_LEN:
break
candidate = bytes([buf[i] for i in range(self.RX_FRAME_LEN)])
if candidate[-1] == self.RX_TAIL:
parsed = self.try_parse_rx_frame(candidate)
for _ in range(self.RX_FRAME_LEN):
buf.popleft()
if parsed:
ts = time.strftime("%Y-%m-%d %H:%M:%S")
row = [ts,
parsed["Current_mA"], parsed["Voltage_mV"],
parsed["Temperature_C"], parsed["TDS_ppm"],
parsed["GasFlow_sccm"], parsed["LiquidFlow_mL"],
parsed["pH"]]
writer.writerow(row)
f.flush()
# 若不想打印可注释下一行
# print(f"[{ts}] I={parsed['Current_mA']} mA, V={parsed['Voltage_mV']} mV, "
# f"T={parsed['Temperature_C']} °C, TDS={parsed['TDS_ppm']}, "
# f"Gas={parsed['GasFlow_sccm']} sccm, Liq={parsed['LiquidFlow_mL']} mL, pH={parsed['pH']}")
else:
# 头不变尾不对丢1字节继续对齐
buf.popleft()
else:
time.sleep(0.01)
finally:
f.close()
print("[RX] 接收线程退出CSV 已关闭")
# ================== 发送固定11字节 ==================
def build_tx_frame(self, mode: int, current_ma: int, voltage_mv: int, temp_c: float, ki: float, pump_percent: float) -> bytes:
"""
发送帧HEAD + [mode, I_hi, I_lo, V_hi, V_lo, T_hi, T_lo, Ki_byte, Pump_byte] + TAIL
- mode: 0=恒压, 1=恒流
- current_ma: mA (0..65535)
- voltage_mv: mV (0..65535)
- temp_c: ℃,将 *100 后拆分为高/低字节
- ki: 0.0..20.0 -> byte = round(ki * 10) 夹到 0..200
- pump_percent: 0..100 -> byte = round(pump * 2) 夹到 0..200
"""
mode_b = 1 if int(mode) == 1 else 0
i_hi, i_lo = self.split_u16_be(current_ma)
v_hi, v_lo = self.split_u16_be(voltage_mv)
t100 = int(round(float(temp_c) * 100.0))
t_hi, t_lo = self.split_u16_be(t100)
ki_b = int(max(0, min(200, round(float(ki) * 10))))
pump_b = int(max(0, min(200, round(float(pump_percent) * 2))))
return bytes((
self.TX_HEAD,
mode_b,
i_hi, i_lo,
v_hi, v_lo,
t_hi, t_lo,
ki_b,
pump_b,
self.TX_TAIL
))
def tx_thread_fn(self):
"""
发送线程函数
用户输入 6 个用逗号分隔的数值:
mode,current_mA,voltage_mV,set_temp_C,Ki,pump_percent
例如: 0,1000,500,0,0,50
"""
print("\n输入 6 个值(用英文逗号分隔),顺序为:")
print("mode,current_mA,voltage_mV,set_temp_C,Ki,pump_percent")
print("示例恒压0,500,1000,25,0,100 stop 结束)\n")
print("示例恒流1,1000,500,25,0,100 stop 结束)\n")
print("示例恒流1,2000,500,25,0,100 stop 结束)\n")
# 1,2000,500,25,0,100
while not self.stop_flag and self.ser and self.ser.is_open:
try:
line = input(">>> ").strip()
except EOFError:
self.stop_flag = True
break
if not line:
continue
if line.lower() == "stop":
self.stop_flag = True
print("[SYS] 停止程序")
break
try:
parts = [p.strip() for p in line.split(",")]
if len(parts) != 6:
raise ValueError("需要 6 个逗号分隔的数值")
mode = int(parts[0])
i_ma = int(float(parts[1]))
v_mv = int(float(parts[2]))
t_c = float(parts[3])
ki = float(parts[4])
pump = float(parts[5])
frame = self.build_tx_frame(mode, i_ma, v_mv, t_c, ki, pump)
self.ser.write(frame)
print("[TX]", " ".join(f"{b:02X}" for b in frame))
except Exception as e:
print("[TX] 输入/打包失败:", e)
print("格式mode,current_mA,voltage_mV,set_temp_C,Ki,pump_percent")
continue
def start(self):
"""启动电解水平台"""
self.ser = self.open_serial()
if self.ser:
try:
self.rx_thread = threading.Thread(target=self.rx_thread_fn, daemon=True)
self.tx_thread = threading.Thread(target=self.tx_thread_fn, daemon=True)
self.rx_thread.start()
self.tx_thread.start()
print("[INFO] 电解水平台已启动")
self.tx_thread.join() # 等待用户输入线程结束(输入 stop
finally:
self.close_serial()
def stop(self):
"""停止电解水平台"""
self.stop_flag = True
if self.rx_thread and self.rx_thread.is_alive():
self.rx_thread.join(timeout=2.0)
if self.tx_thread and self.tx_thread.is_alive():
self.tx_thread.join(timeout=2.0)
self.close_serial()
print("[INFO] 电解水平台已停止")
# ================== 主入口 ==================
if __name__ == "__main__":
# 创建一个简单的 Deck 用于测试
from pylabrobot.resources import Deck
deck = Deck()
platform = ElectrolysisWaterPlatform(deck)
platform.start()

View File

@@ -1,8 +1,23 @@
{
"nodes": [
{
"id": "bioyond_cell_workstation",
"name": "配液分液工站",
"children": [
],
"parent": null,
"type": "device",
"class": "bioyond_cell",
"config": {
"protocol_type": [],
"station_resource": {}
},
"data": {}
},
{
"id": "BatteryStation",
"name": "扣电工作站",
"name": "扣电组装工作站",
"children": [
"coin_cell_deck"
],

View File

@@ -0,0 +1,7 @@
material_name
LiPF6
LiDFOB
DTD
LiFSI
LiPO2F2
1 material_name
2 LiPF6
3 LiDFOB
4 DTD
5 LiFSI
6 LiPO2F2

View File

@@ -47,8 +47,8 @@ class BioyondV1RPC(BaseRequest):
super().__init__()
print("开始初始化 BioyondV1RPC")
self.config = config
self.api_key = config["api_key"]
self.host = config["api_host"]
self.api_key = config.get("api_key", "")
self.host = config.get("api_host", "") or config.get("base_url", "")
self._logger = SimpleLogger()
self.material_cache = {}
self._load_material_cache()
@@ -61,7 +61,7 @@ class BioyondV1RPC(BaseRequest):
:return: 当前时间的 ISO 8601 格式字符串
"""
current_time = datetime.now(timezone.utc).isoformat(
current_time = datetime.now().isoformat(
timespec='milliseconds'
)
# 替换时区部分为 'Z'

View File

@@ -2,137 +2,330 @@
"""
配置文件 - 包含所有配置信息和映射关系
"""
import os
# API配置
# ==================== API 基础配置 ====================
# BioyondCellWorkstation 默认配置(包含所有必需参数)
API_CONFIG = {
"api_key": "",
"api_host": ""
}
# API 连接配置
# "api_host": os.getenv("BIOYOND_API_HOST", "http://172.21.32.65:44389"),#实机
"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.10.169:44388"),# 仿真机
"api_key": os.getenv("BIOYOND_API_KEY", "8A819E5C"),
"timeout": int(os.getenv("BIOYOND_TIMEOUT", "30")),
# 工作流映射配置
WORKFLOW_MAPPINGS = {
"reactor_taken_out": "",
"reactor_taken_in": "",
"Solid_feeding_vials": "",
"Liquid_feeding_vials(non-titration)": "",
"Liquid_feeding_solvents": "",
"Liquid_feeding(titration)": "",
"liquid_feeding_beaker": "",
"Drip_back": "",
}
# 报送配置
"report_token": os.getenv("BIOYOND_REPORT_TOKEN", "CHANGE_ME_TOKEN"),
# 工作流名称到DisplaySectionName的映射
WORKFLOW_TO_SECTION_MAP = {
'reactor_taken_in': '反应器放入',
'liquid_feeding_beaker': '液体投料-烧杯',
'Liquid_feeding_vials(non-titration)': '液体投料-小瓶(非滴定)',
'Liquid_feeding_solvents': '液体投料-溶剂',
'Solid_feeding_vials': '固体投料-小瓶',
'Liquid_feeding(titration)': '液体投料-滴定',
'reactor_taken_out': '反应器取出'
# HTTP 服务配置
"HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.21.32.115"), # HTTP服务监听地址监听计算机飞连ip地址
"HTTP_port": int(os.getenv("BIOYOND_HTTP_PORT", "8080")),
"debug_mode": False,# 调试模式
}
# 库位映射配置
WAREHOUSE_MAPPING = {
"粉末堆栈": {
"粉末加样头堆栈": {
"uuid": "",
"site_uuids": {
# 样品板
"A1": "3a14198e-6929-31f0-8a22-0f98f72260df",
"A2": "3a14198e-6929-4379-affa-9a2935c17f99",
"A3": "3a14198e-6929-56da-9a1c-7f5fbd4ae8af",
"A4": "3a14198e-6929-5e99-2b79-80720f7cfb54",
"B1": "3a14198e-6929-f525-9a1b-1857552b28ee",
"B2": "3a14198e-6929-bf98-0fd5-26e1d68bf62d",
"B3": "3a14198e-6929-2d86-a468-602175a2b5aa",
"B4": "3a14198e-6929-1a98-ae57-e97660c489ad",
# 分装板
"C1": "3a14198e-6929-46fe-841e-03dd753f1e4a",
"C2": "3a14198e-6929-1bc9-a9bd-3b7ca66e7f95",
"C3": "3a14198e-6929-72ac-32ce-9b50245682b8",
"C4": "3a14198e-6929-3bd8-e6c7-4a9fd93be118",
"D1": "3a14198e-6929-8a0b-b686-6f4a2955c4e2",
"D2": "3a14198e-6929-dde1-fc78-34a84b71afdf",
"D3": "3a14198e-6929-a0ec-5f15-c0f9f339f963",
"D4": "3a14198e-6929-7ac8-915a-fea51cb2e884"
"A01": "3a19da56-1379-ff7c-1745-07e200b44ce2",
"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"
}
},
"溶液堆栈": {
"配液站内试剂仓库": {
"uuid": "",
"site_uuids": {
"A1": "3a14198e-d724-e036-afdc-2ae39a7f3383",
"A2": "3a14198e-d724-afa4-fc82-0ac8a9016791",
"A3": "3a14198e-d724-ca48-bb9e-7e85751e55b6",
"A4": "3a14198e-d724-df6d-5e32-5483b3cab583",
"B1": "3a14198e-d724-d818-6d4f-5725191a24b5",
"B2": "3a14198e-d724-be8a-5e0b-012675e195c6",
"B3": "3a14198e-d724-cc1e-5c2c-228a130f40a8",
"B4": "3a14198e-d724-1e28-c885-574c3df468d0",
"C1": "3a14198e-d724-b5bb-adf3-4c5a0da6fb31",
"C2": "3a14198e-d724-ab4e-48cb-817c3c146707",
"C3": "3a14198e-d724-7f18-1853-39d0c62e1d33",
"C4": "3a14198e-d724-28a2-a760-baa896f46b66",
"D1": "3a14198e-d724-d378-d266-2508a224a19f",
"D2": "3a14198e-d724-f56e-468b-0110a8feb36a",
"D3": "3a14198e-d724-0cf1-dea9-a1f40fe7e13c",
"D4": "3a14198e-d724-0ddd-9654-f9352a421de9"
"A01": "3a19da43-57b5-294f-d663-154a1cc32270",
"B01": "3a19da43-57b5-7394-5f49-54efe2c9bef2",
"C01": "3a19da43-57b5-5e75-552f-8dbd0ad1075f",
"A02": "3a19da43-57b5-8441-db94-b4d3875a4b6c",
"B02": "3a19da43-57b5-3e41-c181-5119dddaf50c",
"C02": "3a19da43-57b5-269b-282d-fba61fe8ce96",
"A03": "3a19da43-57b5-7c1e-d02e-c40e8c33f8a1",
"B03": "3a19da43-57b5-659f-621f-1dcf3f640363",
"C03": "3a19da43-57b5-855a-6e71-f398e376dee1",
}
},
"试剂堆栈": {
"试剂替换仓库": {
"uuid": "",
"site_uuids": {
"A1": "3a14198c-c2cf-8b40-af28-b467808f1c36",
"A2": "3a14198c-c2d0-f3e7-871a-e470d144296f",
"A3": "3a14198c-c2d0-dc7d-b8d0-e1d88cee3094",
"A4": "3a14198c-c2d0-2070-efc8-44e245f10c6f",
"B1": "3a14198c-c2d0-354f-39ad-642e1a72fcb8",
"B2": "3a14198c-c2d0-1559-105d-0ea30682cab4",
"B3": "3a14198c-c2d0-725e-523d-34c037ac2440",
"B4": "3a14198c-c2d0-efce-0939-69ca5a7dfd39"
"A01": "3a19da51-8f4e-30f3-ea08-4f8498e9b097",
"B01": "3a19da51-8f4e-1da7-beb0-80a4a01e67a8",
"C01": "3a19da51-8f4e-337d-2675-bfac46880b06",
"D01": "3a19da51-8f4e-e514-b92c-9c44dc5e489d",
"E01": "3a19da51-8f4e-22d1-dd5b-9774ddc80402",
"F01": "3a19da51-8f4e-273a-4871-dff41c29bfd9",
"G01": "3a19da51-8f4e-b32f-454f-74bc1a665653",
"H01": "3a19da51-8f4e-8c93-68c9-0b4382320f59",
"I01": "3a19da51-8f4e-360c-0149-291b47c6089b",
"J01": "3a19da51-8f4e-4152-9bca-8d64df8c1af0"
}
},
"自动堆栈-左": {
"uuid": "",
"site_uuids": {
"A01": "3a19debc-84b5-4c1c-d3a1-26830cf273ff",
"A02": "3a19debc-84b5-033b-b31f-6b87f7c2bf52",
"B01": "3a19debc-84b5-3924-172f-719ab01b125c",
"B02": "3a19debc-84b5-aad8-70c6-b8c6bb2d8750"
}
},
"自动堆栈-右": {
"uuid": "",
"site_uuids": {
"A01": "3a19debe-5200-7df2-1dd9-7d202f158864",
"A02": "3a19debe-5200-573b-6120-8b51f50e1e50",
"B01": "3a19debe-5200-7cd8-7666-851b0a97e309",
"B02": "3a19debe-5200-e6d3-96a3-baa6e3d5e484"
}
},
"手动堆栈": {
"uuid": "",
"site_uuids": {
"A01": "3a19deae-2c7a-36f5-5e41-02c5b66feaea",
"A02": "3a19deae-2c7a-dc6d-c41e-ef285d946cfe",
"A03": "3a19deae-2c7a-5876-c454-6b7e224ca927",
"B01": "3a19deae-2c7a-2426-6d71-e9de3cb158b1",
"B02": "3a19deae-2c7a-79b0-5e44-efaafd1e4cf3",
"B03": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a",
"C01": "3a19deae-2c7a-32bc-768e-556647e292f3",
"C02": "3a19deae-2c7a-e97a-8484-f5a4599447c4",
"C03": "3a19deae-2c7a-3056-6504-10dc73fbc276",
"D01": "3a19deae-2c7a-ffad-875e-8c4cda61d440",
"D02": "3a19deae-2c7a-61be-601c-b6fb5610499a",
"D03": "3a19deae-2c7a-c0f7-05a7-e3fe2491e560",
"E01": "3a19deae-2c7a-a6f4-edd1-b436a7576363",
"E02": "3a19deae-2c7a-4367-96dd-1ca2186f4910",
"E03": "3a19deae-2c7a-b163-2219-23df15200311",
"F01": "3a19deae-2c7a-d594-fd6a-0d20de3c7c4a",
"F02": "3a19deae-2c7a-a194-ea63-8b342b8d8679",
"F03": "3a19deae-2c7a-f7c4-12bd-425799425698",
"G01": "3a19deae-2c7a-0b56-72f1-8ab86e53b955",
"G02": "3a19deae-2c7a-204e-95ed-1f1950f28343",
"G03": "3a19deae-2c7a-392b-62f1-4907c66343f8",
"H01": "3a19deae-2c7a-5602-e876-d27aca4e3201",
"H02": "3a19deae-2c7a-f15c-70e0-25b58a8c9702",
"H03": "3a19deae-2c7a-780b-8965-2e1345f7e834",
"I01": "3a19deae-2c7a-8849-e172-07de14ede928",
"I02": "3a19deae-2c7a-4772-a37f-ff99270bafc0",
"I03": "3a19deae-2c7a-cce7-6e4a-25ea4a2068c4",
"J01": "3a19deae-2c7a-1848-de92-b5d5ed054cc6",
"J02": "3a19deae-2c7a-1d45-b4f8-6f866530e205",
"J03": "3a19deae-2c7a-f237-89d9-8fe19025dee9"
}
},
"4号手套箱内部堆栈": {
"uuid": "",
"site_uuids": {
"A01": "3a1baa20-a7b1-c665-8b9c-d8099d07d2f6",
"A02": "3a1baa20-a7b1-93a7-c988-f9c8ad6c58c9",
"A03": "3a1baa20-a7b1-00ee-f751-da9b20b6c464",
"A04": "3a1baa20-a7b1-4712-c37b-0b5b658ef7b9",
"B01": "3a1baa20-a7b1-9847-fc9c-96d604cd1a8e",
"B02": "3a1baa20-a7b1-4ae9-e604-0601db06249c",
"B03": "3a1baa20-a7b1-8329-ea75-81ca559d9ce1",
"B04": "3a1baa20-a7b1-89c5-d96f-36e98a8f7268",
"C01": "3a1baa20-a7b1-32ec-39e6-8044733839d6",
"C02": "3a1baa20-a7b1-b573-e426-4c86040348b2",
"C03": "3a1baa20-a7b1-cca7-781e-0522b729bf5d",
"C04": "3a1baa20-a7b1-7c98-5fd9-5855355ae4b3"
}
},
"大分液瓶堆栈": {
"uuid": "",
"site_uuids": {
"A01": "3a19da3d-4f3d-bcac-2932-7542041e10e0",
"A02": "3a19da3d-4f3d-4d75-38ac-fb58ad0687c3",
"A03": "3a19da3d-4f3d-b25e-f2b1-85342a5b7eae",
"B01": "3a19da3d-4f3d-fd3e-058a-2733a0925767",
"B02": "3a19da3d-4f3d-37bd-a944-c391ad56857f",
"B03": "3a19da3d-4f3d-e353-7862-c6d1d4bc667f",
"C01": "3a19da3d-4f3d-9519-5da7-76179c958e70",
"C02": "3a19da3d-4f3d-b586-d7ed-9ec244f6f937",
"C03": "3a19da3d-4f3d-5061-249b-35dfef732811"
}
},
"小分液瓶堆栈": {
"uuid": "",
"site_uuids": {
"C03": "3a19da40-55bf-8943-d20d-a8b3ea0d16c0"
}
},
"站内Tip头盒堆栈": {
"uuid": "",
"site_uuids": {
"A01": "3a19deab-d5cc-be1e-5c37-4e9e5a664388",
"A02": "3a19deab-d5cc-b394-8141-27cb3853e8ea",
"B01": "3a19deab-d5cc-4dca-596e-ca7414d5f501",
"B02": "3a19deab-d5cc-9bc0-442b-12d9d59aa62a",
"C01": "3a19deab-d5cc-2eaf-b6a4-f0d54e4f1246",
"C02": "3a19deab-d5cc-d9f4-25df-b8018c372bc7"
}
},
"配液站内配液大板仓库(无需提前上料)": {
"uuid": "",
"site_uuids": {
"A01": "3a1a21dc-06af-3915-9cb9-80a9dc42f386"
}
},
"配液站内配液小板仓库(无需以前入料)": {
"uuid": "",
"site_uuids": {
"A01": "3a1a21de-8e8b-7938-2d06-858b36c10e31"
}
},
"移液站内大瓶板仓库(无需提前如料)": {
"uuid": "",
"site_uuids": {
"A01": "3a1a224c-c727-fa62-1f2b-0037a84b9fca"
}
},
"移液站内小瓶板仓库(无需提前入料)": {
"uuid": "",
"site_uuids": {
"A01": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb"
}
},
"适配器位仓库": {
"uuid": "",
"site_uuids": {
"A01": "3a1abd46-18fe-1f56-6ced-a1f7fe08e36c"
}
},
"1号2号手套箱交接堆栈": {
"uuid": "",
"site_uuids": {
"A01": "3a1baa49-7f77-35aa-60b1-e55a45d065fa"
}
},
"2号手套箱内部堆栈": {
"uuid": "",
"site_uuids": {
"A01": "3a1baa4b-393e-9f86-3921-7a18b0a8e371",
"A02": "3a1baa4b-393e-9425-928b-ee0f6f679d44",
"A03": "3a1baa4b-393e-0baf-632b-59dfdc931a3a",
"B01": "3a1baa4b-393e-f8aa-c8a9-956f3132f05c",
"B02": "3a1baa4b-393e-ef05-42f6-53f4c6e89d70",
"B03": "3a1baa4b-393e-c07b-a924-a9f0dfda9711",
"C01": "3a1baa4b-393e-4c2b-821a-16a7fe025c48",
"C02": "3a1baa4b-393e-2eaf-61a1-9063c832d5a2",
"C03": "3a1baa4b-393e-034e-8e28-8626d934a85f"
}
}
}
# 物料类型配置
MATERIAL_TYPE_MAPPINGS = {
"烧杯": ("BIOYOND_PolymerStation_1FlaskCarrier", "3a14196b-24f2-ca49-9081-0cab8021bf1a"),
"试剂瓶": ("BIOYOND_PolymerStation_1BottleCarrier", ""),
"样品板": ("BIOYOND_PolymerStation_6StockCarrier", "3a14196e-b7a0-a5da-1931-35f3000281e9"),
"分装板": ("BIOYOND_PolymerStation_6VialCarrier", "3a14196e-5dfe-6e21-0c79-fe2036d052c4"),
"样品瓶": ("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"),
"100ml液体": ("YB_1Bottle100mlCarrier", "d37166b3-ecaa-481e-bd84-3032b795ba07"),
"": ("YB_1BottleCarrier", "3a190ca1-2add-2b23-f8e1-bbd348b7f790"),
"高粘液": ("YB_1GaoNianYeBottleCarrier", "abe8df30-563d-43d2-85e0-cabec59ddc16"),
"加样头(大)": ("YB_jia_yang_tou_da_1X1_carrier", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "加样头(大)板": ("YB_jia_yang_tou_da_1X1_carrier", "a8e714ae-2a4e-4eb9-9614-e4c140ec3f16"),
"5ml分液瓶板": ("YB_6x5ml_DispensingVialCarrier", "3a192fa4-007d-ec7b-456e-2a8be7a13f23"),
"5ml分液": ("YB_fen_ye_5ml_Bottle", "3a192c2a-ebb7-58a1-480d-8b3863bf74f4"),
"20ml分液瓶板": ("YB_6x20ml_DispensingVialCarrier", "3a192fa4-47db-3449-162a-eaf8aba57e27"),
"20ml分液瓶": ("YB_fen_ye_20ml_Bottle", "3a192c2b-19e8-f0a3-035e-041ca8ca1035"),
"配液瓶(小)板": ("YB_6x_SmallSolutionBottleCarrier", "3a190c8b-3284-af78-d29f-9a69463ad047"),
"配液瓶(小)": ("YB_pei_ye_xiao_Bottle", "3a190c8c-fe8f-bf48-0dc3-97afc7f508eb"),
"配液瓶(大)板": ("YB_4x_LargeSolutionBottleCarrier", "53e50377-32dc-4781-b3c0-5ce45bc7dc27"),
"配液瓶(大)": ("YB_pei_ye_da_Bottle", "19c52ad1-51c5-494f-8854-576f4ca9c6ca"),
"适配器块": ("YB_AdapterBlock", "efc3bb32-d504-4890-91c0-b64ed3ac80cf"),
"枪头盒": ("YB_TipBox", "3a192c2e-20f3-a44a-0334-c8301839d0b3"),
"枪头": ("YB_Pipette_Tip", "b6196971-1050-46da-9927-333e8dea062d"),
}
# 步骤参数配置各工作流的步骤UUID
WORKFLOW_STEP_IDS = {
"reactor_taken_in": {
"config": ""
SOLID_LIQUID_MAPPINGS = {
# 固体
"LiDFOB": {
"typeId": "3a190ca0-b2f6-9aeb-8067-547e72c11469",
"code": "",
"barCode": "",
"name": "LiDFOB",
"unit": "g",
"parameters": "",
"quantity": "2",
"warningQuantity": "1",
"details": []
},
"liquid_feeding_beaker": {
"liquid": "",
"observe": ""
},
"liquid_feeding_vials_non_titration": {
"liquid": "",
"observe": ""
},
"liquid_feeding_solvents": {
"liquid": "",
"observe": ""
},
"solid_feeding_vials": {
"feeding": "",
"observe": ""
},
"liquid_feeding_titration": {
"liquid": "",
"observe": ""
},
"drip_back": {
"liquid": "",
"observe": ""
}
# "LiPF6": {
# "typeId": "3a190ca0-b2f6-9aeb-8067-547e72c11469",
# "code": "",
# "barCode": "",
# "name": "LiPF6",
# "unit": "g",
# "parameters": "",
# "quantity": 2,
# "warningQuantity": 1,
# "details": []
# },
# "LiFSI": {
# "typeId": "3a190ca0-b2f6-9aeb-8067-547e72c11469",
# "code": "",
# "barCode": "",
# "name": "LiFSI",
# "unit": "g",
# "parameters": "",
# "quantity": 2,
# "warningQuantity": 1,
# "details": []
# },
# "DTC": {
# "typeId": "3a190ca0-b2f6-9aeb-8067-547e72c11469",
# "code": "",
# "barCode": "",
# "name": "DTC",
# "unit": "g",
# "parameters": "",
# "quantity": 2,
# "warningQuantity": 1,
# "details": []
# },
# "LiPO2F2": {
# "typeId": "3a190ca0-b2f6-9aeb-8067-547e72c11469",
# "code": "",
# "barCode": "",
# "name": "LiPO2F2",
# "unit": "g",
# "parameters": "",
# "quantity": 2,
# "warningQuantity": 1,
# "details": []
# },
# 液体
# "SA": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "EC": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "VC": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "AND": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "HTCN": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "DENE": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "TMSP": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "TMSB": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "EP": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "DEC": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "EMC": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "SN": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "DMC": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
# "FEC": ("BIOYOND_PolymerStation_Solid_Stock", "3a190ca0-b2f6-9aeb-8067-547e72c11469"),
}
WORKFLOW_MAPPINGS = {}
LOCATION_MAPPING = {}

View File

@@ -74,6 +74,7 @@ class BioyondResourceSynchronizer(ResourceSynchronizer):
type_mapping=self.workstation.bioyond_config["material_type_mappings"],
deck=self.workstation.deck
)
print("unilab_resources:",unilab_resources)
logger.info(f"从Bioyond同步了 {len(unilab_resources)} 个资源")
return True
@@ -165,12 +166,14 @@ class BioyondWorkstation(WorkstationBase):
self.workflow_sequence = []
self.pending_task_params = []
if "workflow_mappings" in bioyond_config:
self._set_workflow_mappings(bioyond_config["workflow_mappings"])
if self.bioyond_config and "workflow_mappings" in self.bioyond_config:
self._set_workflow_mappings(self.bioyond_config["workflow_mappings"])
logger.info(f"Bioyond工作站初始化完成")
def post_init(self, ros_node: ROS2WorkstationNode):
self._ros_node = ros_node
print("~~~",self._ros_node)
print("deck",self.deck)
ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{
"resources": [self.deck]
})
@@ -468,7 +471,7 @@ def create_bioyond_workstation_example():
"""创建Bioyond工作站示例"""
# 配置参数
device_id = "bioyond_workstation_001"
device_id = "bioyond_cell_workstation_001"
# 子资源配置
children = {
@@ -487,8 +490,8 @@ def create_bioyond_workstation_example():
# Bioyond配置
bioyond_config = {
"base_url": "http://bioyond.example.com/api",
"api_key": "your_api_key_here",
"base_url": "http://172.16.11.219:44388",
"api_key": "8A819E5C",
"sync_interval": 60, # 60秒同步一次
"timeout": 30
}
@@ -512,4 +515,18 @@ def create_bioyond_workstation_example():
if __name__ == "__main__":
by = create_bioyond_workstation_example()
by.get_workstation_status()
by.get_device_status()
by.get_bioyond_status()
by.get_station_info()
by.get_workstation_status()
by.get_bioyond_status()
by.get_station_info()
by.get_workstation_status()
by.get_bioyond_status()
by.get_station_info()
by.get_workstation_status()
by.get_bioyond_status()
by.get_station_info()
pass

Binary file not shown.

View File

@@ -24,6 +24,13 @@ class ElectrodeSheetState(TypedDict):
thickness: float # 厚度 (mm)
mass: float # 质量 (g)
material_type: str # 材料类型(正极、负极、隔膜、弹片、垫片、铝箔等)
height: float
electrolyte_name: str
data_electrolyte_code: str
open_circuit_voltage: float
assembly_pressure: float
electrolyte_volume: float
info: Optional[str] # 附加信息
class ElectrodeSheet(Resource):
@@ -61,6 +68,7 @@ class ElectrodeSheet(Resource):
info=None
)
# TODO: 这个还要不要给self._unilabos_state赋值的
def load_state(self, state: Dict[str, Any]) -> None:
"""格式不变"""
super().load_state(state)
@@ -146,10 +154,10 @@ class MaterialHole(Resource):
):
"""放置极片"""
# TODO: 这里要改diameter找不到加入._unilabos_state后应该没问题
if resource._unilabos_state["diameter"] > self._unilabos_state["diameter"]:
raise ValueError(f"极片直径 {resource._unilabos_state['diameter']} 超过洞位直径 {self._unilabos_state['diameter']}")
if len(self.children) >= self._unilabos_state["max_sheets"]:
raise ValueError(f"洞位已满,无法放置更多极片")
#if resource._unilabos_state["diameter"] > self._unilabos_state["diameter"]:
# raise ValueError(f"极片直径 {resource._unilabos_state['diameter']} 超过洞位直径 {self._unilabos_state['diameter']}")
#if len(self.children) >= self._unilabos_state["max_sheets"]:
# raise ValueError(f"洞位已满,无法放置更多极片")
super().assign_child_resource(resource, location, reassign)
# 根据children的编号取物料对象。
@@ -164,8 +172,6 @@ class MaterialPlateState(TypedDict):
hole_diameter: float
info: Optional[str] # 附加信息
class MaterialPlate(ItemizedResource[MaterialHole]):
"""料板类 - 4x4个洞位每个洞位放1个极片"""
@@ -323,12 +329,13 @@ class PlateSlot(ResourceStack):
class ClipMagazineHole(Container):
"""子弹夹洞位类"""
children: List[ElectrodeSheet] = []
def __init__(
self,
name: str,
diameter: float,
depth: float,
max_sheets: int = 100,
category: str = "clip_magazine_hole",
):
"""初始化子弹夹洞位
@@ -337,6 +344,7 @@ class ClipMagazineHole(Container):
name: 洞位名称
diameter: 洞直径 (mm)
depth: 洞深度 (mm)
max_sheets: 最大极片数量
category: 类别
"""
super().__init__(
@@ -348,131 +356,36 @@ class ClipMagazineHole(Container):
)
self.diameter = diameter
self.depth = depth
self.max_sheets = max_sheets
self._sheets: List[ElectrodeSheet] = []
def can_add_sheet(self, sheet: ElectrodeSheet) -> bool:
"""检查是否可以添加极片
"""检查是否可以添加极片"""
return (len(self._sheets) < self.max_sheets and
sheet.diameter <= self.diameter)
根据洞的深度和极片的厚度来判断是否可以添加极片
"""
# 检查极片直径是否适合洞的直径
if sheet._unilabos_state["diameter"] > self.diameter:
return False
# 计算当前已添加极片的总厚度
current_thickness = sum(s._unilabos_state["thickness"] for s in self.children)
# 检查添加新极片后总厚度是否超过洞的深度
if current_thickness + sheet._unilabos_state["thickness"] > self.depth:
return False
return True
def assign_child_resource(
self,
resource: ElectrodeSheet,
location: Optional[Coordinate] = None,
reassign: bool = True,
):
"""放置极片到洞位中
Args:
resource: 要放置的极片
location: 极片在洞位中的位置对于洞位通常为None
reassign: 是否允许重新分配
"""
# 检查是否可以添加极片
if not self.can_add_sheet(resource):
raise ValueError(f"无法向洞位 {self.name} 添加极片:直径或厚度不匹配")
# 调用父类方法实际执行分配
super().assign_child_resource(resource, location, reassign)
def unassign_child_resource(self, resource: ElectrodeSheet):
"""从洞位中移除极片
Args:
resource: 要移除的极片
"""
if resource not in self.children:
raise ValueError(f"极片 {resource.name} 不在洞位 {self.name}")
# 调用父类方法实际执行移除
super().unassign_child_resource(resource)
def add_sheet(self, sheet: ElectrodeSheet) -> None:
"""添加极片"""
if not self.can_add_sheet(sheet):
raise ValueError(f"无法向洞位 {self.name} 添加极片")
self._sheets.append(sheet)
def take_sheet(self) -> ElectrodeSheet:
"""取出极片"""
if len(self._sheets) == 0:
raise ValueError(f"洞位 {self.name} 没有极片")
return self._sheets.pop()
def get_sheet_count(self) -> int:
"""获取极片数量"""
return len(self._sheets)
def serialize_state(self) -> Dict[str, Any]:
return {
"sheet_count": len(self.children),
"sheets": [sheet.serialize() for sheet in self.children],
"sheet_count": len(self._sheets),
"sheets": [sheet.serialize() for sheet in self._sheets],
}
class ClipMagazine_four(ItemizedResource[ClipMagazineHole]):
"""子弹夹类 - 有4个洞位每个洞位放多个极片"""
children: List[ClipMagazineHole]
def __init__(
self,
name: str,
size_x: float,
size_y: float,
size_z: float,
hole_diameter: float = 14.0,
hole_depth: float = 10.0,
hole_spacing: float = 25.0,
max_sheets_per_hole: int = 100,
category: str = "clip_magazine_four",
model: Optional[str] = None,
):
"""初始化子弹夹
Args:
name: 子弹夹名称
size_x: 长度 (mm)
size_y: 宽度 (mm)
size_z: 高度 (mm)
hole_diameter: 洞直径 (mm)
hole_depth: 洞深度 (mm)
hole_spacing: 洞位间距 (mm)
max_sheets_per_hole: 每个洞位最大极片数量
category: 类别
model: 型号
"""
# 创建4个洞位排成2x2布局
holes = create_ordered_items_2d(
klass=ClipMagazineHole,
num_items_x=2,
num_items_y=2,
dx=(size_x - 2 * hole_spacing) / 2, # 居中
dy=(size_y - hole_spacing) / 2, # 居中
dz=size_z - 0,
item_dx=hole_spacing,
item_dy=hole_spacing,
diameter=hole_diameter,
depth=hole_depth,
)
super().__init__(
name=name,
size_x=size_x,
size_y=size_y,
size_z=size_z,
ordered_items=holes,
category=category,
model=model,
)
# 保存洞位的直径和深度
self.hole_diameter = hole_diameter
self.hole_depth = hole_depth
self.max_sheets_per_hole = max_sheets_per_hole
def serialize(self) -> dict:
return {
**super().serialize(),
"hole_diameter": self.hole_diameter,
"hole_depth": self.hole_depth,
"max_sheets_per_hole": self.max_sheets_per_hole,
}
# TODO: 这个要改
class ClipMagazine(ItemizedResource[ClipMagazineHole]):
"""子弹夹类 - 有6个洞位每个洞位放多个极片"""
@@ -545,9 +458,9 @@ class BatteryState(TypedDict):
"""电池状态字典"""
diameter: float
height: float
electrolyte_name: str
assembly_pressure: float
electrolyte_volume: float
electrolyte_name: str
class Battery(Resource):
"""电池类 - 可容纳极片"""
@@ -556,6 +469,9 @@ class Battery(Resource):
def __init__(
self,
name: str,
size_x=1,
size_y=1,
size_z=1,
category: str = "battery",
):
"""初始化电池
@@ -576,7 +492,13 @@ class Battery(Resource):
size_z=1,
category=category,
)
self._unilabos_state: BatteryState = BatteryState()
self._unilabos_state: BatteryState = BatteryState(
diameter = 1.0,
height = 1.0,
assembly_pressure = 1.0,
electrolyte_volume = 1.0,
electrolyte_name = "DP001"
)
def add_electrolyte_with_bottle(self, bottle: Bottle) -> bool:
to_add_name = bottle._unilabos_state["electrolyte_name"]
@@ -664,6 +586,7 @@ class BatteryPressSlot(Resource):
reassign: bool = True,
):
"""放置极片"""
# TODO: 让高京看下槽位只有一个电池时是否这么写。
if self.has_battery():
raise ValueError(f"槽位已含有一个电池,无法再放置其他电池")
super().assign_child_resource(resource, location, reassign)
@@ -672,6 +595,7 @@ class BatteryPressSlot(Resource):
def get_battery_info(self, index: int) -> Battery:
return self.children[0]
# TODO:这个移液枪架子看一下从哪继承
class TipBox64State(TypedDict):
"""电池状态字典"""
tip_diameter: float = 5.0
@@ -730,15 +654,6 @@ class TipBox64(TipRack):
make_tip=make_tip,
)
self._unilabos_state: WasteTipBoxstate = WasteTipBoxstate()
# 记录网格参数用于前端渲染
self._grid_params = {
"num_items_x": 8,
"num_items_y": 8,
"dx": 8.0,
"dy": 8.0,
"item_dx": 9.0,
"item_dy": 9.0,
}
super().__init__(
name=name,
size_x=size_x,
@@ -750,12 +665,6 @@ class TipBox64(TipRack):
with_tips=True,
)
def serialize(self) -> dict:
return {
**super().serialize(),
**self._grid_params,
}
class WasteTipBoxstate(TypedDict):
@@ -833,15 +742,6 @@ class BottleRackState(TypedDict):
name_to_index: dict
class BottleRackState(TypedDict):
""" bottle_diameter: 瓶子直径 (mm)
bottle_height: 瓶子高度 (mm)
position_spacing: 位置间距 (mm)"""
bottle_diameter: float
bottle_height: float
position_spacing: float
name_to_index: dict
class BottleRack(Resource):
"""瓶架类 - 12个待配位置+12个已配位置"""
@@ -961,7 +861,6 @@ class BottleRack(Resource):
"padding_y": self.padding_y,
}
class BottleState(TypedDict):
diameter: float
height: float
@@ -1014,27 +913,96 @@ class Bottle(Resource):
data.update(self._unilabos_state) # Container自身的信息云端物料将保存这一data本地也通过这里的data进行读写当前类用来表示这个物料的长宽高大小的属性而datastate用来表示物料的内容细节等
return data
class ClipMagazine_four(ItemizedResource[ClipMagazineHole]):
"""子弹夹类 - 有4个洞位每个洞位放多个极片"""
children: List[ClipMagazineHole]
def __init__(
self,
name: str,
size_x: float,
size_y: float,
size_z: float,
hole_diameter: float = 14.0,
hole_depth: float = 10.0,
hole_spacing: float = 25.0,
max_sheets_per_hole: int = 100,
category: str = "clip_magazine_four",
model: Optional[str] = None,
):
"""初始化子弹夹
Args:
name: 子弹夹名称
size_x: 长度 (mm)
size_y: 宽度 (mm)
size_z: 高度 (mm)
hole_diameter: 洞直径 (mm)
hole_depth: 洞深度 (mm)
hole_spacing: 洞位间距 (mm)
max_sheets_per_hole: 每个洞位最大极片数量
category: 类别
model: 型号
"""
# 创建4个洞位排成2x2布局
holes = create_ordered_items_2d(
klass=ClipMagazineHole,
num_items_x=2,
num_items_y=2,
dx=(size_x - 2 * hole_spacing) / 2, # 居中
dy=(size_y - hole_spacing) / 2, # 居中
dz=size_z - 0,
item_dx=hole_spacing,
item_dy=hole_spacing,
diameter=hole_diameter,
depth=hole_depth,
)
super().__init__(
name=name,
size_x=size_x,
size_y=size_y,
size_z=size_z,
ordered_items=holes,
category=category,
model=model,
)
# 保存洞位的直径和深度
self.hole_diameter = hole_diameter
self.hole_depth = hole_depth
self.max_sheets_per_hole = max_sheets_per_hole
def serialize(self) -> dict:
return {
**super().serialize(),
"hole_diameter": self.hole_diameter,
"hole_depth": self.hole_depth,
"max_sheets_per_hole": self.max_sheets_per_hole,
}
class CoincellDeck(Deck):
"""纽扣电池组装工作站台面类"""
def __init__(
self,
name: str = "coin_cell_deck",
size_x: float = 1620.0, # 3.66m
size_y: float = 1270.0, # 1.23m
size_z: float = 500.0,
size_x: float = 1000.0, # 1m
size_y: float = 1000.0, # 1m
size_z: float = 900.0, # 0.9m
origin: Coordinate = Coordinate(0, 0, 0),
category: str = "coin_cell_deck",
setup: bool = False, # 是否自动执行 setup
):
"""初始化纽扣电池组装工作站台面
Args:
name: 台面名称
size_x: 长度 (mm) - 3.66m
size_y: 宽度 (mm) - 1.23m
size_z: 高度 (mm)
size_x: 长度 (mm) - 1m
size_y: 宽度 (mm) - 1m
size_z: 高度 (mm) - 0.9m
origin: 原点坐标
category: 类别
setup: 是否自动执行 setup 配置标准布局
"""
super().__init__(
name=name,
@@ -1044,246 +1012,154 @@ class CoincellDeck(Deck):
origin=origin,
category=category,
)
if setup:
self.setup()
#if __name__ == "__main__":
# # 转移极片的测试代码
# deck = CoincellDeck("coin_cell_deck")
# ban_cao_wei = PlateSlot("ban_cao_wei", max_plates=8)
# deck.assign_child_resource(ban_cao_wei, Coordinate(x=0, y=0, z=0))
#
# plate_1 = MaterialPlate("plate_1", 1,1,1, fill=True)
# for i, hole in enumerate(plate_1.children):
# sheet = ElectrodeSheet(f"hole_{i}_sheet_1")
# sheet._unilabos_state = {
# "diameter": 14,
# "info": "NMC",
# "mass": 5.0,
# "material_type": "positive_electrode",
# "thickness": 0.1
# }
# hole._unilabos_state = {
# "depth": 1.0,
# "diameter": 14,
# "info": "",
# "max_sheets": 1
# }
# hole.assign_child_resource(sheet, Coordinate.zero())
# plate_1._unilabos_state = {
# "hole_spacing_x": 20.0,
# "hole_spacing_y": 20.0,
# "hole_diameter": 5,
# "info": "这是第一块料板"
# }
# plate_1.update_locations()
# ban_cao_wei.assign_child_resource(plate_1, Coordinate.zero())
# # zi_dan_jia = ClipMagazine("zi_dan_jia", 1, 1, 1)
# # deck.assign_child_resource(ban_cao_wei, Coordinate(x=200, y=200, z=0))
#
# from unilabos.resources.graphio import *
# A = tree_to_list([resource_plr_to_ulab(deck)])
# with open("test.json", "w") as f:
# json.dump(A, f)
#
#
#def get_plate_with_14mm_hole(name=""):
# plate = MaterialPlate(name=name)
# for i in range(4):
# for j in range(4):
# hole = MaterialHole(f"{i+1}x{j+1}")
# hole._unilabos_state["diameter"] = 14
# hole._unilabos_state["max_sheets"] = 1
# plate.assign_child_resource(hole)
# return plate
def setup(self) -> None:
"""设置工作站的标准布局 - 包含子弹夹、料盘、瓶架等完整配置"""
# ====================================== 子弹夹 ============================================
zip_dan_jia = ClipMagazine_four("zi_dan_jia", 80, 80, 10)
self.assign_child_resource(zip_dan_jia, Coordinate(x=1400, y=50, z=0))
zip_dan_jia2 = ClipMagazine_four("zi_dan_jia2", 80, 80, 10)
self.assign_child_resource(zip_dan_jia2, Coordinate(x=1600, y=200, z=0))
zip_dan_jia3 = ClipMagazine("zi_dan_jia3", 80, 80, 10)
self.assign_child_resource(zip_dan_jia3, Coordinate(x=1500, y=200, z=0))
zip_dan_jia4 = ClipMagazine("zi_dan_jia4", 80, 80, 10)
self.assign_child_resource(zip_dan_jia4, Coordinate(x=1500, y=300, z=0))
zip_dan_jia5 = ClipMagazine("zi_dan_jia5", 80, 80, 10)
self.assign_child_resource(zip_dan_jia5, Coordinate(x=1600, y=300, z=0))
zip_dan_jia6 = ClipMagazine("zi_dan_jia6", 80, 80, 10)
self.assign_child_resource(zip_dan_jia6, Coordinate(x=1530, y=500, z=0))
zip_dan_jia7 = ClipMagazine("zi_dan_jia7", 80, 80, 10)
self.assign_child_resource(zip_dan_jia7, Coordinate(x=1180, y=400, z=0))
zip_dan_jia8 = ClipMagazine("zi_dan_jia8", 80, 80, 10)
self.assign_child_resource(zip_dan_jia8, Coordinate(x=1280, y=400, z=0))
def create_a_liaopan():
liaopan = MaterialPlate(name="liaopan", size_x=120.8, size_y=120.5, size_z=10.0, fill=True)
for i in range(16):
jipian = ElectrodeSheet(name=f"jipian_{i}", size_x= 12, size_y=12, size_z=0.1)
liaopan1.children[i].assign_child_resource(jipian, location=None)
return liaopan
# 为子弹夹添加极片
for i in range(4):
jipian = ElectrodeSheet(name=f"zi_dan_jia_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia2.children[i].assign_child_resource(jipian, location=None)
for i in range(4):
jipian2 = ElectrodeSheet(name=f"zi_dan_jia2_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia.children[i].assign_child_resource(jipian2, location=None)
for i in range(6):
jipian3 = ElectrodeSheet(name=f"zi_dan_jia3_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia3.children[i].assign_child_resource(jipian3, location=None)
for i in range(6):
jipian4 = ElectrodeSheet(name=f"zi_dan_jia4_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia4.children[i].assign_child_resource(jipian4, location=None)
for i in range(6):
jipian5 = ElectrodeSheet(name=f"zi_dan_jia5_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia5.children[i].assign_child_resource(jipian5, location=None)
for i in range(6):
jipian6 = ElectrodeSheet(name=f"zi_dan_jia6_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia6.children[i].assign_child_resource(jipian6, location=None)
for i in range(6):
jipian7 = ElectrodeSheet(name=f"zi_dan_jia7_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia7.children[i].assign_child_resource(jipian7, location=None)
for i in range(6):
jipian8 = ElectrodeSheet(name=f"zi_dan_jia8_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia8.children[i].assign_child_resource(jipian8, location=None)
def create_a_coin_cell_deck():
deck = Deck(size_x=1200,
size_y=800,
size_z=900)
# ====================================== 物料板 ============================================
# 创建6个4*4的物料板
liaopan1 = MaterialPlate(name="liaopan1", size_x=120, size_y=100, size_z=10.0, fill=True)
self.assign_child_resource(liaopan1, Coordinate(x=1010, y=50, z=0))
for i in range(16):
jipian_1 = ElectrodeSheet(name=f"{liaopan1.name}_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
liaopan1.children[i].assign_child_resource(jipian_1, location=None)
#liaopan = TipBox64(name="liaopan")
liaopan2 = MaterialPlate(name="liaopan2", size_x=120, size_y=100, size_z=10.0, fill=True)
self.assign_child_resource(liaopan2, Coordinate(x=1130, y=50, z=0))
#创建一个4*4的物料板
liaopan1 = MaterialPlate(name="liaopan1", size_x=120.8, size_y=120.5, size_z=10.0, fill=True)
#把物料板放到桌子上
deck.assign_child_resource(liaopan1, Coordinate(x=0, y=0, z=0))
#创建一个极片
for i in range(16):
jipian = ElectrodeSheet(name=f"jipian_{i}", size_x= 12, size_y=12, size_z=0.1)
liaopan1.children[i].assign_child_resource(jipian, location=None)
#创建一个4*4的物料板
liaopan2 = MaterialPlate(name="liaopan2", size_x=120.8, size_y=120.5, size_z=10.0, fill=True)
#把物料板放到桌子上
deck.assign_child_resource(liaopan2, Coordinate(x=500, y=0, z=0))
liaopan3 = MaterialPlate(name="liaopan3", size_x=120, size_y=100, size_z=10.0, fill=True)
self.assign_child_resource(liaopan3, Coordinate(x=1250, y=50, z=0))
#创建一个4*4的物料板
liaopan3 = MaterialPlate(name="liaopan3", size_x=120.8, size_y=120.5, size_z=10.0, fill=True)
#把物料板放到桌子上
deck.assign_child_resource(liaopan3, Coordinate(x=1000, y=0, z=0))
liaopan4 = MaterialPlate(name="liaopan4", size_x=120, size_y=100, size_z=10.0, fill=True)
self.assign_child_resource(liaopan4, Coordinate(x=1010, y=150, z=0))
for i in range(16):
jipian_4 = ElectrodeSheet(name=f"{liaopan4.name}_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
liaopan4.children[i].assign_child_resource(jipian_4, location=None)
print(deck)
liaopan5 = MaterialPlate(name="liaopan5", size_x=120, size_y=100, size_z=10.0, fill=True)
self.assign_child_resource(liaopan5, Coordinate(x=1130, y=150, z=0))
liaopan6 = MaterialPlate(name="liaopan6", size_x=120, size_y=100, size_z=10.0, fill=True)
self.assign_child_resource(liaopan6, Coordinate(x=1250, y=150, z=0))
# ====================================== 瓶架、移液枪 ============================================
# 在台面上放置 3x4 瓶架、6x2 瓶架 与 64孔移液枪头盒
bottle_rack_3x4 = BottleRack(
name="bottle_rack_3x4",
size_x=210.0,
size_y=140.0,
size_z=100.0,
num_items_x=3,
num_items_y=4,
position_spacing=35.0,
orientation="vertical",
)
self.assign_child_resource(bottle_rack_3x4, Coordinate(x=100, y=200, z=0))
bottle_rack_6x2 = BottleRack(
name="bottle_rack_6x2",
size_x=120.0,
size_y=250.0,
size_z=100.0,
num_items_x=6,
num_items_y=2,
position_spacing=35.0,
orientation="vertical",
)
self.assign_child_resource(bottle_rack_6x2, Coordinate(x=300, y=300, z=0))
bottle_rack_6x2_2 = BottleRack(
name="bottle_rack_6x2_2",
size_x=120.0,
size_y=250.0,
size_z=100.0,
num_items_x=6,
num_items_y=2,
position_spacing=35.0,
orientation="vertical",
)
self.assign_child_resource(bottle_rack_6x2_2, Coordinate(x=430, y=300, z=0))
# 将 ElectrodeSheet 放满 3x4 与 6x2 的所有孔位
for idx in range(bottle_rack_3x4.num_items_x * bottle_rack_3x4.num_items_y):
sheet = ElectrodeSheet(name=f"sheet_3x4_{idx}", size_x=12, size_y=12, size_z=0.1)
bottle_rack_3x4.assign_child_resource(sheet, index=idx)
for idx in range(bottle_rack_6x2.num_items_x * bottle_rack_6x2.num_items_y):
sheet = ElectrodeSheet(name=f"sheet_6x2_{idx}", size_x=12, size_y=12, size_z=0.1)
bottle_rack_6x2.assign_child_resource(sheet, index=idx)
tip_box = TipBox64(name="tip_box_64")
self.assign_child_resource(tip_box, Coordinate(x=300, y=100, z=0))
waste_tip_box = WasteTipBox(name="waste_tip_box")
self.assign_child_resource(waste_tip_box, Coordinate(x=300, y=200, z=0))
print(self)
def create_coin_cell_deck(name: str = "coin_cell_deck", size_x: float = 1000.0, size_y: float = 1000.0, size_z: float = 900.0) -> CoincellDeck:
"""创建并配置标准的纽扣电池组装工作站台面
Args:
name: 台面名称
size_x: 长度 (mm)
size_y: 宽度 (mm)
size_z: 高度 (mm)
Returns:
已配置好的 CoincellDeck 对象
"""
# 创建 CoincellDeck 实例并自动执行 setup 配置
deck = CoincellDeck(name=name, size_x=size_x, size_y=size_y, size_z=size_z, setup=True)
return deck
import json
if __name__ == "__main__":
electrode1 = BatteryPressSlot()
#print(electrode1.get_size_x())
#print(electrode1.get_size_y())
#print(electrode1.get_size_z())
#jipian = ElectrodeSheet()
#jipian._unilabos_state["diameter"] = 18
#print(jipian.serialize())
#print(jipian.serialize_state())
deck = CoincellDeck()
"""======================================子弹夹============================================"""
zip_dan_jia = ClipMagazine_four("zi_dan_jia", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia, Coordinate(x=1400, y=50, z=0))
zip_dan_jia2 = ClipMagazine_four("zi_dan_jia2", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia2, Coordinate(x=1600, y=200, z=0))
zip_dan_jia3 = ClipMagazine("zi_dan_jia3", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia3, Coordinate(x=1500, y=200, z=0))
zip_dan_jia4 = ClipMagazine("zi_dan_jia4", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia4, Coordinate(x=1500, y=300, z=0))
zip_dan_jia5 = ClipMagazine("zi_dan_jia5", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia5, Coordinate(x=1600, y=300, z=0))
zip_dan_jia6 = ClipMagazine("zi_dan_jia6", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia6, Coordinate(x=1530, y=500, z=0))
zip_dan_jia7 = ClipMagazine("zi_dan_jia7", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia7, Coordinate(x=1180, y=400, z=0))
zip_dan_jia8 = ClipMagazine("zi_dan_jia8", 80, 80, 10)
deck.assign_child_resource(zip_dan_jia8, Coordinate(x=1280, y=400, z=0))
for i in range(4):
jipian = ElectrodeSheet(name=f"zi_dan_jia_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia2.children[i].assign_child_resource(jipian, location=None)
for i in range(4):
jipian2 = ElectrodeSheet(name=f"zi_dan_jia2_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia.children[i].assign_child_resource(jipian2, location=None)
for i in range(6):
jipian3 = ElectrodeSheet(name=f"zi_dan_jia3_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia3.children[i].assign_child_resource(jipian3, location=None)
for i in range(6):
jipian4 = ElectrodeSheet(name=f"zi_dan_jia4_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia4.children[i].assign_child_resource(jipian4, location=None)
for i in range(6):
jipian5 = ElectrodeSheet(name=f"zi_dan_jia5_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia5.children[i].assign_child_resource(jipian5, location=None)
for i in range(6):
jipian6 = ElectrodeSheet(name=f"zi_dan_jia6_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia6.children[i].assign_child_resource(jipian6, location=None)
for i in range(6):
jipian7 = ElectrodeSheet(name=f"zi_dan_jia7_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia7.children[i].assign_child_resource(jipian7, location=None)
for i in range(6):
jipian8 = ElectrodeSheet(name=f"zi_dan_jia8_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
zip_dan_jia8.children[i].assign_child_resource(jipian8, location=None)
"""======================================子弹夹============================================"""
#liaopan = TipBox64(name="liaopan")
"""======================================物料板============================================"""
#创建一个4*4的物料板
liaopan1 = MaterialPlate(name="liaopan1", size_x=120, size_y=100, size_z=10.0, fill=True)
deck.assign_child_resource(liaopan1, Coordinate(x=1010, y=50, z=0))
for i in range(16):
jipian_1 = ElectrodeSheet(name=f"{liaopan1.name}_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
liaopan1.children[i].assign_child_resource(jipian_1, location=None)
liaopan2 = MaterialPlate(name="liaopan2", size_x=120, size_y=100, size_z=10.0, fill=True)
deck.assign_child_resource(liaopan2, Coordinate(x=1130, y=50, z=0))
liaopan3 = MaterialPlate(name="liaopan3", size_x=120, size_y=100, size_z=10.0, fill=True)
deck.assign_child_resource(liaopan3, Coordinate(x=1250, y=50, z=0))
liaopan4 = MaterialPlate(name="liaopan4", size_x=120, size_y=100, size_z=10.0, fill=True)
deck.assign_child_resource(liaopan4, Coordinate(x=1010, y=150, z=0))
for i in range(16):
jipian_4 = ElectrodeSheet(name=f"{liaopan4.name}_jipian_{i}", size_x=12, size_y=12, size_z=0.1)
liaopan4.children[i].assign_child_resource(jipian_4, location=None)
liaopan5 = MaterialPlate(name="liaopan5", size_x=120, size_y=100, size_z=10.0, fill=True)
deck.assign_child_resource(liaopan5, Coordinate(x=1130, y=150, z=0))
liaopan6 = MaterialPlate(name="liaopan6", size_x=120, size_y=100, size_z=10.0, fill=True)
deck.assign_child_resource(liaopan6, Coordinate(x=1250, y=150, z=0))
#liaopan.children[3].assign_child_resource(jipian, location=None)
"""======================================物料板============================================"""
"""======================================瓶架,移液枪============================================"""
# 在台面上放置 3x4 瓶架、6x2 瓶架 与 64孔移液枪头盒
bottle_rack_3x4 = BottleRack(
name="bottle_rack_3x4",
size_x=210.0,
size_y=140.0,
size_z=100.0,
num_items_x=3,
num_items_y=4,
position_spacing=35.0,
orientation="vertical",
)
deck.assign_child_resource(bottle_rack_3x4, Coordinate(x=100, y=200, z=0))
bottle_rack_6x2 = BottleRack(
name="bottle_rack_6x2",
size_x=120.0,
size_y=250.0,
size_z=100.0,
num_items_x=6,
num_items_y=2,
position_spacing=35.0,
orientation="vertical",
)
deck.assign_child_resource(bottle_rack_6x2, Coordinate(x=300, y=300, z=0))
bottle_rack_6x2_2 = BottleRack(
name="bottle_rack_6x2_2",
size_x=120.0,
size_y=250.0,
size_z=100.0,
num_items_x=6,
num_items_y=2,
position_spacing=35.0,
orientation="vertical",
)
deck.assign_child_resource(bottle_rack_6x2_2, Coordinate(x=430, y=300, z=0))
# 将 ElectrodeSheet 放满 3x4 与 6x2 的所有孔位
for idx in range(bottle_rack_3x4.num_items_x * bottle_rack_3x4.num_items_y):
sheet = ElectrodeSheet(name=f"sheet_3x4_{idx}", size_x=12, size_y=12, size_z=0.1)
bottle_rack_3x4.assign_child_resource(sheet, index=idx)
for idx in range(bottle_rack_6x2.num_items_x * bottle_rack_6x2.num_items_y):
sheet = ElectrodeSheet(name=f"sheet_6x2_{idx}", size_x=12, size_y=12, size_z=0.1)
bottle_rack_6x2.assign_child_resource(sheet, index=idx)
tip_box = TipBox64(name="tip_box_64")
deck.assign_child_resource(tip_box, Coordinate(x=300, y=100, z=0))
waste_tip_box = WasteTipBox(name="waste_tip_box")
deck.assign_child_resource(waste_tip_box, Coordinate(x=300, y=200, z=0))
"""======================================瓶架,移液枪============================================"""
deck = create_coin_cell_deck()
print(deck)
from unilabos.resources.graphio import convert_resources_from_type
from unilabos.config.config import BasicConfig
BasicConfig.ak = "56bbed5b-6e30-438c-b06d-f69eaa63bb45"
BasicConfig.sk = "238222fe-0bf7-4350-a426-e5ced8011dcf"
from unilabos.app.web.client import http_client
resources = convert_resources_from_type([deck], [Resource])
# 检查序列化后的资源
json.dump({"nodes": resources, "links": []}, open("button_battery_decks_unilab.json", "w"), indent=2)
#print(resources)
http_client.remote_addr = "https://uni-lab.test.bohrium.com/api/v1"
http_client.resource_add(resources)

View File

@@ -1,33 +1,133 @@
import csv
import inspect
import json
import os
import threading
import time
import types
from datetime import datetime
from typing import Any, Dict, Optional
from pylabrobot.resources import Resource as PLRResource
from functools import wraps
from pylabrobot.resources import Deck, Resource as PLRResource
from unilabos_msgs.msg import Resource
from unilabos.device_comms.modbus_plc.client import ModbusTcpClient
from unilabos.devices.workstation.coin_cell_assembly.button_battery_station import MaterialHole, MaterialPlate
from unilabos.devices.workstation.workstation_base import WorkstationBase
from unilabos.device_comms.modbus_plc.client import TCPClient, ModbusNode, PLCWorkflow, ModbusWorkflow, WorkflowAction, BaseClient
from unilabos.device_comms.modbus_plc.modbus import DeviceType, Base as ModbusNodeBase, DataType, WorderOrder
from unilabos.devices.workstation.coin_cell_assembly.button_battery_station import *
from unilabos.devices.workstation.coin_cell_assembly.YB_YH_materials import *
from unilabos.ros.nodes.base_device_node import ROS2DeviceNode, BaseROS2DeviceNode
from unilabos.ros.nodes.presets.workstation import ROS2WorkstationNode
from unilabos.devices.workstation.coin_cell_assembly.YB_YH_materials import CoincellDeck
from unilabos.resources.graphio import convert_resources_to_type
from unilabos.utils.log import logger
def _ensure_modbus_slave_kw_alias(modbus_client):
if modbus_client is None:
return
method_names = [
"read_coils",
"write_coils",
"write_coil",
"read_discrete_inputs",
"read_holding_registers",
"write_register",
"write_registers",
]
def _wrap(func):
signature = inspect.signature(func)
has_var_kwargs = any(param.kind == param.VAR_KEYWORD for param in signature.parameters.values())
accepts_unit = has_var_kwargs or "unit" in signature.parameters
accepts_slave = has_var_kwargs or "slave" in signature.parameters
@wraps(func)
def _wrapped(self, *args, **kwargs):
if "slave" in kwargs and not accepts_slave:
slave_value = kwargs.pop("slave")
if accepts_unit and "unit" not in kwargs:
kwargs["unit"] = slave_value
if "unit" in kwargs and not accepts_unit:
unit_value = kwargs.pop("unit")
if accepts_slave and "slave" not in kwargs:
kwargs["slave"] = unit_value
return func(self, *args, **kwargs)
_wrapped._has_slave_alias = True
return _wrapped
for name in method_names:
if not hasattr(modbus_client, name):
continue
bound_method = getattr(modbus_client, name)
func = getattr(bound_method, "__func__", None)
if func is None:
continue
if getattr(func, "_has_slave_alias", False):
continue
wrapped = _wrap(func)
setattr(modbus_client, name, types.MethodType(wrapped, modbus_client))
def _coerce_deck_input(deck: Any) -> Optional[Deck]:
if deck is None:
return None
if isinstance(deck, Deck):
return deck
if isinstance(deck, PLRResource):
return deck if isinstance(deck, Deck) else None
candidates = None
if isinstance(deck, dict):
if "nodes" in deck and isinstance(deck["nodes"], list):
candidates = deck["nodes"]
else:
candidates = [deck]
elif isinstance(deck, list):
candidates = deck
if candidates is None:
return None
try:
converted = convert_resources_to_type(resources_list=candidates, resource_type=Deck)
if isinstance(converted, Deck):
return converted
if isinstance(converted, list):
for item in converted:
if isinstance(item, Deck):
return item
except Exception as exc:
logger.warning(f"deck 转换 Deck 失败: {exc}")
return None
#构建物料系统
class CoinCellAssemblyWorkstation(WorkstationBase):
def __init__(
self,
deck: CoincellDeck,
address: str = "192.168.1.20",
deck: Deck=None,
address: str = "172.21.32.111",
port: str = "502",
debug_mode: bool = True,
debug_mode: bool = False,
*args,
**kwargs,
):
if deck is None and "deck" in kwargs:
deck = kwargs.pop("deck")
else:
kwargs.pop("deck", None)
normalized_deck = _coerce_deck_input(deck)
if deck is None and isinstance(normalized_deck, Deck):
deck = normalized_deck
super().__init__(
#桌子
deck=deck,
@@ -35,10 +135,22 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
**kwargs,
)
self.debug_mode = debug_mode
self.deck = deck
# 如果没有传入 deck则创建标准配置的 deck
if self.deck is None:
self.deck = CoincellDeck(size_x=1000, size_y=1000, size_z=900, setup=True)
else:
# 如果传入了 deck 但还没有 setup可以选择是否 setup
if self.deck is not None and len(self.deck.children) == 0:
# deck 为空,执行 setup
self.deck.setup()
# 否则使用传入的 deck可能已经配置好了
self.deck = self.deck
""" 连接初始化 """
modbus_client = TCPClient(addr=address, port=port)
print("modbus_client", modbus_client)
logger.debug(f"创建 Modbus 客户端: {modbus_client}")
_ensure_modbus_slave_kw_alias(modbus_client.client)
if not debug_mode:
modbus_client.client.connect()
count = 100
@@ -60,9 +172,8 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
self.csv_export_thread = None
self.csv_export_running = False
self.csv_export_file = None
self.coin_num_N = 0 #已组装电池数量
#创建一个物料台面,包含两个极片板
#self.deck = create_a_coin_cell_deck()
#self._ros_node.update_resource(self.deck)
#ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{
@@ -491,11 +602,11 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
try:
# 尝试不同的字节序读取
code_little, read_err = self.client.use_node('REG_DATA_COIN_CELL_CODE').read(10, word_order=WorderOrder.LITTLE)
print(code_little)
# logger.debug(f"读取电池二维码原始数据: {code_little}")
clean_code = code_little[-8:][::-1]
return clean_code
except Exception as e:
print(f"读取电池二维码失败: {e}")
logger.error(f"读取电池二维码失败: {e}")
return "N/A"
@@ -504,11 +615,11 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
try:
# 尝试不同的字节序读取
code_little, read_err = self.client.use_node('REG_DATA_ELECTROLYTE_CODE').read(10, word_order=WorderOrder.LITTLE)
print(code_little)
# logger.debug(f"读取电解液二维码原始数据: {code_little}")
clean_code = code_little[-8:][::-1]
return clean_code
except Exception as e:
print(f"读取电解液二维码失败: {e}")
logger.error(f"读取电解液二维码失败: {e}")
return "N/A"
# ===================== 环境监控区 ======================
@@ -606,7 +717,8 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
print("waiting for start_cmd")
time.sleep(1)
def func_pack_send_bottle_num(self, bottle_num: int):
def func_pack_send_bottle_num(self, bottle_num):
bottle_num = int(bottle_num)
#发送电解液平台数
print("启动")
while (self._unilab_rece_electrolyte_bottle_num()) == False:
@@ -654,16 +766,25 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
# self.success = True
# return self.success
def func_pack_send_msg_cmd(self, elec_use_num) -> bool:
def func_pack_send_msg_cmd(self, elec_use_num, elec_vol, assembly_type, assembly_pressure) -> bool:
"""UNILAB写参数"""
while (self.request_rec_msg_status) == False:
print("wait for request_rec_msg_status to True")
time.sleep(1)
self.success = False
#self._unilab_send_msg_electrolyte_num(elec_num)
time.sleep(1)
#设置平行样数目
self._unilab_send_msg_electrolyte_use_num(elec_use_num)
time.sleep(1)
#发送电解液加注量
self._unilab_send_msg_electrolyte_vol(elec_vol)
time.sleep(1)
#发送电解液组装类型
self._unilab_send_msg_assembly_type(assembly_type)
time.sleep(1)
#发送电池压制力
self._unilab_send_msg_assembly_pressure(assembly_pressure)
time.sleep(1)
self._unilab_send_msg_succ_cmd(True)
time.sleep(1)
while (self.request_rec_msg_status) == True:
@@ -688,15 +809,32 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
data_coin_num = self.data_coin_num
data_electrolyte_code = self.data_electrolyte_code
data_coin_cell_code = self.data_coin_cell_code
print("data_open_circuit_voltage", data_open_circuit_voltage)
print("data_pole_weight", data_pole_weight)
print("data_assembly_time", data_assembly_time)
print("data_assembly_pressure", data_assembly_pressure)
print("data_electrolyte_volume", data_electrolyte_volume)
print("data_coin_num", data_coin_num)
print("data_electrolyte_code", data_electrolyte_code)
print("data_coin_cell_code", data_coin_cell_code)
logger.debug(f"data_open_circuit_voltage: {data_open_circuit_voltage}")
logger.debug(f"data_pole_weight: {data_pole_weight}")
logger.debug(f"data_assembly_time: {data_assembly_time}")
logger.debug(f"data_assembly_pressure: {data_assembly_pressure}")
logger.debug(f"data_electrolyte_volume: {data_electrolyte_volume}")
logger.debug(f"data_coin_num: {data_coin_num}")
logger.debug(f"data_electrolyte_code: {data_electrolyte_code}")
logger.debug(f"data_coin_cell_code: {data_coin_cell_code}")
#接收完信息后读取完毕标志位置True
liaopan3 = self.deck.get_resource("\u7535\u6c60\u6599\u76d8")
#把物料解绑后放到另一盘上
battery = ElectrodeSheet(name=f"battery_{self.coin_num_N}", size_x=14, size_y=14, size_z=2)
battery._unilabos_state = {
"electrolyte_name": data_coin_cell_code,
"data_electrolyte_code": data_electrolyte_code,
"open_circuit_voltage": data_open_circuit_voltage,
"assembly_pressure": data_assembly_pressure,
"electrolyte_volume": data_electrolyte_volume
}
liaopan3.children[self.coin_num_N].assign_child_resource(battery, location=None)
#print(jipian2.parent)
ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{
"resources": [self.deck]
})
self._unilab_rec_msg_succ_cmd(True)
time.sleep(1)
#等待允许读取标志位置False
@@ -754,11 +892,25 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
self.success = True
return self.success
def qiming_coin_cell_code(self, fujipian_panshu:int, fujipian_juzhendianwei:int=0, gemopanshu:int=0, gemo_juzhendianwei:int=0, lvbodian:bool=True, battery_pressure_mode:bool=True, battery_pressure:int=4000, battery_clean_ignore:bool=False) -> bool:
self.success = False
self.client.use_node('REG_MSG_NE_PLATE_NUM').write(fujipian_panshu)
self.client.use_node('REG_MSG_NE_PLATE_MATRIX').write(fujipian_juzhendianwei)
self.client.use_node('REG_MSG_SEPARATOR_PLATE_NUM').write(gemopanshu)
self.client.use_node('REG_MSG_SEPARATOR_PLATE_MATRIX').write(gemo_juzhendianwei)
self.client.use_node('COIL_ALUMINUM_FOIL').write(not lvbodian)
self.client.use_node('REG_MSG_PRESS_MODE').write(not battery_pressure_mode)
# self.client.use_node('REG_MSG_ASSEMBLY_PRESSURE').write(battery_pressure)
self.client.use_node('REG_MSG_BATTERY_CLEAN_IGNORE').write(battery_clean_ignore)
self.success = True
return self.success
def func_allpack_cmd(self, elec_num, elec_use_num, file_path: str="D:\\coin_cell_data") -> bool:
def func_allpack_cmd(self, elec_num, elec_use_num, elec_vol:int=50, assembly_type:int=7, assembly_pressure:int=4200, file_path: str="C:\\Users\\67484\\Desktop") -> bool:
elec_num, elec_use_num, elec_vol, assembly_type, assembly_pressure = int(elec_num), int(elec_use_num), int(elec_vol), int(assembly_type), int(assembly_pressure)
summary_csv_file = os.path.join(file_path, "duandian.csv")
# 如果断点文件存在,先读取之前的进度
if os.path.exists(summary_csv_file):
read_status_flag = True
with open(summary_csv_file, 'r', newline='', encoding='utf-8') as csvfile:
@@ -784,53 +936,37 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
elec_num_N = 0
elec_use_num_N = 0
coin_num_N = 0
print(f"剩余电解液瓶数: {elec_num}, 已组装电池数: {elec_use_num}")
for i in range(20):
print(f"剩余电解液瓶数: {elec_num}, 已组装电池数: {elec_use_num}")
print(f"剩余电解液瓶数: {type(elec_num)}, 已组装电池数: {type(elec_use_num)}")
print(f"剩余电解液瓶数: {type(int(elec_num))}, 已组装电池数: {type(int(elec_use_num))}")
#如果是第一次运行,则进行初始化、切换自动、启动, 如果是断点重启则跳过。
if read_status_flag == False:
pass
#初始化
self.func_pack_device_init()
#self.func_pack_device_init()
#切换自动
self.func_pack_device_auto()
#self.func_pack_device_auto()
#启动,小车收回
self.func_pack_device_start()
#self.func_pack_device_start()
#发送电解液瓶数量,启动搬运,多搬运没事
self.func_pack_send_bottle_num(elec_num)
#self.func_pack_send_bottle_num(elec_num)
last_i = elec_num_N
last_j = elec_use_num_N
for i in range(last_i, elec_num):
print(f"开始第{last_i+i+1}瓶电解液的组装")
#第一个循环从上次断点继续后续循环从0开始
j_start = last_j if i == last_i else 0
self.func_pack_send_msg_cmd(elec_use_num-j_start)
self.func_pack_send_msg_cmd(elec_use_num-j_start, elec_vol, assembly_type, assembly_pressure)
for j in range(j_start, elec_use_num):
print(f"开始第{last_i+i+1}瓶电解液的第{j+j_start+1}个电池组装")
#读取电池组装数据并存入csv
self.func_pack_get_msg_cmd(file_path)
time.sleep(1)
#这里定义物料系统
# TODO:读完再将电池数加一还是进入循环就将电池数加一需要考虑
liaopan1 = self.deck.get_resource("liaopan1")
liaopan4 = self.deck.get_resource("liaopan4")
jipian1 = liaopan1.children[coin_num_N].children[0]
jipian4 = liaopan4.children[coin_num_N].children[0]
#print(jipian1)
#从料盘上去物料解绑后放到另一盘上
jipian1.parent.unassign_child_resource(jipian1)
jipian4.parent.unassign_child_resource(jipian4)
#print(jipian2.parent)
battery = Battery(name = f"battery_{coin_num_N}")
battery.assign_child_resource(jipian1, location=None)
battery.assign_child_resource(jipian4, location=None)
zidanjia6 = self.deck.get_resource("zi_dan_jia6")
zidanjia6.children[0].assign_child_resource(battery, location=None)
# 生成断点文件
@@ -842,6 +978,7 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
writer.writerow([elec_num, elec_use_num, elec_num_N, elec_use_num_N, coin_num_N, timestamp])
csvfile.flush()
coin_num_N += 1
self.coin_num_N = coin_num_N
elec_use_num_N += 1
elec_num_N += 1
elec_use_num_N = 0
@@ -878,34 +1015,25 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
def fun_wuliao_test(self) -> bool:
#找到data_init中构建的2个物料盘
#liaopan1 = self.deck.get_resource("liaopan1")
#liaopan4 = self.deck.get_resource("liaopan4")
#for coin_num_N in range(16):
# liaopan1 = self.deck.get_resource("liaopan1")
# liaopan4 = self.deck.get_resource("liaopan4")
# jipian1 = liaopan1.children[coin_num_N].children[0]
# jipian4 = liaopan4.children[coin_num_N].children[0]
# #print(jipian1)
# #从料盘上去物料解绑后放到另一盘上
# jipian1.parent.unassign_child_resource(jipian1)
# jipian4.parent.unassign_child_resource(jipian4)
#
# #print(jipian2.parent)
# battery = Battery(name = f"battery_{coin_num_N}")
# battery.assign_child_resource(jipian1, location=None)
# battery.assign_child_resource(jipian4, location=None)
#
# zidanjia6 = self.deck.get_resource("zi_dan_jia6")
# zidanjia6.children[0].assign_child_resource(battery, location=None)
# ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{
# "resources": [self.deck]
# })
# time.sleep(2)
for i in range(20):
print(f"输出{i}")
time.sleep(2)
liaopan3 = self.deck.get_resource("\u7535\u6c60\u6599\u76d8")
for i in range(16):
battery = ElectrodeSheet(name=f"battery_{i}", size_x=16, size_y=16, size_z=2)
battery._unilabos_state = {
"diameter": 20.0,
"height": 20.0,
"assembly_pressure": i,
"electrolyte_volume": 20.0,
"electrolyte_name": f"DP{i}"
}
liaopan3.children[i].assign_child_resource(battery, location=None)
ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{
"resources": [self.deck]
})
# for i in range(40):
# print(f"fun_wuliao_test 运行结束{i}")
# time.sleep(1)
# time.sleep(40)
# 数据读取与输出
def func_read_data_and_output(self, file_path: str="D:\\coin_cell_data"):
# 检查CSV导出是否正在运行已运行则跳出防止同时启动两个while循环
@@ -1012,7 +1140,7 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
# else:
# print("子弹夹洞位0没有极片")
#
# #把电解液从瓶中取到电池夹子中
# # TODO:#把电解液从瓶中取到电池夹子中
# battery_site = deck.get_resource("battery_press_1")
# clip_magazine_battery = deck.get_resource("clip_magazine_battery")
# if battery_site.has_battery():
@@ -1102,41 +1230,10 @@ class CoinCellAssemblyWorkstation(WorkstationBase):
'''
if __name__ == "__main__":
from pylabrobot.resources import Resource
Coin_Cell = CoinCellAssemblyWorkstation(Resource("1", 1, 1, 1), debug_mode=True)
#Coin_Cell.func_pack_device_init()
#Coin_Cell.func_pack_device_auto()
#Coin_Cell.func_pack_device_start()
#Coin_Cell.func_pack_send_bottle_num(2)
#Coin_Cell.func_pack_send_msg_cmd(2)
#Coin_Cell.func_pack_get_msg_cmd()
#Coin_Cell.func_pack_get_msg_cmd()
#Coin_Cell.func_pack_send_finished_cmd()
#
#Coin_Cell.func_allpack_cmd(3, 2)
#print(Coin_Cell.data_stack_vision_code)
#print("success")
#创建一个物料台面
#deck = create_a_coin_cell_deck()
##在台面上找到料盘和极片
#liaopan1 = deck.get_resource("liaopan1")
#liaopan2 = deck.get_resource("liaopan2")
#jipian1 = liaopan1.children[1].children[0]
#
##print(jipian1)
##把物料解绑后放到另一盘上
#jipian1.parent.unassign_child_resource(jipian1)
#liaopan2.children[1].assign_child_resource(jipian1, location=None)
##print(jipian2.parent)
from unilabos.resources.graphio import resource_ulab_to_plr, convert_resources_to_type
with open("./button_battery_decks_unilab.json", "r", encoding="utf-8") as f:
bioyond_resources_unilab = json.load(f)
print(f"成功读取 JSON 文件,包含 {len(bioyond_resources_unilab)} 个资源")
ulab_resources = convert_resources_to_type(bioyond_resources_unilab, List[PLRResource])
print(f"转换结果类型: {type(ulab_resources)}")
print(ulab_resources)
# 简单测试
workstation = CoinCellAssemblyWorkstation()
workstation.qiming_coin_cell_code(fujipian_panshu=1, fujipian_juzhendianwei=2, gemopanshu=3, gemo_juzhendianwei=4, lvbodian=False, battery_pressure_mode=False, battery_pressure=4200, battery_clean_ignore=False)
print(f"工作站创建成功: {workstation.deck.name}")
print(f"料盘数量: {len(workstation.deck.children)}")

View File

@@ -0,0 +1,64 @@
Name,DataType,InitValue,Comment,Attribute,DeviceType,Address,
COIL_SYS_START_CMD,BOOL,,,,coil,8010,
COIL_SYS_STOP_CMD,BOOL,,,,coil,8020,
COIL_SYS_RESET_CMD,BOOL,,,,coil,8030,
COIL_SYS_HAND_CMD,BOOL,,,,coil,8040,
COIL_SYS_AUTO_CMD,BOOL,,,,coil,8050,
COIL_SYS_INIT_CMD,BOOL,,,,coil,8060,
COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,,,,coil,8700,
COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,,,,coil,8710,unilab_rec_msg_succ_cmd
COIL_SYS_START_STATUS,BOOL,,,,coil,8210,
COIL_SYS_STOP_STATUS,BOOL,,,,coil,8220,
COIL_SYS_RESET_STATUS,BOOL,,,,coil,8230,
COIL_SYS_HAND_STATUS,BOOL,,,,coil,8240,
COIL_SYS_AUTO_STATUS,BOOL,,,,coil,8250,
COIL_SYS_INIT_STATUS,BOOL,,,,coil,8260,
COIL_REQUEST_REC_MSG_STATUS,BOOL,,,,coil,8500,
COIL_REQUEST_SEND_MSG_STATUS,BOOL,,,,coil,8510,request_send_msg_status
REG_MSG_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,11000,
REG_MSG_ELECTROLYTE_NUM,INT16,,,,hold_register,11002,unilab_send_msg_electrolyte_num
REG_MSG_ELECTROLYTE_VOLUME,INT16,,,,hold_register,11004,unilab_send_msg_electrolyte_vol
REG_MSG_ASSEMBLY_TYPE,INT16,,,,hold_register,11006,unilab_send_msg_assembly_type
REG_MSG_ASSEMBLY_PRESSURE,INT16,,,,hold_register,11008,unilab_send_msg_assembly_pressure
REG_DATA_ASSEMBLY_COIN_CELL_NUM,INT16,,,,hold_register,10000,data_assembly_coin_cell_num
REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,,,,hold_register,10002,data_open_circuit_voltage
REG_DATA_AXIS_X_POS,FLOAT32,,,,hold_register,10004,
REG_DATA_AXIS_Y_POS,FLOAT32,,,,hold_register,10006,
REG_DATA_AXIS_Z_POS,FLOAT32,,,,hold_register,10008,
REG_DATA_POLE_WEIGHT,FLOAT32,,,,hold_register,10010,data_pole_weight
REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,,,,hold_register,10012,data_assembly_time
REG_DATA_ASSEMBLY_PRESSURE,INT16,,,,hold_register,10014,data_assembly_pressure
REG_DATA_ELECTROLYTE_VOLUME,INT16,,,,hold_register,10016,data_electrolyte_volume
REG_DATA_COIN_NUM,INT16,,,,hold_register,10018,data_coin_num
REG_DATA_ELECTROLYTE_CODE,STRING,,,,hold_register,10020,data_electrolyte_code()
REG_DATA_COIN_CELL_CODE,STRING,,,,hold_register,10030,data_coin_cell_code()
REG_DATA_STACK_VISON_CODE,STRING,,,,hold_register,12004,data_stack_vision_code()
REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,,,,hold_register,10050,data_glove_box_pressure
REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,,,,hold_register,10052,data_glove_box_water_content
REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,,,,hold_register,10054,data_glove_box_o2_content
UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8720,
UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8520,
REG_MSG_ELECTROLYTE_NUM_USED,INT16,,,,hold_register,496,
REG_DATA_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,10000,
UNILAB_SEND_FINISHED_CMD,BOOL,,,,coil,8730,
UNILAB_RECE_FINISHED_CMD,BOOL,,,,coil,8530,
REG_DATA_ASSEMBLY_TYPE,INT16,,,,hold_register,10018,ASSEMBLY_TYPE7or8
COIL_ALUMINUM_FOIL,BOOL,,使用铝箔垫,,coil,8340,
REG_MSG_NE_PLATE_MATRIX,INT16,,负极片矩阵点位,,hold_register,440,
REG_MSG_SEPARATOR_PLATE_MATRIX,INT16,,隔膜矩阵点位,,hold_register,450,
REG_MSG_TIP_BOX_MATRIX,INT16,,移液枪头矩阵点位,,hold_register,480,
REG_MSG_NE_PLATE_NUM,INT16,,负极片盘数,,hold_register,443,
REG_MSG_SEPARATOR_PLATE_NUM,INT16,,隔膜盘数,,hold_register,453,
REG_MSG_PRESS_MODE,BOOL,,压制模式false:压力检测模式True:距离模式),,coil,8360,电池压制模式
,,,,,,,
,BOOL,,视觉对位false:使用true:忽略),,coil,8300,视觉对位
,BOOL,,复检false:使用true:忽略),,coil,8310,视觉复检
,BOOL,,手套箱_左仓false:使用true:忽略),,coil,8320,手套箱左仓
,BOOL,,手套箱_右仓false:使用true:忽略),,coil,8420,手套箱右仓
,BOOL,,真空检知false:使用true:忽略),,coil,8350,真空检知
,BOOL,,电解液添加模式false:单次滴液true:二次滴液),,coil,8370,滴液模式
,BOOL,,正极片称重false:使用true:忽略),,coil,8380,正极片称重
,BOOL,,正负极片组装方式false:正装true:倒装),,coil,8390,正负极反装
,BOOL,,压制清洁false:使用true:忽略),,coil,8400,压制清洁
,BOOL,,物料盘摆盘方式false:水平摆盘true:堆叠摆盘),,coil,8410,负极片摆盘方式
REG_MSG_BATTERY_CLEAN_IGNORE,BOOL,,忽略电池清洁false:使用true:忽略),,coil,8460,
1 Name DataType InitValue Comment Attribute DeviceType Address
2 COIL_SYS_START_CMD BOOL coil 8010
3 COIL_SYS_STOP_CMD BOOL coil 8020
4 COIL_SYS_RESET_CMD BOOL coil 8030
5 COIL_SYS_HAND_CMD BOOL coil 8040
6 COIL_SYS_AUTO_CMD BOOL coil 8050
7 COIL_SYS_INIT_CMD BOOL coil 8060
8 COIL_UNILAB_SEND_MSG_SUCC_CMD BOOL coil 8700
9 COIL_UNILAB_REC_MSG_SUCC_CMD BOOL coil 8710 unilab_rec_msg_succ_cmd
10 COIL_SYS_START_STATUS BOOL coil 8210
11 COIL_SYS_STOP_STATUS BOOL coil 8220
12 COIL_SYS_RESET_STATUS BOOL coil 8230
13 COIL_SYS_HAND_STATUS BOOL coil 8240
14 COIL_SYS_AUTO_STATUS BOOL coil 8250
15 COIL_SYS_INIT_STATUS BOOL coil 8260
16 COIL_REQUEST_REC_MSG_STATUS BOOL coil 8500
17 COIL_REQUEST_SEND_MSG_STATUS BOOL coil 8510 request_send_msg_status
18 REG_MSG_ELECTROLYTE_USE_NUM INT16 hold_register 11000
19 REG_MSG_ELECTROLYTE_NUM INT16 hold_register 11002 unilab_send_msg_electrolyte_num
20 REG_MSG_ELECTROLYTE_VOLUME INT16 hold_register 11004 unilab_send_msg_electrolyte_vol
21 REG_MSG_ASSEMBLY_TYPE INT16 hold_register 11006 unilab_send_msg_assembly_type
22 REG_MSG_ASSEMBLY_PRESSURE INT16 hold_register 11008 unilab_send_msg_assembly_pressure
23 REG_DATA_ASSEMBLY_COIN_CELL_NUM INT16 hold_register 10000 data_assembly_coin_cell_num
24 REG_DATA_OPEN_CIRCUIT_VOLTAGE FLOAT32 hold_register 10002 data_open_circuit_voltage
25 REG_DATA_AXIS_X_POS FLOAT32 hold_register 10004
26 REG_DATA_AXIS_Y_POS FLOAT32 hold_register 10006
27 REG_DATA_AXIS_Z_POS FLOAT32 hold_register 10008
28 REG_DATA_POLE_WEIGHT FLOAT32 hold_register 10010 data_pole_weight
29 REG_DATA_ASSEMBLY_PER_TIME FLOAT32 hold_register 10012 data_assembly_time
30 REG_DATA_ASSEMBLY_PRESSURE INT16 hold_register 10014 data_assembly_pressure
31 REG_DATA_ELECTROLYTE_VOLUME INT16 hold_register 10016 data_electrolyte_volume
32 REG_DATA_COIN_NUM INT16 hold_register 10018 data_coin_num
33 REG_DATA_ELECTROLYTE_CODE STRING hold_register 10020 data_electrolyte_code()
34 REG_DATA_COIN_CELL_CODE STRING hold_register 10030 data_coin_cell_code()
35 REG_DATA_STACK_VISON_CODE STRING hold_register 12004 data_stack_vision_code()
36 REG_DATA_GLOVE_BOX_PRESSURE FLOAT32 hold_register 10050 data_glove_box_pressure
37 REG_DATA_GLOVE_BOX_WATER_CONTENT FLOAT32 hold_register 10052 data_glove_box_water_content
38 REG_DATA_GLOVE_BOX_O2_CONTENT FLOAT32 hold_register 10054 data_glove_box_o2_content
39 UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM BOOL coil 8720
40 UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM BOOL coil 8520
41 REG_MSG_ELECTROLYTE_NUM_USED INT16 hold_register 496
42 REG_DATA_ELECTROLYTE_USE_NUM INT16 hold_register 10000
43 UNILAB_SEND_FINISHED_CMD BOOL coil 8730
44 UNILAB_RECE_FINISHED_CMD BOOL coil 8530
45 REG_DATA_ASSEMBLY_TYPE INT16 hold_register 10018 ASSEMBLY_TYPE7or8
46 COIL_ALUMINUM_FOIL BOOL 使用铝箔垫 coil 8340
47 REG_MSG_NE_PLATE_MATRIX INT16 负极片矩阵点位 hold_register 440
48 REG_MSG_SEPARATOR_PLATE_MATRIX INT16 隔膜矩阵点位 hold_register 450
49 REG_MSG_TIP_BOX_MATRIX INT16 移液枪头矩阵点位 hold_register 480
50 REG_MSG_NE_PLATE_NUM INT16 负极片盘数 hold_register 443
51 REG_MSG_SEPARATOR_PLATE_NUM INT16 隔膜盘数 hold_register 453
52 REG_MSG_PRESS_MODE BOOL 压制模式(false:压力检测模式,True:距离模式) coil 8360 电池压制模式
53
54 BOOL 视觉对位(false:使用,true:忽略) coil 8300 视觉对位
55 BOOL 复检(false:使用,true:忽略) coil 8310 视觉复检
56 BOOL 手套箱_左仓(false:使用,true:忽略) coil 8320 手套箱左仓
57 BOOL 手套箱_右仓(false:使用,true:忽略) coil 8420 手套箱右仓
58 BOOL 真空检知(false:使用,true:忽略) coil 8350 真空检知
59 BOOL 电解液添加模式(false:单次滴液,true:二次滴液) coil 8370 滴液模式
60 BOOL 正极片称重(false:使用,true:忽略) coil 8380 正极片称重
61 BOOL 正负极片组装方式(false:正装,true:倒装) coil 8390 正负极反装
62 BOOL 压制清洁(false:使用,true:忽略) coil 8400 压制清洁
63 BOOL 物料盘摆盘方式(false:水平摆盘,true:堆叠摆盘) coil 8410 负极片摆盘方式
64 REG_MSG_BATTERY_CLEAN_IGNORE BOOL 忽略电池清洁(false:使用,true:忽略) coil 8460

View File

@@ -0,0 +1,38 @@
{
"nodes": [
{
"id": "bioyond_cell_workstation",
"name": "配液分液工站",
"children": [
],
"parent": null,
"type": "device",
"class": "bioyond_cell",
"config": {
"protocol_type": [],
"station_resource": {}
},
"data": {}
},
{
"id": "BatteryStation",
"name": "扣电工作站",
"children": [
"coin_cell_deck"
],
"parent": null,
"type": "device",
"class": "coincellassemblyworkstation_device",
"position": {
"x": 600,
"y": 400,
"z": 0
},
"config": {
"debug_mode": false,
"protocol_type": []
}
}
],
"links": []
}

View File

@@ -668,7 +668,7 @@ __all__ = [
if __name__ == "__main__":
# 简单测试HTTP服务
class BioyondWorkstation:
class DummyWorkstation:
device_id = "WS-001"
def process_step_finish_report(self, report_request):

View File

@@ -1,252 +0,0 @@
workstation.bioyond_dispensing_station:
category:
- workstation
- bioyond
class:
action_value_mappings:
create_90_10_vial_feeding_task:
feedback: {}
goal:
delay_time: delay_time
hold_m_name: hold_m_name
order_name: order_name
percent_10_1_assign_material_name: percent_10_1_assign_material_name
percent_10_1_liquid_material_name: percent_10_1_liquid_material_name
percent_10_1_target_weigh: percent_10_1_target_weigh
percent_10_1_volume: percent_10_1_volume
percent_10_2_assign_material_name: percent_10_2_assign_material_name
percent_10_2_liquid_material_name: percent_10_2_liquid_material_name
percent_10_2_target_weigh: percent_10_2_target_weigh
percent_10_2_volume: percent_10_2_volume
percent_10_3_assign_material_name: percent_10_3_assign_material_name
percent_10_3_liquid_material_name: percent_10_3_liquid_material_name
percent_10_3_target_weigh: percent_10_3_target_weigh
percent_10_3_volume: percent_10_3_volume
percent_90_1_assign_material_name: percent_90_1_assign_material_name
percent_90_1_target_weigh: percent_90_1_target_weigh
percent_90_2_assign_material_name: percent_90_2_assign_material_name
percent_90_2_target_weigh: percent_90_2_target_weigh
percent_90_3_assign_material_name: percent_90_3_assign_material_name
percent_90_3_target_weigh: percent_90_3_target_weigh
speed: speed
temperature: temperature
goal_default:
delay_time: ''
hold_m_name: ''
order_name: ''
percent_10_1_assign_material_name: ''
percent_10_1_liquid_material_name: ''
percent_10_1_target_weigh: ''
percent_10_1_volume: ''
percent_10_2_assign_material_name: ''
percent_10_2_liquid_material_name: ''
percent_10_2_target_weigh: ''
percent_10_2_volume: ''
percent_10_3_assign_material_name: ''
percent_10_3_liquid_material_name: ''
percent_10_3_target_weigh: ''
percent_10_3_volume: ''
percent_90_1_assign_material_name: ''
percent_90_1_target_weigh: ''
percent_90_2_assign_material_name: ''
percent_90_2_target_weigh: ''
percent_90_3_assign_material_name: ''
percent_90_3_target_weigh: ''
speed: ''
temperature: ''
handles: {}
result:
return_info: return_info
schema:
description: ''
properties:
feedback:
properties: {}
required: []
title: DispenStationVialFeed_Feedback
type: object
goal:
properties:
delay_time:
type: string
hold_m_name:
type: string
order_name:
type: string
percent_10_1_assign_material_name:
type: string
percent_10_1_liquid_material_name:
type: string
percent_10_1_target_weigh:
type: string
percent_10_1_volume:
type: string
percent_10_2_assign_material_name:
type: string
percent_10_2_liquid_material_name:
type: string
percent_10_2_target_weigh:
type: string
percent_10_2_volume:
type: string
percent_10_3_assign_material_name:
type: string
percent_10_3_liquid_material_name:
type: string
percent_10_3_target_weigh:
type: string
percent_10_3_volume:
type: string
percent_90_1_assign_material_name:
type: string
percent_90_1_target_weigh:
type: string
percent_90_2_assign_material_name:
type: string
percent_90_2_target_weigh:
type: string
percent_90_3_assign_material_name:
type: string
percent_90_3_target_weigh:
type: string
speed:
type: string
temperature:
type: string
required:
- order_name
- percent_90_1_assign_material_name
- percent_90_1_target_weigh
- percent_90_2_assign_material_name
- percent_90_2_target_weigh
- percent_90_3_assign_material_name
- percent_90_3_target_weigh
- percent_10_1_assign_material_name
- percent_10_1_target_weigh
- percent_10_1_volume
- percent_10_1_liquid_material_name
- percent_10_2_assign_material_name
- percent_10_2_target_weigh
- percent_10_2_volume
- percent_10_2_liquid_material_name
- percent_10_3_assign_material_name
- percent_10_3_target_weigh
- percent_10_3_volume
- percent_10_3_liquid_material_name
- speed
- temperature
- delay_time
- hold_m_name
title: DispenStationVialFeed_Goal
type: object
result:
properties:
return_info:
type: string
required:
- return_info
title: DispenStationVialFeed_Result
type: object
required:
- goal
title: DispenStationVialFeed
type: object
type: DispenStationVialFeed
create_diamine_solution_task:
feedback: {}
goal:
delay_time: delay_time
hold_m_name: hold_m_name
liquid_material_name: liquid_material_name
material_name: material_name
order_name: order_name
speed: speed
target_weigh: target_weigh
temperature: temperature
volume: volume
goal_default:
delay_time: ''
hold_m_name: ''
liquid_material_name: ''
material_name: ''
order_name: ''
speed: ''
target_weigh: ''
temperature: ''
volume: ''
handles: {}
result:
return_info: return_info
schema:
description: ''
properties:
feedback:
properties: {}
required: []
title: DispenStationSolnPrep_Feedback
type: object
goal:
properties:
delay_time:
type: string
hold_m_name:
type: string
liquid_material_name:
type: string
material_name:
type: string
order_name:
type: string
speed:
type: string
target_weigh:
type: string
temperature:
type: string
volume:
type: string
required:
- order_name
- material_name
- target_weigh
- volume
- liquid_material_name
- speed
- temperature
- delay_time
- hold_m_name
title: DispenStationSolnPrep_Goal
type: object
result:
properties:
return_info:
type: string
required:
- return_info
title: DispenStationSolnPrep_Result
type: object
required:
- goal
title: DispenStationSolnPrep
type: object
type: DispenStationSolnPrep
module: unilabos.devices.workstation.bioyond_studio.dispensing_station:BioyondDispensingStation
status_types: {}
type: python
config_info: []
description: ''
handles: []
icon: ''
init_param_schema:
config:
properties:
config:
type: string
required:
- config
type: object
data:
properties: {}
required: []
type: object
version: 1.0.0

File diff suppressed because it is too large Load Diff

View File

@@ -1,404 +0,0 @@
bioyond_dispensing_station:
category:
- workstation
- bioyond
- bioyond_dispensing_station
class:
action_value_mappings:
batch_create_90_10_vial_feeding_tasks:
feedback: {}
goal:
delay_time: delay_time
hold_m_name: hold_m_name
liquid_material_name: liquid_material_name
speed: speed
temperature: temperature
titration: titration
goal_default:
delay_time: '600'
hold_m_name: ''
liquid_material_name: NMP
speed: '400'
temperature: '40'
titration: ''
handles:
input:
- data_key: titration
data_source: handle
data_type: object
handler_key: titration
io_type: source
label: Titration Data From Calculation Node
result:
return_info: return_info
schema:
description: 批量创建90%10%小瓶投料任务。从计算节点接收titration数据,包含物料名称、主称固体质量、滴定固体质量和滴定溶剂体积。
properties:
feedback:
properties: {}
required: []
title: BatchCreate9010VialFeedingTasks_Feedback
type: object
goal:
properties:
delay_time:
default: '600'
description: 延迟时间(秒),默认600
type: string
hold_m_name:
description: 库位名称,如"C01",必填参数
type: string
liquid_material_name:
default: NMP
description: 10%物料的液体物料名称,默认为"NMP"
type: string
speed:
default: '400'
description: 搅拌速度,默认400
type: string
temperature:
default: '40'
description: 温度(℃),默认40
type: string
titration:
description: '滴定信息对象,包含: name(物料名称), main_portion(主称固体质量g), titration_portion(滴定固体质量g),
titration_solvent(滴定溶液体积mL)'
type: string
required:
- titration
- hold_m_name
title: BatchCreate9010VialFeedingTasks_Goal
type: object
result:
properties:
return_info:
type: string
required:
- return_info
title: BatchCreate9010VialFeedingTasks_Result
type: object
required:
- goal
title: BatchCreate9010VialFeedingTasks
type: object
type: UniLabJsonCommand
batch_create_diamine_solution_tasks:
feedback: {}
goal:
delay_time: delay_time
liquid_material_name: liquid_material_name
solutions: solutions
speed: speed
temperature: temperature
goal_default:
delay_time: '600'
liquid_material_name: NMP
solutions: ''
speed: '400'
temperature: '20'
handles:
input:
- data_key: solutions
data_source: handle
data_type: array
handler_key: solutions
io_type: source
label: Solution Data From Python
result:
return_info: return_info
schema:
description: 批量创建二胺溶液配置任务。自动为多个二胺样品创建溶液配置任务,每个任务包含固体物料称量、溶剂添加、搅拌混合等步骤。
properties:
feedback:
properties: {}
required: []
title: BatchCreateDiamineSolutionTasks_Feedback
type: object
goal:
properties:
delay_time:
default: '600'
description: 溶液配置完成后的延迟时间用于充分混合和溶解默认600秒
type: string
liquid_material_name:
default: NMP
description: 液体溶剂名称用于溶解固体物料默认为NMPN-甲基吡咯烷酮)
type: string
solutions:
description: '溶液列表JSON数组格式每个元素包含: name(物料名称), order(序号), solid_mass(固体质量g),
solvent_volume(溶剂体积mL)。示例: [{"name": "MDA", "order": 0, "solid_mass":
5.0, "solvent_volume": 20}, {"name": "MPDA", "order": 1, "solid_mass":
4.5, "solvent_volume": 18}]'
type: string
speed:
default: '400'
description: 搅拌速度rpm用于混合溶液默认400转/分钟
type: string
temperature:
default: '20'
description: 配置温度溶液配置过程的目标温度默认20℃室温
type: string
required:
- solutions
title: BatchCreateDiamineSolutionTasks_Goal
type: object
result:
properties:
return_info:
description: 批量任务创建结果汇总JSON格式包含总数、成功数、失败数及每个任务的详细信息
type: string
required:
- return_info
title: BatchCreateDiamineSolutionTasks_Result
type: object
required:
- goal
title: BatchCreateDiamineSolutionTasks
type: object
type: UniLabJsonCommand
create_90_10_vial_feeding_task:
feedback: {}
goal:
delay_time: delay_time
hold_m_name: hold_m_name
order_name: order_name
percent_10_1_assign_material_name: percent_10_1_assign_material_name
percent_10_1_liquid_material_name: percent_10_1_liquid_material_name
percent_10_1_target_weigh: percent_10_1_target_weigh
percent_10_1_volume: percent_10_1_volume
percent_10_2_assign_material_name: percent_10_2_assign_material_name
percent_10_2_liquid_material_name: percent_10_2_liquid_material_name
percent_10_2_target_weigh: percent_10_2_target_weigh
percent_10_2_volume: percent_10_2_volume
percent_10_3_assign_material_name: percent_10_3_assign_material_name
percent_10_3_liquid_material_name: percent_10_3_liquid_material_name
percent_10_3_target_weigh: percent_10_3_target_weigh
percent_10_3_volume: percent_10_3_volume
percent_90_1_assign_material_name: percent_90_1_assign_material_name
percent_90_1_target_weigh: percent_90_1_target_weigh
percent_90_2_assign_material_name: percent_90_2_assign_material_name
percent_90_2_target_weigh: percent_90_2_target_weigh
percent_90_3_assign_material_name: percent_90_3_assign_material_name
percent_90_3_target_weigh: percent_90_3_target_weigh
speed: speed
temperature: temperature
goal_default:
delay_time: ''
hold_m_name: ''
order_name: ''
percent_10_1_assign_material_name: ''
percent_10_1_liquid_material_name: ''
percent_10_1_target_weigh: ''
percent_10_1_volume: ''
percent_10_2_assign_material_name: ''
percent_10_2_liquid_material_name: ''
percent_10_2_target_weigh: ''
percent_10_2_volume: ''
percent_10_3_assign_material_name: ''
percent_10_3_liquid_material_name: ''
percent_10_3_target_weigh: ''
percent_10_3_volume: ''
percent_90_1_assign_material_name: ''
percent_90_1_target_weigh: ''
percent_90_2_assign_material_name: ''
percent_90_2_target_weigh: ''
percent_90_3_assign_material_name: ''
percent_90_3_target_weigh: ''
speed: ''
temperature: ''
handles: {}
result:
return_info: return_info
schema:
description: ''
properties:
feedback:
properties: {}
required: []
title: DispenStationVialFeed_Feedback
type: object
goal:
properties:
delay_time:
type: string
hold_m_name:
type: string
order_name:
type: string
percent_10_1_assign_material_name:
type: string
percent_10_1_liquid_material_name:
type: string
percent_10_1_target_weigh:
type: string
percent_10_1_volume:
type: string
percent_10_2_assign_material_name:
type: string
percent_10_2_liquid_material_name:
type: string
percent_10_2_target_weigh:
type: string
percent_10_2_volume:
type: string
percent_10_3_assign_material_name:
type: string
percent_10_3_liquid_material_name:
type: string
percent_10_3_target_weigh:
type: string
percent_10_3_volume:
type: string
percent_90_1_assign_material_name:
type: string
percent_90_1_target_weigh:
type: string
percent_90_2_assign_material_name:
type: string
percent_90_2_target_weigh:
type: string
percent_90_3_assign_material_name:
type: string
percent_90_3_target_weigh:
type: string
speed:
type: string
temperature:
type: string
required:
- order_name
- percent_90_1_assign_material_name
- percent_90_1_target_weigh
- percent_90_2_assign_material_name
- percent_90_2_target_weigh
- percent_90_3_assign_material_name
- percent_90_3_target_weigh
- percent_10_1_assign_material_name
- percent_10_1_target_weigh
- percent_10_1_volume
- percent_10_1_liquid_material_name
- percent_10_2_assign_material_name
- percent_10_2_target_weigh
- percent_10_2_volume
- percent_10_2_liquid_material_name
- percent_10_3_assign_material_name
- percent_10_3_target_weigh
- percent_10_3_volume
- percent_10_3_liquid_material_name
- speed
- temperature
- delay_time
- hold_m_name
title: DispenStationVialFeed_Goal
type: object
result:
properties:
return_info:
type: string
required:
- return_info
title: DispenStationVialFeed_Result
type: object
required:
- goal
title: DispenStationVialFeed
type: object
type: DispenStationVialFeed
create_diamine_solution_task:
feedback: {}
goal:
delay_time: delay_time
hold_m_name: hold_m_name
liquid_material_name: liquid_material_name
material_name: material_name
order_name: order_name
speed: speed
target_weigh: target_weigh
temperature: temperature
volume: volume
goal_default:
delay_time: ''
hold_m_name: ''
liquid_material_name: ''
material_name: ''
order_name: ''
speed: ''
target_weigh: ''
temperature: ''
volume: ''
handles: {}
result:
return_info: return_info
schema:
description: ''
properties:
feedback:
properties: {}
required: []
title: DispenStationSolnPrep_Feedback
type: object
goal:
properties:
delay_time:
type: string
hold_m_name:
type: string
liquid_material_name:
type: string
material_name:
type: string
order_name:
type: string
speed:
type: string
target_weigh:
type: string
temperature:
type: string
volume:
type: string
required:
- order_name
- material_name
- target_weigh
- volume
- liquid_material_name
- speed
- temperature
- delay_time
- hold_m_name
title: DispenStationSolnPrep_Goal
type: object
result:
properties:
return_info:
type: string
required:
- return_info
title: DispenStationSolnPrep_Result
type: object
required:
- goal
title: DispenStationSolnPrep
type: object
type: DispenStationSolnPrep
module: unilabos.devices.workstation.bioyond_studio.dispensing_station:BioyondDispensingStation
status_types: {}
type: python
config_info: []
description: ''
handles: []
icon: preparation_station.webp
init_param_schema:
config:
properties:
config:
type: string
required:
- config
type: object
data:
properties: {}
required: []
type: object
version: 1.0.0

View File

@@ -1,231 +1,3 @@
hplc.agilent:
category:
- characterization_chromatic
class:
action_value_mappings:
auto-check_status:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 检查安捷伦HPLC设备状态的函数。用于监控设备的运行状态、连接状态、错误信息等关键指标。该函数定期查询设备状态确保系统稳定运行及时发现和报告设备异常。适用于自动化流程中的设备监控、故障诊断、系统维护等场景。
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: check_status参数
type: object
type: UniLabJsonCommand
auto-extract_data_from_txt:
feedback: {}
goal: {}
goal_default:
file_path: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 从文本文件中提取分析数据的函数。用于解析安捷伦HPLC生成的结果文件提取峰面积、保留时间、浓度等关键分析数据。支持多种文件格式的自动识别和数据结构化处理为后续数据分析和报告生成提供标准化的数据格式。适用于批量数据处理、结果验证、质量控制等分析工作流程。
properties:
feedback: {}
goal:
properties:
file_path:
type: string
required:
- file_path
type: object
result: {}
required:
- goal
title: extract_data_from_txt参数
type: object
type: UniLabJsonCommand
auto-start_sequence:
feedback: {}
goal: {}
goal_default:
params: null
resource: null
wf_name: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 启动安捷伦HPLC分析序列的函数。用于执行预定义的分析方法序列包括样品进样、色谱分离、检测等完整的分析流程。支持参数配置、资源分配、工作流程管理等功能实现全自动的样品分析。适用于批量样品处理、标准化分析、质量检测等需要连续自动分析的应用场景。
properties:
feedback: {}
goal:
properties:
params:
type: string
resource:
type: object
wf_name:
type: string
required:
- wf_name
type: object
result: {}
required:
- goal
title: start_sequence参数
type: object
type: UniLabJsonCommand
auto-try_close_sub_device:
feedback: {}
goal: {}
goal_default:
device_name: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 尝试关闭HPLC子设备的函数。用于安全地关闭泵、检测器、进样器等各个子模块确保设备正常断开连接并保护硬件安全。该函数提供错误处理和状态确认机制避免强制关闭可能造成的设备损坏。适用于设备维护、系统重启、紧急停机等需要安全关闭设备的场景。
properties:
feedback: {}
goal:
properties:
device_name:
type: string
required: []
type: object
result: {}
required:
- goal
title: try_close_sub_device参数
type: object
type: UniLabJsonCommand
auto-try_open_sub_device:
feedback: {}
goal: {}
goal_default:
device_name: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 尝试打开HPLC子设备的函数。用于初始化和连接泵、检测器、进样器等各个子模块建立设备通信并进行自检。该函数提供连接验证和错误恢复机制确保子设备正常启动并准备就绪。适用于设备初始化、系统启动、设备重连等需要建立设备连接的场景。
properties:
feedback: {}
goal:
properties:
device_name:
type: string
required: []
type: object
result: {}
required:
- goal
title: try_open_sub_device参数
type: object
type: UniLabJsonCommand
execute_command_from_outer:
feedback: {}
goal:
command: command
goal_default:
command: ''
handles: {}
result:
success: success
schema:
description: ''
properties:
feedback:
properties:
status:
type: string
required:
- status
title: SendCmd_Feedback
type: object
goal:
properties:
command:
type: string
required:
- command
title: SendCmd_Goal
type: object
result:
properties:
return_info:
type: string
success:
type: boolean
required:
- return_info
- success
title: SendCmd_Result
type: object
required:
- goal
title: SendCmd
type: object
type: SendCmd
module: unilabos.devices.hplc.AgilentHPLC:HPLCDriver
status_types:
could_run: bool
data_file: String
device_status: str
driver_init_ok: bool
finish_status: str
is_running: bool
status_text: str
success: bool
type: python
config_info: []
description: 安捷伦高效液相色谱HPLC分析设备用于复杂化合物的分离、检测和定量分析。该设备通过UI自动化技术控制安捷伦ChemStation软件实现全自动的样品分析流程。具备序列启动、设备状态监控、数据文件提取、结果处理等功能。支持多样品批量处理和实时状态反馈适用于药物分析、环境检测、食品安全、化学研究等需要高精度色谱分析的实验室应用。
handles: []
icon: ''
init_param_schema:
config:
properties:
driver_debug:
default: false
type: string
required: []
type: object
data:
properties:
could_run:
type: boolean
data_file:
items:
type: string
type: array
device_status:
type: string
driver_init_ok:
type: boolean
finish_status:
type: string
is_running:
type: boolean
status_text:
type: string
success:
type: boolean
required:
- status_text
- device_status
- could_run
- driver_init_ok
- is_running
- success
- finish_status
- data_file
type: object
version: 1.0.0
hplc.agilent-zhida:
category:
- characterization_chromatic

View File

@@ -1,194 +1 @@
raman.home_made:
category:
- characterization_optic
class:
action_value_mappings:
auto-ccd_time:
feedback: {}
goal: {}
goal_default:
int_time: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 设置CCD检测器积分时间的函数。用于配置拉曼光谱仪的信号采集时间控制光谱数据的质量和信噪比。较长的积分时间可获得更高的信号强度和更好的光谱质量但会增加测量时间。该函数允许根据样品特性和测量要求动态调整检测参数优化测量效果。
properties:
feedback: {}
goal:
properties:
int_time:
type: string
required:
- int_time
type: object
result: {}
required:
- goal
title: ccd_time参数
type: object
type: UniLabJsonCommand
auto-laser_on_power:
feedback: {}
goal: {}
goal_default:
output_voltage_laser: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 设置激光器输出功率的函数。用于控制拉曼光谱仪激光器的功率输出,调节激光强度以适应不同样品的测量需求。适当的激光功率能够获得良好的拉曼信号同时避免样品损伤。该函数支持精确的功率控制,确保测量结果的稳定性和重现性。
properties:
feedback: {}
goal:
properties:
output_voltage_laser:
type: string
required:
- output_voltage_laser
type: object
result: {}
required:
- goal
title: laser_on_power参数
type: object
type: UniLabJsonCommand
auto-raman_without_background:
feedback: {}
goal: {}
goal_default:
int_time: null
laser_power: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 执行无背景扣除的拉曼光谱测量函数。用于直接采集样品的拉曼光谱信号,不进行背景校正处理。该函数配置积分时间和激光功率参数,获取原始光谱数据用于后续的数据处理分析。适用于对光谱数据质量要求较高或需要自定义背景处理流程的测量场景。
properties:
feedback: {}
goal:
properties:
int_time:
type: string
laser_power:
type: string
required:
- int_time
- laser_power
type: object
result: {}
required:
- goal
title: raman_without_background参数
type: object
type: UniLabJsonCommand
auto-raman_without_background_average:
feedback: {}
goal: {}
goal_default:
average: null
int_time: null
laser_power: null
sample_name: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 执行多次平均的无背景拉曼光谱测量函数。通过多次测量取平均值来提高光谱数据的信噪比和测量精度,减少随机噪声影响。该函数支持自定义平均次数、积分时间、激光功率等参数,并可为样品指定名称便于数据管理。适用于对测量精度要求较高的定量分析和研究应用。
properties:
feedback: {}
goal:
properties:
average:
type: string
int_time:
type: string
laser_power:
type: string
sample_name:
type: string
required:
- sample_name
- int_time
- laser_power
- average
type: object
result: {}
required:
- goal
title: raman_without_background_average参数
type: object
type: UniLabJsonCommand
raman_cmd:
feedback: {}
goal:
command: command
goal_default:
command: ''
handles: {}
result:
success: success
schema:
description: ''
properties:
feedback:
properties:
status:
type: string
required:
- status
title: SendCmd_Feedback
type: object
goal:
properties:
command:
type: string
required:
- command
title: SendCmd_Goal
type: object
result:
properties:
return_info:
type: string
success:
type: boolean
required:
- return_info
- success
title: SendCmd_Result
type: object
required:
- goal
title: SendCmd
type: object
type: SendCmd
module: unilabos.devices.raman_uv.home_made_raman:RamanObj
status_types: {}
type: python
config_info: []
description: 拉曼光谱分析设备用于物质的分子结构和化学成分表征。该设备集成激光器和CCD检测器通过串口通信控制激光功率和光谱采集。具备背景扣除、多次平均、自动数据处理等功能支持高精度的拉曼光谱测量。适用于材料表征、化学分析、质量控制、研究开发等需要分子指纹识别和结构分析的实验应用。
handles: []
icon: ''
init_param_schema:
config:
properties:
baudrate_ccd:
default: 921600
type: string
baudrate_laser:
default: 9600
type: string
port_ccd:
type: string
port_laser:
type: string
required:
- port_laser
- port_ccd
type: object
data:
properties: {}
required: []
type: object
version: 1.0.0
{}

View File

@@ -0,0 +1,584 @@
coincellassemblyworkstation_device:
category:
- coin_cell_workstation
class:
action_value_mappings:
auto-change_hole_sheet_to_2:
feedback: {}
goal: {}
goal_default:
hole: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
hole:
type: object
required:
- hole
type: object
result: {}
required:
- goal
title: change_hole_sheet_to_2参数
type: object
type: UniLabJsonCommandAsync
auto-fill_plate:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: fill_plate参数
type: object
type: UniLabJsonCommandAsync
auto-fun_wuliao_test:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: fun_wuliao_test参数
type: object
type: UniLabJsonCommand
auto-func_allpack_cmd:
feedback: {}
goal: {}
goal_default:
assembly_pressure: 4200
assembly_type: 7
elec_num: null
elec_use_num: null
elec_vol: 50
file_path: C:\Users\67484\Desktop
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
assembly_pressure:
default: 4200
type: integer
assembly_type:
default: 7
type: integer
elec_num:
type: string
elec_use_num:
type: string
elec_vol:
default: 50
type: integer
file_path:
default: C:\Users\67484\Desktop
type: string
required:
- elec_num
- elec_use_num
type: object
result: {}
required:
- goal
title: func_allpack_cmd参数
type: object
type: UniLabJsonCommand
auto-func_get_csv_export_status:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_get_csv_export_status参数
type: object
type: UniLabJsonCommand
auto-func_pack_device_auto:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_pack_device_auto参数
type: object
type: UniLabJsonCommand
auto-func_pack_device_init:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_pack_device_init参数
type: object
type: UniLabJsonCommand
auto-func_pack_device_start:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_pack_device_start参数
type: object
type: UniLabJsonCommand
auto-func_pack_device_stop:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_pack_device_stop参数
type: object
type: UniLabJsonCommand
auto-func_pack_get_msg_cmd:
feedback: {}
goal: {}
goal_default:
file_path: D:\coin_cell_data
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
file_path:
default: D:\coin_cell_data
type: string
required: []
type: object
result: {}
required:
- goal
title: func_pack_get_msg_cmd参数
type: object
type: UniLabJsonCommand
auto-func_pack_send_bottle_num:
feedback: {}
goal: {}
goal_default:
bottle_num: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
bottle_num:
type: string
required:
- bottle_num
type: object
result: {}
required:
- goal
title: func_pack_send_bottle_num参数
type: object
type: UniLabJsonCommand
auto-func_pack_send_finished_cmd:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_pack_send_finished_cmd参数
type: object
type: UniLabJsonCommand
auto-func_pack_send_msg_cmd:
feedback: {}
goal: {}
goal_default:
assembly_pressure: null
assembly_type: null
elec_use_num: null
elec_vol: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
assembly_pressure:
type: string
assembly_type:
type: string
elec_use_num:
type: string
elec_vol:
type: string
required:
- elec_use_num
- elec_vol
- assembly_type
- assembly_pressure
type: object
result: {}
required:
- goal
title: func_pack_send_msg_cmd参数
type: object
type: UniLabJsonCommand
auto-func_read_data_and_output:
feedback: {}
goal: {}
goal_default:
file_path: D:\coin_cell_data
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
file_path:
default: D:\coin_cell_data
type: string
required: []
type: object
result: {}
required:
- goal
title: func_read_data_and_output参数
type: object
type: UniLabJsonCommand
auto-func_stop_read_data:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: func_stop_read_data参数
type: object
type: UniLabJsonCommand
auto-modify_deck_name:
feedback: {}
goal: {}
goal_default:
resource_name: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
resource_name:
type: string
required:
- resource_name
type: object
result: {}
required:
- goal
title: modify_deck_name参数
type: object
type: UniLabJsonCommand
auto-post_init:
feedback: {}
goal: {}
goal_default:
ros_node: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
ros_node:
type: object
required:
- ros_node
type: object
result: {}
required:
- goal
title: post_init参数
type: object
type: UniLabJsonCommand
auto-qiming_coin_cell_code:
feedback: {}
goal: {}
goal_default:
battery_clean_ignore: false
battery_pressure: 4000
battery_pressure_mode: true
fujipian_juzhendianwei: 0
fujipian_panshu: null
gemo_juzhendianwei: 0
gemopanshu: 0
lvbodian: true
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
battery_clean_ignore:
default: false
type: boolean
battery_pressure:
default: 4000
type: integer
battery_pressure_mode:
default: true
type: boolean
fujipian_juzhendianwei:
default: 0
type: integer
fujipian_panshu:
type: integer
gemo_juzhendianwei:
default: 0
type: integer
gemopanshu:
default: 0
type: integer
lvbodian:
default: true
type: boolean
required:
- fujipian_panshu
type: object
result: {}
required:
- goal
title: qiming_coin_cell_code参数
type: object
type: UniLabJsonCommand
module: unilabos.devices.workstation.coin_cell_assembly.coin_cell_assembly:CoinCellAssemblyWorkstation
status_types:
data_assembly_coin_cell_num: int
data_assembly_pressure: int
data_assembly_time: float
data_axis_x_pos: float
data_axis_y_pos: float
data_axis_z_pos: float
data_coin_cell_code: str
data_coin_num: int
data_electrolyte_code: str
data_electrolyte_volume: int
data_glove_box_o2_content: float
data_glove_box_pressure: float
data_glove_box_water_content: float
data_open_circuit_voltage: float
data_pole_weight: float
request_rec_msg_status: bool
request_send_msg_status: bool
sys_mode: str
sys_status: str
type: python
config_info: []
description: ''
handles: []
icon: ''
init_param_schema:
config:
properties:
address:
default: 172.21.32.111
type: string
debug_mode:
default: false
type: boolean
deck:
type: object
port:
default: '502'
type: string
required: []
type: object
data:
properties:
data_assembly_coin_cell_num:
type: integer
data_assembly_pressure:
type: integer
data_assembly_time:
type: number
data_axis_x_pos:
type: number
data_axis_y_pos:
type: number
data_axis_z_pos:
type: number
data_coin_cell_code:
type: string
data_coin_num:
type: integer
data_electrolyte_code:
type: string
data_electrolyte_volume:
type: integer
data_glove_box_o2_content:
type: number
data_glove_box_pressure:
type: number
data_glove_box_water_content:
type: number
data_open_circuit_voltage:
type: number
data_pole_weight:
type: number
request_rec_msg_status:
type: boolean
request_send_msg_status:
type: boolean
sys_mode:
type: string
sys_status:
type: string
required:
- sys_status
- sys_mode
- request_rec_msg_status
- request_send_msg_status
- data_assembly_coin_cell_num
- data_assembly_time
- data_open_circuit_voltage
- data_axis_x_pos
- data_axis_y_pos
- data_axis_z_pos
- data_pole_weight
- data_assembly_pressure
- data_electrolyte_volume
- data_coin_num
- data_coin_cell_code
- data_electrolyte_code
- data_glove_box_pressure
- data_glove_box_o2_content
- data_glove_box_water_content
type: object
registry_type: device
version: 1.0.0

View File

@@ -1,479 +1 @@
reaction_station.bioyond:
category:
- work_station
- reaction_station_bioyond
class:
action_value_mappings:
drip_back:
feedback: {}
goal:
assign_material_name: assign_material_name
temperature: temperature
time: time
titration_type: titration_type
torque_variation: torque_variation
volume: volume
goal_default:
assign_material_name: ''
temperature: ''
time: ''
titration_type: ''
torque_variation: ''
volume: ''
handles: {}
result: {}
schema:
description: 滴回去
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称(不能为空)
type: string
temperature:
description: 温度设定(°C)
type: string
time:
description: 观察时间(分钟)
type: string
titration_type:
description: 是否滴定(1=否, 2=是)
type: string
torque_variation:
description: 是否观察 (1=否, 2=是)
type: string
volume:
description: 分液公式(μL)
type: string
required:
- volume
- assign_material_name
- time
- torque_variation
- titration_type
- temperature
type: object
result: {}
required:
- goal
title: drip_back参数
type: object
type: UniLabJsonCommand
liquid_feeding_beaker:
feedback: {}
goal:
assign_material_name: assign_material_name
temperature: temperature
time: time
titration_type: titration_type
torque_variation: torque_variation
volume: volume
goal_default:
assign_material_name: ''
temperature: ''
time: ''
titration_type: ''
torque_variation: ''
volume: ''
handles: {}
result: {}
schema:
description: 液体进料烧杯
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称
type: string
temperature:
description: 温度设定(°C)
type: string
time:
description: 观察时间(分钟)
type: string
titration_type:
description: 是否滴定(1=否, 2=是)
type: string
torque_variation:
description: 是否观察 (1=否, 2=是)
type: string
volume:
description: 分液公式(μL)
type: string
required:
- volume
- assign_material_name
- time
- torque_variation
- titration_type
- temperature
type: object
result: {}
required:
- goal
title: liquid_feeding_beaker参数
type: object
type: UniLabJsonCommand
liquid_feeding_solvents:
feedback: {}
goal:
assign_material_name: assign_material_name
solvents: solvents
temperature: temperature
time: time
titration_type: titration_type
torque_variation: torque_variation
volume: volume
goal_default:
assign_material_name: ''
solvents: ''
temperature: '25.00'
time: '360'
titration_type: '1'
torque_variation: '2'
volume: ''
handles:
input:
- data_key: solvents
data_source: handle
data_type: object
handler_key: solvents
io_type: source
label: Solvents Data From Calculation Node
result: {}
schema:
description: 液体投料-溶剂。可以直接提供volume(μL),或通过solvents对象自动从additional_solvent(mL)计算volume。
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称
type: string
solvents:
description: '溶剂信息对象(可选),包含: additional_solvent(溶剂体积mL), total_liquid_volume(总液体体积mL)。如果提供,将自动计算volume'
type: string
temperature:
default: '25.00'
description: 温度设定(°C),默认25.00
type: string
time:
default: '360'
description: 观察时间(分钟),默认360
type: string
titration_type:
default: '1'
description: 是否滴定(1=否, 2=是),默认1
type: string
torque_variation:
default: '2'
description: 是否观察 (1=否, 2=是),默认2
type: string
volume:
description: 分液量(μL)。可直接提供,或通过solvents参数自动计算
type: string
required:
- assign_material_name
type: object
result: {}
required:
- goal
title: liquid_feeding_solvents参数
type: object
type: UniLabJsonCommand
liquid_feeding_titration:
feedback: {}
goal:
assign_material_name: assign_material_name
temperature: temperature
time: time
titration_type: titration_type
torque_variation: torque_variation
volume_formula: volume_formula
goal_default:
assign_material_name: ''
temperature: ''
time: ''
titration_type: ''
torque_variation: ''
volume_formula: ''
handles: {}
result: {}
schema:
description: 液体进料(滴定)
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称
type: string
temperature:
description: 温度设定(°C)
type: string
time:
description: 观察时间(分钟)
type: string
titration_type:
description: 是否滴定(1=否, 2=是)
type: string
torque_variation:
description: 是否观察 (1=否, 2=是)
type: string
volume_formula:
description: 分液公式(μL)
type: string
required:
- volume_formula
- assign_material_name
- time
- torque_variation
- titration_type
- temperature
type: object
result: {}
required:
- goal
title: liquid_feeding_titration参数
type: object
type: UniLabJsonCommand
liquid_feeding_vials_non_titration:
feedback: {}
goal:
assign_material_name: assign_material_name
temperature: temperature
time: time
titration_type: titration_type
torque_variation: torque_variation
volume_formula: volume_formula
goal_default:
assign_material_name: ''
temperature: ''
time: ''
titration_type: ''
torque_variation: ''
volume_formula: ''
handles: {}
result: {}
schema:
description: 液体进料小瓶(非滴定)
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称
type: string
temperature:
description: 温度设定(°C)
type: string
time:
description: 观察时间(分钟)
type: string
titration_type:
description: 是否滴定(1=否, 2=是)
type: string
torque_variation:
description: 是否观察 (1=否, 2=是)
type: string
volume_formula:
description: 分液公式(μL)
type: string
required:
- volume_formula
- assign_material_name
- time
- torque_variation
- titration_type
- temperature
type: object
result: {}
required:
- goal
title: liquid_feeding_vials_non_titration参数
type: object
type: UniLabJsonCommand
process_and_execute_workflow:
feedback: {}
goal:
task_name: task_name
workflow_name: workflow_name
goal_default:
task_name: ''
workflow_name: ''
handles: {}
result: {}
schema:
description: 处理并执行工作流
properties:
feedback: {}
goal:
properties:
task_name:
description: 任务名称
type: string
workflow_name:
description: 工作流名称
type: string
required:
- workflow_name
- task_name
type: object
result: {}
required:
- goal
title: process_and_execute_workflow参数
type: object
type: UniLabJsonCommand
reactor_taken_in:
feedback: {}
goal:
assign_material_name: assign_material_name
cutoff: cutoff
temperature: temperature
goal_default:
assign_material_name: ''
cutoff: ''
temperature: ''
handles: {}
result: {}
schema:
description: 反应器放入 - 将反应器放入工作站,配置物料名称、粘度上限和温度参数
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称
type: string
cutoff:
description: 粘度上限
type: string
temperature:
description: 温度设定(°C)
type: string
required:
- cutoff
- temperature
- assign_material_name
type: object
result: {}
required:
- goal
title: reactor_taken_in参数
type: object
type: UniLabJsonCommand
reactor_taken_out:
feedback: {}
goal: {}
goal_default: {}
handles: {}
result: {}
schema:
description: 反应器取出 - 从工作站中取出反应器,无需参数的简单操作
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result:
properties:
code:
description: 操作结果代码(1表示成功,0表示失败)
type: integer
return_info:
description: 操作结果详细信息
type: string
type: object
required:
- goal
title: reactor_taken_out参数
type: object
type: UniLabJsonCommand
solid_feeding_vials:
feedback: {}
goal:
assign_material_name: assign_material_name
material_id: material_id
temperature: temperature
time: time
torque_variation: torque_variation
goal_default:
assign_material_name: ''
material_id: ''
temperature: ''
time: ''
torque_variation: ''
handles: {}
result: {}
schema:
description: 固体进料小瓶 - 通过小瓶向反应器中添加固体物料,支持多种粉末类型(盐、面粉、BTDA)
properties:
feedback: {}
goal:
properties:
assign_material_name:
description: 物料名称(用于获取试剂瓶位ID)
type: string
material_id:
description: 粉末类型ID1=盐21分钟2=面粉27分钟3=BTDA38分钟
type: string
temperature:
description: 温度设定(°C)
type: string
time:
description: 观察时间(分钟)
type: string
torque_variation:
description: 是否观察 (1=否, 2=是)
type: string
required:
- assign_material_name
- material_id
- time
- torque_variation
- temperature
type: object
result: {}
required:
- goal
title: solid_feeding_vials参数
type: object
type: UniLabJsonCommand
module: unilabos.devices.workstation.bioyond_studio.reaction_station:BioyondReactionStation
protocol_type: []
status_types:
all_workflows: dict
bioyond_status: dict
workstation_status: dict
type: python
config_info: []
description: Bioyond反应站
handles: []
icon: reaction_station.webp
init_param_schema:
config:
properties:
config:
type: object
deck:
type: object
required: []
type: object
data:
properties:
all_workflows:
type: object
bioyond_status:
type: object
workstation_status:
type: object
required:
- bioyond_status
- all_workflows
- workstation_status
type: object
version: 1.0.0
{}

View File

@@ -834,174 +834,3 @@ linear_motion.toyo_xyz.sim:
mesh: toyo_xyz
type: device
version: 1.0.0
motor.iCL42:
category:
- robot_linear_motion
class:
action_value_mappings:
auto-execute_run_motor:
feedback: {}
goal: {}
goal_default:
mode: null
position: null
velocity: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 步进电机执行运动函数。直接执行电机运动命令,包括位置设定、速度控制和路径规划。该函数处理底层的电机控制协议,消除警告信息,设置运动参数并启动电机运行。适用于需要直接控制电机运动的应用场景。
properties:
feedback: {}
goal:
properties:
mode:
type: string
position:
type: number
velocity:
type: integer
required:
- mode
- position
- velocity
type: object
result: {}
required:
- goal
title: execute_run_motor参数
type: object
type: UniLabJsonCommand
auto-init_device:
feedback: {}
goal: {}
goal_default: {}
handles: {}
placeholder_keys: {}
result: {}
schema:
description: iCL42电机设备初始化函数。建立与iCL42步进电机驱动器的串口通信连接配置通信参数包括波特率、数据位、校验位等。该函数是电机使用前的必要步骤确保驱动器处于可控状态并准备接收运动指令。
properties:
feedback: {}
goal:
properties: {}
required: []
type: object
result: {}
required:
- goal
title: init_device参数
type: object
type: UniLabJsonCommand
auto-run_motor:
feedback: {}
goal: {}
goal_default:
mode: null
position: null
velocity: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: 步进电机运动控制函数。根据指定的运动模式、目标位置和速度参数控制电机运动。支持多种运动模式和精确的位置控制,自动处理运动轨迹规划和执行。该函数提供异步执行和状态反馈,确保运动的准确性和可靠性。
properties:
feedback: {}
goal:
properties:
mode:
type: string
position:
type: number
velocity:
type: integer
required:
- mode
- position
- velocity
type: object
result: {}
required:
- goal
title: run_motor参数
type: object
type: UniLabJsonCommand
execute_command_from_outer:
feedback: {}
goal:
command: command
goal_default:
command: ''
handles: {}
result:
success: success
schema:
description: ''
properties:
feedback:
properties:
status:
type: string
required:
- status
title: SendCmd_Feedback
type: object
goal:
properties:
command:
type: string
required:
- command
title: SendCmd_Goal
type: object
result:
properties:
return_info:
type: string
success:
type: boolean
required:
- return_info
- success
title: SendCmd_Result
type: object
required:
- goal
title: SendCmd
type: object
type: SendCmd
module: unilabos.devices.motor.iCL42:iCL42Driver
status_types:
is_executing_run: bool
motor_position: int
success: bool
type: python
config_info: []
description: iCL42步进电机驱动器用于实验室设备的精密线性运动控制。该设备通过串口通信控制iCL42型步进电机驱动器支持多种运动模式和精确的位置、速度控制。具备位置反馈、运行状态监控和故障检测功能。适用于自动进样器、样品传送、精密定位平台等需要准确线性运动控制的实验室自动化设备。
handles: []
icon: ''
init_param_schema:
config:
properties:
device_address:
default: 1
type: integer
device_com:
default: COM9
type: string
required: []
type: object
data:
properties:
is_executing_run:
type: boolean
motor_position:
type: integer
success:
type: boolean
required:
- motor_position
- is_executing_run
- success
type: object
version: 1.0.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
YB_Pipette_Tip:
category:
- yb3
- YB_bottle
class:
module: unilabos.resources.bioyond.YB_bottles:YB_Pipette_Tip
type: pylabrobot
description: YB_Pipette_Tip
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_fen_ye_20ml_Bottle:
category:
- yb3
- YB_bottle
class:
module: unilabos.resources.bioyond.YB_bottles:YB_fen_ye_20ml_Bottle
type: pylabrobot
description: YB_fen_ye_20ml_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_fen_ye_5ml_Bottle:
category:
- yb3
- YB_bottle
class:
module: unilabos.resources.bioyond.YB_bottles:YB_fen_ye_5ml_Bottle
type: pylabrobot
description: YB_fen_ye_5ml_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_pei_ye_da_Bottle:
category:
- yb3
- YB_bottle
class:
module: unilabos.resources.bioyond.YB_bottles:YB_pei_ye_da_Bottle
type: pylabrobot
description: YB_pei_ye_da_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_pei_ye_xiao_Bottle:
category:
- yb3
- YB_bottle
class:
module: unilabos.resources.bioyond.YB_bottles:YB_pei_ye_xiao_Bottle
type: pylabrobot
description: YB_pei_ye_xiao_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0

View File

@@ -0,0 +1,208 @@
YB_1Bottle100mlCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_1Bottle100mlCarrier
type: pylabrobot
description: YB_1Bottle100mlCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_1BottleCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_1BottleCarrier
type: pylabrobot
description: YB_1BottleCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_1GaoNianYeBottleCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_1GaoNianYeBottleCarrier
type: pylabrobot
description: YB_1GaoNianYeBottleCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_4x_LargeSolutionBottleCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_4x_LargeSolutionBottleCarrier
type: pylabrobot
description: YB_4x_LargeSolutionBottleCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_6StockCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_6StockCarrier
type: pylabrobot
description: YB_6StockCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_6VialCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_6VialCarrier
type: pylabrobot
description: YB_6VialCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_6x20ml_DispensingVialCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_6x20ml_DispensingVialCarrier
type: pylabrobot
description: YB_6x20ml_DispensingVialCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_6x5ml_DispensingVialCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_6x5ml_DispensingVialCarrier
type: pylabrobot
description: YB_6x5ml_DispensingVialCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_6x_SmallSolutionBottleCarrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_6x_SmallSolutionBottleCarrier
type: pylabrobot
description: YB_6x_SmallSolutionBottleCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_AdapterBlock:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_AdapterBlock
type: pylabrobot
description: YB_AdapterBlock
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_TipBox:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_TipBox
type: pylabrobot
description: YB_TipBox
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_gao_nian_ye_Bottle:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottles:YB_gao_nian_ye_Bottle
type: pylabrobot
description: YB_gao_nian_ye_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_jia_yang_tou_da:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottles:YB_jia_yang_tou_da
type: pylabrobot
description: YB_jia_yang_tou_da
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_jia_yang_tou_da_1X1_carrier:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottle_carriers:YB_jia_yang_tou_da_1X1_carrier
type: pylabrobot
description: YB_jia_yang_tou_da_1X1_carrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_ye_100ml_Bottle:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottles:YB_ye_100ml_Bottle
type: pylabrobot
description: YB_ye_100ml_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_ye_Bottle:
category:
- yb3
- YB_bottle_carriers
class:
module: unilabos.resources.bioyond.YB_bottles:YB_ye_Bottle
type: pylabrobot
description: YB_ye_Bottle
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0

View File

@@ -1,48 +0,0 @@
BIOYOND_PolymerStation_1BottleCarrier:
category:
- bottle_carriers
class:
module: unilabos.resources.bioyond.bottle_carriers:BIOYOND_PolymerStation_1BottleCarrier
type: pylabrobot
description: BIOYOND_PolymerStation_1BottleCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
BIOYOND_PolymerStation_1FlaskCarrier:
category:
- bottle_carriers
class:
module: unilabos.resources.bioyond.bottle_carriers:BIOYOND_PolymerStation_1FlaskCarrier
type: pylabrobot
description: BIOYOND_PolymerStation_1FlaskCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
BIOYOND_PolymerStation_6StockCarrier:
category:
- bottle_carriers
class:
module: unilabos.resources.bioyond.bottle_carriers:BIOYOND_PolymerStation_6StockCarrier
type: pylabrobot
description: BIOYOND_PolymerStation_6StockCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0
BIOYOND_PolymerStation_6VialCarrier:
category:
- bottle_carriers
class:
module: unilabos.resources.bioyond.bottle_carriers:BIOYOND_PolymerStation_6VialCarrier
type: pylabrobot
description: BIOYOND_PolymerStation_6VialCarrier
handles: []
icon: ''
init_param_schema: {}
registry_type: resource
version: 1.0.0

View File

@@ -1,50 +0,0 @@
BIOYOND_PolymerStation_Liquid_Vial:
category:
- bottles
class:
module: unilabos.resources.bioyond.bottles:BIOYOND_PolymerStation_Liquid_Vial
type: pylabrobot
handles: []
icon: ''
init_param_schema: {}
version: 1.0.0
BIOYOND_PolymerStation_Reagent_Bottle:
category:
- bottles
class:
module: unilabos.resources.bioyond.bottles:BIOYOND_PolymerStation_Reagent_Bottle
type: pylabrobot
handles: []
icon: ''
init_param_schema: {}
version: 1.0.0
BIOYOND_PolymerStation_Solid_Stock:
category:
- bottles
class:
module: unilabos.resources.bioyond.bottles:BIOYOND_PolymerStation_Solid_Stock
type: pylabrobot
handles: []
icon: ''
init_param_schema: {}
version: 1.0.0
BIOYOND_PolymerStation_Solid_Vial:
category:
- bottles
class:
module: unilabos.resources.bioyond.bottles:BIOYOND_PolymerStation_Solid_Vial
type: pylabrobot
handles: []
icon: ''
init_param_schema: {}
version: 1.0.0
BIOYOND_PolymerStation_Solution_Beaker:
category:
- bottles
class:
module: unilabos.resources.bioyond.bottles:BIOYOND_PolymerStation_Solution_Beaker
type: pylabrobot
handles: []
icon: ''
init_param_schema: {}
version: 1.0.0

View File

@@ -22,21 +22,15 @@ BIOYOND_PolymerReactionStation_Deck:
init_param_schema: {}
registry_type: resource
version: 1.0.0
YB_Deck11:
BIOYOND_YB_Deck:
category:
- deck
class:
module: unilabos.resources.bioyond.decks:YB_Deck
module: unilabos.resources.bioyond.decks:BIOYOND_YB_Deck
type: pylabrobot
description: BIOYOND PolymerReactionStation Deck
description: BIOYOND_YB_Deck
handles: []
icon: 配液站.webp
init_param_schema: {}
registry_type: resource
version: 1.0.0

View File

@@ -0,0 +1,653 @@
from pylabrobot.resources import create_homogeneous_resources, Coordinate, ResourceHolder, create_ordered_items_2d
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
from unilabos.resources.bioyond.YB_bottles import (
YB_jia_yang_tou_da,
YB_ye_Bottle,
YB_ye_100ml_Bottle,
YB_gao_nian_ye_Bottle,
YB_fen_ye_5ml_Bottle,
YB_fen_ye_20ml_Bottle,
YB_pei_ye_xiao_Bottle,
YB_pei_ye_da_Bottle,
YB_Pipette_Tip,
)
# 命名约定:试剂瓶-Bottle烧杯-Beaker烧瓶-Flask小瓶-Vial
def BIOYOND_Electrolyte_6VialCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 30.0
bottle_spacing_x = 42.0 # X方向间距
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
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="Electrolyte_6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
# for i in range(6):
# carrier[i] = YB_Solid_Vial(f"{name}_vial_{i+1}")
return carrier
def BIOYOND_Electrolyte_1BottleCarrier(name: str) -> BottleCarrier:
"""1瓶载架 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 100.0
# 烧杯尺寸
beaker_diameter = 80.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="Electrolyte_1BottleCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
# carrier[0] = YB_Solution_Beaker(f"{name}_beaker_1")
return carrier
def YB_6StockCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 20.0
bottle_spacing_x = 42.0 # X方向间距
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
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6StockCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
# for i in range(6):
# carrier[i] = YB_Solid_Stock(f"{name}_vial_{ordering[i]}")
return carrier
def YB_6VialCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 30.0
bottle_spacing_x = 42.0 # X方向间距
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
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
# for i in range(3):
# carrier[i] = YB_Solid_Vial(f"{name}_solidvial_{ordering[i]}")
# for i in range(3, 6):
# carrier[i] = YB_Liquid_Vial(f"{name}_liquidvial_{ordering[i]}")
return carrier
# 1瓶载架 - 单个中央位置
def YB_1BottleCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="1BottleCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_ye_Bottle(f"{name}_flask_1")
return carrier
# 高粘液瓶载架 - 单个中央位置
def YB_1GaoNianYeBottleCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="1GaoNianYeBottleCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_gao_nian_ye_Bottle(f"{name}_flask_1")
return carrier
# 100ml液体瓶载架 - 单个中央位置
def YB_1Bottle100mlCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="1Bottle100mlCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_ye_100ml_Bottle(f"{name}_flask_1")
return carrier
# 5ml分液瓶板 - 4x2布局8个位置
def YB_6x5ml_DispensingVialCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 15.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
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=4,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6x5ml_DispensingVialCarrier",
)
carrier.num_items_x = 4
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
for i in range(8):
carrier[i] = YB_fen_ye_5ml_Bottle(f"{name}_vial_{ordering[i]}")
return carrier
# 20ml分液瓶板 - 4x2布局8个位置
def YB_6x20ml_DispensingVialCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 70.0
# 瓶位尺寸
bottle_diameter = 20.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
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=4,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6x20ml_DispensingVialCarrier",
)
carrier.num_items_x = 4
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
for i in range(8):
carrier[i] = YB_fen_ye_20ml_Bottle(f"{name}_vial_{ordering[i]}")
return carrier
# 配液瓶(小)板 - 4x2布局8个位置
def YB_6x_SmallSolutionBottleCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 65.0
# 瓶位尺寸
bottle_diameter = 35.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
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=4,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6x_SmallSolutionBottleCarrier",
)
carrier.num_items_x = 4
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
for i in range(8):
carrier[i] = YB_pei_ye_xiao_Bottle(f"{name}_bottle_{ordering[i]}")
return carrier
# 配液瓶(大)板 - 2x2布局4个位置
def YB_4x_LargeSolutionBottleCarrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 95.0
# 瓶位尺寸
bottle_diameter = 55.0
bottle_spacing_x = 60.0 # X方向间距
bottle_spacing_y = 60.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (2 - 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=2,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="4x_LargeSolutionBottleCarrier",
)
carrier.num_items_x = 2
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "B1", "B2"]
for i in range(4):
carrier[i] = YB_pei_ye_da_Bottle(f"{name}_bottle_{ordering[i]}")
return carrier
# 加样头(大)板 - 1x1布局1个位置
def YB_jia_yang_tou_da_1X1_carrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 95.0
# 瓶位尺寸
bottle_diameter = 35.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
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=1,
num_items_y=1,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6x_LargeDispenseHeadCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_jia_yang_tou_da(f"{name}_head_1")
return carrier
def YB_AdapterBlock(name: str) -> BottleCarrier:
"""适配器块 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 30.0
# 适配器尺寸
adapter_diameter = 80.0
# 计算中央位置
center_x = (carrier_size_x - adapter_diameter) / 2
center_y = (carrier_size_y - adapter_diameter) / 2
center_z = 0.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=adapter_diameter,
resource_size_y=adapter_diameter,
name_prefix=name,
),
model="AdapterBlock",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
# 适配器块本身不包含瓶子,只是一个支撑结构
return carrier
def YB_TipBox(name: str) -> BottleCarrier:
"""枪头盒 - 8x12布局96个位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 55.0
# 枪头尺寸
tip_diameter = 10.0
tip_spacing_x = 9.0 # X方向间距
tip_spacing_y = 9.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (12 - 1) * tip_spacing_x - tip_diameter) / 2
start_y = (carrier_size_y - (8 - 1) * tip_spacing_y - tip_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=12,
num_items_y=8,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=tip_spacing_x,
item_dy=tip_spacing_y,
size_x=tip_diameter,
size_y=tip_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="TipBox",
)
carrier.num_items_x = 12
carrier.num_items_y = 8
carrier.num_items_z = 1
# 创建96个枪头
for i in range(96):
row = chr(65 + i // 12) # A-H
col = (i % 12) + 1 # 1-12
carrier[i] = YB_Pipette_Tip(f"{name}_tip_{row}{col}")
return carrier

View File

@@ -0,0 +1,163 @@
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
# 工厂函数
"""加样头(大)"""
def YB_jia_yang_tou_da(
name: str,
diameter: float = 20.0,
height: float = 100.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建粉末瓶"""
return Bottle(
name=name,
diameter=diameter,# 未知
height=height,
max_volume=max_volume,
barcode=barcode,
model="Solid_Stock",
)
"""液1x1"""
def YB_ye_Bottle(
name: str,
diameter: float = 40.0,
height: float = 70.0,
max_volume: float = 50000.0, # 50mL
barcode: str = None,
) -> Bottle:
"""创建液体瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Liquid_Bottle",
)
"""100ml液体"""
def YB_ye_100ml_Bottle(
name: str,
diameter: float = 50.0,
height: float = 90.0,
max_volume: float = 100000.0, # 100mL
barcode: str = None,
) -> Bottle:
"""创建100ml液体瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Liquid_Bottle_100ml",
)
"""高粘液"""
def YB_gao_nian_ye_Bottle(
name: str,
diameter: float = 40.0,
height: float = 70.0,
max_volume: float = 50000.0, # 50mL
barcode: str = None,
) -> Bottle:
"""创建高粘液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="High_Viscosity_Liquid",
)
"""5ml分液瓶"""
def YB_fen_ye_5ml_Bottle(
name: str,
diameter: float = 20.0,
height: float = 50.0,
max_volume: float = 5000.0, # 5mL
barcode: str = None,
) -> Bottle:
"""创建5ml分液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Separation_Bottle_5ml",
)
"""20ml分液瓶"""
def YB_fen_ye_20ml_Bottle(
name: str,
diameter: float = 30.0,
height: float = 65.0,
max_volume: float = 20000.0, # 20mL
barcode: str = None,
) -> Bottle:
"""创建20ml分液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Separation_Bottle_20ml",
)
"""配液瓶(小)"""
def YB_pei_ye_xiao_Bottle(
name: str,
diameter: float = 35.0,
height: float = 60.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建配液瓶(小)"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Mixing_Bottle_Small",
)
"""配液瓶(大)"""
def YB_pei_ye_da_Bottle(
name: str,
diameter: float = 55.0,
height: float = 100.0,
max_volume: float = 150000.0, # 150mL
barcode: str = None,
) -> Bottle:
"""创建配液瓶(大)"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Mixing_Bottle_Large",
)
"""枪头"""
def YB_Pipette_Tip(
name: str,
diameter: float = 10.0,
height: float = 50.0,
max_volume: float = 1000.0, # 1mL
barcode: str = None,
) -> Bottle:
"""创建枪头"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="Pipette_Tip",
)

View File

@@ -1,27 +1,26 @@
from unilabos.resources.warehouse import WareHouse, warehouse_factory
from unilabos.resources.warehouse import WareHouse, YB_warehouse_factory
def bioyond_warehouse_1x4x4(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=4,
num_items_x=1,
num_items_y=4,
num_items_z=1,
num_items_z=4,
dx=10.0,
dy=10.0,
dz=10.0,
item_dx=147.0,
item_dy=106.0,
item_dz=130.0,
item_dx=137.0,
item_dy=96.0,
item_dz=120.0,
category="warehouse",
)
def bioyond_warehouse_1x4x2(name: str) -> WareHouse:
"""创建BioYond 4x1x2仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=1,
num_items_y=4,
@@ -38,22 +37,39 @@ def bioyond_warehouse_1x4x2(name: str) -> WareHouse:
# 定义benyond的堆栈
def bioyond_warehouse_1x2x2(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=1,
num_items_x=2,
num_items_y=2,
num_items_z=2,
num_items_z=1,
dx=10.0,
dy=10.0,
dz=10.0,
item_dx=137.0,
item_dy=96.0,
item_dz=120.0,
category="warehouse",
category="YB_warehouse",
)
def bioyond_warehouse_2x2x1(name: str) -> WareHouse:
"""创建BioYond 2x2x1仓库自动堆栈"""
return YB_warehouse_factory(
name=name,
num_items_x=2,
num_items_y=2,
num_items_z=1,
dx=10.0,
dy=10.0,
dz=10.0,
item_dx=137.0,
item_dy=96.0,
item_dz=120.0,
category="YB_warehouse",
)
def bioyond_warehouse_10x1x1(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=10,
num_items_y=1,
@@ -68,7 +84,7 @@ def bioyond_warehouse_10x1x1(name: str) -> WareHouse:
)
def bioyond_warehouse_1x3x3(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=1,
num_items_y=3,
@@ -83,7 +99,7 @@ def bioyond_warehouse_1x3x3(name: str) -> WareHouse:
)
def bioyond_warehouse_2x1x3(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=2,
num_items_y=1,
@@ -99,7 +115,7 @@ def bioyond_warehouse_2x1x3(name: str) -> WareHouse:
def bioyond_warehouse_3x3x1(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=3,
num_items_y=3,
@@ -114,7 +130,7 @@ def bioyond_warehouse_3x3x1(name: str) -> WareHouse:
)
def bioyond_warehouse_5x1x1(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=5,
num_items_y=1,
@@ -129,7 +145,7 @@ def bioyond_warehouse_5x1x1(name: str) -> WareHouse:
)
def bioyond_warehouse_3x3x1_2(name: str) -> WareHouse:
"""创建BioYond 4x1x4仓库"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=3,
num_items_y=3,
@@ -145,7 +161,7 @@ def bioyond_warehouse_3x3x1_2(name: str) -> WareHouse:
def bioyond_warehouse_liquid_and_lid_handling(name: str) -> WareHouse:
"""创建BioYond开关盖加液模块台面"""
return warehouse_factory(
return YB_warehouse_factory(
name=name,
num_items_x=2,
num_items_y=5,
@@ -159,3 +175,35 @@ def bioyond_warehouse_liquid_and_lid_handling(name: str) -> WareHouse:
category="warehouse",
removed_positions=None
)
def bioyond_warehouse_3x5x1(name: str) -> WareHouse:
"""创建BioYond 3x5x1仓库手动堆栈"""
return YB_warehouse_factory(
name=name,
num_items_x=3,
num_items_y=5,
num_items_z=1,
dx=10.0,
dy=10.0,
dz=10.0,
item_dx=137.0,
item_dy=96.0,
item_dz=120.0,
category="warehouse",
)
def bioyond_warehouse_20x1x1(name: str) -> WareHouse:
"""创建BioYond 20x1x1仓库粉末加样头堆栈"""
return YB_warehouse_factory(
name=name,
num_items_x=20,
num_items_y=1,
num_items_z=1,
dx=10.0,
dy=10.0,
dz=10.0,
item_dx=137.0,
item_dy=96.0,
item_dz=120.0,
category="warehouse",
)

View File

@@ -1,276 +0,0 @@
from pylabrobot.resources import create_homogeneous_resources, Coordinate, ResourceHolder, create_ordered_items_2d
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
from unilabos.resources.bioyond.bottles import (
BIOYOND_PolymerStation_Solid_Stock,
BIOYOND_PolymerStation_Solid_Vial,
BIOYOND_PolymerStation_Liquid_Vial,
BIOYOND_PolymerStation_Solution_Beaker,
BIOYOND_PolymerStation_Reagent_Bottle
)
# 命名约定:试剂瓶-Bottle烧杯-Beaker烧瓶-Flask小瓶-Vial
def BIOYOND_Electrolyte_6VialCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 30.0
bottle_spacing_x = 42.0 # X方向间距
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
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="BIOYOND_Electrolyte_6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
for i in range(6):
carrier[i] = BIOYOND_PolymerStation_Solid_Vial(f"{name}_vial_{i+1}")
return carrier
def BIOYOND_Electrolyte_1BottleCarrier(name: str) -> BottleCarrier:
"""1瓶载架 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 100.0
# 烧杯尺寸
beaker_diameter = 80.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="BIOYOND_Electrolyte_1BottleCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = BIOYOND_PolymerStation_Solution_Beaker(f"{name}_beaker_1")
return carrier
def BIOYOND_PolymerStation_6StockCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 20.0
bottle_spacing_x = 42.0 # X方向间距
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
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="BIOYOND_PolymerStation_6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
for i in range(6):
carrier[i] = BIOYOND_PolymerStation_Solid_Stock(f"{name}_vial_{ordering[i]}")
return carrier
def BIOYOND_PolymerStation_6VialCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 30.0
bottle_spacing_x = 42.0 # X方向间距
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
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="BIOYOND_PolymerStation_6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
for i in range(3):
carrier[i] = BIOYOND_PolymerStation_Solid_Vial(f"{name}_solidvial_{ordering[i]}")
for i in range(3, 6):
carrier[i] = BIOYOND_PolymerStation_Liquid_Vial(f"{name}_liquidvial_{ordering[i]}")
return carrier
def BIOYOND_PolymerStation_1BottleCarrier(name: str) -> BottleCarrier:
"""1瓶载架 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="BIOYOND_PolymerStation_1BottleCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = BIOYOND_PolymerStation_Reagent_Bottle(f"{name}_flask_1")
return carrier
def BIOYOND_PolymerStation_1FlaskCarrier(name: str) -> BottleCarrier:
"""1瓶载架 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 70.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="BIOYOND_PolymerStation_1FlaskCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = BIOYOND_PolymerStation_Reagent_Bottle(f"{name}_bottle_1")
return carrier

View File

@@ -1,92 +0,0 @@
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
# 工厂函数
def BIOYOND_PolymerStation_Solid_Stock(
name: str,
diameter: float = 20.0,
height: float = 100.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建粉末瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="BIOYOND_PolymerStation_Solid_Stock",
)
def BIOYOND_PolymerStation_Solid_Vial(
name: str,
diameter: float = 25.0,
height: float = 60.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建粉末瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="BIOYOND_PolymerStation_Solid_Vial",
)
def BIOYOND_PolymerStation_Liquid_Vial(
name: str,
diameter: float = 25.0,
height: float = 60.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建滴定液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="BIOYOND_PolymerStation_Liquid_Vial",
)
def BIOYOND_PolymerStation_Solution_Beaker(
name: str,
diameter: float = 60.0,
height: float = 70.0,
max_volume: float = 200000.0, # 200mL
barcode: str = None,
) -> Bottle:
"""创建溶液烧杯"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="BIOYOND_PolymerStation_Solution_Beaker",
)
def BIOYOND_PolymerStation_Reagent_Bottle(
name: str,
diameter: float = 70.0,
height: float = 120.0,
max_volume: float = 500000.0, # 500mL
barcode: str = None,
) -> Bottle:
"""创建试剂瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="BIOYOND_PolymerStation_Reagent_Bottle",
)

View File

@@ -1,7 +1,8 @@
from os import name
from pickle import TRUE
from pylabrobot.resources import Deck, Coordinate, Rotation
from unilabos.resources.bioyond.warehouses import bioyond_warehouse_1x4x4, bioyond_warehouse_1x4x2, bioyond_warehouse_liquid_and_lid_handling, bioyond_warehouse_1x2x2, bioyond_warehouse_1x3x3, bioyond_warehouse_10x1x1, bioyond_warehouse_3x3x1, bioyond_warehouse_3x3x1_2, bioyond_warehouse_5x1x1
from unilabos.resources.bioyond.YB_warehouses import bioyond_warehouse_1x4x4, bioyond_warehouse_1x4x2, bioyond_warehouse_liquid_and_lid_handling, bioyond_warehouse_1x2x2, bioyond_warehouse_1x3x3, bioyond_warehouse_10x1x1, bioyond_warehouse_3x3x1, bioyond_warehouse_3x3x1_2, bioyond_warehouse_5x1x1, bioyond_warehouse_20x1x1, bioyond_warehouse_2x2x1, bioyond_warehouse_3x5x1
class BIOYOND_PolymerReactionStation_Deck(Deck):
@@ -85,40 +86,32 @@ class BIOYOND_YB_Deck(Deck):
def setup(self) -> None:
# 添加仓库
self.warehouses = {
"321窗口": bioyond_warehouse_1x2x2("321窗口"),
"43窗口": bioyond_warehouse_1x2x2("43窗口"),
"手动传递窗": bioyond_warehouse_1x3x3("手动传递窗"),
"手动传递窗": bioyond_warehouse_1x3x3("手动传递窗"),
"加样头堆栈": bioyond_warehouse_10x1x1("加样头堆栈"),
"加样头堆栈右": bioyond_warehouse_10x1x1("加样头堆栈右"),
"15ml配液堆栈左": bioyond_warehouse_3x3x1("15ml配液堆栈左"),
"母液加样右": bioyond_warehouse_3x3x1_2("母液加样右"),
"大瓶母液堆栈左": bioyond_warehouse_5x1x1("大瓶母液堆栈左"),
"大瓶母液堆栈右": bioyond_warehouse_5x1x1("大瓶母液堆栈右"),
"自动堆栈-左": bioyond_warehouse_2x2x1("自动堆栈-左"),
"自动堆栈-右": bioyond_warehouse_2x2x1("自动堆栈-右"),
"手动堆栈-": bioyond_warehouse_3x5x1("手动堆栈-"),
"手动堆栈-": bioyond_warehouse_3x5x1("手动堆栈-"),
"粉末加样头堆栈": bioyond_warehouse_20x1x1("粉末加样头堆栈"),
"配液站内试剂仓库": bioyond_warehouse_3x3x1("配液站内试剂仓库"),
"试剂替换仓库": bioyond_warehouse_10x1x1("试剂替换仓库"),
}
# warehouse 的位置
self.warehouse_locations = {
"321窗口": Coordinate(-150.0, 158.0, 0.0),
"43窗口": Coordinate(4160.0, 158.0, 0.0),
"手动传递窗": Coordinate(-150.0, 877.0, 0.0),
"手动传递窗": Coordinate(4160.0, 877.0, 0.0),
"加样头堆栈": Coordinate(385.0, 1300.0, 0.0),
"加样头堆栈右": Coordinate(2187.0, 1300.0, 0.0),
"15ml配液堆栈左": Coordinate(749.0, 355.0, 0.0),
"母液加样右": Coordinate(2152.0, 333.0, 0.0),
"大瓶母液堆栈左": Coordinate(1164.0, 676.0, 0.0),
"大瓶母液堆栈右": Coordinate(2717.0, 676.0, 0.0),
"自动堆栈-左": Coordinate(-300.0, 158.0, 0.0),
"自动堆栈-右": Coordinate(4160.0, 158.0, 0.0),
"手动堆栈-": Coordinate(-400.0, 877.0, 0.0),
"手动堆栈-": Coordinate(4160.0, 877.0, 0.0),
"粉末加样头堆栈": Coordinate(385.0, 1300.0, 0.0),
"配液站内试剂仓库": Coordinate(1164.0, 676.0, 0.0),
"试剂替换仓库": Coordinate(2717.0, 676.0, 0.0),
}
for warehouse_name, warehouse in self.warehouses.items():
self.assign_child_resource(warehouse, location=self.warehouse_locations[warehouse_name])
def YB_Deck(name: str) -> Deck:
by=BIOYOND_YB_Deck(name=name)
by.setup()
return by
# def YB_Deck(name: str) -> Deck:
# # by=BIOYOND_YB_Deck(name=name)
# # by.setup()
# return None

View File

@@ -625,6 +625,8 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: Dict[st
Returns:
pylabrobot 格式的物料列表
"""
print("1:bioyond_materials:",bioyond_materials)
# print("2:type_mapping:",type_mapping)
plr_materials = []
for material in bioyond_materials:
@@ -635,6 +637,8 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: Dict[st
plr_material: ResourcePLR = initialize_resource(
{"name": material["name"], "class": className}, resource_type=ResourcePLR
)
print("plr_material:",plr_material)
print("code:",material.get("code", ""))
plr_material.code = material.get("code", "") and material.get("barCode", "") or ""
plr_material.unilabos_uuid = str(uuid.uuid4())

View File

@@ -8,7 +8,7 @@ from unilabos.resources.itemized_carrier import ItemizedCarrier, ResourcePLR
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def warehouse_factory(
def YB_warehouse_factory(
name: str,
num_items_x: int = 1,
num_items_y: int = 4,
@@ -44,7 +44,8 @@ def warehouse_factory(
name_prefix=name,
)
len_x, len_y = (num_items_x, num_items_y) if num_items_z == 1 else (num_items_y, num_items_z) if num_items_x == 1 else (num_items_x, num_items_z)
keys = [f"{LETTERS[j]}{i + 1}" for i in range(len_x) for j in range(len_y)]
keys = [f"{LETTERS[len_y-1-j]}{str(i+1).zfill(2)}" for j in range(len_y) for i in range(len_x)]
sites = {i: site for i, site in zip(keys, _sites.values())}
return WareHouse(