mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 13:01:12 +00:00
电池装配工站二次开发教程(带目录)上传至dev (#94)
* 电池装配工站二次开发教程 * Update intro.md * 物料教程 * 更新物料教程,json格式注释
This commit is contained in:
147
docs/developer_guide/add_batteryPLC.md
Normal file
147
docs/developer_guide/add_batteryPLC.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# 电池装配工站接入(PLC)
|
||||
|
||||
本指南将引导你完成电池装配工站(以 PLC 控制为例)的接入流程,包括新建工站文件、编写驱动与寄存器读写、生成注册表、上传及注意事项。
|
||||
|
||||
## 1. 新建工站文件
|
||||
|
||||
### 1.1 创建工站文件
|
||||
|
||||
在 `unilabos/devices/workstation/coin_cell_assembly` 目录下新建工站文件,如 `coin_cell_assembly.py`。工站类需继承 `WorkstationBase`,并在构造函数中初始化通信客户端与寄存器映射。
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
# 工站基类
|
||||
from unilabos.devices.workstation.workstation_base import WorkstationBase
|
||||
# Modbus 通讯与寄存器 CSV 支持
|
||||
from unilabos.device_comms.modbus_plc.client import TCPClient, BaseClient
|
||||
|
||||
class CoinCellAssemblyWorkstation(WorkstationBase):
|
||||
def __init__(
|
||||
self,
|
||||
station_resource,
|
||||
address: str = "192.168.1.20",
|
||||
port: str = "502",
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(station_resource=station_resource, *args, **kwargs)
|
||||
self.station_resource = station_resource # 物料台面(Deck)
|
||||
self.success: bool = False
|
||||
self.allow_data_read: bool = False
|
||||
self.csv_export_thread = None
|
||||
self.csv_export_running = False
|
||||
self.csv_export_file: Optional[str] = None
|
||||
|
||||
# 连接 PLC,并注册寄存器节点
|
||||
tcp = TCPClient(addr=address, port=port)
|
||||
tcp.client.connect()
|
||||
self.nodes = BaseClient.load_csv(".../PLC_register.csv")
|
||||
self.client = tcp.register_node_list(self.nodes)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 2. 编写驱动与寄存器读写
|
||||
|
||||
### 2.1 寄存器示例
|
||||
|
||||
- `COIL_SYS_START_CMD`(BOOL,地址 8010):启动命令(脉冲式)
|
||||
- `COIL_SYS_START_STATUS`(BOOL,地址 8210):启动状态
|
||||
- `REG_DATA_OPEN_CIRCUIT_VOLTAGE`(FLOAT32,地址 10002):开路电压
|
||||
- `REG_DATA_ASSEMBLY_PRESSURE`(INT16,地址 10014):压制扣电压力
|
||||
|
||||
### 2.2 最小驱动示例
|
||||
|
||||
```python
|
||||
from unilabos.device_comms.modbus_plc.modbus import WorderOrder
|
||||
|
||||
def start_and_read_metrics(self):
|
||||
# 1) 下发启动(置 True 再复位 False)
|
||||
self.client.use_node('COIL_SYS_START_CMD').write(True)
|
||||
self.client.use_node('COIL_SYS_START_CMD').write(False)
|
||||
|
||||
# 2) 等待进入启动状态
|
||||
while True:
|
||||
status, _ = self.client.use_node('COIL_SYS_START_STATUS').read(1)
|
||||
if bool(status[0]):
|
||||
break
|
||||
|
||||
# 3) 读取关键数据(FLOAT32 需读 2 个寄存器并指定字节序)
|
||||
voltage, _ = self.client.use_node('REG_DATA_OPEN_CIRCUIT_VOLTAGE').read(
|
||||
2, word_order=WorderOrder.LITTLE
|
||||
)
|
||||
pressure, _ = self.client.use_node('REG_DATA_ASSEMBLY_PRESSURE').read(1)
|
||||
|
||||
return {
|
||||
'open_circuit_voltage': voltage,
|
||||
'assembly_pressure': pressure,
|
||||
}
|
||||
```
|
||||
|
||||
> 提示:若需参数下发,可在 PLC 端设置标志寄存器并完成握手复位,避免粘连与竞争。
|
||||
|
||||
## 3. 本地生成注册表并校验
|
||||
|
||||
完成工站类与驱动后,需要生成(或更新)工站注册表供系统识别。
|
||||
|
||||
|
||||
### 3.1 新增工站设备(或资源)首次生成注册表
|
||||
首先通过以下命令启动unilab。进入unilab系统状态检查页面
|
||||
|
||||
```bash
|
||||
python unilabos\app\main.py -g celljson.json --ak <user的AK> --sk <user的SK>
|
||||
```
|
||||
|
||||
点击注册表编辑,进入注册表编辑页面
|
||||

|
||||
|
||||
按照图示步骤填写自动生成注册表信息:
|
||||

|
||||
|
||||
步骤说明:
|
||||
1. 选择新增的工站`coin_cell_assembly.py`文件
|
||||
2. 点击分析按钮,分析`coin_cell_assembly.py`文件
|
||||
3. 选择`coin_cell_assembly.py`文件中继承`WorkstationBase`类
|
||||
4. 填写新增的工站.py文件与`unilabos`目录的距离。例如,新增的工站文件`coin_cell_assembly.py`路径为`unilabos\devices\workstation\coin_cell_assembly\coin_cell_assembly.py`,则此处填写`unilabos.devices.workstation.coin_cell_assembly`。
|
||||
5. 此处填写新定义工站的类的名字(名称可以自拟)
|
||||
6. 填写新的工站注册表备注信息
|
||||
7. 生成注册表
|
||||
|
||||
以上操作步骤完成,则会生成的新的注册表ymal文件,如下图:
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 3.2 添加新生成注册表
|
||||
在`unilabos\registry\devices`目录下新建一个yaml文件,此处新建文件命名为`coincellassemblyworkstation_device.yaml`,将上面生成的新的注册表信息粘贴到`coincellassemblyworkstation_device.yaml`文件中。
|
||||
|
||||
在终端输入以下命令进行注册表补全操作。
|
||||
```bash
|
||||
python unilabos\app\register.py --complete_registry
|
||||
```
|
||||
|
||||
|
||||
### 3.3 启动并上传注册表
|
||||
|
||||
新增设备之后,启动unilab需要增加`--upload_registry`参数,来上传注册表信息。
|
||||
|
||||
```bash
|
||||
python unilabos\app\main.py -g celljson.json --ak <user的AK> --sk <user的SK> --upload_registry
|
||||
```
|
||||
|
||||
## 4. 注意事项
|
||||
|
||||
- 在新生成的 YAML 中,确认 `module` 指向新工站类,本例中需检查`coincellassemblyworkstation_device.yaml`文件中是否指向了`coin_cell_assembly.py`文件中定义的`CoinCellAssemblyWorkstation`类文件:
|
||||
|
||||
```
|
||||
module: unilabos.devices.workstation.coin_cell_assembly.coin_cell_assembly:CoinCellAssemblyWorkstation
|
||||
```
|
||||
|
||||
- 首次新增设备(或资源)需要在网页端新增注册表信息,`--complete_registry`补全注册表,`--upload_registry`上传注册表信息。
|
||||
|
||||
- 如果不是新增设备(或资源),仅对工站驱动的.py文件进行了修改,则不需要在网页端新增注册表信息。只需要运行补全注册表信息之后,上传注册表即可。
|
||||
|
||||
|
||||
BIN
docs/developer_guide/image_add_batteryPLC/unilab_new_yaml.png
Normal file
BIN
docs/developer_guide/image_add_batteryPLC/unilab_new_yaml.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 428 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 310 KiB |
BIN
docs/developer_guide/image_add_batteryPLC/unilab_sys_status.png
Normal file
BIN
docs/developer_guide/image_add_batteryPLC/unilab_sys_status.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
409
docs/developer_guide/materials_tutorial.md
Normal file
409
docs/developer_guide/materials_tutorial.md
Normal file
@@ -0,0 +1,409 @@
|
||||
# 物料教程(Resource)
|
||||
|
||||
本教程面向 Uni-Lab-OS 的开发者,讲解“物料”的核心概念、3种物料格式(UniLab、PyLabRobot、奔耀Bioyond)及其相互转换方法,并说明4种 children 结构表现形式及使用场景。
|
||||
|
||||
---
|
||||
|
||||
## 1. 物料是什么
|
||||
|
||||
- **物料(Resource)**:指实验工作站中的实体对象,包括设备(device)、操作甲板 (deck)、试剂、实验耗材,也包括设备上承载的具体物料或者包含的容器(如container/plate/well/瓶/孔/片等)。
|
||||
- **物料基本信息**(以 UniLab list格式为例):
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "plate", // 某一类物料的唯一名称
|
||||
"name": "50ml瓶装试剂托盘", // 在云端显示的名称
|
||||
"sample_id": null, // 同类物料的不同样品
|
||||
"children": [
|
||||
"50ml试剂瓶" // 表示托盘上有一个 50ml 试剂瓶
|
||||
],
|
||||
"parent": "deck", // 此物料放置在 deck 上
|
||||
"type": "plate", // 物料类型
|
||||
"class": "plate", // 物料对应的注册/类名
|
||||
"position": {
|
||||
"x": 0, // 初始放置位置
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"config": { // 固有配置(尺寸、旋转等)
|
||||
"size_x": 400.0,
|
||||
"size_y": 400.0,
|
||||
"size_z": 400.0,
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"type": "Rotation"
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"bottle_number": 1 // 动态数据(可变化)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 3种物料格式概览(UniLab、PyLabRobot、奔耀Bioyond)
|
||||
|
||||
### 2.1 UniLab 物料格式(云端/项目内通用)
|
||||
|
||||
- 结构特征:顶层通常是 `nodes` 列表;每个节点是扁平字典,`children` 是子节点 `id` 列表;`parent` 为父节点 `id` 或 `null`。
|
||||
- 用途:
|
||||
- 云端数据存储、前端可视化、与图结构算法互操作
|
||||
- 在上传/下载/部署配置时作为标准交换格式
|
||||
|
||||
示例片段(UniLab 物料格式):
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"nodes": [
|
||||
|
||||
{
|
||||
"id": "a",
|
||||
"name": "name_a",
|
||||
"sample_id": 1,
|
||||
"type": "deck",
|
||||
"class": "deck",
|
||||
"parent": null,
|
||||
"children": ["b1"],
|
||||
"position": {"x": 0, "y": 0, "z": 0},
|
||||
"config": {},
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
|
||||
"id": "b1",
|
||||
"name": "name_b1",
|
||||
"sample_id": 1,
|
||||
"type": "plate",
|
||||
"class": "plate",
|
||||
"parent": "a1",
|
||||
"children": [],
|
||||
"position": {"x": 0, "y": 0, "z": 0},
|
||||
"config": {},
|
||||
"data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 PyLabRobot(PLR)物料格式(实验流程运行时)
|
||||
|
||||
- 结构特征:严格的层级树,`children` 为“子资源字典列表”(每个子节点本身是完整对象)。
|
||||
- 用途:
|
||||
- 实验流程执行与调度,PLR 运行时期望的资源对象格式
|
||||
- 通过 `Resource.deserialize/serialize`、`load_all_state/serialize_all_state` 与对象交互
|
||||
|
||||
示例片段(PRL 物料格式)::
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "deck",
|
||||
"type": "Deck",
|
||||
"category": "deck",
|
||||
"location": {"x": 0, "y": 0, "z": 0, "type": "Coordinate"},
|
||||
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
||||
"parent_name": null,
|
||||
"children": [
|
||||
{
|
||||
"name": "plate_1",
|
||||
"type": "Plate",
|
||||
"category": "plate_96",
|
||||
"location": {"x": 100, "y": 0, "z": 0, "type": "Coordinate"},
|
||||
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
||||
"parent_name": "deck",
|
||||
"children": [
|
||||
{
|
||||
"name": "A1",
|
||||
"type": "Well",
|
||||
"category": "well",
|
||||
"location": {"x": 0, "y": 0, "z": 0, "type": "Coordinate"},
|
||||
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
||||
"parent_name": "plate_1",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 2.3 奔耀 Bioyond 物料格式(第三方来源)
|
||||
一般是厂商自己定义的json格式和字段,信息需要提取和对应。以下为示例说明。
|
||||
|
||||
- 结构特征:顶层 `data` 列表,每项包含 `typeName`、`code`、`barCode`、`name`、`quantity`、`unit`、`locations`(仓位 `whName`、`x/y/z`)、`detail`(细粒度内容,如瓶内液体或孔位物料)。
|
||||
- 用途:
|
||||
- 第三方 WMS/设备的物料清单输入
|
||||
- 需要自定义映射表将 `typeName` → PLR 类名,对 `locations`/`detail` 进行落位/赋值
|
||||
|
||||
示例片段(奔耀Bioyond 物料格式):
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "3a1b5c10-d4f3-01ac-1e64-5b4be2add4b1",
|
||||
"typeName": "液",
|
||||
"code": "0006-00014",
|
||||
"barCode": "",
|
||||
"name": "EMC",
|
||||
"quantity": 50,
|
||||
"lockQuantity": 2.057,
|
||||
"unit": "瓶",
|
||||
"status": 1,
|
||||
"isUse": false,
|
||||
"locations": [
|
||||
{
|
||||
"id": "3a19da43-57b5-5e75-552f-8dbd0ad1075f",
|
||||
"whid": "3a19da43-57b4-a2a8-3f52-91dbbeb836db",
|
||||
"whName": "配液站内试剂仓库",
|
||||
"code": "0003-0003",
|
||||
"x": 1,
|
||||
"y": 3,
|
||||
"z": 1,
|
||||
"quantity": 0
|
||||
}
|
||||
],
|
||||
"detail": [
|
||||
{
|
||||
"code": "0006-00014-01",
|
||||
"name": "EMC-瓶-1",
|
||||
"x": 1,
|
||||
"y": 3,
|
||||
"z": 1,
|
||||
"quantity": 500.0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"code": 1,
|
||||
"message": "",
|
||||
"timestamp": 0
|
||||
}
|
||||
```
|
||||
### 2.4 3种物料格式关键字段对应(UniLab、PyLabRobot、奔耀Bioyond)
|
||||
|
||||
| 含义 | UniLab | PyLabRobot (PLR) | 奔耀 Bioyond |
|
||||
| - | - | - | - |
|
||||
| 节点唯一名 | `id` | `name` | `name` |
|
||||
| 父节点引用 | `parent` | `parent_name` | `locations` 坐标(无直接父名,需映射坐标下的物料) |
|
||||
| 子节点集合 | `children`(id 列表或对象列表,视结构而定) | `children`(对象列表) | `detail`(明细,非严格树结构,需要自定义映射) |
|
||||
| 类型(抽象类别) | `type`(device/container/plate/deck/…) | `category`(plate/well/…),以及类名 `type` | `typeName`(厂商自定义,如“液”、“加样头(大)”) |
|
||||
| 运行/业务数据 | `data` | 通过 `serialize_all_state()`/`load_all_state()` 管理的状态 | `quantity`、`lockQuantity` 等业务数值 |
|
||||
| 固有配置 | `config`(size_x/size_y/size_z/model/ordering…) | 资源字典中的同名键(反序列化时按构造签名取用) | 厂商自定义字段(需映射入 PLR/UniLab 的 `config` 或 `data`) |
|
||||
| 空间位置 | `position`(x/y/z) | `location`(Coordinate) + `rotation`(Rotation) | `locations`(whName、x/y/z),不含旋转 |
|
||||
| 条码/标识 | `config.barcode`(可选) | 常放在配置键中(如 `barcode`) | `barCode` |
|
||||
| 数量单位 | 无固定键,通常在 `data` | 无固定键,通常在配置或状态中 | `unit` |
|
||||
| 物料编码 | 通常在 `config` 或 `data` 自定义 | 通常在配置中自定义 | `code` |
|
||||
|
||||
说明:
|
||||
- Bioyond 不提供显式的树形父子关系,通常通过 `locations` 将物料落位到某仓位/坐标。用 `detail` 表示子级明细。
|
||||
|
||||
---
|
||||
|
||||
## 3. children 的四种结构表示
|
||||
|
||||
- **list(扁平列表)**:每个节点是扁平字典,`children` 为子节点 `id` 数组。示例:UniLab `nodes` 中的单个节点。
|
||||
|
||||
```json
|
||||
{
|
||||
"nodes": [
|
||||
{ "id": "root", "parent": null, "children": ["child1"] },
|
||||
{ "id": "child1", "parent": "root", "children": [] }
|
||||
]
|
||||
}
|
||||
```
|
||||
- **dict(嵌套字典)**:节点的 `children` 是 `{ child_id: child_node_dict }` 字典。
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "root",
|
||||
"parent": null,
|
||||
"children": {
|
||||
"child1": { "id": "child1", "parent": "root", "children": {} }
|
||||
}
|
||||
}
|
||||
```
|
||||
- **tree(树形列表)**:顶层是 `[root_node, ...]`,每个 `node.children` 是“子节点对象列表”(而非 id 列表)。
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "root",
|
||||
"parent": null,
|
||||
"children": [
|
||||
{ "id": "child1", "parent": "root", "children": [] }
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
- **nestdict(顶层嵌套字典)**:顶层是 `{root_id: root_node, ...}`,或者根节点自身带 `children: {id: node}` 形态。
|
||||
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"id": "root",
|
||||
"parent": null,
|
||||
"children": {
|
||||
"child1": { "id": "child1", "parent": "root", "children": {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这些结构之间可使用 `graphio.py` 中的工具函数互转(见下一节)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 转换函数及调用
|
||||
|
||||
核心代码文件:`unilabos/resources/graphio.py`
|
||||
|
||||
### 4.1 结构互转(list/dict/tree/nestdict)
|
||||
|
||||
代码引用:
|
||||
|
||||
```217:239:unilabos/resources/graphio.py
|
||||
def dict_to_tree(nodes: dict, devices_only: bool = False) -> list[dict]:
|
||||
# ... 由扁平 dict(id->node)生成树(children 为对象列表)
|
||||
```
|
||||
|
||||
```241:267:unilabos/resources/graphio.py
|
||||
def dict_to_nested_dict(nodes: dict, devices_only: bool = False) -> dict:
|
||||
# ... 由扁平 dict 生成嵌套字典(children 为 {id:node})
|
||||
```
|
||||
|
||||
```270:273:unilabos/resources/graphio.py
|
||||
def list_to_nested_dict(nodes: list[dict]) -> dict:
|
||||
# ... 由扁平列表(children 为 id 列表)转嵌套字典
|
||||
```
|
||||
|
||||
```275:286:unilabos/resources/graphio.py
|
||||
def tree_to_list(tree: list[dict]) -> list[dict]:
|
||||
# ... 由树形列表转回扁平列表(children 还原为 id 列表)
|
||||
```
|
||||
|
||||
```289:337:unilabos/resources/graphio.py
|
||||
def nested_dict_to_list(nested_dict: dict) -> list[dict]:
|
||||
# ... 由嵌套字典转回扁平列表
|
||||
```
|
||||
|
||||
常见路径:
|
||||
|
||||
- UniLab 扁平列表 → 树:`dict_to_tree({r["id"]: r for r in resources})`
|
||||
- 树 → UniLab 扁平列表:`tree_to_list(resources_tree)`
|
||||
- 扁平列表 ↔ 嵌套字典:`list_to_nested_dict` / `nested_dict_to_list`
|
||||
|
||||
### 4.2 UniLab ↔ PyLabRobot(PLR)
|
||||
|
||||
高层封装:
|
||||
|
||||
```339:368:unilabos/resources/graphio.py
|
||||
def convert_resources_to_type(resources_list: list[dict], resource_type: Union[type, list[type]], *, plr_model: bool = False):
|
||||
# UniLab -> (NestedDict or PLR)
|
||||
```
|
||||
|
||||
```371:395:unilabos/resources/graphio.py
|
||||
def convert_resources_from_type(resources_list, resource_type: Union[type, list[type]], *, is_plr: bool = False):
|
||||
# (NestedDict or PLR) -> UniLab 扁平列表
|
||||
```
|
||||
|
||||
底层转换:
|
||||
|
||||
```398:441:unilabos/resources/graphio.py
|
||||
def resource_ulab_to_plr(resource: dict, plr_model=False) -> "ResourcePLR":
|
||||
# UniLab 单节点(树根) -> PLR Resource 对象
|
||||
```
|
||||
|
||||
```443:481:unilabos/resources/graphio.py
|
||||
def resource_plr_to_ulab(resource_plr: "ResourcePLR", parent_name: str = None, with_children=True):
|
||||
# PLR Resource -> UniLab 单节点(dict)
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
from unilabos.resources.graphio import convert_resources_to_type, convert_resources_from_type
|
||||
from pylabrobot.resources.resource import Resource as ResourcePLR
|
||||
|
||||
# UniLab 扁平列表 -> PLR 根资源对象
|
||||
plr_root = convert_resources_to_type(resources_list=ulab_list, resource_type=ResourcePLR)
|
||||
|
||||
# PLR 资源对象 -> UniLab 扁平列表(用于保存/上传)
|
||||
ulab_flat = convert_resources_from_type(resources_list=plr_root, resource_type=ResourcePLR)
|
||||
```
|
||||
|
||||
可选项:
|
||||
|
||||
- `plr_model=True`:保留 `model` 字段(默认会移除)。
|
||||
- `with_children=False`:`resource_plr_to_ulab` 仅转换当前节点。
|
||||
|
||||
### 4.3 奔耀(Bioyond)→ PLR(及进一步到 UniLab)
|
||||
|
||||
转换入口:
|
||||
|
||||
```483:527:unilabos/resources/graphio.py
|
||||
def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict = {}, deck: Any = None) -> list[dict]:
|
||||
# Bioyond 列表 -> PLR 资源列表,并可根据 deck.warehouses 将资源落位
|
||||
```
|
||||
|
||||
使用示例:
|
||||
|
||||
```python
|
||||
import json
|
||||
from unilabos.resources.graphio import resource_bioyond_to_plr, convert_resources_from_type
|
||||
from pylabrobot.resources.resource import Resource as ResourcePLR
|
||||
|
||||
resp = json.load(open("unilabos/devices/workstation/bioyond_cell/bioyond_test_yibin.json", encoding="utf-8"))
|
||||
materials = resp["data"]
|
||||
|
||||
# 将第三方类型name映射到 PLR 资源类名(需根据现场定义)
|
||||
type_mapping = {
|
||||
"液": "RegularContainer",
|
||||
"加样头(大)": "RegularContainer"
|
||||
}
|
||||
|
||||
plr_list = resource_bioyond_to_plr(materials, type_mapping=type_mapping, deck=None)
|
||||
|
||||
# 如需上传云端(UniLab 扁平格式):
|
||||
ulab_flat = convert_resources_from_type(plr_list, [ResourcePLR])
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `type_mapping` 必须由开发者根据设备/物料种类人工维护。
|
||||
- 如传入 `deck`,且 `deck.warehouses` 命名与 `whName` 对应,可将物料安放到仓库坐标(x/y/z)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 何时使用哪种格式
|
||||
|
||||
- **云端/持久化**:使用 UniLab 物料格式(扁平 `nodes` 列表,children 为 id 列表)。便于版本化、可视化与网络传输。
|
||||
- **实验工作流执行**:使用 PyLabRobot(PLR)格式。PLR 运行时依赖严格的树形资源结构与对象 API。
|
||||
- **第三方设备/系统(Bioyond)输入**:保持来源格式不变,使用 `resource_bioyond_to_plr` + 人工 `type_mapping` 将其转换为 PLR(必要时再转 UniLab)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 常见问题与注意事项
|
||||
|
||||
- **children 形态不一致**:不同函数期望不同 children 形态,注意在进入转换前先用“结构互转”工具函数标准化形态。
|
||||
- **devices_only**:`dict_to_tree/dict_to_nested_dict` 支持仅保留 `type == device` 的节点。
|
||||
- **模型/类型字段**:PLR 对象序列化参数有所差异,`resource_ulab_to_plr` 内部会根据构造签名移除不兼容字段(如 `category`)。
|
||||
- **驱动初始化**:`initialize_resource(s)` 支持从注册表/类路径创建 PLR/UniLab 资源或列表。
|
||||
|
||||
参考代码:
|
||||
|
||||
```530:577:unilabos/resources/graphio.py
|
||||
def initialize_resource(resource_config: dict, resource_type: Any = None) -> Union[list[dict], ResourcePLR]:
|
||||
# 从注册类/模块反射创建资源,或将 UniLab 字典包装为列表
|
||||
```
|
||||
|
||||
```580:597:unilabos/resources/graphio.py
|
||||
def initialize_resources(resources_config) -> list[dict]:
|
||||
# 批量初始化
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user