编辑 | blame | 历史 | 原始文档

项目架构说明文档

📋 项目主体架构

核心主体:TaskExecutionEngine(任务执行引擎)

位置com.mes.task.service.TaskExecutionEngine

职责:多设备任务执行的核心引擎,负责:
- 串行/并行执行模式控制
- 设备步骤执行调度
- 设备协调检查
- 错误处理和重试
- 实时状态通知

🔄 调用流程

1. 任务启动流程

用户请求 (Controller)
    ↓
MultiDeviceTaskServiceImpl.startTask()
    ├─ 验证设备组
    ├─ 获取设备列表
    ├─ 创建任务记录 (PENDING)
    └─ 异步执行 executeTaskAsync()
        ↓
    TaskExecutionEngine.execute()
        ├─ 设备协调检查 (DeviceCoordinationService)
        ├─ 确定执行模式 (串行/并行)
        └─ 执行设备步骤

2. 设备步骤执行流程

TaskExecutionEngine.executeStep()
    ↓
检查是否有 DeviceInteraction
    ├─ 有 → executeInteractionStepWithRetry()
    │       ↓
    │   DeviceInteraction.execute(InteractionContext)
    │       ↓
    │   具体设备交互实现(如 LoadVehicleInteraction)
    │       ↓
    │   调用 DeviceInteractionService
    │       ↓
    │   最终调用 DeviceLogicHandler
    │
    └─ 无 → 直接调用 DeviceLogicHandler
            ↓
        DeviceLogicHandlerFactory.getHandler(deviceType)
            ↓
        BaseDeviceLogicHandler.execute()
            ↓
        子类实现 doExecute()

3. 两种执行路径

路径A:通过 DeviceInteraction(推荐用于复杂设备)

TaskExecutionEngine
    ↓
DeviceInteraction.execute(InteractionContext)
    ↓
具体实现类(如 LoadVehicleInteraction)
    ├─ 状态检查
    ├─ 设备选择(多实例协调)
    ├─ 数据准备
    └─ 调用 DeviceInteractionService
        ↓
    DeviceLogicHandler.execute()

适用场景
- 需要多实例协调的设备(如大车设备)
- 需要复杂前置检查的设备
- 需要数据转换和准备的设备

路径B:直接调用 DeviceLogicHandler(简单设备)

TaskExecutionEngine
    ↓
DeviceLogicHandlerFactory.getHandler(deviceType)
    ↓
BaseDeviceLogicHandler.execute()
    ├─ 参数解析
    ├─ 逻辑参数提取 (extraParams.deviceLogic)
    └─ 子类实现 doExecute()

适用场景
- 简单设备,逻辑单一
- 不需要复杂协调的设备

🏗️ 分层架构

第一层:Controller 层(API入口)

位置com.mes.task.controller.*

职责
- 接收HTTP请求
- 参数验证
- 调用Service层

主要类
- MultiDeviceTaskController - 任务管理API
- TaskStatusNotificationController - SSE实时通知API

第二层:Service 层(业务逻辑)

位置com.mes.task.service.*

职责
- 业务逻辑处理
- 事务管理
- 调用执行引擎

主要类
- MultiDeviceTaskServiceImpl - 任务服务实现
- 创建任务记录
- 异步执行任务
- 任务状态管理

  • TaskExecutionEngine - 核心执行引擎
  • 设备协调检查
  • 执行模式判断(串行/并行)
  • 步骤执行调度
  • 重试机制

第三层:Interaction 层(设备交互)

位置com.mes.interaction.*

职责
- 设备交互逻辑封装
- 多设备协调
- 数据传递

主要组件

3.1 DeviceInteraction(设备交互接口)

接口com.mes.interaction.DeviceInteraction

实现类示例
- LoadVehicleInteraction - 大车设备交互
- LargeGlassInteraction - 大理片笼交互
- GlassStorageInteraction - 玻璃存储交互

注册机制
- DeviceInteractionRegistry - 自动注册所有 @ComponentDeviceInteraction 实现

3.2 DeviceLogicHandler(设备逻辑处理器)

接口com.mes.interaction.DeviceLogicHandler

