(graph)= # 实验室组态图 组态(configuration)图是指在自动化领域中,用来描述和展示控制系统中各个组件之间关系的图形化表示方法。 它是一个系统的框架图,通过图形符号和连接线,将各个组件(如传感器、执行器、控制器等)以及它们之间的关系进行可视化展示。 Uni-Lab 的组态图当前支持 node-link json 和 graphml 格式,其中包含4类重要信息: * 单个设备/物料配置,即图中节点的参数; * 父子关系,如一台工作站包含它的多个子设备、放置着多个物料耗材; * 物理连接关系,如流体管路连接、AGV/机械臂/直线模组转运连接。 * 通信转接关系,如多个 IO 设备通过 IO 板卡或 PLC 转为 Modbus;串口转网口等 * 控制逻辑关系,如某个输出量被某个输入量 PID 控制 ## 父子关系、物质流与"编译"操作 在计算机操作系统下,软件操作数据和文件。在实验操作系统下,实验“软件”利用仪器“硬件”操作物质。实验人员能理解的操作,最终都是对物质的处理。将实验步骤,转化为硬件指令,这个操作我们可以类比为“编译”。 对用户来说,“直接操作设备执行单个指令”不是个真实需求,真正的需求是**“执行对实验有意义的单个完整动作”——加入某种液体多少量;萃取分液;洗涤仪器等等。就像实验步骤文字书写的那样。** 而这些对实验有意义的单个完整动作,**一般需要多个设备的协同**,还依赖于他们的**物理连接关系(管道相连;机械臂可转运)**。 于是 Uni-Lab 实现了抽象的“工作站”,即注册表中的 `workstation` 设备(`WorkstationNode`类)来处理编译、规划操作。以泵骨架组成的自动有机实验室为例,设备管道连接关系如下: ![topology](image/02-topology-and-chemputer-compile/topology.png) 接收“移液”动作,编译为一系列泵指令和阀指令 ```text Goal received: { 'from_vessel': 'flask_acetone', 'to_vessel': 'reactor', 'volume': 2000.0, 'flowrate': 100.0 }, running steps: ``` ```JSON [ { "device_id": "pump_reagents", "action_name": "set_valve_position", "action_kwargs": {"command": "3"} }, { "device_id": "pump_reagents", "action_name": "set_position", "action_kwargs": { "position": 2000.0, "max_velocity": 100.0 } }, { "device_id": "pump_reagents", "action_name": "set_valve_position", "action_kwargs": {"command": '5'} }, { "device_id": "pump_reagents", "action_name": "set_position", "action_kwargs": { "position": 0.0, "max_velocity": 100.0 } } ] ``` 若想开发新的“编译”/“规划”功能,在 `unilabos/compilers` 实现一个新函数即可。详情请见 [添加新实验操作(Protocol)](../developer_guide/add_protocol.md) ## 通信转接关系 Uni-Lab 秉持着**通信逻辑**与**业务逻辑**分离的设计理念,以追求实验设备、通信设备最大的代码复用性。 如对 IO 板卡8路 IO 控制的8个电磁阀,经过设备抽象层后,仅有逻辑意义上分立的8个电磁阀。在组态图中,他们通过代表通信关系的边(edge)与 IO 板卡设备相连,边的属性包含 IO 地址。 在实际使用中,对抽象的电磁阀发送开关动作请求,将通过 Uni-Lab 设备抽象&通信中间件转化为对 IO 板卡发送 IO 读写指令。因此一定意义上,组态图的通信转接部分代表了简化的电气接线图。 代码架构上,实验设备位于 Uni-Lab 仓库/注册表的 `devices` 目录,通信设备位于 Uni-Lab 仓库/注册表的 `device_comms` 目录。 ![configuration](image/01-communication-instruction/configuration.png)