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/interaction/vehicle/handler/LoadVehicleLogicHandler.java | 741 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 647 insertions(+), 94 deletions(-)
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 62569ad..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
@@ -62,9 +62,19 @@
private S7SerializerProvider s7SerializerProvider;
// MES瀛楁鍒楄〃锛堣繘鐗囧拰鍑虹墖鍏辩敤鍚屼竴濂楀崗璁級
+ // 鏍规嵁鍗忚锛屼娇鐢ㄥ甫鏁板瓧鍚庣紑鐨勫瓧娈靛悕锛�1-6瀵瑰簲6涓幓鐠冧綅缃級
+ // 鏀寔璇诲彇鎵�鏈�6涓幓鐠冪殑淇℃伅
private static final List<String> MES_FIELDS = Arrays.asList(
- "mesSend", "mesGlassId", "mesWidth", "mesHeight",
- "startSlot", "targetSlot", "workLine"
+ "mesSend", "mesConfirm",
+ // 鐜荤拑1-6鐨処D
+ "mesGlassId1", "mesGlassId2", "mesGlassId3", "mesGlassId4", "mesGlassId5", "mesGlassId6",
+ // 鐜荤拑1-6鐨勫昂瀵�
+ "mesWidth1", "mesWidth2", "mesWidth3", "mesWidth4", "mesWidth5", "mesWidth6",
+ "mesHeight1", "mesHeight2", "mesHeight3", "mesHeight4", "mesHeight5", "mesHeight6",
+ "mesThickness1", "mesThickness2", "mesThickness3", "mesThickness4", "mesThickness5", "mesThickness6",
+ // 鐜荤拑1-6鐨勮捣濮嬩綅缃拰鐩爣浣嶇疆
+ "start1", "start2", "start3", "start4", "start5", "start6",
+ "target1", "target2", "target3", "target4", "target5", "target6"
);
// 鐩戞帶绾跨▼姹狅細鐢ㄤ簬瀹氭湡妫�鏌ュぇ杞︾姸鎬佸苟鍗忚皟鍗ц浆绔嬭澶�
@@ -102,6 +112,10 @@
// 璁板綍褰撳墠浠诲姟锛歞eviceId -> 浠诲姟淇℃伅
private final Map<String, MesTaskInfo> currentTasks = new ConcurrentHashMap<>();
+ /**
+ * 璁板綍鏈�杩戜竴娆″凡瀹屾垚浣哅ES鏈浣嶇殑浠诲姟绛惧悕锛岄伩鍏嶉噸澶嶆媺璧�
+ */
+ private final Map<String, CompletedMesRecord> lastCompletedMesRecords = new ConcurrentHashMap<>();
@Autowired
public LoadVehicleLogicHandler(
@@ -131,14 +145,25 @@
if (needsStateCheck(operation)) {
VehicleStatus status = statusManager.getVehicleStatus(deviceId);
if (status != null && !status.isAvailable()) {
- return DevicePlcVO.OperationResult.builder()
- .success(false)
- .message(String.format("杞﹁締 %s (%s) 褰撳墠鐘舵�佷负 %s锛屾棤娉曟墽琛屾搷浣� %s",
- deviceConfig.getDeviceName(),
- deviceId,
- status.getState(),
- operation))
- .build();
+ // 瀵逛簬 feedGlass 鎿嶄綔锛屽鏋滅姸鎬佹槸 EXECUTING锛屽厑璁哥户缁墽琛�
+ // 鍥犱负瀹氭椂鍣ㄥ彲鑳戒細閲嶅璋冪敤锛屾垨鑰呴渶瑕佺瓑寰呬换鍔″畬鎴�
+ 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()
+ .success(false)
+ .message(String.format("杞﹁締 %s (%s) 褰撳墠鐘舵�佷负 %s锛屾棤娉曟墽琛屾搷浣� %s",
+ deviceConfig.getDeviceName(),
+ deviceId,
+ status.getState(),
+ operation))
+ .build();
+ }
}
}
@@ -196,6 +221,12 @@
break;
case "setOnlineState":
result = handleSetOnlineState(deviceConfig, params, logicParams);
+ break;
+ case "checkMesConfirm":
+ result = checkMesConfirm(deviceConfig, logicParams);
+ break;
+ case "markBroken":
+ result = handleMarkBroken(deviceConfig, params, logicParams);
break;
default:
log.warn("涓嶆敮鎸佺殑鎿嶄綔绫诲瀷: {}", operation);
@@ -317,8 +348,7 @@
// 浠庨�昏緫鍙傛暟涓幏鍙栭厤缃紙浠� extraParams.deviceLogic 璇诲彇锛�
Integer vehicleCapacity = getLogicParam(logicParams, "vehicleCapacity", 6000);
Integer glassGap = getLogicParam(logicParams, "glassGap", 200); // 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
- Boolean autoFeed = getLogicParam(logicParams, "autoFeed", true);
- Integer maxRetryCount = getLogicParam(logicParams, "maxRetryCount", 5);
+ Boolean autoFeed = getLogicParam(logicParams, "autoFeed", true); // 鑷姩涓婃枡锛氭槸鍚﹁嚜鍔ㄨЕ鍙戜笂鏂欒姹傦紙鍐欏叆plcRequest=1锛�
// 浠庤繍琛屾椂鍙傛暟涓幏鍙栨暟鎹紙浠庢帴鍙h皟鐢ㄦ椂浼犲叆锛�
List<GlassInfo> glassInfos = extractGlassInfos(params);
@@ -475,6 +505,10 @@
Map<String, Object> payload = new HashMap<>();
payload.put("plcRequest", 0);
payload.put("plcReport", 0);
+ // 娓呯┖state1~6锛岄伩鍏嶉仐鐣欑姸鎬佸鑷磋鍒�
+ for (int i = 1; i <= 6; i++) {
+ payload.put("state" + i, 0);
+ }
payload.put("onlineState", Boolean.TRUE);
log.info("澶ц溅璁惧閲嶇疆: deviceId={}", deviceConfig.getId());
@@ -490,7 +524,14 @@
statusManager.clearVehicleTask(deviceConfig.getDeviceId());
statusManager.updateVehicleStatus(deviceConfig.getDeviceId(), VehicleState.IDLE);
stopStateMonitoring(deviceConfig.getDeviceId());
+ handleStopTaskMonitor(deviceConfig);
+ handleStopIdleMonitor(deviceConfig);
updateDeviceOnlineStatus(deviceConfig, true);
+ } else {
+ // 鍗充究閲嶇疆澶辫触锛屼篃灏濊瘯鍋滄鍐呴儴鐩戞帶锛岄伩鍏嶄换鍔″彇娑堝悗浠嶇劧鍙嶅鍐橮LC
+ stopStateMonitoring(deviceConfig.getDeviceId());
+ handleStopTaskMonitor(deviceConfig);
+ handleStopIdleMonitor(deviceConfig);
}
return result;
@@ -572,7 +613,6 @@
payload.put(field, "");
}
- payload.put("plcGlassCount", 0);
payload.put("plcRequest", 0);
payload.put("plcReport", 0);
payload.put("onlineState", Boolean.TRUE);
@@ -590,13 +630,23 @@
payload,
"澶ц溅璁惧-娓呯┖鐜荤拑鏁版嵁"
);
+
+ // 鍚屾娓呯┖state1~6绛夊姩鎬佸瓧娈碉紙鍦ㄥ姩鎬佹暟鎹尯涓級
+ clearDynamicTaskStates(deviceConfig);
// 娓呯┖鍚庯紝鎭㈠涓虹┖闂茬姸鎬侊紝鍋滄鐩戞帶
if (Boolean.TRUE.equals(result.getSuccess())) {
statusManager.clearVehicleTask(deviceConfig.getDeviceId());
statusManager.updateVehicleStatus(deviceConfig.getDeviceId(), VehicleState.IDLE);
stopStateMonitoring(deviceConfig.getDeviceId());
+ handleStopTaskMonitor(deviceConfig);
+ handleStopIdleMonitor(deviceConfig);
updateDeviceOnlineStatus(deviceConfig, true);
+ } else {
+ // 鍐欏叆澶辫触涔熷皾璇曞仠姝㈢洃鎺э紝閬垮厤浠诲姟鍙栨秷鍚庝粛鏃ц繍琛�
+ stopStateMonitoring(deviceConfig.getDeviceId());
+ handleStopTaskMonitor(deviceConfig);
+ handleStopIdleMonitor(deviceConfig);
}
return result;
@@ -663,9 +713,8 @@
Map<String, Object> defaultParams = new HashMap<>();
defaultParams.put("vehicleCapacity", 6000);
defaultParams.put("glassGap", 200); // 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
- defaultParams.put("autoFeed", true);
+ defaultParams.put("autoFeed", true); // 鑷姩涓婃枡锛氭槸鍚﹁嚜鍔ㄨЕ鍙戜笂鏂欒姹傦紙鍐欏叆plcRequest=1锛夛紝榛樿true
defaultParams.put("maxRetryCount", 5);
- defaultParams.put("defaultGlassLength", 2000);
// MES浠诲姟鐩稿叧閰嶇疆
defaultParams.put("vehicleSpeed", 1.0); // 杞﹁締閫熷害锛堟牸/绉掞紝grid/s锛夛紝榛樿1鏍�/绉�
@@ -768,7 +817,7 @@
* @param vehicleCapacity 杞﹁締瀹归噺锛坢m锛�
* @param glassGap 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
* @param deviceId 璁惧ID锛堢敤浜庢棩蹇楋級
- * @return 瑙勫垝鍚庣殑鐜荤拑鍒楄〃锛屽鏋滅幓鐠冩病鏈夐暱搴﹀垯杩斿洖null锛堢敤浜庢祴璇昅ES绋嬪簭锛�
+ * @return 瑙勫垝鍚庣殑鐜荤拑鍒楄〃锛屽鏋滅幓鐠冩病鏈夐暱搴﹀垯杩斿洖null锛圡ES鏈彁渚涢暱搴︽暟鎹級
*/
private List<GlassInfo> planGlassLoading(List<GlassInfo> source,
int vehicleCapacity,
@@ -782,8 +831,8 @@
for (GlassInfo info : source) {
Integer glassLength = info.getLength();
+ // 濡傛灉鐜荤拑娌℃湁闀垮害锛岃鏄嶮ES鏈彁渚涳紝鐩存帴鎶ラ敊
if (glassLength == null || glassLength <= 0) {
- // 鐜荤拑娌℃湁闀垮害锛岀洿鎺ユ姤閿欙紙鐢ㄤ簬娴嬭瘯MES绋嬪簭锛�
log.error("鐜荤拑[{}]缂哄皯闀垮害鏁版嵁锛屾棤娉曡繘琛屽閲忚绠椼�俤eviceId={}锛岃妫�鏌ES绋嬪簭鏄惁姝g‘鎻愪緵鐜荤拑闀垮害銆�",
info.getGlassId(), deviceId);
return null;
@@ -1278,84 +1327,177 @@
}
try {
+ // 妫�鏌ユ槸鍚﹀凡鏈変换鍔″湪鎵ц涓�
+ MesTaskInfo existingTask = currentTasks.get(deviceId);
+ if (existingTask != null) {
+ log.debug("璁惧宸叉湁浠诲姟鍦ㄦ墽琛屼腑锛岃烦杩囨鏌ES浠诲姟: deviceId={}", deviceId);
+ return DevicePlcVO.OperationResult.builder()
+ .success(true)
+ .message("浠诲姟鎵ц涓紝鏃犻渶閲嶅妫�鏌ES浠诲姟")
+ .data(Collections.singletonMap("waiting", false))
+ .build();
+ }
+
// 璇诲彇MES瀛楁锛堣繘鐗囧拰鍑虹墖鍏辩敤锛�
Map<String, Object> mesData = plcDynamicDataService.readPlcData(
deviceConfig, MES_FIELDS, serializer);
if (mesData == null || mesData.isEmpty()) {
+ log.warn("璇诲彇MES瀛楁澶辫触: deviceId={}, mesData涓虹┖鎴杗ull", deviceId);
return DevicePlcVO.OperationResult.builder()
.success(false)
.message("璇诲彇MES瀛楁澶辫触")
.build();
}
-
+
+ // 瑙f瀽mesSend
Integer mesSend = parseInteger(mesData.get("mesSend"));
+
if (mesSend == null || mesSend == 0) {
+ Map<String, Object> waitData = new HashMap<>();
+ waitData.put("completed", false);
+ waitData.put("waiting", true);
+ waitData.put("waitingReason", "mesSend=0");
return DevicePlcVO.OperationResult.builder()
.success(true)
- .message("鏆傛棤MES浠诲姟锛坢esSend=0锛�")
+ .message("绛夊緟MES鍙戦�佽姹傦紙mesSend=0锛�")
+ .data(waitData)
.build();
}
- // mesSend=1锛岃鍙栦换鍔″弬鏁�
- String glassId = parseString(mesData.get("mesGlassId"));
- Integer startSlot = parseInteger(mesData.get("startSlot")); // 璧峰浣嶇疆缂栧彿
- Integer targetSlot = parseInteger(mesData.get("targetSlot")); // 鐩爣浣嶇疆缂栧彿
- Integer workLine = parseInteger(mesData.get("workLine"));
-
- if (glassId == null || glassId.isEmpty()) {
- return DevicePlcVO.OperationResult.builder()
- .success(false)
- .message("MES鏈彁渚涚幓鐠僆D")
- .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();
+ }
}
- // 鍒ゆ柇鏄繘鐗囪繕鏄嚭鐗囦换鍔�
- // 鏂规硶锛氶�氳繃startSlot鍒ゆ柇
- // - 濡傛灉startSlot鏄崸杞珛缂栧彿锛堝900/901锛夛紝鍒欐槸杩涚墖浠诲姟
- // - 濡傛灉startSlot鏄牸瀛愮紪鍙凤紙鍦ㄥぇ鐞嗙墖绗艰寖鍥村唴锛夛紝鍒欐槸鍑虹墖浠诲姟
- boolean isOutbound = isOutboundTask(startSlot, logicParams);
+ // mesSend=1锛岃褰曟棩蹇�
+ log.info("妫�娴嬪埌mesSend=1锛屽紑濮嬭鍙朚ES浠诲姟淇℃伅: deviceId={}", deviceId);
- // 浣嶇疆鏄犲皠
- Integer startPosition;
- if (isOutbound) {
- // 鍑虹墖浠诲姟锛歴tartSlot鏄牸瀛愮紪鍙凤紝闇�瑕佹槧灏勫埌瀹為檯浣嶇疆
- startPosition = mapOutboundPosition(startSlot, logicParams);
- } else {
- // 杩涚墖浠诲姟锛歴tartSlot鏄崸杞珛缂栧彿锛岄�氳繃positionMapping鏄犲皠
- startPosition = mapPosition(startSlot, logicParams);
+ // mesSend=1锛岃鍙栨墍鏈夌幓鐠冪殑浠诲姟鍙傛暟锛堟敮鎸�1-6涓幓鐠冿級
+ List<GlassTaskInfo> glasses = new ArrayList<>();
+ boolean isOutbound = false; // 灏嗗湪澶勭悊绗竴涓湁鏁堢幓鐠冩椂纭畾
+
+ // 璇诲彇鎵�鏈�6涓幓鐠冪殑淇℃伅
+ for (int i = 1; i <= 6; i++) {
+ String glassId = parseString(mesData.get("mesGlassId" + i));
+ if (glassId == null || glassId.isEmpty()) {
+ continue; // 璺宠繃绌虹殑鐜荤拑ID
+ }
+
+ Integer startSlot = parseInteger(mesData.get("start" + i));
+ Integer targetSlot = parseInteger(mesData.get("target" + i));
+ Integer width = parseInteger(mesData.get("mesWidth" + i));
+ Integer height = parseInteger(mesData.get("mesHeight" + i));
+ Integer thickness = parseInteger(mesData.get("mesThickness" + i));
+
+ log.debug("璇诲彇鐜荤拑{}淇℃伅: deviceId={}, glassId={}, startSlot={}, targetSlot={}, width={}, height={}, thickness={}",
+ i, deviceId, glassId, startSlot, targetSlot, width, height, thickness);
+
+ if (startSlot == null || targetSlot == null) {
+ log.warn("鐜荤拑{}淇℃伅涓嶅畬鏁达紝璺宠繃: glassId={}, startSlot={}, targetSlot={}",
+ i, glassId, startSlot, targetSlot);
+ continue;
+ }
+
+ // 瀵逛簬绗竴涓湁鏁堢幓鐠冿紝鍒ゆ柇鏄繘鐗囪繕鏄嚭鐗囦换鍔�
+ if (glasses.isEmpty()) {
+ isOutbound = isOutboundTask(startSlot, logicParams);
+ }
+
+ // 浣嶇疆鏄犲皠
+ Integer startPosition;
+ if (isOutbound) {
+ // 鍑虹墖浠诲姟锛歴tartSlot鏄牸瀛愮紪鍙凤紝闇�瑕佹槧灏勫埌瀹為檯浣嶇疆
+ startPosition = mapOutboundPosition(startSlot, logicParams);
+ } else {
+ // 杩涚墖浠诲姟锛歴tartSlot鏄崸杞珛缂栧彿锛岄�氳繃positionMapping鏄犲皠
+ startPosition = mapPosition(startSlot, logicParams);
+ }
+
+ // targetSlot缁熶竴閫氳繃positionMapping鏄犲皠
+ Integer targetPosition = mapPosition(targetSlot, logicParams);
+
+ if (startPosition == null || targetPosition == null) {
+ log.warn("鐜荤拑{}浣嶇疆鏄犲皠澶辫触锛岃烦杩�: glassId={}, startSlot={}, targetSlot={}",
+ i, glassId, startSlot, targetSlot);
+ continue;
+ }
+
+ // 鍒涘缓鐜荤拑浠诲姟淇℃伅
+ GlassTaskInfo glassInfo = new GlassTaskInfo();
+ glassInfo.glassId = glassId;
+ glassInfo.startSlot = startSlot;
+ glassInfo.targetSlot = targetSlot;
+ glassInfo.startPosition = startPosition;
+ glassInfo.targetPosition = targetPosition;
+ glassInfo.width = width;
+ glassInfo.height = height;
+ glassInfo.thickness = thickness;
+ glasses.add(glassInfo);
}
- // targetSlot缁熶竴閫氳繃positionMapping鏄犲皠
- Integer targetPosition = mapPosition(targetSlot, logicParams);
-
- if (startPosition == null || targetPosition == null) {
+ if (glasses.isEmpty()) {
+ // 璁板綍璇︾粏鐨凪ES鏁版嵁锛屽府鍔╄皟璇�
+ log.warn("MES鏈彁渚涙湁鏁堢殑鐜荤拑淇℃伅: deviceId={}, mesSend={}, mesData={}",
+ deviceId, mesSend, mesData);
+ Map<String, Object> waitData = new HashMap<>();
+ waitData.put("completed", false);
+ waitData.put("waiting", true);
+ waitData.put("waitingReason", "glassInfoMissing");
return DevicePlcVO.OperationResult.builder()
.success(false)
- .message(String.format("浣嶇疆鏄犲皠澶辫触: startSlot=%s, targetSlot=%s, isOutbound=%s",
- startSlot, targetSlot, isOutbound))
+ .message("MES鏈彁渚涙湁鏁堢殑鐜荤拑淇℃伅锛坢esSend=1浣嗘湭鎵惧埌鏈夋晥鐨刧lassId銆乻tartSlot銆乼argetSlot锛�")
+ .data(waitData)
.build();
}
// 璇诲彇褰撳墠浣嶇疆
Integer currentPosition = getCurrentPosition(deviceConfig, logicParams);
- // 璁$畻鏃堕棿
+ // 浣跨敤绗竴涓幓鐠冪殑浣嶇疆璁$畻鏃堕棿锛堟墍鏈夌幓鐠冧娇鐢ㄧ浉鍚岀殑璺緞锛�
+ GlassTaskInfo firstGlass = glasses.get(0);
TimeCalculation timeCalc = calculateTime(
- currentPosition, startPosition, targetPosition, logicParams);
+ currentPosition, firstGlass.startPosition, firstGlass.targetPosition, logicParams);
// 鍒涘缓浠诲姟淇℃伅
MesTaskInfo taskInfo = new MesTaskInfo();
- taskInfo.glassId = glassId;
- taskInfo.startSlot = startSlot;
- taskInfo.targetSlot = targetSlot;
- taskInfo.startPosition = startPosition;
- taskInfo.targetPosition = targetPosition;
+ taskInfo.glasses = glasses;
taskInfo.currentPosition = currentPosition;
taskInfo.gotime = timeCalc.gotime;
taskInfo.cartime = timeCalc.cartime;
- taskInfo.workLine = workLine;
taskInfo.createdTime = System.currentTimeMillis();
taskInfo.isOutbound = isOutbound;
+ taskInfo.mesSignature = mesSignature;
+
+ // 浠庨厤缃腑璇诲彇鐮存崯鐜荤拑绱㈠紩锛堢敤浜庢祴璇曞満鏅級
+ // 閰嶇疆鏍煎紡锛歜rokenGlassIndices: [0, 2] 琛ㄧず绗�1涓拰绗�3涓幓鐠冨簲璇ョ牬鎹�
+ @SuppressWarnings("unchecked")
+ List<Integer> brokenIndices = getLogicParam(logicParams, "brokenGlassIndices", null);
+ if (brokenIndices != null && !brokenIndices.isEmpty()) {
+ taskInfo.brokenGlassIndices = new ArrayList<>();
+ for (Integer index : brokenIndices) {
+ if (index != null && index >= 0 && index < glasses.size()) {
+ taskInfo.brokenGlassIndices.add(index);
+ }
+ }
+ if (!taskInfo.brokenGlassIndices.isEmpty()) {
+ log.info("浠诲姟鍒涘缓鏃舵爣璁扮牬鎹熺幓鐠�: deviceId={}, brokenIndices={}",
+ deviceId, taskInfo.brokenGlassIndices);
+ }
+ }
currentTasks.put(deviceId, taskInfo);
@@ -1363,23 +1505,43 @@
Map<String, Object> payload = new HashMap<>();
payload.put("plcRequest", 0);
plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
+ log.info("宸叉竻绌簆lcRequest=0: deviceId={}", deviceId);
// 鏇存柊杞﹁締鐘舵�佷负鎵ц涓�
statusManager.updateVehicleStatus(deviceId, deviceConfig.getDeviceName(), VehicleState.EXECUTING);
// 鍚姩浠诲姟鐩戞帶
handleStartTaskMonitor(deviceConfig, params, logicParams);
+ log.info("宸插惎鍔ㄤ换鍔$洃鎺�: deviceId={}", deviceId);
String taskType = isOutbound ? "鍑虹墖" : "杩涚墖";
- log.info("MES{}浠诲姟宸插垱寤�: deviceId={}, glassId={}, startSlot={}(浣嶇疆{}鏍�), targetSlot={}(浣嶇疆{}鏍�), 璺濈{}鏍�->{}鏍�, gotime={}ms({}绉�), cartime={}ms({}绉�)",
- taskType, deviceId, glassId, startSlot, startPosition, targetSlot, targetPosition,
- Math.abs(startPosition - currentPosition), Math.abs(targetPosition - startPosition),
+ String glassIds = glasses.stream()
+ .map(g -> g.glassId)
+ .collect(java.util.stream.Collectors.joining(","));
+ log.info("MES{}浠诲姟宸插垱寤�: deviceId={}, glassCount={}, glassIds=[{}], 璧峰浣嶇疆={}鏍�, 鐩爣浣嶇疆={}鏍�, 璺濈{}鏍�->{}鏍�, gotime={}ms({}绉�), cartime={}ms({}绉�)",
+ taskType, deviceId, glasses.size(), glassIds,
+ firstGlass.startPosition, firstGlass.targetPosition,
+ Math.abs(firstGlass.startPosition - currentPosition),
+ Math.abs(firstGlass.targetPosition - firstGlass.startPosition),
timeCalc.gotime, timeCalc.gotime / 1000.0, timeCalc.cartime, timeCalc.cartime / 1000.0);
+
+ // 鏋勫缓璇︾粏鐨勬楠ゆ彁绀轰俊鎭�
+ StringBuilder stepMessage = new StringBuilder();
+ stepMessage.append("妫�娴嬪埌MES浠诲姟锛坢esSend=1锛夛紝宸叉竻绌鸿姹傚瓧锛坧lcRequest=0锛�");
+ stepMessage.append("锛涘紑濮嬭绠楁椂闂达紝棰勮鍒拌揪璧峰浣嶇疆鑰楁椂").append(timeCalc.gotime / 1000.0).append("绉�");
+ stepMessage.append("锛岃繍杈撳埌鐩爣浣嶇疆鑰楁椂").append(timeCalc.cartime / 1000.0).append("绉�");
+ if (!isOutbound) {
+ stepMessage.append("锛涜繘鐗囦换鍔★細绛夊緟鐜荤拑涓婅溅鍚庯紝灏嗗憡鐭ュ崸杞珛璁惧");
+ }
+
+ Map<String, Object> successData = new HashMap<>();
+ successData.put("waiting", false);
+ successData.put("taskStarted", true);
return DevicePlcVO.OperationResult.builder()
.success(true)
- .message(String.format("MES%s浠诲姟宸插垱寤�: glassId=%s, start=%d, target=%d",
- taskType, glassId, startPosition, targetPosition))
+ .message(stepMessage.toString())
+ .data(successData)
.build();
} catch (Exception e) {
@@ -1531,7 +1693,22 @@
}
// 鑾峰彇閫熷害锛堟牸/绉掞紝grid/s锛�
- Double speed = getLogicParam(logicParams, "vehicleSpeed", 1.0);
+ // 杩欓噷涓嶈兘鐩存帴鐢� Double 娉涘瀷锛屽惁鍒欏綋閰嶇疆閲屾槸 Integer 鏃朵細鍑虹幇
+ // java.lang.Integer cannot be cast to java.lang.Double 鐨勫紓甯�
+ Object speedObj = getLogicParam(logicParams, "vehicleSpeed", 1.0);
+ Double speed = null;
+ if (speedObj instanceof Double) {
+ speed = (Double) speedObj;
+ } else if (speedObj instanceof Integer) {
+ speed = ((Integer) speedObj).doubleValue();
+ } else if (speedObj instanceof Number) {
+ speed = ((Number) speedObj).doubleValue();
+ } else {
+ try {
+ speed = Double.parseDouble(String.valueOf(speedObj));
+ } catch (Exception ignore) {
+ }
+ }
if (speed == null || speed <= 0) {
speed = 1.0; // 榛樿1鏍�/绉�
}
@@ -1645,24 +1822,90 @@
long state1Time = taskInfo.gotime; // 鍒拌揪璧峰浣嶇疆锛屼笂杞﹀畬鎴�
long state2Time = taskInfo.gotime + taskInfo.cartime; // 鍒拌揪鐩爣浣嶇疆锛岃繍杈撳畬鎴�
- // 鏇存柊state鐘舵��
- if (elapsed >= state1Time && elapsed < state2Time) {
- // state搴旇涓�1
- if (taskInfo.isOutbound) {
- // 鍑虹墖浠诲姟锛氬埌杈炬簮浣嶇疆锛堝ぇ鐞嗙墖绗硷級锛屽彇鐗囧畬鎴�
- updateStateIfNeeded(deviceConfig, serializer, stateValues, 1, taskInfo);
- } else {
- // 杩涚墖浠诲姟锛氬埌杈捐捣濮嬩綅缃紙鍗ц浆绔嬶級锛屼笂杞﹀畬鎴�
- updateStateIfNeeded(deviceConfig, serializer, stateValues, 1, taskInfo);
- }
- } else if (elapsed >= state2Time) {
- // state搴旇涓�2锛堣繍杈撳畬鎴愶級
- updateStateIfNeeded(deviceConfig, serializer, stateValues, 2, taskInfo);
+ // 鑾峰彇瓒呮椂鏃堕棿閰嶇疆锛堥粯璁わ細瓒呰繃棰勬湡瀹屾垚鏃堕棿鐨�200%瑙嗕负瓒呮椂鏈畬鎴愶級
+ Double timeoutRatio = getLogicParam(logicParams, "state3TimeoutRatio", 2.0);
+ long state3TimeoutTime = (long) (state2Time * timeoutRatio); // 瓒呮椂鏃堕棿鐐�
+
+ // 鏇存柊state鐘舵�侊紙姣忎釜鐜荤拑瀵瑰簲涓�涓猻tate锛�
+ int glassCount = taskInfo.glasses.size();
+ boolean hasStateOne = false; // 鏍囪鏄惁鏈塻tate鍙樹负1
+ boolean hasStateTwo = false; // 鏍囪鏄惁鏈塻tate鍙樹负2
+ String currentStepDesc = ""; // 褰撳墠姝ラ鎻忚堪
+
+ for (int i = 0; i < glassCount && i < 6; i++) {
+ String stateField = "state" + (i + 1);
+ Object currentValue = stateValues.get(stateField);
+ Integer currentState = parseInteger(currentValue);
- // 妫�鏌ユ槸鍚︽墍鏈塻tate閮�>=2锛屽鏋滄槸鍒欑粰MES姹囨姤
- if (allStatesCompleted(stateValues)) {
- reportToMes(deviceConfig, serializer, taskInfo, logicParams);
+ // 濡傛灉褰撳墠state宸茬粡鏄�3锛堟湭瀹屾垚锛夋垨8锛堢牬鎹燂級锛岃烦杩�
+ if (currentState != null && (currentState == 3 || currentState == 8)) {
+ continue;
}
+
+ // 浼樺厛妫�鏌ユ槸鍚︽爣璁颁负鐮存崯锛坰tate=8锛�
+ // 妫�鏌ヤ换鍔′俊鎭腑鏄惁鏍囪浜嗚鐜荤拑涓虹牬鎹�
+ if (taskInfo.brokenGlassIndices != null && taskInfo.brokenGlassIndices.contains(i)) {
+ updateStateIfNeeded(deviceConfig, serializer, stateValues, stateField, 8, taskInfo);
+ log.info("鐜荤拑鏍囪涓虹牬鎹�: deviceId={}, stateField={}, glassIndex={}",
+ deviceConfig.getDeviceId(), stateField, i);
+ continue;
+ }
+
+ // 妫�鏌ヨ秴鏃舵湭瀹屾垚锛坰tate=3锛�
+ if (elapsed >= state3TimeoutTime && (currentState == null || currentState < 2)) {
+ updateStateIfNeeded(deviceConfig, serializer, stateValues, stateField, 3, taskInfo);
+ log.warn("浠诲姟瓒呮椂鏈畬鎴�: deviceId={}, stateField={}, elapsed={}ms, expectedTime={}ms",
+ deviceConfig.getDeviceId(), stateField, elapsed, state2Time);
+ continue;
+ }
+
+ // 姝e父鐘舵�佹洿鏂�
+ if (elapsed >= state1Time && elapsed < state2Time) {
+ // state搴旇涓�1锛堜笂杞﹀畬鎴愶級
+ boolean stateChanged = updateStateIfNeeded(deviceConfig, serializer, stateValues, stateField, 1, taskInfo);
+ if (stateChanged) {
+ hasStateOne = true;
+ currentStepDesc = "鐜荤拑宸蹭笂杞︼紙state=1锛夛紝姝e湪杩愯緭鍒扮洰鏍囦綅缃�";
+ } else if (currentState != null && currentState == 1) {
+ currentStepDesc = "鐜荤拑宸蹭笂杞︼紙state=1锛夛紝姝e湪杩愯緭鍒扮洰鏍囦綅缃�";
+ }
+ } else if (elapsed >= state2Time) {
+ // state搴旇涓�2锛堣繍杈撳畬鎴愶級
+ boolean stateChanged = updateStateIfNeeded(deviceConfig, serializer, stateValues, stateField, 2, taskInfo);
+ if (stateChanged) {
+ hasStateTwo = true;
+ currentStepDesc = "鐜荤拑宸插埌杈剧洰鏍囦綅缃紙state=2锛夛紝绛夊緟MES纭";
+ } else if (currentState != null && currentState == 2) {
+ currentStepDesc = "鐜荤拑宸插埌杈剧洰鏍囦綅缃紙state=2锛夛紝绛夊緟MES纭";
+ }
+ } else {
+ // 杩樺湪鍓嶅線璧峰浣嶇疆
+ currentStepDesc = "姝e湪鍓嶅線璧峰浣嶇疆锛岄璁¤�楁椂" + (state1Time / 1000.0) + "绉�";
+ }
+ }
+
+ // 褰搒tate鍙樹负1鏃讹紙鐜荤拑涓婅溅瀹屾垚锛夛紝娓呯┖鍗ц浆绔嬭澶囩殑plcRequest锛堝彧鎵ц涓�娆★級
+ if (hasStateOne && !taskInfo.transferPlcRequestCleared) {
+ clearTransferPlcRequest(deviceConfig, logicParams);
+ taskInfo.transferPlcRequestCleared = true; // 鏍囪宸叉竻绌猴紝閬垮厤閲嶅鎵ц
+ if (!taskInfo.isOutbound) {
+ currentStepDesc = "鐜荤拑宸蹭笂杞︼紙state=1锛夛紝宸插憡鐭ュ崸杞珛璁惧锛坧lcRequest=0锛夛紝姝e湪杩愯緭鍒扮洰鏍囦綅缃�";
+ }
+ }
+
+ // 妫�鏌ユ槸鍚︽墍鏈塻tate閮�>=2锛屽鏋滄槸鍒欑粰MES姹囨姤
+ if (elapsed >= state2Time && allStatesCompleted(stateValues, glassCount)) {
+ reportToMes(deviceConfig, serializer, taskInfo, logicParams);
+ // 璁板綍MES纭寮�濮嬬瓑寰呯殑鏃堕棿锛堝彧璁板綍涓�娆★級
+ if (taskInfo.mesConfirmStartTime == null) {
+ taskInfo.mesConfirmStartTime = System.currentTimeMillis();
+ currentStepDesc = "鐜荤拑宸插埌杈剧洰鏍囦綅缃紙state=2锛夛紝宸插彂閫佹眹鎶ワ紙plcReport=1锛夛紝绛夊緟MES纭";
+ }
+ }
+
+ // 淇濆瓨褰撳墠姝ラ鎻忚堪鍒颁换鍔′俊鎭腑锛屼緵checkMesConfirm浣跨敤
+ if (!currentStepDesc.isEmpty()) {
+ taskInfo.currentStepDesc = currentStepDesc;
}
} catch (Exception e) {
@@ -1672,30 +1915,97 @@
/**
* 鏇存柊state鐘舵�侊紙濡傛灉闇�瑕侊級
+ * @return 鏄惁鍙戠敓浜嗙姸鎬佸彉鍖栵紙浠庨潪鐩爣鐘舵�佸彉涓虹洰鏍囩姸鎬侊級
*/
- private void updateStateIfNeeded(DeviceConfig deviceConfig,
+ private boolean updateStateIfNeeded(DeviceConfig deviceConfig,
EnhancedS7Serializer serializer,
Map<String, Object> currentStates,
+ String stateField,
int targetState,
MesTaskInfo taskInfo) {
- // 杩欓噷鍙互鏍规嵁瀹為檯闇�姹傛洿鏂皊tate瀛楁
- // 鏆傛椂鍙褰曟棩蹇楋紝瀹為檯鏇存柊鍙兘闇�瑕佹牴鎹叿浣揚LC瀛楁閰嶇疆
- log.debug("浠诲姟鐘舵�佹洿鏂�: deviceId={}, targetState={}",
- deviceConfig.getDeviceId(), targetState);
+ // 妫�鏌ュ綋鍓峴tate鍊�
+ Object currentValue = currentStates.get(stateField);
+ Integer currentState = parseInteger(currentValue);
+
+ // 濡傛灉褰撳墠state灏忎簬鐩爣state锛屽垯鏇存柊
+ // 娉ㄦ剰锛氬鏋滃綋鍓峴tate宸茬粡鏄�3锛堟湭瀹屾垚锛夋垨8锛堢牬鎹燂級锛屼笉鍐嶆洿鏂�
+ if (currentState != null && (currentState == 3 || currentState == 8)) {
+ log.debug("浠诲姟鐘舵�佸凡涓哄紓甯哥姸鎬侊紝涓嶅啀鏇存柊: deviceId={}, stateField={}, currentState={}, targetState={}",
+ deviceConfig.getDeviceId(), stateField, currentState, targetState);
+ return false;
+ }
+
+ if (currentState == null || currentState < targetState) {
+ // 瀹為檯鍐欏叆PLC鐨剆tate瀛楁
+ try {
+ Map<String, Object> payload = new HashMap<>();
+ payload.put(stateField, targetState);
+ plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
+
+ log.info("浠诲姟鐘舵�佸凡鏇存柊鍒癙LC: deviceId={}, stateField={}, currentState={}, targetState={}",
+ deviceConfig.getDeviceId(), stateField, currentState, targetState);
+ // 杩斿洖true琛ㄧず鐘舵�佸彂鐢熶簡鍙樺寲
+ return true;
+ } catch (Exception e) {
+ log.error("鍐欏叆PLC state瀛楁澶辫触: deviceId={}, stateField={}, targetState={}, error={}",
+ deviceConfig.getDeviceId(), stateField, targetState, e.getMessage());
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 娓呯┖鍗ц浆绔嬭澶囩殑plcRequest锛堝綋澶ц溅state=1鏃讹紝琛ㄧず鐜荤拑宸蹭笂杞︼級
+ */
+ private void clearTransferPlcRequest(DeviceConfig deviceConfig, Map<String, Object> logicParams) {
+ try {
+ // 鏌ユ壘鍚岀粍鐨勫崸杞珛璁惧
+ List<DeviceConfig> transferDevices = findTransferDevicesInSameGroup(deviceConfig);
+ if (transferDevices.isEmpty()) {
+ log.debug("鏈壘鍒板悓缁勭殑鍗ц浆绔嬭澶囷紝璺宠繃娓呯┖plcRequest: deviceId={}", deviceConfig.getId());
+ return;
+ }
+
+ // 灏嗘瘡涓崸杞珛璁惧鐨� plcRequest 缃� 0
+ for (DeviceConfig transferDevice : transferDevices) {
+ Map<String, Object> payload = new HashMap<>();
+ payload.put("plcRequest", 0);
+
+ DevicePlcVO.OperationResult result = devicePlcOperationService.writeFields(
+ transferDevice.getId(),
+ payload,
+ "澶ц溅state=1鑷姩娓呯┖鍗ц浆绔嬭姹�"
+ );
+
+ if (Boolean.TRUE.equals(result.getSuccess())) {
+ log.info("宸茶嚜鍔ㄦ竻绌哄崸杞珛璁惧 plcRequest: vehicleDeviceId={}, transferDeviceId={}, transferDeviceName={}",
+ deviceConfig.getId(), transferDevice.getId(), transferDevice.getDeviceName());
+ } else {
+ log.warn("鑷姩娓呯┖鍗ц浆绔嬭澶� plcRequest 澶辫触: vehicleDeviceId={}, transferDeviceId={}, message={}",
+ deviceConfig.getId(), transferDevice.getId(), result.getMessage());
+ }
+ }
+ } catch (Exception e) {
+ log.error("娓呯┖鍗ц浆绔嬭澶噋lcRequest寮傚父: deviceId={}", deviceConfig.getId(), e);
+ }
}
/**
* 妫�鏌ユ槸鍚︽墍鏈塻tate閮藉凡瀹屾垚锛�>=2锛�
*/
- private boolean allStatesCompleted(Map<String, Object> stateValues) {
- for (Object value : stateValues.values()) {
+ private boolean allStatesCompleted(Map<String, Object> stateValues, int glassCount) {
+ // 鍙鏌ュ疄闄呮湁鐜荤拑鐨剆tate瀛楁
+ for (int i = 1; i <= glassCount && i <= 6; i++) {
+ String stateField = "state" + i;
+ Object value = stateValues.get(stateField);
Integer state = parseInteger(value);
if (state == null || state < 2) {
return false;
}
}
- return !stateValues.isEmpty();
+ return glassCount > 0;
}
/**
@@ -1713,8 +2023,11 @@
plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
String taskType = taskInfo.isOutbound ? "鍑虹墖" : "杩涚墖";
- log.info("宸茬粰MES姹囨姤({}浠诲姟): deviceId={}, glassId={}",
- taskType, deviceConfig.getDeviceId(), taskInfo.glassId);
+ String glassIds = taskInfo.glasses.stream()
+ .map(g -> g.glassId)
+ .collect(java.util.stream.Collectors.joining(","));
+ log.info("宸茬粰MES姹囨姤({}浠诲姟): deviceId={}, glassCount={}, glassIds=[{}]",
+ taskType, deviceConfig.getDeviceId(), taskInfo.glasses.size(), glassIds);
// 澶氳澶囦换鍔″満鏅笅锛屼笉鍦ㄨ繖閲岄樆濉炵瓑寰匨ES纭锛岀敱浠诲姟寮曟搸瀹氭椂璋冪敤checkMesConfirm
} catch (Exception e) {
@@ -1742,8 +2055,93 @@
.build();
}
+ String deviceId = deviceConfig.getDeviceId();
+ MesTaskInfo taskInfo = currentTasks.get(deviceId);
+
+ // 濡傛灉娌℃湁浠诲姟璁板綍锛屼紭鍏堝皾璇曡ˉ鍋挎�у湴妫�鏌ヤ竴娆ES浠诲姟锛堥伩鍏嶅洜鏃跺簭闂涓�鐩磏oTask锛�
+ if (taskInfo == null) {
+ log.info("妫�鏌ES纭鏃舵湭鎵惧埌浠诲姟璁板綍锛屽皾璇曡ˉ鍋挎鏌ES浠诲姟: deviceId={}", deviceId);
+ try {
+ DevicePlcVO.OperationResult checkResult =
+ handleCheckMesTask(deviceConfig, Collections.emptyMap(), logicParams);
+ if (Boolean.TRUE.equals(checkResult.getSuccess())) {
+ taskInfo = currentTasks.get(deviceId);
+ if (taskInfo != null) {
+ log.info("琛ュ伩妫�鏌ES浠诲姟鎴愬姛锛屽凡鍒涘缓浠诲姟璁板綍: deviceId={}", deviceId);
+ } else {
+ log.info("琛ュ伩妫�鏌ES浠诲姟鎵ц鎴愬姛浣嗘湭鍒涘缓浠诲姟璁板綍: deviceId={}, message={}",
+ deviceId, checkResult.getMessage());
+ }
+ } else {
+ log.warn("琛ュ伩妫�鏌ES浠诲姟澶辫触: deviceId={}, message={}", deviceId, checkResult.getMessage());
+ }
+ } catch (Exception e) {
+ log.warn("琛ュ伩妫�鏌ES浠诲姟寮傚父: deviceId={}, error={}", deviceId, e.getMessage());
+ }
+ }
+
+ // 琛ュ伩鍚庝粛鐒舵病鏈変换鍔¤褰曪紝璇存槑MES灏氭湭鎻愪緵鍙墽琛屼换鍔�
+ if (taskInfo == null) {
+ Map<String, Object> waitData = new HashMap<>();
+ waitData.put("completed", false);
+ waitData.put("waiting", true);
+ waitData.put("waitingReason", "noTask");
+ return DevicePlcVO.OperationResult.builder()
+ .success(true)
+ .message("绛夊緟MES鍙戦�佽姹傦紙mesSend=1锛�")
+ .data(waitData)
+ .build();
+ }
+
+ // 鑾峰彇MES纭瓒呮椂閰嶇疆锛堥粯璁�30绉掞級
+ Integer mesConfirmTimeoutMs = getLogicParam(logicParams, "mesConfirmTimeoutMs", 30000);
+
Map<String, Object> data = new HashMap<>();
try {
+ // 濡傛灉灏氭湭鍚慚ES姹囨姤锛坧lcReport=1锛夛紝鏃犻渶妫�鏌ョ‘璁�
+ if (taskInfo.mesConfirmStartTime == null) {
+ 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)
+ .data(data)
+ .build();
+ }
+
+ // 妫�鏌ヨ秴鏃�
+ long waitTime = System.currentTimeMillis() - taskInfo.mesConfirmStartTime;
+ if (waitTime > mesConfirmTimeoutMs) {
+ log.warn("MES纭瓒呮椂: deviceId={}, waitTime={}ms, timeout={}ms",
+ deviceId, waitTime, mesConfirmTimeoutMs);
+ data.put("completed", false);
+ data.put("timeout", true);
+ data.put("waitTime", waitTime);
+
+ // 瓒呮椂瑙嗕负浠诲姟澶辫触锛氭竻鐞嗕换鍔$姸鎬佸苟鍋滄鐩戞帶锛岄伩鍏嶇户缁疮鍔犵瓑寰呮椂闂�
+ try {
+ clearTaskStates(deviceConfig, serializer);
+ } catch (Exception e) {
+ log.warn("MES纭瓒呮椂鏃舵竻绌轰换鍔$姸鎬佸け璐�: deviceId={}, error={}", deviceId, e.getMessage());
+ }
+ statusManager.updateVehicleStatus(deviceConfig.getDeviceId(), VehicleState.ERROR);
+ statusManager.clearVehicleTask(deviceConfig.getDeviceId());
+ currentTasks.remove(deviceConfig.getDeviceId());
+ handleStopTaskMonitor(deviceConfig);
+
+ return DevicePlcVO.OperationResult.builder()
+ .success(false)
+ .message(String.format("MES纭瓒呮椂: 绛夊緟鏃堕棿%dms锛岃秴鏃舵椂闂�%dms", waitTime, mesConfirmTimeoutMs))
+ .data(data)
+ .build();
+ }
+
Object confirmValue = plcDynamicDataService.readPlcField(
deviceConfig, "mesConfirm", serializer);
Integer confirm = parseInteger(confirmValue);
@@ -1753,6 +2151,10 @@
if (completed) {
// MES宸茬‘璁わ紝娓呯┖state鍜屾眹鎶ュ瓧
clearTaskStates(deviceConfig, serializer);
+
+ // 璁板綍宸插畬鎴愮殑浠诲姟绛惧悕锛岄伩鍏峂ES鏈浣嶆椂琚噸澶嶆媺璧�
+ lastCompletedMesRecords.put(deviceId,
+ new CompletedMesRecord(taskInfo.mesSignature, System.currentTimeMillis()));
// 浠诲姟瀹屾垚锛屾仮澶嶄负绌洪棽鐘舵��
statusManager.updateVehicleStatus(
@@ -1771,16 +2173,26 @@
plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
log.info("MES浠诲姟宸茬‘璁ゅ畬鎴�: deviceId={}", deviceConfig.getDeviceId());
+ String taskType = taskInfo.isOutbound ? "鍑虹墖" : "杩涚墖";
return DevicePlcVO.OperationResult.builder()
.success(true)
- .message("MES浠诲姟宸茬‘璁ゅ畬鎴�")
+ .message(String.format("%s浠诲姟瀹屾垚锛歁ES宸茬‘璁わ紙mesConfirm=1锛夛紝宸叉竻绌簊tate鍜屾眹鎶ュ瓧锛屽ぇ杞︾┖闂诧紙plcRequest=1锛夛紝鍙互绛夊緟涓嬫浠诲姟", taskType))
.data(data)
.build();
}
+ // 鏋勫缓璇︾粏鐨勭瓑寰呮彁绀轰俊鎭�
+ String waitMessage = "绛夊緟MES纭涓紙mesConfirm=0锛�";
+ if (taskInfo.currentStepDesc != null && !taskInfo.currentStepDesc.isEmpty()) {
+ waitMessage = taskInfo.currentStepDesc + "锛�" + waitMessage;
+ } else if (taskInfo.mesConfirmStartTime != null) {
+ long waitMillis = System.currentTimeMillis() - taskInfo.mesConfirmStartTime;
+ waitMessage = String.format("绛夊緟MES纭涓紙mesConfirm=0锛夛紝宸茬瓑寰�%.1f绉�", waitMillis / 1000.0);
+ }
+
return DevicePlcVO.OperationResult.builder()
.success(true)
- .message("绛夊緟MES纭涓�")
+ .message(waitMessage)
.data(data)
.build();
} catch (Exception e) {
@@ -1793,6 +2205,84 @@
}
}
+ /**
+ * 璁剧疆鐜荤拑涓虹牬鎹熺姸鎬侊紙state=8锛�
+ * 鐢ㄤ簬娴嬭瘯鍦烘櫙锛屾ā鎷熺幓鐠冪牬鎹�
+ */
+ private DevicePlcVO.OperationResult handleMarkBroken(DeviceConfig deviceConfig,
+ Map<String, Object> params,
+ Map<String, Object> logicParams) {
+ String deviceId = deviceConfig.getDeviceId();
+ MesTaskInfo taskInfo = currentTasks.get(deviceId);
+ if (taskInfo == null) {
+ return DevicePlcVO.OperationResult.builder()
+ .success(false)
+ .message("娌℃湁姝e湪鎵ц鐨勪换鍔�")
+ .build();
+ }
+
+ // 浠庡弬鏁颁腑鑾峰彇瑕佹爣璁颁负鐮存崯鐨勭幓鐠冪储寮曪紙0-based锛�
+ // 鏀寔鍗曚釜绱㈠紩鎴栫储寮曞垪琛�
+ List<Integer> brokenIndices = new ArrayList<>();
+ Object brokenIndexObj = params.get("glassIndex");
+ if (brokenIndexObj != null) {
+ if (brokenIndexObj instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<Object> indexList = (List<Object>) brokenIndexObj;
+ for (Object idx : indexList) {
+ Integer index = parseInteger(idx);
+ if (index != null && index >= 0 && index < taskInfo.glasses.size()) {
+ brokenIndices.add(index);
+ }
+ }
+ } else {
+ Integer index = parseInteger(brokenIndexObj);
+ if (index != null && index >= 0 && index < taskInfo.glasses.size()) {
+ brokenIndices.add(index);
+ }
+ }
+ }
+
+ if (brokenIndices.isEmpty()) {
+ return DevicePlcVO.OperationResult.builder()
+ .success(false)
+ .message("鏈寚瀹氭湁鏁堢殑鐜荤拑绱㈠紩")
+ .build();
+ }
+
+ // 鏍囪涓虹牬鎹�
+ if (taskInfo.brokenGlassIndices == null) {
+ taskInfo.brokenGlassIndices = new ArrayList<>();
+ }
+ for (Integer index : brokenIndices) {
+ if (!taskInfo.brokenGlassIndices.contains(index)) {
+ taskInfo.brokenGlassIndices.add(index);
+ }
+ }
+
+ // 绔嬪嵆鍐欏叆PLC鐨剆tate瀛楁
+ EnhancedS7Serializer serializer = s7SerializerProvider.getSerializer(deviceConfig);
+ if (serializer != null) {
+ try {
+ Map<String, Object> payload = new HashMap<>();
+ for (Integer index : brokenIndices) {
+ String stateField = "state" + (index + 1);
+ payload.put(stateField, 8);
+ }
+ plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
+ log.info("宸叉爣璁扮幓鐠冧负鐮存崯骞跺啓鍏LC: deviceId={}, brokenIndices={}",
+ deviceId, brokenIndices);
+ } catch (Exception e) {
+ log.error("鍐欏叆鐮存崯鐘舵�佸埌PLC澶辫触: deviceId={}, error={}", deviceId, e.getMessage());
+ }
+ }
+
+ return DevicePlcVO.OperationResult.builder()
+ .success(true)
+ .message(String.format("宸叉爣璁扮幓鐠冧负鐮存崯: indices=%s", brokenIndices))
+ .build();
+ }
+
/**
* 娓呯┖浠诲姟鐘舵��
*/
@@ -1841,20 +2331,47 @@
}
/**
- * MES浠诲姟淇℃伅
+ * 鍗曚釜鐜荤拑鐨勪换鍔′俊鎭�
*/
- private static class MesTaskInfo {
+ private static class GlassTaskInfo {
String glassId;
Integer startSlot;
Integer targetSlot;
Integer startPosition;
Integer targetPosition;
+ Integer width;
+ Integer height;
+ Integer thickness;
+ }
+
+ /**
+ * MES浠诲姟淇℃伅锛堝彲鑳藉寘鍚涓幓鐠冿級
+ */
+ private static class MesTaskInfo {
+ List<GlassTaskInfo> glasses = new ArrayList<>(); // 澶氫釜鐜荤拑淇℃伅
Integer currentPosition;
long gotime;
long cartime;
- Integer workLine;
long createdTime;
boolean isOutbound = false; // 鏄惁涓哄嚭鐗囦换鍔★紙false=杩涚墖锛宼rue=鍑虹墖锛�
+ boolean transferPlcRequestCleared = false; // 鏄惁宸叉竻绌哄崸杞珛plcRequest锛堥伩鍏嶉噸澶嶆竻绌猴級
+ 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;
+ }
}
/**
@@ -1919,5 +2436,41 @@
log.debug("鏈壘鍒癟askExecutionContext锛屾棤娉曢�氱煡鍗ц浆绔嬫壂鐮佽澶囨殏鍋�");
}
}
+
+ private void clearDynamicTaskStates(DeviceConfig deviceConfig) {
+ if (plcDynamicDataService == null || s7SerializerProvider == null) {
+ return;
+ }
+ try {
+ EnhancedS7Serializer serializer = s7SerializerProvider.getSerializer(deviceConfig);
+ if (serializer != null) {
+ clearTaskStates(deviceConfig, serializer);
+ }
+ } catch (Exception e) {
+ 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();
+ }
}
--
Gitblit v1.8.0