基类BaseDeviceLogicHandler
- 提供通用功能:
- 参数解析
- 逻辑参数提取(从 extraParams.deviceLogic
- 错误处理

实现类示例
- LoadVehicleLogicHandler - 大车设备逻辑
- HorizontalScannerLogicHandler - 卧转立扫码逻辑
- HorizontalTransferLogicHandler - 卧转立逻辑
- LargeGlassLogicHandler - 大理片笼逻辑

注册机制
- DeviceLogicHandlerFactory - 自动注册所有 DeviceLogicHandler 实现
- 通过 @PostConstruct 初始化映射表

第四层:Coordination 层(设备协调)

位置com.mes.device.service.*com.mes.interaction.*.coordination.*

职责
- 设备间数据传递
- 设备状态同步
- 设备依赖管理
- 多实例协调

主要类
- DeviceCoordinationService - 通用设备协调服务
- VehicleCoordinationService - 大车设备协调服务
- VehicleStatusManager - 大车状态管理器

第五层:PLC 操作层(硬件通信)

位置com.mes.device.service.DevicePlcOperationService

职责
- PLC读写操作
- 地址映射
- 通信管理

📦 如何添加新设备

步骤1:定义设备类型常量

DeviceConfig.DeviceType 中添加:

public static final class DeviceType {
    public static final String NEW_DEVICE = "新设备类型";
}

步骤2:创建设备逻辑处理器(必须)

位置com.mes.interaction.*.handler.NewDeviceLogicHandler

@Component
public class NewDeviceLogicHandler extends BaseDeviceLogicHandler {
    
    @Override
    public String getDeviceType() {
        return DeviceConfig.DeviceType.NEW_DEVICE;
    }
    
    @Override
    protected DevicePlcVO.OperationResult doExecute(
            DeviceConfig deviceConfig,
            String operation,
            Map<String, Object> params,
            Map<String, Object> logicParams) {
        
        // 1. 从 logicParams 中获取配置参数
        Integer timeout = getLogicParam(logicParams, "timeout", 5000);
        String mode = getLogicParam(logicParams, "mode", "default");
        
        // 2. 从 params 中获取运行时参数
        String glassId = (String) params.get("glassId");
        
        // 3. 执行设备逻辑
        // ... 具体实现
        
        // 4. 调用PLC操作
        Map<String, Object> plcParams = new HashMap<>();
        plcParams.put("field1", value1);
        DevicePlcVO.OperationResult result = 
            devicePlcOperationService.writePlcData(deviceConfig, plcParams);
        
        return result;
    }
    
    @Override
    protected Map<String, Object> getDefaultLogicParams() {
        Map<String, Object> defaults = new HashMap<>();
        defaults.put("timeout", 5000);
        defaults.put("mode", "default");
        return defaults;
    }
}

自动注册
- 实现 DeviceLogicHandler 接口
- 添加 @Component 注解
- DeviceLogicHandlerFactory 会自动发现并注册

步骤3:创建设备交互类(可选,复杂设备推荐)

位置com.mes.interaction.*.flow.NewDeviceInteraction

@Component
public class NewDeviceInteraction implements DeviceInteraction {
    
    @Override
    public String getDeviceType() {
        return DeviceConfig.DeviceType.NEW_DEVICE;
    }
    
    @Override
    public InteractionResult execute(InteractionContext context) {
        DeviceConfig device = context.getCurrentDevice();
        
        // 1. 前置条件检查
        if (device == null) {
            return InteractionResult.fail("设备配置不存在");
        }
        
        // 2. 数据准备
        List<String> glassIds = context.getParameters().getGlassIds();
        
        // 3. 调用设备逻辑处理器
        DeviceInteractionService service = ...;
        Map<String, Object> params = new HashMap<>();
        params.put("glassIds", glassIds);
        
        DevicePlcVO.OperationResult result = 
            service.executeDeviceOperation(device, "operationName", params);
        
        if (result.isSuccess()) {
            // 4. 数据传递到下一个设备
            context.getSharedData().put("processedGlasses", glassIds);
            return InteractionResult.success("执行成功", result.getData());
        } else {
            return InteractionResult.fail(result.getMessage());
        }
    }
}

自动注册
- 实现 DeviceInteraction 接口
- 添加 @Component 注解
- DeviceInteractionRegistry 会自动发现并注册

步骤4:配置设备逻辑参数(前端)

在设备配置的 extraParams.deviceLogic 中配置:

{
  "deviceLogic": {
    "timeout": 5000,
    "mode": "default",
    "customParam1": "value1"
  }
}

步骤5:设备组织方式选择

简单设备(推荐放在通用包)

interaction/
└── impl/
    └── NewDeviceLogicHandler.java

复杂设备(需要协调、状态管理等)

interaction/
└── newdevice/
    ├── handler/
    │   └── NewDeviceLogicHandler.java
    ├── flow/
    │   └── NewDeviceInteraction.java
    ├── coordination/  (可选)
    │   └── NewDeviceCoordinationService.java
    └── model/  (可选)
        └── NewDeviceStatus.java

🔍 执行流程详解

串行执行模式

TaskExecutionEngine.execute()
    ↓
for (每个设备) {
    1. 创建步骤记录 (TaskStepDetail)
    2. executeStep()
        ↓
    3. 检查是否有 DeviceInteraction
        ├─ 有 → DeviceInteraction.execute()
        │       ↓
        │   调用 DeviceLogicHandler
        │
        └─ 无 → 直接调用 DeviceLogicHandler
                ↓
            BaseDeviceLogicHandler.execute()
                ↓
            子类 doExecute()
    4. 更新步骤状态
    5. 传递数据到下一个设备
}

并行执行模式

TaskExecutionEngine.execute()
    ↓
创建线程池任务列表
    ↓
for (每个设备) {
    提交到线程池执行
        ↓
    executeStep() (同上)
}
    ↓
等待所有任务完成
    ↓
汇总结果

📝 关键接口说明

DeviceLogicHandler

接口方法
java DevicePlcVO.OperationResult execute( DeviceConfig deviceConfig, String operation, Map<String, Object> params );

调用时机
- 任务执行引擎直接调用
- 或通过 DeviceInteraction 间接调用

DeviceInteraction

接口方法
java InteractionResult execute(InteractionContext context);

调用时机
- 任务执行引擎优先检查是否有 DeviceInteraction
- 如果有,优先使用 DeviceInteraction
- 如果没有,直接调用 DeviceLogicHandler

InteractionContext

包含内容
- currentDevice - 当前设备配置
- taskContext - 任务上下文
- parameters - 任务参数
- sharedData - 设备间共享数据

🎯 最佳实践

1. 何时使用 DeviceInteraction?

使用场景
- ✅ 需要多实例协调(如大车设备)
- ✅ 需要复杂前置检查
- ✅ 需要数据转换和准备
- ✅ 需要状态管理

不使用场景
- ❌ 简单设备,逻辑单一
- ❌ 不需要协调的设备

2. 参数设计

logicParams(逻辑参数)
- 从 extraParams.deviceLogic 中读取
- 设备配置时设置,运行时不变
- 如:超时时间、模式、容量等

params(运行时参数)
- 任务执行时动态传入
- 如:玻璃ID、位置、数量等

3. 错误处理

在 BaseDeviceLogicHandler 中
- 自动捕获异常
- 返回统一的错误格式

在子类中
- 可以抛出业务异常
- 会被基类捕获并转换

4. 数据传递

通过 InteractionContext.sharedData
```java
// 在设备A中设置
context.getSharedData().put("glassIds", glassIds);

// 在设备B中获取
List glassIds = (List) context.getSharedData().get("glassIds");
```

📚 相关文件位置

核心文件

  • TaskExecutionEngine.java - 任务执行引擎
  • MultiDeviceTaskServiceImpl.java - 任务服务
  • DeviceLogicHandlerFactory.java - 处理器工厂
  • DeviceInteractionRegistry.java - 交互注册中心

基类

  • BaseDeviceLogicHandler.java - 逻辑处理器基类
  • DeviceInteraction.java - 交互接口

示例实现

  • LoadVehicleLogicHandler.java - 大车设备逻辑处理器
  • LoadVehicleInteraction.java - 大车设备交互
  • HorizontalScannerLogicHandler.java - 卧转立扫码处理器

🔧 调试技巧

1. 查看注册的设备处理器

@Autowired
private DeviceLogicHandlerFactory factory;

// 查看所有已注册的设备类型
Set<String> types = factory.getSupportedDeviceTypes();

2. 查看注册的设备交互

@Autowired
private DeviceInteractionRegistry registry;

// 查看所有已注册的交互
Map<String, DeviceInteraction> interactions = registry.getInteractions();

3. 日志输出

  • 任务执行:查看 TaskExecutionEngine 日志
  • 设备执行:查看具体 Handler 日志
  • 协调服务:查看 DeviceCoordinationService 日志

✅ 总结

  1. 项目主体TaskExecutionEngine 是核心执行引擎
  2. 调用流程:Controller → Service → Engine → Interaction/Handler → PLC
  3. 分层架构:Controller → Service → Interaction → Coordination → PLC
  4. 添加设备:实现 DeviceLogicHandler(必须)+ DeviceInteraction(可选)
  5. 自动注册:通过 Spring 的 @Component 和工厂类自动发现和注册