huang
9 小时以前 fc4e5c458094c6bf5238d7d21291325f19a57adb
mes-processes/mes-plcSend/src/main/java/com/mes/interaction/workstation/scanner/handler/HorizontalScannerLogicHandler.java
@@ -7,9 +7,8 @@
import com.mes.device.vo.DevicePlcVO;
import com.mes.interaction.workstation.base.WorkstationBaseHandler;
import com.mes.interaction.workstation.config.WorkstationLogicConfig;
import com.mes.s7.enhanced.EnhancedS7Serializer;
import com.mes.s7.provider.S7SerializerProvider;
import com.mes.service.PlcDynamicDataService;
import com.mes.plc.client.PlcClient;
import com.mes.plc.factory.PlcClientFactory;
import com.mes.task.model.TaskExecutionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -33,18 +32,16 @@
    private static final List<String> MES_FIELDS = Arrays.asList("mesSend", "mesGlassId", "mesWidth", "mesHeight", "workLine");
    private final PlcDynamicDataService plcDynamicDataService;
    private final GlassInfoService glassInfoService;
    private final S7SerializerProvider s7SerializerProvider;
    private final PlcClientFactory plcClientFactory;
    public HorizontalScannerLogicHandler(DevicePlcOperationService devicePlcOperationService,
                                         PlcDynamicDataService plcDynamicDataService,
                                         GlassInfoService glassInfoService,
                                         S7SerializerProvider s7SerializerProvider) {
                                         PlcClientFactory plcClientFactory) {
        super(devicePlcOperationService);
        this.plcDynamicDataService = plcDynamicDataService;
        this.glassInfoService = glassInfoService;
        this.s7SerializerProvider = s7SerializerProvider;
        this.plcClientFactory = plcClientFactory;
        this.setPlcClientFactory(plcClientFactory);
    }
    @Override
