From 73aa66976e35252378be3f09be2474193ccd0bf6 Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期五, 05 十二月 2025 17:15:20 +0800
Subject: [PATCH] 修改任务执行步骤状态完成检验
---
mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java | 310 ++++++++++++++++++++++++++++++++++++++++----
mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java | 75 ++++++++++
mes-common/serverBase/src/main/java/com/mes/exception/GlobalExceptionHandler.java | 35 ++++
3 files changed, 389 insertions(+), 31 deletions(-)
diff --git a/mes-common/serverBase/src/main/java/com/mes/exception/GlobalExceptionHandler.java b/mes-common/serverBase/src/main/java/com/mes/exception/GlobalExceptionHandler.java
index fc6f5f2..0ae08fb 100644
--- a/mes-common/serverBase/src/main/java/com/mes/exception/GlobalExceptionHandler.java
+++ b/mes-common/serverBase/src/main/java/com/mes/exception/GlobalExceptionHandler.java
@@ -2,9 +2,15 @@
import com.mes.result.Result;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.http.HttpServletRequest;
/**
* @author zhoush
@@ -22,10 +28,35 @@
return Result.error(se.getCode(), se.getMessage());
}
+ /**
+ * 澶勭悊濯掍綋绫诲瀷涓嶅尮閰嶅紓甯革紙閫氬父鍙戠敓鍦⊿SE杩炴帴宸插叧闂椂锛�
+ */
+ @ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
+ @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
+ @ResponseBody
+ public Result<Object> handleMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException e, HttpServletRequest request) {
+ // 濡傛灉鏄疭SE璇锋眰锛岄潤榛樺鐞嗭紝涓嶈褰曢敊璇�
+ String acceptHeader = request.getHeader("Accept");
+ if (acceptHeader != null && acceptHeader.contains("text/event-stream")) {
+ log.debug("SSE杩炴帴宸插叧闂紝蹇界暐濯掍綋绫诲瀷寮傚父: {}", e.getMessage());
+ return null; // 杩斿洖null锛屼笉鍐欏叆鍝嶅簲
+ }
+ log.warn("濯掍綋绫诲瀷涓嶅尮閰�: {}", e.getMessage());
+ return Result.error();
+ }
+
@ExceptionHandler(Exception.class)
@ResponseBody
- public Result<Object> error(Exception e) {
- e.printStackTrace();
+ public Result<Object> error(Exception e, HttpServletRequest request) {
+ // 濡傛灉鏄疭SE璇锋眰涓旀槸濯掍綋绫诲瀷寮傚父锛岄潤榛樺鐞�
+ if (e instanceof HttpMediaTypeNotAcceptableException) {
+ String acceptHeader = request.getHeader("Accept");
+ if (acceptHeader != null && acceptHeader.contains("text/event-stream")) {
+ log.debug("SSE杩炴帴宸插叧闂紝蹇界暐寮傚父: {}", e.getMessage());
+ return null;
+ }
+ }
+ log.error("鍏ㄥ眬寮傚父澶勭悊: ", e);
return Result.error();
}
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java b/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java
index 7a04e23..b77deae 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java
@@ -112,6 +112,10 @@
// 璁板綍褰撳墠浠诲姟锛歞eviceId -> 浠诲姟淇℃伅
private final Map<String, MesTaskInfo> currentTasks = new ConcurrentHashMap<>();
+ /**
+ * 璁板綍鏈�杩戜竴娆″凡瀹屾垚浣哅ES鏈浣嶇殑浠诲姟绛惧悕锛岄伩鍏嶉噸澶嶆媺璧�
+ */
+ private final Map<String, CompletedMesRecord> lastCompletedMesRecords = new ConcurrentHashMap<>();
@Autowired
public LoadVehicleLogicHandler(
@@ -145,6 +149,10 @@
// 鍥犱负瀹氭椂鍣ㄥ彲鑳戒細閲嶅璋冪敤锛屾垨鑰呴渶瑕佺瓑寰呬换鍔″畬鎴�
if ("feedGlass".equals(operation) && status.isExecuting()) {
log.debug("杞﹁締 {} 褰撳墠鐘舵�佷负 EXECUTING锛屼絾鍏佽缁х画鎵ц feedGlass锛堝畾鏃跺櫒閲嶅璋冪敤锛�", deviceId);
+ // 鍏佽缁х画鎵ц锛屼笉杩斿洖閿欒
+ } else if ("clearGlass".equals(operation) || "clearPlc".equals(operation) || "clear".equals(operation)) {
+ // 娓呴櫎鎿嶄綔搴旇鍏佽鍦ㄤ换浣曠姸鎬佷笅鎵ц锛屽洜涓哄叾鐩殑灏辨槸閲嶇疆璁惧鐘舵��
+ log.debug("杞﹁締 {} 褰撳墠鐘舵�佷负 {}锛屼絾鍏佽鎵ц娓呴櫎鎿嶄綔 {}", deviceId, status.getState(), operation);
// 鍏佽缁х画鎵ц锛屼笉杩斿洖閿欒
} else {
return DevicePlcVO.OperationResult.builder()
@@ -1356,6 +1364,25 @@
.build();
}
+ // 鏋勫缓褰撳墠MES鏁版嵁绛惧悕锛岀敤浜庡垽鏂槸鍚︿负宸茬‘璁や絾鏈浣嶇殑鏃т换鍔�
+ String mesSignature = buildMesSignature(mesData);
+ CompletedMesRecord completedRecord = lastCompletedMesRecords.get(deviceId);
+ if (completedRecord != null
+ && mesSignature.equals(completedRecord.signature)) {
+ Integer mesConfirm = parseInteger(mesData.get("mesConfirm"));
+ if (mesConfirm != null && mesConfirm == 1) {
+ Map<String, Object> waitData = new HashMap<>();
+ waitData.put("completed", true);
+ waitData.put("waiting", true);
+ waitData.put("waitingReason", "mesNotReset");
+ return DevicePlcVO.OperationResult.builder()
+ .success(true)
+ .message("MES宸茬‘璁ゅ畬鎴愪絾鏈浣嶏紙mesSend/mesConfirm锛夛紝绛夊緟澶嶄綅鍚庡啀鎺ユ敹鏂颁换鍔�")
+ .data(waitData)
+ .build();
+ }
+ }
+
// mesSend=1锛岃褰曟棩蹇�
log.info("妫�娴嬪埌mesSend=1锛屽紑濮嬭鍙朚ES浠诲姟淇℃伅: deviceId={}", deviceId);
@@ -1453,6 +1480,7 @@
taskInfo.cartime = timeCalc.cartime;
taskInfo.createdTime = System.currentTimeMillis();
taskInfo.isOutbound = isOutbound;
+ taskInfo.mesSignature = mesSignature;
// 浠庨厤缃腑璇诲彇鐮存崯鐜荤拑绱㈠紩锛堢敤浜庢祴璇曞満鏅級
// 閰嶇疆鏍煎紡锛歜rokenGlassIndices: [0, 2] 琛ㄧず绗�1涓拰绗�3涓幓鐠冨簲璇ョ牬鎹�
@@ -2075,9 +2103,14 @@
data.put("completed", false);
data.put("waiting", true);
data.put("waitingReason", "waitingReport");
+ String detail = taskInfo.currentStepDesc;
+ String message = "澶ц溅浠诲姟鎵ц涓紝灏氭湭姹囨姤锛屾棤闇�妫�鏌ョ‘璁�";
+ if (detail != null && !detail.isEmpty()) {
+ message = detail + "锛�" + message;
+ }
return DevicePlcVO.OperationResult.builder()
.success(true)
- .message("澶ц溅浠诲姟鎵ц涓紝灏氭湭姹囨姤锛屾棤闇�妫�鏌ョ‘璁�")
+ .message(message)
.data(data)
.build();
}
@@ -2118,6 +2151,10 @@
if (completed) {
// MES宸茬‘璁わ紝娓呯┖state鍜屾眹鎶ュ瓧
clearTaskStates(deviceConfig, serializer);
+
+ // 璁板綍宸插畬鎴愮殑浠诲姟绛惧悕锛岄伩鍏峂ES鏈浣嶆椂琚噸澶嶆媺璧�
+ lastCompletedMesRecords.put(deviceId,
+ new CompletedMesRecord(taskInfo.mesSignature, System.currentTimeMillis()));
// 浠诲姟瀹屾垚锛屾仮澶嶄负绌洪棽鐘舵��
statusManager.updateVehicleStatus(
@@ -2321,6 +2358,20 @@
List<Integer> brokenGlassIndices = null; // 鏍囪涓虹牬鎹熺殑鐜荤拑绱㈠紩鍒楄〃锛�0-based锛岀敤浜庢祴璇曞満鏅級
Long mesConfirmStartTime = null; // MES纭寮�濮嬬瓑寰呯殑鏃堕棿锛堢敤浜庤秴鏃舵娴嬶級
String currentStepDesc = null; // 褰撳墠姝ラ鎻忚堪锛堢敤浜庢樉绀鸿缁嗙殑鎵ц鐘舵�侊級
+ String mesSignature = null; // MES鏁版嵁绛惧悕锛岀敤浜庨伩鍏嶆湭澶嶄綅鏃堕噸澶嶆媺璧�
+ }
+
+ /**
+ * 璁板綍宸插畬鎴愪絾MES鏈浣嶇殑浠诲姟淇℃伅
+ */
+ private static class CompletedMesRecord {
+ final String signature;
+ final long completedAt;
+
+ CompletedMesRecord(String signature, long completedAt) {
+ this.signature = signature;
+ this.completedAt = completedAt;
+ }
}
/**
@@ -2399,5 +2450,27 @@
log.warn("娓呯┖澶ц溅state瀛楁澶辫触: deviceId={}, error={}", deviceConfig != null ? deviceConfig.getId() : "null", e.getMessage());
}
}
+
+ /**
+ * 灏哅ES鏁版嵁鏋勯�犳垚绛惧悕瀛楃涓诧紝鐢ㄤ簬璇嗗埆鏄惁涓哄悓涓�鎵规浠诲姟
+ */
+ private String buildMesSignature(Map<String, Object> mesData) {
+ if (mesData == null || mesData.isEmpty()) {
+ return "empty";
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("mesSend=").append(mesData.getOrDefault("mesSend", ""))
+ .append(";mesConfirm=").append(mesData.getOrDefault("mesConfirm", ""));
+ for (int i = 1; i <= 6; i++) {
+ sb.append(";g").append(i).append("=")
+ .append(mesData.getOrDefault("mesGlassId" + i, ""))
+ .append(",s").append(mesData.getOrDefault("start" + i, ""))
+ .append(",t").append(mesData.getOrDefault("target" + i, ""))
+ .append(",w").append(mesData.getOrDefault("mesWidth" + i, ""))
+ .append(",h").append(mesData.getOrDefault("mesHeight" + i, ""))
+ .append(",th").append(mesData.getOrDefault("mesThickness" + i, ""));
+ }
+ return sb.toString();
+ }
}
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java b/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
index e2d0469..6d9c433 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
@@ -676,21 +676,72 @@
task.getTaskId(), device.getId());
return;
}
+ // 宸插畬鎴�/澶辫触鐨勬楠や笉鍐嶅洖閫�鐘舵��
+ if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())
+ || TaskStepDetail.Status.FAILED.name().equals(step.getStatus())) {
+ return;
+ }
// 杩涚墖澶ц溅璁惧锛氬彧鏈夊湪鐪熸寮�濮嬪鐞嗘椂鎵嶈缃负RUNNING
+ // 鍏堟鏌ュ崸杞珛璁惧鏄惁宸插畬鎴愶紝濡傛灉杩樺湪鎵ц涓紝涓嶅簲璇ュ紑濮嬪ぇ杞︾殑宸ヤ綔
+ boolean transferCompleted = isTransferDeviceCompleted(task.getTaskId(), context);
+ if (!transferCompleted) {
+ // 鍗ц浆绔嬭繕鍦ㄦ墽琛屼腑锛岀瓑寰呭崸杞珛瀹屾垚
+ if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+ step.setStatus(TaskStepDetail.Status.PENDING.name());
+ step.setSuccessMessage("绛夊緟鍗ц浆绔嬪畬鎴�");
+ if (step.getStartTime() == null) {
+ step.setStartTime(new Date());
+ }
+ taskStepDetailMapper.updateById(step);
+ notificationService.notifyStepUpdate(task.getTaskId(), step);
+ }
+ log.debug("鍗ц浆绔嬭繕鍦ㄦ墽琛屼腑锛岃繘鐗囧ぇ杞︾瓑寰�: taskId={}, deviceId={}",
+ task.getTaskId(), device.getId());
+ return;
+ }
+
// 妫�鏌ユ槸鍚︽湁鍗ц浆绔嬩富浣撳凡杈撳嚭銆佸噯澶囦笂澶ц溅鐨勭幓鐠冧俊鎭�
List<String> readyGlassIds = getTransferReadyGlassIds(context);
- // 濡傛灉褰撳墠娌℃湁鏂扮殑鐜荤拑锛屾棤璁烘楠ゆ槸鍚﹀凡杩涘叆RUNNING锛岄兘搴旇杞MES浠诲姟/纭鐘舵��
+ // 濡傛灉褰撳墠娌℃湁鏂扮殑鐜荤拑锛屼絾鍗ц浆绔嬪凡瀹屾垚锛屽彲浠ヨ疆璇ES浠诲姟/纭鐘舵��
if (CollectionUtils.isEmpty(readyGlassIds)) {
- // 杞MES浠诲姟/纭锛岄伩鍏嶉敊杩嘙ES渚у悗鍐欏叆鐨勪换鍔�
- pollMesForVehicle(task, step, device, context);
- // 濡傛灉浠嶇劧娌℃湁鍗ц浆绔嬭緭鍑虹殑鐜荤拑锛屼繚鎸�/鏇存柊涓篜ENDING鎻愮ず
- if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())
- && !TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
- step.setStatus(TaskStepDetail.Status.PENDING.name());
- step.setSuccessMessage("绛夊緟鍗ц浆绔嬭緭鍑虹幓鐠�");
- taskStepDetailMapper.updateById(step);
- notificationService.notifyStepUpdate(task.getTaskId(), step);
+ // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸茶杞�
+ @SuppressWarnings("unchecked")
+ List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+ List<String> loadedGlassIds = getLoadedGlassIds(context);
+
+ if (initialGlassIds != null && !initialGlassIds.isEmpty()) {
+ // 濡傛灉鎵�鏈夊垵濮嬬幓鐠冮兘宸茶杞斤紝璇存槑宸茬粡澶勭悊瀹岋紝涓嶅簲璇ュ啀鍙樺洖绛夊緟
+ if (loadedGlassIds != null && !loadedGlassIds.isEmpty()
+ && loadedGlassIds.containsAll(initialGlassIds)) {
+ // 鎵�鏈夌幓鐠冮兘宸茶杞斤紝淇濇寔RUNNING鐘舵�侊紝缁х画杞MES浠诲姟/纭
+ if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) {
+ step.setStatus(TaskStepDetail.Status.RUNNING.name());
+ if (step.getStartTime() == null) {
+ step.setStartTime(new Date());
+ }
+ taskStepDetailMapper.updateById(step);
+ notificationService.notifyStepUpdate(task.getTaskId(), step);
+ }
+ pollMesForVehicle(task, step, device, context);
+ return;
+ }
+ }
+
+ // 濡傛灉澶ц溅宸茬粡瑁呰浇杩囩幓鐠冿紙RUNNING鐘舵�侊級锛岃疆璇ES浠诲姟/纭鐘舵��
+ if (TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) {
+ pollMesForVehicle(task, step, device, context);
+ } else {
+ // 濡傛灉杩樻病鏈夎杞借繃鐜荤拑锛岀瓑寰呭崸杞珛杈撳嚭
+ if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+ step.setStatus(TaskStepDetail.Status.PENDING.name());
+ step.setSuccessMessage("绛夊緟鍗ц浆绔嬭緭鍑虹幓鐠�");
+ if (step.getStartTime() == null) {
+ step.setStartTime(new Date());
+ }
+ taskStepDetailMapper.updateById(step);
+ notificationService.notifyStepUpdate(task.getTaskId(), step);
+ }
}
return;
}
@@ -784,9 +835,48 @@
task.getTaskId(), device.getId(), e.getMessage());
}
+ // 濡傛灉MES宸茬‘璁ゅ畬鎴愶紙mesConfirm=1锛夛紝妫�鏌ュ崸杞珛璁惧鐘舵�佸拰鐜荤拑淇℃伅
+ // 濡傛灉鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鍙互鏍囪涓哄畬鎴�
+ if (mesResult != null && mesResult.getData() != null) {
+ Object completedFlag = mesResult.getData().get("completed");
+ boolean mesConfirmed = false;
+ if (completedFlag instanceof Boolean) {
+ mesConfirmed = (Boolean) completedFlag;
+ } else if (completedFlag != null) {
+ mesConfirmed = "true".equalsIgnoreCase(String.valueOf(completedFlag));
+ }
+
+ if (mesConfirmed) {
+ // MES宸茬‘璁ゅ畬鎴愶紝妫�鏌ュ崸杞珛璁惧鏄惁宸插畬鎴�
+ boolean transferCompletedForMes = isTransferDeviceCompleted(task.getTaskId(), context);
+ if (transferCompletedForMes) {
+ // 妫�鏌ヤ换鍔′笂涓嬫枃涓殑鍒濆鐜荤拑ID鍜屽凡瑁呰浇鐨勭幓鐠僆D
+ @SuppressWarnings("unchecked")
+ List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+ List<String> loadedGlassIds = getLoadedGlassIds(context);
+
+ if (initialGlassIds != null && !initialGlassIds.isEmpty()
+ && loadedGlassIds != null && !loadedGlassIds.isEmpty()) {
+ // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸茶杞�
+ boolean allGlassesLoaded = loadedGlassIds.containsAll(initialGlassIds);
+ if (allGlassesLoaded) {
+ // 鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鏍囪涓哄畬鎴�
+ log.info("MES宸茬‘璁や笖鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冨凡瑁呰浇锛屼换鍔¤嚜鍔ㄥ畬鎴�: taskId={}, deviceId={}, initialCount={}, loadedCount={}",
+ task.getTaskId(), device.getId(), initialGlassIds.size(), loadedGlassIds.size());
+ // mesResult宸茬粡鍖呭惈completed=true锛屼笉闇�瑕佷慨鏀�
+ }
+ }
+ } else {
+ // 鍗ц浆绔嬭繕鏈畬鎴愶紝涓嶅簲璇ユ爣璁颁负瀹屾垚
+ log.debug("MES宸茬‘璁や絾鍗ц浆绔嬫湭瀹屾垚锛岀瓑寰呭崸杞珛瀹屾垚: taskId={}, deviceId={}",
+ task.getTaskId(), device.getId());
+ }
+ }
+ }
+
// 鏇存柊姝ラ鐘舵�侊紙澶ц溅璁惧淇濇寔RUNNING锛岀洿鍒癕ES纭瀹屾垚鎴栦换鍔″彇娑堬級
if (mesResult != null) {
- updateStepStatusForVehicle(step, mesResult);
+ updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
updateTaskProgress(task, step.getStepOrder(), opSuccess);
if (!opSuccess) {
@@ -794,7 +884,7 @@
DeviceCoordinationService.DeviceStatus.FAILED, context);
}
} else {
- updateStepStatusForVehicle(step, feedResult);
+ updateStepStatusForVehicle(task.getTaskId(), step, feedResult);
boolean opSuccess = Boolean.TRUE.equals(feedResult.getSuccess());
updateTaskProgress(task, step.getStepOrder(), opSuccess);
if (!opSuccess) {
@@ -844,10 +934,10 @@
List<String> processedGlassIds = getProcessedGlassIds(context);
boolean isRunning = TaskStepDetail.Status.RUNNING.name().equals(step.getStatus());
- // 濡傛灉璁惧宸茬粡鍦ㄨ繍琛屼腑锛屽嵆浣挎病鏈夋柊鐜荤拑锛屼篃瑕佺户缁洃鎺ES浠诲姟鍜岀‘璁ょ姸鎬�
+ // 濡傛灉娌℃湁宸插鐞嗙幓鐠冿紝鍒欎笉搴斾富鍔ㄦ妸姝ラ鎷夊埌RUNNING锛屽彧淇濇寔宸茶繍琛岀姸鎬�
if (CollectionUtils.isEmpty(processedGlassIds)) {
if (isRunning) {
- // 璁惧姝e湪杩愯涓紝鍏堟鏌ES浠诲姟锛岀劧鍚庣洃鎺ES纭鐘舵��
+ // 宸茬粡鍦ㄨ繍琛岀殑鎯呭喌涓嬶紝缁х画杞MES浠诲姟/纭锛岄伩鍏嶉敊杩囩‘璁�
DeviceLogicHandler handler = handlerFactory.getHandler(device.getDeviceType());
if (handler != null) {
Map<String, Object> logicParams = parseLogicParams(device);
@@ -876,7 +966,7 @@
// 鏇存柊姝ラ鐘舵�侊紙澶ц溅璁惧淇濇寔RUNNING锛岀洿鍒癕ES纭瀹屾垚鎴栦换鍔″彇娑堬級
if (mesResult != null) {
- updateStepStatusForVehicle(step, mesResult);
+ updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
updateTaskProgress(task, step.getStepOrder(), opSuccess);
if (!opSuccess) {
@@ -885,10 +975,10 @@
}
}
}
- return;
} else {
- // 娌℃湁鏁版嵁锛屼笖璁惧鏈繍琛岋紝淇濇寔PENDING鐘舵��
- if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+ // 鏈繍琛屼笖娌℃湁宸插鐞嗙幓鐠冿紝淇濇寔PENDING
+ if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())
+ && !TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
step.setStatus(TaskStepDetail.Status.PENDING.name());
step.setSuccessMessage("绛夊緟澶х悊鐗囩澶勭悊瀹屾垚");
taskStepDetailMapper.updateById(step);
@@ -896,8 +986,8 @@
}
log.debug("鍑虹墖澶ц溅璁惧瀹氭椂鍣細鏆傛棤宸插鐞嗙殑鐜荤拑淇℃伅: taskId={}, deviceId={}",
task.getTaskId(), device.getId());
- return;
}
+ return;
}
log.debug("鍑虹墖澶ц溅璁惧瀹氭椂鍣ㄦ娴嬪埌宸插鐞嗙殑鐜荤拑淇℃伅: taskId={}, deviceId={}, glassCount={}",
@@ -974,7 +1064,7 @@
// 鏇存柊姝ラ鐘舵�侊紙澶ц溅璁惧淇濇寔RUNNING锛岀洿鍒癕ES纭瀹屾垚鎴栦换鍔″彇娑堬級
if (mesResult != null) {
- updateStepStatusForVehicle(step, mesResult);
+ updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
updateTaskProgress(task, step.getStepOrder(), opSuccess);
if (!opSuccess) {
@@ -982,7 +1072,7 @@
DeviceCoordinationService.DeviceStatus.FAILED, context);
}
} else {
- updateStepStatusForVehicle(step, feedResult);
+ updateStepStatusForVehicle(task.getTaskId(), step, feedResult);
boolean opSuccess = Boolean.TRUE.equals(feedResult.getSuccess());
updateTaskProgress(task, step.getStepOrder(), opSuccess);
if (!opSuccess) {
@@ -1030,14 +1120,57 @@
task.getTaskId(), device.getId());
return;
}
+ // 濡傛灉姝ラ宸茬粡瀹屾垚锛屼笉鍐嶅鐞�
+ if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
+ // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸插鐞嗗畬
+ @SuppressWarnings("unchecked")
+ List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+ List<String> processedGlassIds = getProcessedGlassIds(context);
+
+ if (initialGlassIds != null && !initialGlassIds.isEmpty()
+ && processedGlassIds != null && !processedGlassIds.isEmpty()
+ && processedGlassIds.containsAll(initialGlassIds)) {
+ // 鎵�鏈夌幓鐠冮兘宸插鐞嗗畬锛屼繚鎸佸畬鎴愮姸鎬�
+ log.debug("澶х悊鐗囩璁惧宸插畬鎴愪笖鎵�鏈夌幓鐠冨凡澶勭悊: taskId={}, deviceId={}, initialCount={}, processedCount={}",
+ task.getTaskId(), device.getId(), initialGlassIds.size(), processedGlassIds.size());
+ return;
+ }
+ }
+
// 澶х悊鐗囩璁惧锛氬彧鏈夊湪鐪熸寮�濮嬪鐞嗘椂鎵嶈缃负RUNNING
// 妫�鏌ユ槸鍚︽湁宸茶杞界殑鐜荤拑淇℃伅锛堜粠杩涚墖澶ц溅鏉ョ殑锛�
List<String> loadedGlassIds = getLoadedGlassIds(context);
if (CollectionUtils.isEmpty(loadedGlassIds)) {
- // 娌℃湁鏁版嵁锛屼繚鎸乄AITING鐘舵�佸拰PENDING姝ラ鐘舵��
+ // 娌℃湁鏁版嵁锛屾鏌ユ槸鍚︽墍鏈夌幓鐠冮兘宸插鐞嗗畬
+ @SuppressWarnings("unchecked")
+ List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+ List<String> processedGlassIds = getProcessedGlassIds(context);
+
+ if (initialGlassIds != null && !initialGlassIds.isEmpty()
+ && processedGlassIds != null && !processedGlassIds.isEmpty()
+ && processedGlassIds.containsAll(initialGlassIds)) {
+ // 鎵�鏈夌幓鐠冮兘宸插鐞嗗畬锛屾爣璁颁负瀹屾垚
+ if (!TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
+ step.setStatus(TaskStepDetail.Status.COMPLETED.name());
+ step.setSuccessMessage("鎵�鏈夌幓鐠冨凡澶勭悊瀹屾垚");
+ if (step.getEndTime() == null) {
+ step.setEndTime(new Date());
+ }
+ if (step.getStartTime() != null && step.getEndTime() != null) {
+ step.setDurationMs(step.getEndTime().getTime() - step.getStartTime().getTime());
+ }
+ taskStepDetailMapper.updateById(step);
+ notificationService.notifyStepUpdate(task.getTaskId(), step);
+ checkAndCompleteTaskIfDone(step.getTaskId());
+ }
+ return;
+ }
+
+ // 娌℃湁鏁版嵁涓旀湭瀹屾垚锛屼繚鎸乄AITING鐘舵�佸拰PENDING姝ラ鐘舵��
deviceCoordinationService.syncDeviceStatus(device,
DeviceCoordinationService.DeviceStatus.WAITING, context);
- if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+ if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())
+ && !TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
step.setStatus(TaskStepDetail.Status.PENDING.name());
step.setSuccessMessage("绛夊緟杩涚墖澶ц溅瑁呰浇鐜荤拑");
taskStepDetailMapper.updateById(step);
@@ -1141,7 +1274,14 @@
*/
private void setLoadedGlassIds(TaskExecutionContext context, List<String> glassIds) {
if (context != null) {
- context.getSharedData().put("loadedGlassIds", new ArrayList<>(glassIds));
+ // 绱姞璁板綍锛岄伩鍏嶅悗缁� containsAll 鍒ゆ柇鍥犺鐩栦涪澶卞巻鍙茬幓鐠冭�屽洖閫�涓虹瓑寰�
+ List<String> merged = new ArrayList<>(getLoadedGlassIds(context)); // 纭繚鍙彉
+ if (glassIds != null) {
+ merged.addAll(glassIds);
+ }
+ // 鍘婚噸
+ List<String> distinct = merged.stream().distinct().collect(java.util.stream.Collectors.toList());
+ context.getSharedData().put("loadedGlassIds", distinct);
}
}
@@ -1438,6 +1578,9 @@
}
step.setOutputData(toJson(result));
taskStepDetailMapper.updateById(step);
+ if (StringUtils.hasText(step.getTaskId())) {
+ notificationService.notifyStepUpdate(step.getTaskId(), step);
+ }
}
/**
@@ -1508,8 +1651,14 @@
/**
* 鏇存柊澶ц溅璁惧姝ラ鐘舵�侊紙淇濇寔RUNNING锛岀洿鍒版墜鍔ㄥ仠姝㈡垨浠诲姟鍙栨秷锛涘け璐ユ椂鏍囪涓篎AILED锛�
*/
- private void updateStepStatusForVehicle(TaskStepDetail step, DevicePlcVO.OperationResult result) {
+ private void updateStepStatusForVehicle(String taskId, TaskStepDetail step, DevicePlcVO.OperationResult result) {
if (step == null || result == null) {
+ return;
+ }
+ // 濡傛灉姝ラ宸茬粡澶勪簬瀹屾垚鎴栧け璐ョ姸鎬侊紝鍒欎笉鍐嶈閲嶅鏇存柊锛堥槻姝㈢姸鎬佸弽澶嶅垏鎹級
+ if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())
+ || TaskStepDetail.Status.FAILED.name().equals(step.getStatus())) {
+ log.debug("姝ラ宸插畬鎴愭垨澶辫触锛屼笉鍐嶆洿鏂扮姸鎬�: stepId={}, status={}", step.getId(), step.getStatus());
return;
}
boolean success = Boolean.TRUE.equals(result.getSuccess());
@@ -1546,16 +1695,20 @@
if (success && !completed) {
// 鎴愬姛浣嗘湭瀹屾垚锛氭牴鎹畐aiting鐘舵�佸喅瀹氭樉绀轰负绛夊緟杩樻槸鎵ц涓�
- if (waiting) {
+ // 娉ㄦ剰锛氬鏋滄楠ゅ凡缁忔槸RUNNING鐘舵�侊紙璇存槑宸茬粡瑁呰浇杩囩幓鐠冿級锛屼笉搴旇鏀瑰洖PENDING
+ boolean isAlreadyRunning = TaskStepDetail.Status.RUNNING.name().equals(step.getStatus());
+ if (waiting && !isAlreadyRunning) {
+ // 鍙湁鍦ㄨ繕娌℃湁寮�濮嬭繍琛屾椂锛屾墠璁剧疆涓篜ENDING
step.setStatus(TaskStepDetail.Status.PENDING.name());
} else {
+ // 濡傛灉宸茬粡杩愯杩囷紝鎴栬�呬笉鏄瓑寰呯姸鎬侊紝淇濇寔鎴栬缃负RUNNING
step.setStatus(TaskStepDetail.Status.RUNNING.name());
}
String message = result.getMessage();
if (!StringUtils.hasText(message) && waiting) {
message = "澶ц溅璁惧绛夊緟涓�" + (StringUtils.hasText(waitingReason) ? "锛�" + waitingReason + "锛�" : "");
}
- step.setSuccessMessage(StringUtils.hasText(message) ? message : (waiting ? "澶ц溅璁惧绛夊緟涓�" : "澶ц溅璁惧杩愯涓�"));
+ step.setSuccessMessage(StringUtils.hasText(message) ? message : (waiting && !isAlreadyRunning ? "澶ц溅璁惧绛夊緟涓�" : "澶ц溅璁惧杩愯涓�"));
step.setErrorMessage(null);
if (step.getStartTime() != null) {
step.setDurationMs(now.getTime() - step.getStartTime().getTime());
@@ -1589,6 +1742,8 @@
step.setOutputData(toJson(result));
taskStepDetailMapper.updateById(step);
+ // 閫氱煡鍓嶇姝ラ鐘舵�佸凡鏇存柊
+ notificationService.notifyStepUpdate(taskId, step);
}
/**
@@ -1629,9 +1784,48 @@
task.getTaskId(), device.getId(), e.getMessage());
}
+ // 濡傛灉MES宸茬‘璁ゅ畬鎴愶紙mesConfirm=1锛夛紝妫�鏌ュ崸杞珛璁惧鐘舵�佸拰鐜荤拑淇℃伅
+ // 濡傛灉鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鍙互鏍囪涓哄畬鎴�
+ if (mesResult != null && mesResult.getData() != null) {
+ Object completedFlag = mesResult.getData().get("completed");
+ boolean mesConfirmed = false;
+ if (completedFlag instanceof Boolean) {
+ mesConfirmed = (Boolean) completedFlag;
+ } else if (completedFlag != null) {
+ mesConfirmed = "true".equalsIgnoreCase(String.valueOf(completedFlag));
+ }
+
+ if (mesConfirmed) {
+ // MES宸茬‘璁ゅ畬鎴愶紝妫�鏌ュ崸杞珛璁惧鏄惁宸插畬鎴�
+ boolean transferCompleted = isTransferDeviceCompleted(task.getTaskId(), context);
+ if (transferCompleted) {
+ // 妫�鏌ヤ换鍔′笂涓嬫枃涓殑鍒濆鐜荤拑ID鍜屽凡瑁呰浇鐨勭幓鐠僆D
+ @SuppressWarnings("unchecked")
+ List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+ List<String> loadedGlassIds = getLoadedGlassIds(context);
+
+ if (initialGlassIds != null && !initialGlassIds.isEmpty()
+ && loadedGlassIds != null && !loadedGlassIds.isEmpty()) {
+ // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸茶杞�
+ boolean allGlassesLoaded = loadedGlassIds.containsAll(initialGlassIds);
+ if (allGlassesLoaded) {
+ // 鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鏍囪涓哄畬鎴�
+ log.info("MES宸茬‘璁や笖鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冨凡瑁呰浇锛屼换鍔¤嚜鍔ㄥ畬鎴�: taskId={}, deviceId={}, initialCount={}, loadedCount={}",
+ task.getTaskId(), device.getId(), initialGlassIds.size(), loadedGlassIds.size());
+ // mesResult宸茬粡鍖呭惈completed=true锛屼笉闇�瑕佷慨鏀�
+ }
+ }
+ } else {
+ // 鍗ц浆绔嬭繕鏈畬鎴愶紝涓嶅簲璇ユ爣璁颁负瀹屾垚
+ log.debug("MES宸茬‘璁や絾鍗ц浆绔嬫湭瀹屾垚锛岀瓑寰呭崸杞珛瀹屾垚: taskId={}, deviceId={}",
+ task.getTaskId(), device.getId());
+ }
+ }
+ }
+
// 鏇存柊姝ラ鐘舵��
if (mesResult != null) {
- updateStepStatusForVehicle(step, mesResult);
+ updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
updateTaskProgress(task, step.getStepOrder(), opSuccess);
if (!opSuccess) {
@@ -2455,6 +2649,66 @@
}
}
+ /**
+ * 妫�鏌ュ崸杞珛璁惧鏄惁宸插畬鎴�
+ * 杩斿洖true琛ㄧず鍗ц浆绔嬪凡瀹屾垚锛圕OMPLETED锛夛紝鍙互鍒ゆ柇澶ц溅鏄惁瀹屾垚
+ * 杩斿洖false琛ㄧず鍗ц浆绔嬭繕鍦ㄨ繍琛屼腑锛圧UNNING锛夋垨绛夊緟涓紙PENDING锛夛紝涓嶅簲璇ユ爣璁板ぇ杞︿负瀹屾垚
+ */
+ private boolean isTransferDeviceCompleted(String taskId, TaskExecutionContext context) {
+ if (taskId == null || context == null) {
+ return false;
+ }
+ try {
+ // 浠庝笂涓嬫枃涓幏鍙栬澶囧垪琛�
+ @SuppressWarnings("unchecked")
+ List<DeviceConfig> devices = (List<DeviceConfig>) context.getSharedData().get("devices");
+ if (devices == null || devices.isEmpty()) {
+ return false;
+ }
+
+ // 鏌ユ壘鍗ц浆绔嬭澶�
+ DeviceConfig transferDevice = null;
+ for (DeviceConfig device : devices) {
+ if (DeviceConfig.DeviceType.WORKSTATION_TRANSFER.equals(device.getDeviceType())) {
+ transferDevice = device;
+ break;
+ }
+ }
+
+ if (transferDevice == null) {
+ // 娌℃湁鍗ц浆绔嬭澶囷紝杩斿洖true锛堜笉褰卞搷鍒ゆ柇锛�
+ return true;
+ }
+
+ // 鏌ユ壘鍗ц浆绔嬭澶囩殑姝ラ锛堝簲璇ュ彧鏈変竴涓楠わ級
+ List<TaskStepDetail> transferSteps = taskStepDetailMapper.selectList(
+ Wrappers.<TaskStepDetail>lambdaQuery()
+ .eq(TaskStepDetail::getTaskId, taskId)
+ .eq(TaskStepDetail::getDeviceId, transferDevice.getId())
+ .orderByDesc(TaskStepDetail::getStepOrder)
+ .last("LIMIT 1")
+ );
+
+ if (transferSteps == null || transferSteps.isEmpty()) {
+ // 娌℃湁鎵惧埌姝ラ锛岃繑鍥瀎alse锛堝崸杞珛鍙兘杩樻病寮�濮嬶級
+ return false;
+ }
+
+ // 妫�鏌ユ楠ょ姸鎬侊細鍙湁COMPLETED鎵嶇畻瀹屾垚锛孯UNNING鎴朠ENDING閮戒笉绠楀畬鎴�
+ TaskStepDetail transferStep = transferSteps.get(0);
+ String status = transferStep.getStatus();
+ boolean isCompleted = TaskStepDetail.Status.COMPLETED.name().equals(status);
+
+ log.debug("妫�鏌ュ崸杞珛璁惧鐘舵��: taskId={}, deviceId={}, status={}, isCompleted={}",
+ taskId, transferDevice.getId(), status, isCompleted);
+
+ return isCompleted;
+ } catch (Exception e) {
+ log.warn("妫�鏌ュ崸杞珛璁惧鐘舵�佸け璐�: taskId={}", taskId, e);
+ return false;
+ }
+ }
+
private String determineOperation(DeviceConfig device, Map<String, Object> params) {
if (params != null && params.containsKey("operation")) {
Object op = params.get("operation");
--
Gitblit v1.8.0