diff --git a/app.db b/app.db index 19ff680..cb50140 100644 Binary files a/app.db and b/app.db differ diff --git a/src/main/java/com/iflytop/digester/DigestionTaskTheadManager.java b/src/main/java/com/iflytop/digester/DigestionTaskTheadManager.java index 2edbbdc..03a95cb 100644 --- a/src/main/java/com/iflytop/digester/DigestionTaskTheadManager.java +++ b/src/main/java/com/iflytop/digester/DigestionTaskTheadManager.java @@ -63,7 +63,7 @@ public class DigestionTaskTheadManager { DigestionTaskTheadManager.this.handleOnMessageArrived(topic, message); } public void deliveryComplete(IMqttDeliveryToken token) { - System.out.println("deliveryComplete---------" + token.isComplete()); + // nothing to do here } }); try { diff --git a/src/main/java/com/iflytop/digester/DigestionTaskThread.java b/src/main/java/com/iflytop/digester/DigestionTaskThread.java index de45f04..8ee7d05 100644 --- a/src/main/java/com/iflytop/digester/DigestionTaskThread.java +++ b/src/main/java/com/iflytop/digester/DigestionTaskThread.java @@ -6,9 +6,9 @@ import com.iflytop.digester.underframework.dao.model.UfMdbNotification; import com.iflytop.digester.underframework.dao.record.UfActiveRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; + +import java.util.*; + public class DigestionTaskThread extends Thread { // 任务完成回调 public interface FinishCallback { @@ -37,6 +37,10 @@ public class DigestionTaskThread extends Thread { private FinishCallback finishCallback; // 消解任务管理器 private DigestionTaskTheadManager manager; + // 预检查是否完成 + private Boolean isPrecheckFinished; + // 预检查锁 + private final Object precheckLock = new Object(); // 消解任务 public DigestionTaskThread(MdbDigestionTask taskModel) { @@ -101,13 +105,7 @@ public class DigestionTaskThread extends Thread { this.executeRound(round); } // 执行最后一轮 - this.executeRound(lastRound); - // 检查试管 - this.tubeCheck(); - // 启动异常处理线程 - this.startErrorProcessThread(); - // 消解结束 - this.finish(); + this.executeLastRound(lastRound); this.errorProcessThread.join(); this.updateTaskStatus("Finish", "消解任务结束"); @@ -138,26 +136,8 @@ public class DigestionTaskThread extends Thread { device.door.close(); } - // 消解结束 - private void finish() { - var device = Device.getInstance(); - - // 余温加热 - this.heatingSlot.heating(100, 10); - // 移动到加液盘 - device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); - // 打开门 - device.door.open(); - // 等待取出 - this.waitForTubeRackTakeOut(); - // 关闭门 - device.door.close(); - // 释放加热位 - this.heatingSlot.setTubeRackNo(null); - } - // 检查试管 - private void tubeCheck() throws InterruptedException { + private void tubeCheckAndMove() throws InterruptedException { var device = Device.getInstance(); // 移动到加液盘 device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); @@ -230,6 +210,77 @@ public class DigestionTaskThread extends Thread { device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); } + // 执行消解最后一轮配置 + private void executeLastRound( MdbDigestionSolution.DigestionSolutionRound digestionRound ) throws InterruptedException { + this.isPrecheckFinished = false; + var device = Device.getInstance(); + + // 预检查定时, 在结束前10分钟执行 + Integer totalDurationCount = 0; + for ( var heating : digestionRound.heatings ) { + totalDurationCount += heating.duration; + } + long preCheckDuration = totalDurationCount - 10; + if ( 0 >= preCheckDuration ) { + preCheckDuration = 0; + } + var preCheckTimerTask = new TimerTask() { + @Override + public void run() { + try { + // 检查试管 + DigestionTaskThread.this.tubeCheckAndMove(); + // 启动异常处理线程 + DigestionTaskThread.this.startErrorProcessThread(); + // 预检查完成 + DigestionTaskThread.this.isPrecheckFinished = true; + synchronized ( DigestionTaskThread.this.precheckLock ) { + DigestionTaskThread.this.precheckLock.notifyAll(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + var preCheckTimer = new Timer(); + preCheckTimer.schedule(preCheckTimerTask, preCheckDuration * 60 * 1000); + + // 加热 + for ( var heating : digestionRound.heatings ) { + this.updateTaskStatus("heating", String.format("加热 %d℃ %d分钟", heating.temperature, heating.duration)); + this.heatingSlot.heating(heating.temperature, heating.duration); + } + + // 等待预检查完成 + if ( !this.isPrecheckFinished ) { + this.updateTaskStatus("PreCheckWait", "等待预检完成"); + synchronized ( this.precheckLock ) { + try { + this.precheckLock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + // 加水定容 + if ( 0 < digestionRound.waterVolume ) { + device.liquidAddition.addLiquidToTubes(this.heatingSlot.getExistTubeIndexes(), "water", digestionRound.waterVolume); + } + + // 正常消解结束 + // 移动到加液盘 + device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); + // 打开门 + device.door.open(); + // 等待取出 + this.waitForTubeRackTakeOut(); + // 关闭门 + device.door.close(); + // 释放加热位 + this.heatingSlot.setTubeRackNo(null); + } + // 执行消解异常处理配置 private void executeErrorRound( MdbDigestionSolution.DigestionSolutionErrorRound errorRound ) throws InterruptedException { var device = Device.getInstance(); diff --git a/src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java b/src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java index 63e5bda..46918e7 100644 --- a/src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java +++ b/src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java @@ -68,11 +68,13 @@ public class TransferRobotArmInstance { return ; } - try { - waitingLocks.add(lock); - lock.wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); + synchronized ( lock ) { + try { + waitingLocks.add(lock); + lock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } } @@ -80,7 +82,10 @@ public class TransferRobotArmInstance { private void unlockArm( Object lock ) { waitingLocks.remove(lock); if ( !waitingLocks.isEmpty() ) { - waitingLocks.get(0).notify(); + var nextLock = waitingLocks.get(0); + synchronized ( nextLock ) { + nextLock.notify(); + } } } } diff --git a/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java b/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java index b474890..c53c8fa 100644 --- a/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java +++ b/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java @@ -103,6 +103,8 @@ public class MdbDigestionSolution extends UfActiveRecord { public List liquids; // 加热配置 public List heatings; + // 加水定容 + public Integer waterVolume = 0; } public static class DigestionSolutionErrorRound { diff --git a/src/main/java/com/iflytop/digester/underframework/UfApplication.java b/src/main/java/com/iflytop/digester/underframework/UfApplication.java index 4c4037f..2396038 100644 --- a/src/main/java/com/iflytop/digester/underframework/UfApplication.java +++ b/src/main/java/com/iflytop/digester/underframework/UfApplication.java @@ -7,6 +7,7 @@ import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -23,6 +24,9 @@ implements ApplicationContextAware, WebMvcConfigurer { @Resource private UfConnectionManager connections; + @Resource + private Environment env; + // get application instance public static UfApplication getApp() { return UfApplication.app; @@ -33,6 +37,11 @@ implements ApplicationContextAware, WebMvcConfigurer { UfApplication.app = this; } + // get environment + public Environment getEnv() { + return this.env; + } + @Override public void setApplicationContext( @Nonnull ApplicationContext applicationContext) throws BeansException { UfApplication.context = applicationContext; diff --git a/src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java b/src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java index 1bf415f..bb1a585 100644 --- a/src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java +++ b/src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java @@ -33,7 +33,11 @@ public class UfCmdSnippetExecutor { * @param params - params */ static public void execute(String snippetName, Map params) { - LOG.info("[Snippet Execute] : {} ({})", snippetName, UfJsonHelper.objectToJson(params)); + Boolean logEnabled = UfApplication.getApp().getEnv().getProperty("device.snippet-execute-log-enable", Boolean.class); + if ( Boolean.TRUE.equals(logEnabled) ) { + LOG.info("[Snippet Execute] : {} ({})", snippetName, UfJsonHelper.objectToJson(params)); + } + // var snippet = UfActiveRecord.findOne(UfMdbSnippet.class, Map.of("key", snippetName)); // if (null == snippet) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c2ff9a5..5205a12 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,6 +9,7 @@ spring: driver-class-name: org.sqlite.JDBC device: + snippet-execute-log-enable : false connections: - name : zcancmder type : ZcancmderWebsocket