Bladeren bron

涂胶优化

sunxianglong 2 maanden geleden
bovenliggende
commit
9ee4cd7304

+ 4 - 11
src/main/java/com/jeesite/modules/scheduling/ProductTjBScheduling.java

@@ -33,7 +33,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
  *   32.0   框架码 String[30]
  *   64.1   扫码反馈信号
  *   64.3   质量校验通过反馈(校验通过 MES 写 true,工位完成后 MES 写 false)
- *   64.5   整体完成信号
+ *   74.1   整体完成信号
  *   74.0   涂胶数据采集触发
  *   76.0   涂胶序号 Word
  *   78.0   涂胶速度 Real
@@ -56,7 +56,7 @@ public class ProductTjBScheduling {
 	private static final int SN_LENGTH = 30;
 	private static final String ADDR_SCAN_FEEDBACK = "DB1300.64.1";
 	private static final String ADDR_QUALITY_PASS = "DB1300.64.3";
-	private static final String ADDR_COMPLETE = "DB1300.64.5";
+	private static final String ADDR_COMPLETE = "DB1300.74.1";
 	private static final String ADDR_GLUE_COLLECT = "DB1300.74.0";
 	private static final String ADDR_GLUE_SEQ = "DB1300.76.0";
 	private static final String ADDR_GLUE_SPEED = "DB1300.78.0";
@@ -78,11 +78,10 @@ public class ProductTjBScheduling {
 	private MesProductRecordService mesProductRecordService;
 
 	private final AtomicBoolean running = new AtomicBoolean(false);
-	private volatile String lastCheckedSn;
 	private volatile String lastKnownSn;
 	private volatile String lastCompletedSn;
 
-	@Scheduled(fixedRate = 1000)
+	@Scheduled(fixedRate = 100)
 	public void collect() {
 		String enabled = Global.getConfig("mes.tj.b.enabled");
 		if (StringUtils.isBlank(enabled) || !"true".equalsIgnoreCase(enabled.trim())) {
@@ -123,7 +122,6 @@ public class ProductTjBScheduling {
 	 */
 	private void handleScanFeedback(S7PLC s7PLC) {
 		if (!s7PLC.readBoolean(ADDR_SCAN_FEEDBACK)) {
-			lastCheckedSn = null;
 			lastCompletedSn = null;
 			return;
 		}
@@ -132,9 +130,6 @@ public class ProductTjBScheduling {
 			return;
 		}
 		lastKnownSn = sn;
-		if (sn.equals(lastCheckedSn)) {
-			return;
-		}
 
 		boolean pass = doQualityCheck(sn);
 		if (pass) {
@@ -143,7 +138,6 @@ public class ProductTjBScheduling {
 		} else {
 			logger.warn("涂胶B质量校验未通过 sn={}", sn);
 		}
-		lastCheckedSn = sn;
 	}
 
 	/**
@@ -180,7 +174,7 @@ public class ProductTjBScheduling {
 	}
 
 	/**
-	 * 整体完成信号为 true:提交 OP240B 工位 OK → 成功后将 DB1300.64.3 置 false
+	 * DB1300.74.1 整体完成信号为 true:提交工位 OK → 成功后将 DB1300.64.3 置 false
 	 */
 	private void handleComplete(S7PLC s7PLC) {
 		if (!s7PLC.readBoolean(ADDR_COMPLETE)) {
@@ -206,7 +200,6 @@ public class ProductTjBScheduling {
 
 		s7PLC.writeBoolean(ADDR_QUALITY_PASS, false);
 		lastCompletedSn = sn;
-		lastCheckedSn = null;
 		logger.info("涂胶B工位完成 sn={},已提交 OK 并将 {} 置 false", sn, ADDR_QUALITY_PASS);
 	}
 

+ 32 - 8
src/main/java/com/jeesite/modules/scheduling/ProductTjScheduling.java

@@ -27,8 +27,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
  * DB1300 点位:
  *   0.0    框架码 String[30]
  *   64.0   扫码反馈信号
- *   64.2   质量校验通过反馈(校验通过 MES 写 true)
+ *   64.2   质量校验通过反馈(校验通过 MES 写 true,工位完成后 MES 写 false)
  *   64.4   涂胶数据采集触发
+ *   64.5   整体完成信号(true 时 MES 将 64.2 置 false)
  *   66.0   涂胶序号 Word
  *   68.0   涂胶速度 Real
  *   72.0   涂胶长度 Word
@@ -50,6 +51,7 @@ public class ProductTjScheduling {
 	private static final String ADDR_SCAN_FEEDBACK = "DB1300.64.0";
 	private static final String ADDR_QUALITY_PASS = "DB1300.64.2";
 	private static final String ADDR_GLUE_COLLECT = "DB1300.64.4";
+	private static final String ADDR_COMPLETE = "DB1300.64.5";
 	private static final String ADDR_GLUE_SEQ = "DB1300.66.0";
 	private static final String ADDR_GLUE_SPEED = "DB1300.68.0";
 	private static final String ADDR_GLUE_LENGTH = "DB1300.72.0";
@@ -68,10 +70,10 @@ public class ProductTjScheduling {
 	private MesProductTjService mesProductTjService;
 
 	private final AtomicBoolean running = new AtomicBoolean(false);
-	private volatile String lastCheckedSn;
 	private volatile String lastKnownSn;
+	private volatile String lastCompletedSn;
 
-	@Scheduled(fixedRate = 1000)
+	@Scheduled(fixedRate = 100)
 	public void collect() {
 		String enabled = Global.getConfig("mes.tj.enabled");
 		if (StringUtils.isBlank(enabled) || !"true".equalsIgnoreCase(enabled.trim())) {
@@ -93,6 +95,7 @@ public class ProductTjScheduling {
 			s7PLC = new S7PLC(EPlcType.S1200, ip);
 			handleScanFeedback(s7PLC);
 			handleGlueCollect(s7PLC);
+			handleComplete(s7PLC);
 		} catch (Exception e) {
 			logger.error("涂胶S7任务失败[{}]:{}", ip, e.getMessage());
 		} finally {
@@ -111,7 +114,7 @@ public class ProductTjScheduling {
 	 */
 	private void handleScanFeedback(S7PLC s7PLC) {
 		if (!s7PLC.readBoolean(ADDR_SCAN_FEEDBACK)) {
-			lastCheckedSn = null;
+			lastCompletedSn = null;
 			return;
 		}
 		String sn = readWorkpieceCode(s7PLC);
@@ -119,9 +122,6 @@ public class ProductTjScheduling {
 			return;
 		}
 		lastKnownSn = sn;
-		if (sn.equals(lastCheckedSn)) {
-			return;
-		}
 
 		boolean pass = doQualityCheck(sn);
 		if (pass) {
@@ -130,7 +130,6 @@ public class ProductTjScheduling {
 		} else {
 			logger.warn("涂胶质量校验未通过 sn={}", sn);
 		}
-		lastCheckedSn = sn;
 	}
 
 	/**
@@ -166,6 +165,31 @@ public class ProductTjScheduling {
 		logger.info("涂胶数据采集完成 sn={} 序号={},已将 {} 置 false", sn, glueSeq, ADDR_GLUE_COLLECT);
 	}
 
+	/**
+	 * DB1300.64.5 整体完成信号为 true:将 DB1300.64.2 置 false(不提交工位结果)
+	 */
+	private void handleComplete(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_COMPLETE)) {
+			return;
+		}
+
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			sn = lastKnownSn;
+		}
+		if (StringUtils.isBlank(sn)) {
+			logger.error("涂胶工位完成复位失败:无工件码,保持 {}=true 待重试", ADDR_COMPLETE);
+			return;
+		}
+		if (sn.equals(lastCompletedSn)) {
+			return;
+		}
+
+		s7PLC.writeBoolean(ADDR_QUALITY_PASS, false);
+		lastCompletedSn = sn;
+		logger.info("涂胶工位完成 sn={},已将 {} 置 false", sn, ADDR_QUALITY_PASS);
+	}
+
 	private boolean saveTjData(String sn, int glueSeq, float glueSpeed, int glueLength) {
 		try {
 			MesProductTj entity = new MesProductTj();

+ 1 - 1
src/main/resources/config/application.yml

@@ -55,7 +55,7 @@ jdbc:
   driver: com.mysql.cj.jdbc.Driver
 #  url: jdbc:mysql://127.0.0.1:3306/mes_cloud_ljr?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
   url: jdbc:mysql://10.0.20.10:3306/mes_cloud_ljr?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
-#  url: jdbc:mysql://192.168.22.99:3306/mes_cloud?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
+# 0 url: jdbc:mysql://192.168.22.99:3306/mes_cloud?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
 #  username: mes_cloud
 #  password: YD57bSRabiyWBwkZ
   username: root

+ 71 - 5
src/test/java/com/jeesite/test/ProductTjQualityCheckTest.java

@@ -1,5 +1,7 @@
 package com.jeesite.test;
 
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
 import com.jeesite.common.config.Global;
 import com.jeesite.common.lang.StringUtils;
 import com.jeesite.common.tests.BaseSpringContextTests;
@@ -16,12 +18,13 @@ import org.springframework.test.context.ActiveProfiles;
 /**
  * 涂胶 / FSW 定时任务质量校验联调测试。
  * <p>
- * 覆盖以下类的 {@code checkQualityCommon} 调用逻辑,不连接 PLC/Modbus:
+ * 覆盖以下类的 {@code checkQualityCommon} 调用逻辑:
  * <ul>
  *   <li>{@link com.jeesite.modules.scheduling.ProductTjScheduling}(OP220)</li>
  *   <li>{@link com.jeesite.modules.scheduling.ProductTjBScheduling}(mes.tj.b.oprno)</li>
  *   <li>{@link com.jeesite.modules.scheduling.FswModbusScheduling}(mes.fsw.modbus.oprno)</li>
  * </ul>
+ * 另含 ProductTjScheduling 写 DB1300.64.2 的 PLC 联调(需连涂胶 PLC)。
  * <p>
  * 使用方式:
  * <ul>
@@ -36,7 +39,7 @@ public class ProductTjQualityCheckTest extends BaseSpringContextTests {
 	// ===================== 自行填写 =====================
 
 	/** 待测工件码(必填) */
-	private static final String TEST_SN = "0050010200173E5240017067171A02";
+	private static final String TEST_SN = "0050010200173E5240017067251A22";
 
 	/** 产线编号,与 application.yml 中 mes.tj.lineSn / mes.tj.b.lineSn 一致 */
 	private static final String TEST_LINE_SN = "XT";
@@ -56,12 +59,20 @@ public class ProductTjQualityCheckTest extends BaseSpringContextTests {
 	 */
 	private static final String FSW_LINE_SN = "XT";
 
+	/**
+	 * 涂胶 PLC IP;留空则读取 mes.tj.plc.ip,仍为空则使用 10.0.40.100
+	 */
+	private static final String TJ_PLC_IP = "";
+
 	// ===================== 自行填写结束 =====================
 
 	/** ProductTjScheduling 固定工位号 */
 	private static final String TJ_A_OPRNO = "OP220";
 
-	private static final String DEFAULT_TJ_B_OPRNO = "OP240B";
+	private static final String DEFAULT_TJ_B_OPRNO = "OP240";
+	private static final String DEFAULT_TJ_PLC_IP = "10.0.40.100";
+	/** 与 ProductTjScheduling.ADDR_QUALITY_PASS 一致 */
+	private static final String ADDR_QUALITY_PASS = "DB1300.64.2";
 
 	@Autowired
 	private MesProductRecordController mesProductRecordController;
@@ -105,7 +116,17 @@ public class ProductTjQualityCheckTest extends BaseSpringContextTests {
 	}
 
 	/**
-	 * 手动联调:依次执行涂胶 A/B 与 FSW 质量校验。
+	 * 模拟 ProductTjScheduling 写 DB1300.64.2=true(不做质量校验,直接写点位)。
+	 * 需涂胶 PLC 可达(mes.tj.plc.ip)。
+	 */
+	@Test
+	public void testProductTjSchedulingWriteQualityPass64_2() {
+		boolean written = writeQualityPassLikeTjScheduling(true);
+		org.junit.Assert.assertTrue("写 DB1300.64.2=true 失败(检查 PLC 连通性)", written);
+	}
+
+	/**
+	 * 手动联调:依次执行涂胶 A/B 与 FSW 质量校验,以及 A 侧写 64.2。
 	 */
 	public static void main(String[] args) {
 		if (StringUtils.isBlank(TEST_SN)) {
@@ -113,7 +134,7 @@ public class ProductTjQualityCheckTest extends BaseSpringContextTests {
 			return;
 		}
 
-		System.out.println("========== 涂胶/FSW 质量校验联调(不连 PLC/Modbus)==========");
+		System.out.println("========== 涂胶/FSW 质量校验联调 ==========");
 		ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
 		try {
 			MesProductRecordController controller = ctx.getBean(MesProductRecordController.class);
@@ -127,6 +148,10 @@ public class ProductTjQualityCheckTest extends BaseSpringContextTests {
 			QualityCheckResult aResult = tester.checkQualityLikeTjScheduling(sn, lineSn);
 			printResult("ProductTjScheduling", TJ_A_OPRNO, aResult, lineSn);
 
+			System.out.println("\n--- ProductTjScheduling 写 DB1300.64.2=true(跳过质量校验)---");
+			boolean ok = writeQualityPassLikeTjScheduling(true);
+			System.out.println(ok ? "写 64.2=true 成功" : "写 64.2=true 失败");
+
 			String bOprno = resolveTjBOprnoStatic();
 			System.out.println("\n--- ProductTjBScheduling (" + bOprno + ") ---");
 			QualityCheckResult bResult = tester.checkQualityLikeTjBScheduling(sn, lineSn, bOprno);
@@ -157,6 +182,47 @@ public class ProductTjQualityCheckTest extends BaseSpringContextTests {
 	}
 
 	/**
+	 * 直接写 DB1300.64.2(不做质量校验),并回读确认。
+	 *
+	 * @param value true=质量通过反馈,false=复位
+	 * @return true=写入并回读一致
+	 */
+	static boolean writeQualityPassLikeTjScheduling(boolean value) {
+		String ip = resolveTjPlcIp();
+		S7PLC s7PLC = null;
+		try {
+			System.out.println("连接涂胶 PLC: " + ip);
+			s7PLC = new S7PLC(EPlcType.S1200, ip);
+			boolean before = s7PLC.readBoolean(ADDR_QUALITY_PASS);
+			System.out.println("写前 " + ADDR_QUALITY_PASS + "=" + before);
+
+			s7PLC.writeBoolean(ADDR_QUALITY_PASS, value);
+			boolean after = s7PLC.readBoolean(ADDR_QUALITY_PASS);
+			System.out.println("写后 " + ADDR_QUALITY_PASS + "=" + after + "(期望 " + value + ")");
+			return after == value;
+		} catch (Exception e) {
+			System.out.println("写 " + ADDR_QUALITY_PASS + " 异常: " + e.getMessage());
+			e.printStackTrace();
+			return false;
+		} finally {
+			if (s7PLC != null) {
+				try {
+					s7PLC.close();
+				} catch (Exception ignore) {
+				}
+			}
+		}
+	}
+
+	private static String resolveTjPlcIp() {
+		if (StringUtils.isNotBlank(TJ_PLC_IP)) {
+			return TJ_PLC_IP.trim();
+		}
+		String ip = Global.getConfig("mes.tj.plc.ip");
+		return StringUtils.isBlank(ip) ? DEFAULT_TJ_PLC_IP : ip.trim();
+	}
+
+	/**
 	 * 与 ProductTjBScheduling.doQualityCheck 相同:5 位工位号补 A,6 位及以上原样传入。
 	 */
 	QualityCheckResult checkQualityLikeTjBScheduling(String sn, String lineSn, String oprno) {