@@ -57,22 +54,22 @@
                                                    String operation,
                                                    Map<String, Object> params,
                                                    Map<String, Object> logicParams) {
        EnhancedS7Serializer serializer = s7SerializerProvider.getSerializer(deviceConfig);
        if (serializer == null) {
            return buildResult(deviceConfig, operation, false, "获取PLC序列化器失败", null);
        PlcClient plcClient = getPlcClient(deviceConfig);
        if (plcClient == null) {
            return buildResult(deviceConfig, operation, false, "获取PLC客户端失败", null);
        }
        if ("clearPlc".equalsIgnoreCase(operation) || "reset".equalsIgnoreCase(operation)) {
            return clearPlc(deviceConfig, serializer);
            return clearPlc(deviceConfig, plcClient);
        }
        WorkstationLogicConfig config = parseWorkstationConfig(logicParams);
        return executeScan(deviceConfig, config, serializer, params);
        return executeScan(deviceConfig, config, plcClient, params);
    }
    private DevicePlcVO.OperationResult executeScan(DeviceConfig deviceConfig,
                                                    WorkstationLogicConfig config,
                                                    EnhancedS7Serializer serializer,
                                                    PlcClient plcClient,
                                                    Map<String, Object> params) {
        try {
            // 从参数中获取玻璃ID(定时器每次只处理一个)
@@ -85,7 +82,7 @@
            }
            
            // 执行单次扫描(定时器会循环调用此方法)
            return executeSingleScan(deviceConfig, config, serializer, inputGlassId, params);
            return executeSingleScan(deviceConfig, config, plcClient, inputGlassId, params);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("卧转立扫码等待MES数据被中断, deviceId={}", deviceConfig.getId(), e);
@@ -101,19 +98,19 @@
     */
    private DevicePlcVO.OperationResult executeSingleScan(DeviceConfig deviceConfig,
                                                          WorkstationLogicConfig config,
                                                          EnhancedS7Serializer serializer,
                                                          PlcClient plcClient,
                                                          String inputGlassId,
                                                          Map<String, Object> params) throws InterruptedException {
        // 1. 写入plcRequest=1和plcGlassId(如果提供了玻璃ID)
        triggerScanRequest(deviceConfig, serializer, inputGlassId);
        triggerScanRequest(deviceConfig, plcClient, inputGlassId);
        
        // 2. 等待MES回写mesSend=1以及玻璃信息
        Map<String, Object> mesData = waitForMesData(deviceConfig, serializer, config);
        Map<String, Object> mesData = waitForMesData(deviceConfig, plcClient, config);
        if (mesData == null || mesData.isEmpty()) {
            log.error("等待MES写入玻璃信息超时: deviceId={}, timeout={}ms", 
                    deviceConfig.getId(), config.getScanIntervalMs());
            // 超时也要清空plcRequest
            clearPlcRequestFields(deviceConfig, serializer);
            clearPlcRequestFields(deviceConfig, plcClient);
            return buildResult(deviceConfig, "scanOnce", false,
                    String.format("等待MES写入玻璃信息超时(%dms)", config.getScanIntervalMs()), null);
        }
@@ -122,16 +119,16 @@
        String glassId = parseString(mesData.get("mesGlassId"));
        if (!StringUtils.hasText(glassId)) {
            // MES未提供玻璃ID也要清空plcRequest
            clearPlcRequestFields(deviceConfig, serializer);
            clearPlcRequestFields(deviceConfig, plcClient);
            return buildResult(deviceConfig, "scanOnce", false, "MES写区未提供玻璃ID", null);
        }
        // 读取MES尺寸数据:mesWidth=表宽,mesHeight=长
        // 读取MES尺寸数据:mesWidth=宽,mesHeight=长
        Integer rawWidth = parseInteger(mesData.get("mesWidth"));
        Integer rawHeight = parseInteger(mesData.get("mesHeight"));
        Integer workLine = parseInteger(mesData.get("workLine"));
        // 4. 清空plcRequest和plcGlassId(只清除PLC字段)
        clearPlcRequestFields(deviceConfig, serializer);
        clearPlcRequestFields(deviceConfig, plcClient);
        // 5. 更新玻璃信息状态:将state从0改为1(已扫码交互)
        boolean updated = glassInfoService.updateGlassStateAfterScan(glassId, rawWidth, rawHeight, workLine);
@@ -144,12 +141,11 @@
        saveScannedGlassId(params, glassId);
        Integer intervalMs = config != null ? config.getScanIntervalMs() : null;
        String msg = String.format("玻璃[%s] 尺寸[表宽:%s x 长:%s] 已接收,workLine=%s,扫描间隔=%s",
        String msg = String.format("玻璃[%s] 尺寸[宽:%s x 长:%s] 已接收,workLine=%s",
                glassId,
                rawWidth != null ? rawWidth + "mm" : "-",
                rawHeight != null ? rawHeight + "mm" : "-",
                workLine != null ? workLine : "-",
                intervalMs != null ? intervalMs + "ms" : "-");
                workLine != null ? workLine : "-");
        Map<String, Object> resultData = new HashMap<>();
        resultData.put("glassIds", Collections.singletonList(glassId));
        if (workLine != null) {
@@ -189,13 +185,13 @@
    }
    private DevicePlcVO.OperationResult clearPlc(DeviceConfig deviceConfig,
                                                 EnhancedS7Serializer serializer) {
                                                 PlcClient plcClient) {
        try {
            // 只清空PLC操作区字段(plcRequest、plcGlassId),不清空MES写区字段
            Map<String, Object> resetFields = new HashMap<>();
            resetFields.put("plcRequest", 0);
            resetFields.put("plcGlassId", "");
            plcDynamicDataService.writePlcData(deviceConfig, resetFields, serializer);
            plcClient.writeData(resetFields);
            return buildResult(deviceConfig, "clearPlc", true, "已清空PLC操作区字段(保留MES写区字段)", null);
        } catch (Exception e) {
            log.error("卧转立扫码清空PLC失败, deviceId={}", deviceConfig.getId(), e);
@@ -206,7 +202,7 @@
    /**
     * 触发MES请求:写入plcRequest=1和plcGlassId(如果提供了玻璃ID)
     */
    private void triggerScanRequest(DeviceConfig deviceConfig, EnhancedS7Serializer serializer, String glassId) {
    private void triggerScanRequest(DeviceConfig deviceConfig, PlcClient plcClient, String glassId) {
        Map<String, Object> writeFields = new HashMap<>();
        writeFields.put("plcRequest", 1);
        
@@ -214,18 +210,18 @@
            writeFields.put("plcGlassId", glassId);
        }
        
        plcDynamicDataService.writePlcData(deviceConfig, writeFields, serializer);
        plcClient.writeData(writeFields);
    }
    
    /**
     * 清空PLC请求字段:只清除plcRequest和plcGlassId(不清除MES写区字段)
     */
    private void clearPlcRequestFields(DeviceConfig deviceConfig, EnhancedS7Serializer serializer) {
    private void clearPlcRequestFields(DeviceConfig deviceConfig, PlcClient plcClient) {
        try {
            Map<String, Object> clearFields = new HashMap<>();
            clearFields.put("plcRequest", 0);
            clearFields.put("plcGlassId", "");
            plcDynamicDataService.writePlcData(deviceConfig, clearFields, serializer);
            plcClient.writeData(clearFields);
        } catch (Exception e) {
            log.error("清空PLC请求字段失败: deviceId={}", deviceConfig.getId(), e);
            // 不清空不影响主流程,只记录错误
@@ -233,14 +229,14 @@
    }
    private Map<String, Object> waitForMesData(DeviceConfig deviceConfig,
                                               EnhancedS7Serializer serializer,
                                               PlcClient plcClient,
                                               WorkstationLogicConfig config) throws InterruptedException {
        long timeoutMs = Math.max(config.getScanIntervalMs(), 3_000);
        long deadline = System.currentTimeMillis() + timeoutMs;
        int pollInterval = Math.max(200, Math.min(config.getScanIntervalMs() / 5, 1_000));
        
        while (System.currentTimeMillis() < deadline) {
            Map<String, Object> mesData = plcDynamicDataService.readPlcData(deviceConfig, MES_FIELDS, serializer);
            Map<String, Object> mesData = plcClient.readData(MES_FIELDS.toArray(new String[0]));
            
            if (mesData != null && !mesData.isEmpty()) {
                Integer mesSend = parseInteger(mesData.get("mesSend"));
@@ -260,7 +256,7 @@
        
        // 超时前最后一次尝试读取
        log.warn("等待MES数据超时: deviceId={}, timeout={}ms", deviceConfig.getId(), timeoutMs);
        Map<String, Object> lastMesData = plcDynamicDataService.readPlcData(deviceConfig, MES_FIELDS, serializer);
        Map<String, Object> lastMesData = plcClient.readData(MES_FIELDS.toArray(new String[0]));
        if (lastMesData != null && !lastMesData.isEmpty()) {
            log.warn("超时前最后一次读取到的数据: deviceId={}, mesData={}", 
                    deviceConfig.getId(), lastMesData);
@@ -272,7 +268,7 @@
    private GlassInfo buildGlassInfo(String glassId, Integer width, Integer height, Integer workLine) {
        GlassInfo glassInfo = new GlassInfo();
        glassInfo.setGlassId(glassId.trim());
        // mesWidth=表宽 -> glassWidth, mesHeight=长 -> glassLength
        // mesWidth=宽 -> glassWidth, mesHeight=长 -> glassLength
        if (width != null) {
            glassInfo.setGlassWidth(width);
        }