工业流程引擎架构
节点业务层(FlowNode)
核心作用:封装具体的工业工序逻辑,实现业务与调度层的解耦,支持灵活拓展。
核心组件:各类工业节点(如:设备启停节点、IO读写节点、延时等待节点、条件判断节点、循环工序节点、报警提示节点、数据保存节点等)。
实现机制:每个节点继承统一接口,绑定对应的硬件抽象层(HAL)接口或业务服务,节点执行时调用底层硬件或业务逻辑。
-
解构用户请求:
-
主题:工业流程引擎架构——第四部分:节点业务层(FlowNode)。
-
核心功能:封装具体的工业工序逻辑,实现业务与调度层的解耦,支持灵活扩展。
-
核心组件:各类工业节点(设备启停、IO读写、延时等待、条件判断、循环工序、报警提示、数据保存等)。
-
实现机制:每个节点继承统一接口,绑定硬件抽象层(HAL)或业务服务,执行时调用底层硬件或业务逻辑。
-
要求:
-
完整的设计方案(系统框图、软件流程图)。
-
用通俗易懂的实例进行详细、深入、准确的解释。
-
UML建模(类图、时序图等)。
-
完整的项目文件结构。
-
-
-
领域与背景分析:
-
这是关于工业流程引擎的“插件层”或“策略层”。
-
之前的部分:流程模型(数据)、画布渲染(UI)、流程运行器(编排/状态机)。
-
当前部分:实际的工作单元(做具体工作的事物)。该层必须高度可扩展,以便工程师可以添加新的设备类型或业务逻辑,而无需更改核心调度引擎。
-
关键概念:策略模式、工厂模式、依赖注入(HAL/服务)、命令模式、模板方法模式。
-
-
起草内容结构:
-
标题与定位:核心哲学,将其比作“工具箱”或“乐高积木”。
-
总体架构(系统框图):展示FlowNode如何适配FlowRunner、HAL和业务服务。
-
核心组件(节点类型):根据列表(设备、IO、定时、条件、循环、警报、数据)进行详细阐述。
-
实现机制(设计模式):统一接口(
INodeExecutor)、模板方法、工厂模式、HAL绑定。 -
软件流程图:节点执行的生命周期(初始化 -> 输入验证 -> 硬件调用 -> 输出处理 -> 完成)。
-
UML建模:类图展示
NodeExecutor接口、抽象基类、具体节点(DeviceStartNode、DelayNode等)和HAL接口。展示“执行节点”的时序图。 -
通俗实例:芯片封装产线中的“加热节点”或“IO读取节点”。
-
项目文件结构:
executor/、hal/、factory/。 -
开发机制与步骤:如何添加新节点(扩展机制)。
-
-
起草过程中的自我修正/细化:
-
注意:提到了“硬件抽象层(HAL)”。确保HAL被清晰地建模为接口,而FlowNode实现依赖于这些接口(依赖倒置)。
-
节点类型:按类别(设备控制、流程控制、数据处理)对它们进行分组,使其结构更清晰。
-
执行逻辑:调度层(FlowRunner)调用
NodeExecutor.execute(context)。节点决定如何运行(同步/异步),但FlowRunner处理超时/重试。实际上,节点内部逻辑可以是同步的,而FlowRunner处理包装器。澄清这一点:节点包含业务逻辑,它可能调用异步HAL调用,但它必须将控制权返回给FlowRunner。
-
-
编写Mermaid图表:
-
系统框图:层级结构 FlowRunner -> NodeFactory -> NodeExecutors -> HAL/Service层。
-
软件流程图:
execute方法内部的详细流程:解析输入 -> 调用HAL -> 处理结果 -> 设置输出变量。 -
UML类图:接口
INodeExecutor,抽象类BaseNodeExecutor(含模板方法doExecute),具体类HeaterNode、DelayNode、AlarmNode,HAL接口IDeviceService。 -
UML时序图:
FlowRunner->HeaterNode->PLCConnector-> 返回。
-
-
打磨细节(通俗实例):
-
使用“加热节点”示例。输入:
targetTemp,deviceId。输出:actualTemp。逻辑:调用halService.writeRegister(deviceId, targetTemp),然后循环读取直到达到温度。或异步启动。 -
解释“循环工序节点”如何在内部使用
while循环,但在引擎的DAG中仅将其视为单个节点。
-
-
对照要求检查:
-
FlowNode的完整设计方案?是的。
-
系统框图 + 软件流程图?是的。
-
通俗易懂的实例?是的(芯片封装/加热)。
-
UML(类图、时序图)?是的。
-
Markdown + Mermaid?是的。
-
项目文件结构?是的。
-
深入机制/方法/步骤?是的。
-
-
生成最终输出(将详细内容组织成连贯的叙述)。确保代码块具有正确的mermaid语法。结构保持清晰干净。
工业流程引擎架构 —— 节点业务层(FlowNode)深度设计方案
一、定位与核心哲学
在整体分层架构中,节点业务层(FlowNode) 是工业流程引擎的 “可更换的机械臂/工具箱”。它封装了所有的“动作”和“判断”,是调度层(大脑)与硬件层(肌肉)之间的“神经末梢”。
通俗类比:如果把整个引擎比作一家自动化餐厅:
- 画布层 = 厨师面前的平板电脑(显示菜谱流程)。
- 调度层 = 餐厅的中央调度系统(决定先做哪道菜)。
- 节点业务层(FlowNode) = 厨师手中的不同厨具(炒锅、蒸笼、烤箱、计时器)。
- 调度系统说:“开始炒菜”,炒锅(节点)负责具体翻动。
- 调度系统说:“蒸米饭”,蒸笼(节点)负责控制蒸汽。
- 每一种厨具(节点)都遵循统一的接口(有把手、能加热/操作),但内部实现完全不同。当餐厅需要做新菜时(扩展新工艺),只需添置一个新厨具(新节点类),完全不用改造调度系统。
核心设计目标:
- 开闭原则(OCP):对扩展开放(新增节点类型),对修改关闭(不碰调度层和画布层)。
- 单一职责:每个节点类只负责一种工业工序(如只负责“Modbus写寄存器”)。
- 依赖倒置:节点不直接依赖硬件驱动,而是依赖 硬件抽象层接口(HAL),便于测试和硬件替换。
- 可组合性:节点执行后可产生标准化的输出(变量),供后续节点(如条件网关)消费。
二、总体架构设计(系统框图)
FlowNode层在整体架构中处于 “执行落地” 的位置,上承调度器,下接硬件/中间件。
┌─────────────────────────────────────────────────────────────────────────────┐
│ 流程调度层(FlowRunner) │
│ (调用 NodeExecutorProxy 执行节点) │
└───────────────────────────────┬─────────────────────────────────────────────┘
│ 传递 ExecutionContext + NodeConfig
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 节点业务层门面(NodeExecutorFactory) │
│ 根据节点类型(如 SERVICE_TASK)动态创建执行器 │
└───────────────────────────────┬─────────────────────────────────────────────┘
│
┌───────────────────────────────┼─────────────────────────────────────────────┐
│ 统一节点执行器接口(NodeExecutor) │
│ ┌────────────────────────────┴──────────────────────────────────────────┐ │
│ │ 抽象基类 AbstractNodeExecutor(模板方法模式) │ │
│ │ ├─ validateInputs() → 校验输入参数 │ │
│ │ ├─ doExecute() → 具体业务逻辑(子类实现) │ │
│ │ └─ writeOutputs() → 写入输出变量到上下文 │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────┬────────────┼────────────┬───────────────┐ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────┐ │
│ │设备控制类 │ │ 流程控制 │ │ 数据IO │ │ 逻辑判断 │ │ 通知类 │ │
│ │·设备启停 │ │ ·延时等待 │ │ ·读寄存器│ │ ·条件判断 │ │ ·报警提示│ │
│ │·电机调速 │ │ ·循环工序 │ │ ·写数据库│ │ ·表达式 │ │ ·邮件短信│ │
│ │·加热控制 │ │ ·子流程 │ │ ·文件操作│ │ │ │ │ │
│ └──────┬──────┘ └─────┬────┘ └────┬─────┘ └──────┬─────┘ └────┬─────┘ │
└──────────┼───────────────┼───────────┼───────────────┼────────────┼───────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 硬件抽象层(HAL)& 基础服务层 │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────────────────┐ │
│ │ PLC连接器 │ │ 传感器驱动 │ │ 数据库DAO │ │ 消息中间件(MQTT) │ │
│ │ (Modbus) │ │ (OPC UA) │ │ (JDBC) │ │ 邮件/短信网关 │ │
│ └────────────┘ └────────────┘ └────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
三、核心组件与节点类型详解
3.1 统一节点接口设计(模板方法模式)
每个节点执行器都遵循以下标准生命周期:
public interface NodeExecutor {
// 判断是否支持该节点类型
boolean supports(NodeType type);
// 执行入口(由调度层调用)
void execute(ExecutionContext ctx, NodeEntity node) throws NodeExecutionException;
}
// 抽象基类(模板方法模式)
public abstract class AbstractNodeExecutor implements NodeExecutor {
@Override
public final void execute(ExecutionContext ctx, NodeEntity node) {
// 1. 前置校验(必须通过才能继续)
validateInputs(ctx, node);
// 2. 记录开始时间
long startTime = System.currentTimeMillis();
try {
// 3. 核心业务(子类实现)
Object result = doExecute(ctx, node);
// 4. 写入输出变量
writeOutputs(ctx, node, result);
// 5. 记录成功日志
} catch (Exception e) {
// 6. 异常统一处理
handleException(ctx, node, e);
throw new NodeExecutionException(e);
} finally {
// 7. 记录执行耗时(监控埋点)
recordMetrics(ctx, node, System.currentTimeMillis() - startTime);
}
}
// 子类必须实现
protected abstract Object doExecute(ExecutionContext ctx, NodeEntity node);
// 可选重写
protected void validateInputs(...) { /* 默认空实现 */ }
protected void writeOutputs(...) { /* 默认:将result存入变量 resultVar */ }
}
3.2 七大核心工业节点实现(面向实际场景)
(1)设备启停节点(DeviceControlNode)
- 作用:启动或停止一台物理设备(电机、泵、加热器)。
- 配置参数:
deviceId、action(START/STOP)、protocol(Modbus/OPC UA)。 - 执行逻辑:通过HAL层向PLC发送写寄存器指令。
- 输出变量:
deviceStatus(ON/OFF)、executionTime。
(2)IO读写节点(IOReadWriteNode)
- 作用:读取传感器值或向执行器写入模拟量/数字量。
- 配置参数:
registerAddress、dataType(BOOL/INT/FLOAT)、value(写入值)。 - 执行逻辑:
- 读取:
hal.readRegister(deviceId, address)→ 存入变量readValue。 - 写入:
hal.writeRegister(deviceId, address, value)。
- 读取:
- 输出变量:
readValue(读取模式)。
(3)延时等待节点(DelayNode)
- 作用:使流程暂停指定的毫秒/秒/分钟。常用于“等待物料到位”或“等待化学反应”。
- 配置参数:
duration、unit(SECONDS/MILLIS)。 - 执行逻辑:
Thread.sleep(durationMs)或 异步定时回调(工业场景强烈建议异步,避免阻塞调度线程)。 - 输出变量:
waitTime、elapsedSeconds。
(4)条件判断节点(ConditionNode)
- 作用:在节点内部执行复杂逻辑判断(注意:画布层有网关,此节点用于节点内部判定)。
- 配置参数:
expression(如${temperature > 100 && pressure < 5})。 - 执行逻辑:使用
Aviator/SpEL解析表达式。 - 输出变量:
conditionResult(Boolean)。
(5)循环工序节点(LoopNode)
- 作用:对一组设备动作进行批量循环(如“拧紧5颗螺丝”)。将此逻辑封装在单个节点内,避免画布膨胀。
- 配置参数:
loopCount、iteratorVar(循环变量名)、subNodeId(被循环的子流程ID)。 - 执行逻辑:
for (i=0; i<loopCount; i++) { ctx.setVariable(iteratorVar, i); executeSubNode(i); }。 - 输出变量:
loopIndex、loopCompletedCount。
(6)报警提示节点(AlarmNode)
- 作用:当工艺异常时,向监控系统推送报警,并触发声光提示。
- 配置参数:
alarmLevel(INFO/WARN/CRITICAL)、message、recipients(接收人)。 - 执行逻辑:调用
notificationService.sendAlarm(level, msg),同时记录到报警历史库。
(7)数据保存节点(DataSaveNode)
- 作用:将工艺过程中的关键参数(温度、压力、良率)持久化到数据库或时序库(InfluxDB)。
- 配置参数:
tableName、fieldMapping(上下文变量 ↔ 数据库字段)。 - 执行逻辑:
jdbcTemplate.insert(tableName, mappedData)或influxDB.write(point)。 - 输出变量:
savedRecordId、saveTimestamp。
四、软件流程图(节点执行生命周期)
4.1 节点通用执行流程(由抽象基类定义)
4.2 具体节点示例:设备加热节点(HeaterNode)内部逻辑
五、UML建模(详尽)
5.1 节点业务层核心类图(含HAL依赖)
5.2 节点执行时序图(调度层 → 节点 → HAL)
六、通俗实例:芯片封装产线 —— FlowNode实战
6.1 场景节点拆解
我们以“芯片封装主流程”为例,将画布上的每个图形节点对应到具体的FlowNode实现类:
| 画布节点名称 | 节点类型 | 对应的FlowNode类 | 配置参数示例 | 执行动作 |
|---|---|---|---|---|
| 开始 | START_EVENT | (内置) | 无 | 初始化上下文 |
| 加热平台预热 | SERVICE_TASK | HeaterNode | deviceId=heater_01, targetTemp=150, tolerance=2, timeout=60 | 调用HAL启动加热器,闭环控制到150℃ |
| 精密定位 | SERVICE_TASK | IOReadWriteNode | deviceId=aligner_01, register=40010, value=${visionOffset} | 写入偏移量,驱动定位平台 |
| 芯片处理 | SERVICE_TASK | DeviceControlNode | deviceId=handler_01, action=START | 启动处理单元执行封装 |
| 质量检测 | CONDITION(配合网关) | ConditionNode | expression=${qualityScore > 85} | 计算得分,输出布尔值给网关路由 |
| 数据保存 | SERVICE_TASK | DataSaveNode | tableName=production_batch, fields={batchNo, temp, score} | 将关键参数存入生产数据库 |
| 异常报警 | SERVICE_TASK | AlarmNode | level=CRITICAL, message=封装失败 | 推送短信+大屏声光报警 |
| 延时等待 | SERVICE_TASK | DelayNode | duration=10, unit=SECONDS | 等待胶水固化(非阻塞) |
6.2 关键节点代码实现(精简版)
(1) 加热节点(HeaterNode)—— 闭环PID控制模拟
@Component
public class HeaterNode extends AbstractNodeExecutor {
@Autowired private IIOService ioService; // HAL注入
@Override
protected Object doExecute(ExecutionContext ctx, NodeEntity node) {
// 1. 读取配置
String deviceId = node.getConfig().getParam("deviceId").toString();
double targetTemp = (double) node.getConfig().getParam("targetTemp");
double tolerance = (double) node.getConfig().getParam("tolerance", 2.0);
int timeoutSec = (int) node.getConfig().getParam("timeoutSec", 60);
int tempRegister = 40001;
int heaterRegister = 40002;
// 2. 读取当前温度
double currentTemp = (double) ioService.readRegister(deviceId, tempRegister, DataType.FLOAT32);
if (currentTemp >= targetTemp - tolerance) {
return currentTemp; // 已经够热,跳过
}
// 3. 启动加热
ioService.writeRegister(deviceId, heaterRegister, 1);
long startTime = System.currentTimeMillis();
try {
// 4. 闭环等待(轮询检测)
while (true) {
Thread.sleep(5000); // 5秒检测一次
currentTemp = (double) ioService.readRegister(deviceId, tempRegister, DataType.FLOAT32);
if (currentTemp >= targetTemp - tolerance) {
break;
}
long elapsed = (System.currentTimeMillis() - startTime) / 1000;
if (elapsed > timeoutSec) {
throw new TimeoutException("加热超时,当前温度: " + currentTemp);
}
}
} finally {
// 5. 关闭加热器(不管成功还是超时,都要关)
ioService.writeRegister(deviceId, heaterRegister, 0);
}
return currentTemp;
}
@Override
protected void writeOutputs(ExecutionContext ctx, NodeEntity node, Object result) {
ctx.setVariable("actualTemp", result);
ctx.setVariable("heatingDuration", System.currentTimeMillis() - startTime);
}
}
(2) 循环节点(LoopNode)—— 批量拧螺丝
@Component
public class LoopNode extends AbstractNodeExecutor {
@Autowired private NodeExecutorFactory factory;
@Override
protected Object doExecute(ExecutionContext ctx, NodeEntity node) {
int loopCount = (int) node.getConfig().getParam("loopCount");
String subNodeId = node.getConfig().getParam("subNodeId").toString();
String iteratorVar = node.getConfig().getParam("iteratorVar", "index");
List<Integer> results = new ArrayList<>();
for (int i = 1; i <= loopCount; i++) {
ctx.setVariable(iteratorVar, i); // 动态注入循环变量
NodeEntity subNode = ctx.loadSubNode(subNodeId);
NodeExecutor executor = factory.getExecutor(subNode.getNodeType());
executor.execute(ctx, subNode); // 递归执行子节点
results.add(i);
}
return results;
}
}
6.3 节点扩展机制(如何新增一种节点)
假设产线新购了一台 “AOI光学检测仪”,需要新增一个节点。
- 定义节点类型:在
NodeType枚举中增加AOI_INSPECTION。 - 编写节点类:
public class AOIInspectionNode extends AbstractNodeExecutor { @Autowired private IAOIService aoiService; @Override protected Object doExecute(...) { String imagePath = ctx.getVariable("imagePath").toString(); InspectionResult result = aoiService.inspect(imagePath); return result; } } - 注册到工厂:在启动类中调用
factory.register(NodeType.AOI_INSPECTION, new AOIInspectionNode())。 - 画布支持:在前端画布组件库中增加“AOI检测”的拖拽图标(图标关联
NodeType.AOI_INSPECTION)。 - 完成:工程师可在画布上拖拽使用,调度层无需任何改动。
七、项目文件结构(节点业务层专属)
engine-core/src/main/java/com/engine/node/
│
├── api/ # 对外接口
│ ├── NodeExecutor.java # 执行器接口
│ └── NodeType.java # 节点类型枚举
│
├── base/ # 抽象基类与工具
│ ├── AbstractNodeExecutor.java # 模板方法抽象类
│ ├── NodeExecutionException.java # 自定义异常
│ ├── NodeExecutionContextWrapper.java # 上下文包装器
│ └── validation/
│ ├── InputValidator.java # 校验器接口
│ └── DefaultInputValidator.java
│
├── factory/ # 工厂与注册中心
│ ├── NodeExecutorFactory.java
│ ├── NodeExecutorRegistry.java
│ └── DefaultNodeExecutorFactory.java
│
├── hal/ # 硬件抽象层接口(供节点依赖)
│ ├── IDeviceService.java
│ ├── IIOService.java
│ ├── IAlarmService.java
│ ├── IExpressionEvaluator.java
│ ├── IDataPersistenceService.java
│ └── ITimerService.java
│
├── impl/ # 具体节点实现(按功能分类)
│ ├── device/ # 设备控制类
│ │ ├── DeviceControlNode.java
│ │ ├── MotorSpeedNode.java
│ │ └── HeaterNode.java
│ │
│ ├── io/ # IO读写类
│ │ ├── IOReadWriteNode.java
│ │ └── AnalogOutputNode.java
│ │
│ ├── flow/ # 流程控制类
│ │ ├── DelayNode.java
│ │ ├── LoopNode.java
│ │ ├── SubProcessNode.java
│ │ └── WaitForEventNode.java
│ │
│ ├── logic/ # 逻辑判断类
│ │ ├── ConditionNode.java
│ │ ├── ScriptNode.java (支持Groovy脚本)
│ │ └── SwitchCaseNode.java
│ │
│ ├── notify/ # 通知报警类
│ │ ├── AlarmNode.java
│ │ ├── EmailNotificationNode.java
│ │ └── MessageQueueNode.java
│ │
│ └── data/ # 数据持久化类
│ ├── DataSaveNode.java
│ ├── DataQueryNode.java
│ └── FileExportNode.java
│
├── hook/ # 节点钩子(AOP扩展)
│ ├── NodeExecutionHook.java
│ ├── LoggingHook.java # 自动打印日志
│ └── MetricsHook.java # 自动采集指标(耗时/次数)
│
└── support/ # 辅助工具
├── ExpressionEvaluatorFactory.java # 表达式引擎工厂
├── DataTypeMapper.java # 数据类型转换
└── NodeConfigHelper.java # 配置解析辅助
八、开发机理与实施步骤
8.1 节点开发原则(SOLID最佳实践)
| 原则 | 在FlowNode层中的应用 |
|---|---|
| 单一职责(SRP) | 一个节点类只做一件事(如加热节点只管加热,不负责数据保存)。 |
| 开闭原则(OCP) | 新增工艺节点无需修改调度层,只需新增类并注册。 |
| 里氏替换(LSP) | 所有子类都能替换父类(AbstractNodeExecutor),调度层只认接口。 |
| 依赖倒置(DIP) | 节点依赖HAL接口(如 IIOService),而非具体的Modbus驱动实现。 |
| 接口隔离(ISP) | HAL接口拆分为 IDeviceService、IIOService、IAlarmService,而非大而全的万能接口。 |
8.2 节点测试策略(高可靠性保障)
工业节点必须经过严格的单元测试和模拟测试:
| 测试类型 | 工具/方法 | 验证内容 |
|---|---|---|
| 单元测试 | JUnit5 + Mockito | Mock HAL接口,验证节点逻辑分支(正常/异常/超时)。 |
| 集成测试 | Testcontainers + 模拟PLC | 连接仿真PLC(如 ModbusSimulator),验证真实协议交互。 |
| 混沌测试 | 随机注入超时/网络断连 | 验证节点的重试机制和异常捕获是否健壮。 |
@ExtendWith(MockitoExtension.class)
class HeaterNodeTest {
@Mock IIOService ioService;
@InjectMocks HeaterNode node;
@Test
void testHeaterReachesTarget() {
// 模拟温度逐步上升
when(ioService.readRegister(any(), eq(40001), any()))
.thenReturn(25.0, 100.0, 148.0); // mock 三次返回值
Object result = node.doExecute(ctx, nodeEntity);
verify(ioService).writeRegister(any(), eq(40002), eq(0)); // 最终关闭
assertEquals(148.0, result);
}
}
8.3 开发实施路线图(Sprint划分)
| 阶段 | 周期 | 核心任务 | 产出物 |
|---|---|---|---|
| Sprint 1:基础框架搭建 | 2天 | 定义 NodeExecutor 接口,实现 AbstractNodeExecutor 基类 | 基类代码 + 模板方法实现 |
| Sprint 2:核心节点开发(设备+IO+延时) | 5天 | 实现 DeviceControlNode、IOReadWriteNode、DelayNode | 3个核心节点 + 单元测试 |
| Sprint 3:逻辑与流程节点(条件+循环) | 4天 | 集成Aviator表达式引擎,实现 ConditionNode、LoopNode | 表达式评估 + 循环逻辑 |
| Sprint 4:数据与通知节点 | 3天 | 实现 DataSaveNode(JDBC)、AlarmNode(邮件/短信) | 数据库存储 + 通知集成 |
| Sprint 5:工厂与动态注册 | 3天 | 实现 NodeExecutorFactory,支持Spring自动扫描注册 | 工厂类 + 注解 @NodeType |
| Sprint 6:硬件抽象层(HAL)实现 | 5天 | 实现 Modbus/OPC UA 适配器,注入到节点 | HAL实现类 + 集成测试 |
| Sprint 7:性能与监控 | 2天 | 增加节点执行耗时统计、熔断降级 | 监控埋点 + Metrics上报 |
8.4 注解驱动的自动化注册(极简扩展方案)
为方便开发者新增节点,采用 Spring + 自定义注解 自动注册:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NodeType {
com.engine.node.api.NodeType value();
}
// 使用方式
@Component
@NodeType(com.engine.node.api.NodeType.AOI_INSPECTION)
public class AOIInspectionNode extends AbstractNodeExecutor {
// ...
}
// 自动注册逻辑
@Component
public class NodeExecutorAutoRegistrar implements ApplicationListener<ContextRefreshedEvent> {
@Autowired private NodeExecutorFactory factory;
@Override public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext()
.getBeansWithAnnotation(NodeType.class);
beans.forEach((name, bean) -> {
NodeType ann = bean.getClass().getAnnotation(NodeType.class);
factory.register(ann.value(), (NodeExecutor) bean);
});
}
}
九、总结
节点业务层(FlowNode)是工业流程引擎的 “最后一公里”,它将抽象的流程调度转化为具体的设备动作、数据操作和逻辑判断。
设计精髓:
- 模板方法统一形态:通过
AbstractNodeExecutor固化执行生命周期(校验 → 执行 → 输出),确保所有节点行为一致。 - 依赖倒置解耦硬件:节点依赖HAL接口(
IIOService等),更换硬件供应商(从Modbus换成Profibus)只需替换HAL实现,节点代码零改动。 - 策略模式无限扩展:通过
NodeExecutorFactory动态路由,新增一种工序只需写一个类加一个注解,完美契合工业现场“工艺千变万化”的需求。 - 分层测试保安全:通过Mock测试和仿真PLC测试,确保每个节点在接入真实设备前逻辑完备。
FlowNode层交付给工厂的价值:
- 工艺工程师只需拖拽节点,无需关心底层硬件驱动。
- 设备厂商只需按照HAL接口规范开发适配器,即可接入系统。
- 核心调度层(FlowRunner)永不变,保障了整个工业软件平台的稳定性和长期可维护性。
当FlowNode层与之前设计的数据模型层(静态定义)、画布渲染层(可视化编辑)、流程调度层(动态执行)组合在一起时,便构建了一个完整的、工业级的、支持热插拔业务逻辑的低代码自动化平台。
2626

被折叠的 条评论
为什么被折叠?



