From 8f3a85044b6e4b56a8dd0b104ca023933f1f129c Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期三, 03 十二月 2025 16:58:36 +0800
Subject: [PATCH] 统一卧转立扫码、卧转立、大车、大理片笼的定时器逻辑和步骤状态;添加设备拓扑图清除数据、联机状态切换按钮,
---
mes-processes/mes-plcSend/src/main/java/com/mes/interaction/workstation/transfer/handler/HorizontalTransferLogicHandler.java | 206 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 161 insertions(+), 45 deletions(-)
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/workstation/transfer/handler/HorizontalTransferLogicHandler.java b/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/workstation/transfer/handler/HorizontalTransferLogicHandler.java
index c942e41..b5d7d50 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/workstation/transfer/handler/HorizontalTransferLogicHandler.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/workstation/transfer/handler/HorizontalTransferLogicHandler.java
@@ -16,9 +16,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
-import javax.annotation.PreDestroy;
+import javax.annotation.PreDestroy;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
@@ -92,6 +91,8 @@
return handleStopMonitor(deviceConfig);
case "clearBuffer":
return handleClearBuffer(deviceConfig);
+ case "clearPlc":
+ return handleClearPlc(deviceConfig);
default:
return buildResult(deviceConfig, operation, false,
"涓嶆敮鎸佺殑鎿嶄綔: " + operation);
@@ -124,46 +125,66 @@
try {
// 1. 浠庢暟鎹簱鏌ヨ鏈�杩戞壂鐮佺殑鐜荤拑淇℃伅锛堟渶杩�1鍒嗛挓鍐呯殑璁板綍锛�
List<GlassInfo> recentGlasses = queryRecentScannedGlasses(deviceConfig, logicParams);
- if (recentGlasses.isEmpty()) {
- return buildResult(deviceConfig, "checkAndProcess", true,
- "鏆傛棤寰呭鐞嗙殑鐜荤拑淇℃伅");
+ boolean hasNewGlass = false;
+
+ if (!recentGlasses.isEmpty()) {
+ log.info("鏌ヨ鍒版渶杩戞壂鐮佺殑鐜荤拑: deviceId={}, count={}",
+ deviceId, recentGlasses.size());
+
+ // 2. 鏇存柊缂撳啿闃熷垪锛涗粎鍦ㄦ湁鈥滄柊鐜荤拑鈥濆姞鍏ョ紦鍐叉椂鎵嶆洿鏂版渶鍚庢壂鐮佹椂闂�
+ hasNewGlass = updateBuffer(deviceId, recentGlasses);
+ if (hasNewGlass) {
+ lastScanTime
+ .computeIfAbsent(deviceId, k -> new AtomicLong())
+ .set(System.currentTimeMillis());
+ }
+ } else {
+ log.debug("鏈煡璇㈠埌鏈�杩戞壂鐮佺殑鐜荤拑: deviceId={}", deviceId);
}
- log.info("鏌ヨ鍒版渶杩戞壂鐮佺殑鐜荤拑: deviceId={}, count={}",
- deviceId, recentGlasses.size());
-
- // 2. 鏇存柊缂撳啿闃熷垪锛涗粎鍦ㄦ湁鈥滄柊鐜荤拑鈥濆姞鍏ョ紦鍐叉椂鎵嶆洿鏂版渶鍚庢壂鐮佹椂闂�
- boolean hasNewGlass = updateBuffer(deviceId, recentGlasses);
- if (hasNewGlass) {
- lastScanTime
- .computeIfAbsent(deviceId, k -> new AtomicLong())
- .set(System.currentTimeMillis());
- }
-
- // 3. 妫�鏌ユ槸鍚﹂渶瑕佺珛鍗冲鐞嗭紙瀹归噺宸叉弧鎴�30s鍐呮棤鏂扮幓鐠冿級
+ // 3. 妫�鏌ョ紦鍐查槦鍒楋紙鍗充娇鏌ヨ涓嶅埌鏂扮幓鐠冿紝缂撳啿涓彲鑳借繕鏈夊緟澶勭悊鐨勭幓鐠冿級
List<GlassBufferItem> buffer = glassBuffer.get(deviceId);
if (buffer == null || buffer.isEmpty()) {
+ // 缂撳啿涓虹┖涓旀棤鏂扮幓鐠冿紝杩斿洖绌虹姸鎬�
return buildResult(deviceConfig, "checkAndProcess", true,
- "缂撳啿闃熷垪涓虹┖");
+ "缂撳啿闃熷垪涓虹┖锛屾棤寰呭鐞嗙幓鐠�");
}
// 4. 鍒ゆ柇鏄惁婊¤冻澶勭悊鏉′欢
boolean shouldProcess = shouldProcessBatch(deviceId, buffer, config);
if (!shouldProcess) {
- return buildResult(deviceConfig, "checkAndProcess", true,
- "绛夊緟鏇村鐜荤拑鎴�30s瓒呮椂");
+ // 鏈弧瓒冲鐞嗘潯浠讹細鏋勯�犲甫鏈夌瓑寰呰繘搴︾殑鎻愮ず淇℃伅锛屼究浜庡墠绔睍绀�
+ String waitMessage;
+ AtomicLong lastTime = lastScanTime.get(deviceId);
+ Integer delayMs = config.getTransferDelayMs();
+ if (lastTime != null && delayMs != null && delayMs > 0) {
+ long elapsedMs = System.currentTimeMillis() - lastTime.get();
+ if (elapsedMs < 0) {
+ elapsedMs = 0;
+ }
+ long totalMs = delayMs;
+ long elapsedSec = elapsedMs / 1000;
+ long totalSec = totalMs / 1000;
+ waitMessage = String.format("绛夊緟鏇村鐜荤拑鎴栬秴鏃惰Е鍙戞壒娆″鐞� (宸茬瓑寰� %d/%d 绉�)",
+ elapsedSec, totalSec);
+ } else {
+ // 娌℃湁鏈夋晥鐨勬渶鍚庢壂鐮佹椂闂存垨閰嶇疆锛岄��鍥炲埌鍥哄畾鎻愮ず
+ waitMessage = "绛夊緟鏇村鐜荤拑鎴�30s瓒呮椂";
+ }
+ return buildResult(deviceConfig, "checkAndProcess", true, waitMessage);
}
- // 5. 瀹归噺鍒ゆ柇鍜屾壒娆$粍瑁�
- List<GlassInfo> batch = assembleBatch(buffer, config.getVehicleCapacity());
+ // 5. 瀹归噺鍒ゆ柇鍜屾壒娆$粍瑁咃紙鑰冭檻鐜荤拑闂撮殭锛�
+ Integer glassGap = getLogicParam(logicParams, "glassGap", 200); // 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
+ List<GlassInfo> batch = assembleBatch(buffer, config.getVehicleCapacity(), glassGap);
if (batch.isEmpty()) {
return buildResult(deviceConfig, "checkAndProcess", false,
"鏃犳硶缁勮鏈夋晥鎵规锛堝閲忎笉瓒筹級");
}
- // 6. 鍐欏叆PLC
+ // 6. 鍐欏叆PLC锛堝皾璇曚粠浠诲姟鍙傛暟涓幏鍙栧崸杞珛缂栧彿锛�
DevicePlcVO.OperationResult writeResult = writeBatchToPlc(
- deviceConfig, batch, serializer, logicParams);
+ deviceConfig, batch, serializer, logicParams, params);
if (!Boolean.TRUE.equals(writeResult.getSuccess())) {
return writeResult;
@@ -198,9 +219,23 @@
batch.stream().map(GlassInfo::getGlassId).collect(Collectors.toList()),
GlassInfo.Status.PROCESSED);
- String msg = String.format("鎵规宸插啓鍏LC: glassCount=%d, glassIds=%s",
- batch.size(),
- batch.stream().map(GlassInfo::getGlassId).collect(Collectors.joining(",")));
+ // 8. 妫�鏌ョ紦鍐叉槸鍚︿负绌猴紝濡傛灉涓虹┖涓旀棤鏂扮幓鐠冿紝鏍囪涓哄畬鎴�
+ List<GlassBufferItem> remainingBuffer = glassBuffer.get(deviceId);
+ boolean bufferEmpty = remainingBuffer == null || remainingBuffer.isEmpty();
+ boolean noNewGlass = !hasNewGlass;
+
+ String msg;
+ if (bufferEmpty && noNewGlass) {
+ // 缂撳啿宸叉竻绌轰笖鏃犳柊鐜荤拑锛屼换鍔″畬鎴�
+ msg = String.format("鎵规宸插啓鍏LC: glassCount=%d, glassIds=%s, 缂撳啿宸叉竻绌猴紝浠诲姟瀹屾垚",
+ batch.size(),
+ batch.stream().map(GlassInfo::getGlassId).collect(Collectors.joining(",")));
+ } else {
+ // 缂撳啿杩樻湁鐜荤拑鎴栧彲鑳芥湁鏂扮幓鐠冿紝缁х画杩愯
+ msg = String.format("鎵规宸插啓鍏LC: glassCount=%d, glassIds=%s",
+ batch.size(),
+ batch.stream().map(GlassInfo::getGlassId).collect(Collectors.joining(",")));
+ }
return buildResult(deviceConfig, "checkAndProcess", true, msg);
} catch (Exception e) {
@@ -223,8 +258,8 @@
}
try {
- // 浠庨厤缃腑鑾峰彇workLine锛岀敤浜庤繃婊�
- String workLine = getLogicParam(logicParams, "workLine", null);
+ // 浠庨厤缃腑鑾峰彇workLine锛岀敤浜庤繃婊わ紙閰嶇疆涓槸Integer绫诲瀷锛�
+ Integer workLine = getLogicParam(logicParams, "workLine", null);
// 鏌ヨ鏈�杩�2鍒嗛挓鍐呯殑鐜荤拑璁板綍锛堟墿澶ф椂闂寸獥鍙o紝纭繚涓嶉仐婕忥級
Date twoMinutesAgo = new Date(System.currentTimeMillis() - 120000);
@@ -235,9 +270,9 @@
.orderByDesc(GlassInfo::getCreatedTime)
.last("LIMIT 20"); // 闄愬埗鏌ヨ鏁伴噺锛岄伩鍏嶈繃澶�
- // 濡傛灉閰嶇疆浜唚orkLine锛屽垯杩囨护description
- if (workLine != null && !workLine.isEmpty()) {
- wrapper.like(GlassInfo::getDescription, "workLine=" + workLine);
+ // 濡傛灉閰嶇疆浜唚orkLine锛屽垯杩囨护work_line瀛楁
+ if (workLine != null) {
+ wrapper.eq(GlassInfo::getWorkLine, workLine);
}
List<GlassInfo> recentGlasses = glassInfoMapper.selectList(wrapper);
@@ -280,17 +315,21 @@
/**
* 鍒ゆ柇鏄惁搴旇澶勭悊鎵规
+ * 娉ㄦ剰锛氳繖閲屽彧鍋氱矖鐣ュ垽鏂紝绮剧‘鐨勫閲忚绠楋紙鍚棿闅欙級鍦╝ssembleBatch涓畬鎴�
*/
private boolean shouldProcessBatch(String deviceId,
List<GlassBufferItem> buffer,
WorkstationLogicConfig config) {
// 鏉′欢1锛氱紦鍐查槦鍒楀凡婊★紙杈惧埌瀹归噺闄愬埗锛�
+ // 绮楃暐璁$畻锛氭墍鏈夌幓鐠冮暱搴︿箣鍜岋紙涓嶈�冭檻闂撮殭锛屽洜涓洪棿闅欐槸鍔ㄦ�佺殑锛�
int totalLength = buffer.stream()
.mapToInt(item -> item.glassInfo.getGlassLength() != null ?
item.glassInfo.getGlassLength() : 0)
.sum();
- if (totalLength >= config.getVehicleCapacity()) {
- log.info("缂撳啿闃熷垪瀹归噺宸叉弧锛岃Е鍙戞壒娆″鐞�: deviceId={}, totalLength={}, capacity={}",
+ // 绮楃暐鍒ゆ柇锛氬鏋滄�婚暱搴︽帴杩戝閲忥紙鐣欎竴浜涗綑閲忕粰闂撮殭锛夛紝灏辫Е鍙戝鐞�
+ // 绮剧‘鍒ゆ柇浼氬湪assembleBatch涓畬鎴�
+ if (totalLength >= config.getVehicleCapacity() * 0.8) { // 80%闃堝�硷紝鐣欎綑閲忕粰闂撮殭
+ log.info("缂撳啿闃熷垪瀹归噺鎺ヨ繎婊¤浇锛岃Е鍙戞壒娆″鐞�: deviceId={}, totalLength={}, capacity={}",
deviceId, totalLength, config.getVehicleCapacity());
return true;
}
@@ -310,25 +349,50 @@
}
/**
- * 缁勮鎵规锛堝閲忓垽鏂級
+ * 缁勮鎵规锛堝閲忓垽鏂紝鑰冭檻鐜荤拑闂撮殭锛�
+ * @param buffer 缂撳啿闃熷垪
+ * @param vehicleCapacity 杞﹁締瀹归噺锛坢m锛�
+ * @param glassGap 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
+ * @return 缁勮濂界殑鎵规鍒楄〃
*/
private List<GlassInfo> assembleBatch(List<GlassBufferItem> buffer,
- int vehicleCapacity) {
+ int vehicleCapacity,
+ int glassGap) {
List<GlassInfo> batch = new ArrayList<>();
int usedLength = 0;
+ int gap = Math.max(glassGap, 0); // 纭繚闂撮殧涓嶄负璐熸暟
for (GlassBufferItem item : buffer) {
GlassInfo glass = item.glassInfo;
int glassLength = glass.getGlassLength() != null ?
glass.getGlassLength() : 0;
- if (usedLength + glassLength <= vehicleCapacity && batch.size() < 6) {
- batch.add(glass);
- usedLength += glassLength;
+ if (glassLength <= 0) {
+ continue; // 璺宠繃鏃犳晥闀垮害鐨勭幓鐠�
+ }
+
+ if (batch.isEmpty()) {
+ // 绗竴鍧楃幓鐠冿紝涓嶉渶瑕侀棿闅�
+ if (glassLength <= vehicleCapacity && batch.size() < 6) {
+ batch.add(glass);
+ usedLength = glassLength;
+ } else {
+ break; // 绗竴鍧楀氨瑁呬笉涓�
+ }
} else {
- break;
+ // 鍚庣画鐜荤拑闇�瑕佽�冭檻闂撮殭锛氱幓鐠冮暱搴� + 闂撮殭
+ int requiredLength = glassLength + gap;
+ if (usedLength + requiredLength <= vehicleCapacity && batch.size() < 6) {
+ batch.add(glass);
+ usedLength += requiredLength; // 鍖呭惈闂撮殭
+ } else {
+ break; // 瑁呬笉涓嬩簡
+ }
}
}
+
+ log.debug("鎵规缁勮瀹屾垚: batchSize={}, usedLength={}, capacity={}, glassGap={}",
+ batch.size(), usedLength, vehicleCapacity, gap);
return batch;
}
@@ -340,7 +404,8 @@
DeviceConfig deviceConfig,
List<GlassInfo> batch,
EnhancedS7Serializer serializer,
- Map<String, Object> logicParams) {
+ Map<String, Object> logicParams,
+ Map<String, Object> params) {
Map<String, Object> payload = new HashMap<>();
@@ -354,10 +419,33 @@
// 鍐欏叆鐜荤拑鏁伴噺
payload.put("plcGlassCount", count);
- // 鍐欏叆浣嶇疆淇℃伅锛堝鏋滄湁閰嶇疆锛�
- Integer inPosition = getLogicParam(logicParams, "inPosition", null);
+ // 鍐欏叆鍗ц浆绔嬬紪鍙凤紙浼樺厛浠庝换鍔″弬鏁拌幏鍙栵紝鍏舵浠庤澶囬厤缃幏鍙栵級
+ Integer inPosition = null;
+ if (params != null) {
+ try {
+ Object ctxObj = params.get("_taskContext");
+ if (ctxObj instanceof com.mes.task.model.TaskExecutionContext) {
+ com.mes.task.model.TaskExecutionContext ctx =
+ (com.mes.task.model.TaskExecutionContext) ctxObj;
+ Object positionObj = ctx.getParameters().getExtra() != null
+ ? ctx.getParameters().getExtra().get("inPosition") : null;
+ if (positionObj instanceof Number) {
+ inPosition = ((Number) positionObj).intValue();
+ }
+ }
+ } catch (Exception e) {
+ log.debug("浠庝换鍔″弬鏁拌幏鍙栧崸杞珛缂栧彿澶辫触: deviceId={}", deviceConfig.getId(), e);
+ }
+ }
+ // 濡傛灉浠诲姟鍙傛暟涓病鏈夛紝浠庤澶囬厤缃腑鑾峰彇
+ if (inPosition == null) {
+ inPosition = getLogicParam(logicParams, "inPosition", null);
+ }
if (inPosition != null) {
payload.put("inPosition", inPosition);
+ log.info("鍐欏叆鍗ц浆绔嬬紪鍙�: deviceId={}, inPosition={}", deviceConfig.getId(), inPosition);
+ } else {
+ log.debug("鏈厤缃崸杞珛缂栧彿锛岃烦杩囧啓鍏�: deviceId={}", deviceConfig.getId());
}
// 鍐欏叆璇锋眰瀛楋紙瑙﹀彂澶ц溅锛�
@@ -365,8 +453,8 @@
try {
plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
- log.info("鎵规宸插啓鍏LC: deviceId={}, glassCount={}",
- deviceConfig.getId(), count);
+ log.info("鎵规宸插啓鍏LC: deviceId={}, glassCount={}, inPosition={}",
+ deviceConfig.getId(), count, inPosition);
return buildResult(deviceConfig, "writeBatchToPlc", true,
"鎵规鍐欏叆鎴愬姛");
} catch (Exception e) {
@@ -450,6 +538,34 @@
log.info("宸叉竻绌虹紦鍐查槦鍒�: deviceId={}", deviceId);
return buildResult(deviceConfig, "clearBuffer", true, "缂撳啿闃熷垪宸叉竻绌�");
}
+
+ /**
+ * 娓呯┖PLC鐩稿叧瀛楁锛堜緵娴嬭瘯椤甸潰涓�閿竻绌轰娇鐢級
+ */
+ private DevicePlcVO.OperationResult handleClearPlc(DeviceConfig deviceConfig) {
+ try {
+ EnhancedS7Serializer serializer = s7SerializerProvider.getSerializer(deviceConfig);
+ if (serializer == null) {
+ return buildResult(deviceConfig, "clearPlc", false, "鑾峰彇PLC搴忓垪鍖栧櫒澶辫触");
+ }
+
+ Map<String, Object> payload = new HashMap<>();
+ // 鏍规嵁鍗ц浆绔嬩富浣撳啓鍏ョ殑瀛楁杩涜娓呯┖
+ for (int i = 1; i <= 6; i++) {
+ payload.put("plcGlassId" + i, "");
+ }
+ payload.put("plcGlassCount", 0);
+ payload.put("plcRequest", 0);
+ payload.put("inPosition", 0);
+
+ plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
+ log.info("鍗ц浆绔嬩富浣撴竻绌篜LC瀛楁瀹屾垚: deviceId={}", deviceConfig.getId());
+ return buildResult(deviceConfig, "clearPlc", true, "宸叉竻绌哄崸杞珛涓讳綋PLC瀛楁");
+ } catch (Exception e) {
+ log.error("鍗ц浆绔嬩富浣撴竻绌篜LC澶辫触: deviceId={}", deviceConfig.getId(), e);
+ return buildResult(deviceConfig, "clearPlc", false, "娓呯┖PLC澶辫触: " + e.getMessage());
+ }
+ }
/**
* 鏋勫缓鎿嶄綔缁撴灉
--
Gitblit v1.8.0