From cec9e0a61ddcdf4975d25a3ef2e447aa7572c5e3 Mon Sep 17 00:00:00 2001 From: sige Date: Wed, 24 Apr 2024 14:19:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E7=BB=84=E6=B5=8B=E8=AF=95=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E8=BF=9B=E8=A1=8C=EF=BC=8C=E6=A3=80=E6=9F=A5=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.db | Bin 385024 -> 385024 bytes .../com/iflytop/digester/DigestionTaskThread.java | 55 ++++++++++++++++++--- .../digester/controller/HeatSlotController.java | 4 ++ .../deviceinstance/HeatingTurntableSlot.java | 2 - .../deviceinstance/LiquidAdditionInstance.java | 48 +++++++++++++++++- .../underframework/dao/record/UfActiveRecord.java | 4 +- 6 files changed, 103 insertions(+), 10 deletions(-) diff --git a/app.db b/app.db index a000dab562db89e32aeb875192fc7b62e13dbf20..57905b2899b342629bd25c262b90c2467923db01 100644 GIT binary patch delta 30368 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 OdbE9ql(C(()c+UY1J+{z delta 17143 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 diff --git a/src/main/java/com/iflytop/digester/DigestionTaskThread.java b/src/main/java/com/iflytop/digester/DigestionTaskThread.java index fb31728..007773a 100644 --- a/src/main/java/com/iflytop/digester/DigestionTaskThread.java +++ b/src/main/java/com/iflytop/digester/DigestionTaskThread.java @@ -8,9 +8,7 @@ import com.iflytop.digester.underframework.dao.model.UfMdbOption; import com.iflytop.digester.underframework.dao.record.UfActiveRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.*; - public class DigestionTaskThread extends Thread { // 任务完成回调 public interface FinishCallback { @@ -148,6 +146,7 @@ public class DigestionTaskThread extends Thread { this.taskModel.save(); if ( "auto".equals(this.taskModel.mode) ) { + this.lockLiquidPlate(); // 打开门 device.door.open(); // 等待放入试管架 @@ -175,6 +174,7 @@ public class DigestionTaskThread extends Thread { // 搬运到加热转盘 device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index); + this.unlockLiquidPlate(); // 加热 for ( var heating : digestionRound.heatings ) { @@ -184,6 +184,7 @@ public class DigestionTaskThread extends Thread { } // 移至加液区, 以便执行下一轮 + this.lockLiquidPlate(); device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); this.updateTaskStatus("RoundFinish", "配置轮次执行结束"); } @@ -204,6 +205,9 @@ public class DigestionTaskThread extends Thread { } this.updateTaskStatus("Liquid", "摇匀"); liquidAddition.shake(digestionRound.shakingCount); + // 搬运到加热转盘 + device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index); + this.unlockLiquidPlate(); // 预检查定时, 在结束前10分钟执行 Integer totalDurationCount = 0; @@ -245,6 +249,10 @@ public class DigestionTaskThread extends Thread { this.updateTaskStatus("PreCheckWait", "预检完成"); } + // 移动到加液盘准备取出 + this.lockLiquidPlate(); + device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); // 移动到加液盘 + // 加水定容 if ( 0 < digestionRound.waterVolume ) { this.updateTaskStatus("Water", String.format("加水定容 : %d", digestionRound.waterVolume)); @@ -253,12 +261,12 @@ public class DigestionTaskThread extends Thread { // 正常消解结束; this.updateTaskStatus("LastRound", "取出试管架"); - device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); // 移动到加液盘 device.door.open(); // 打开门 this.waitForTubeRackTakeOut(); // 等待取出 device.door.close(); // 关闭门 this.heatingSlot.setTubeRackNo(null); // 释放加热位 this.updateTaskStatus("LastRound", "执行最后一轮配置结束"); + this.unlockLiquidPlate(); } // 执行消解最后一轮预检查 @@ -268,6 +276,8 @@ public class DigestionTaskThread extends Thread { // 检查试管 var device = Device.getInstance(); + this.lockLiquidPlate(); + // 移动到加液盘 device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); // 拍照检查异常试管 @@ -302,6 +312,7 @@ public class DigestionTaskThread extends Thread { // 将正常试管放入加热转盘 device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index); + this.unlockLiquidPlate(); // 启动异常处理线程 DigestionTaskThread.this.errorProcessThread = new Thread(DigestionTaskThread.this::executeErrorProcess); @@ -361,6 +372,7 @@ public class DigestionTaskThread extends Thread { this.updateTaskStatus("TubeCheck", String.format("取出剩余异常试管 : [%s]", errorTubeIndexes)); // 如果还存在异常, 则直接取出 var device = Device.getInstance(); + this.lockLiquidPlate(); // 等待放入空试管架 device.door.open(); this.waitForEmptyTubeRackPutIn(); @@ -377,6 +389,7 @@ public class DigestionTaskThread extends Thread { device.door.open(); this.waitForTubeRackTakeOut(); device.door.close(); + this.unlockLiquidPlate(); } catch (InterruptedException e) { UfMdbNotification.error("消解异常处理失败 : " + e.getMessage()); this.updateTaskStatus("Error", String.format("消解异常处理失败 : %s", e.getMessage())); @@ -399,6 +412,7 @@ public class DigestionTaskThread extends Thread { } this.updateTaskStatus("ErrorRound", "移动异常试管架至加液区"); + this.lockLiquidPlate(); device.transferArm.moveTubeRackToLiquidPlate(errorSlot.index); var liquidAddition = device.liquidAddition; @@ -412,6 +426,7 @@ public class DigestionTaskThread extends Thread { this.updateTaskStatus("ErrorRound", "移动异常试管架至加热区"); device.transferArm.moveTubeRackToHeatingTurntable(errorSlot.index); + this.unlockLiquidPlate(); for ( var heating : errorRound.heatings ) { this.updateTaskStatus("ErrorRoundHeating", String.format("异常加热 %d℃ %d分钟", heating.temperature, heating.duration)); @@ -420,19 +435,21 @@ public class DigestionTaskThread extends Thread { } this.updateTaskStatus("ErrorRound", "移动异常试管架至加液区"); + this.lockLiquidPlate(); device.transferArm.moveTubeRackToLiquidPlate(errorSlot.index); // 拍照检查是否存在消解完成的试管 this.executeErrorRoundTakeShotAndCheckFinishedTubes(); + this.updateTaskStatus("ErrorRound", "移动异常试管架至加热区"); + device.transferArm.moveTubeRackToHeatingTurntable(errorSlot.index); + // 如果不存在消解完成的试管则本轮次结束 if (this.finishedErrorTubeIndexes.isEmpty()) { + this.unlockLiquidPlate(); return ; } - this.updateTaskStatus("ErrorRound", "移动异常试管架至加热区"); - device.transferArm.moveTubeRackToHeatingTurntable(errorSlot.index); - // 等待放入空试管架 device.door.open(); this.waitForEmptyTubeRackPutIn(); @@ -446,6 +463,7 @@ public class DigestionTaskThread extends Thread { device.door.open(); this.waitForTubeRackTakeOut(); device.door.close(); + this.unlockLiquidPlate(); // 更新异常试管索引列表 this.errorTubeIndexes.removeAll(this.finishedErrorTubeIndexes); @@ -539,6 +557,31 @@ public class DigestionTaskThread extends Thread { this.updateTaskStatus("TubeRackTakeOutWaitDone", "试管架已取出"); } + // 使用加液盘 + private void lockLiquidPlate() { + var lockName = this.taskModel.id; + if ( "manual".equals(this.taskModel.mode) ) { + lockName = this.taskModel.batchNo; + } + + var device = Device.getInstance(); + this.updateTaskStatus("WaitForLiquidPlate", "等待加液盘空闲"); + device.liquidAddition.lockLiquidPlate(lockName); + this.updateTaskStatus("WaitForLiquidPlate", "锁定加液盘"); + } + + // 释放加液盘 + private void unlockLiquidPlate() { + var lockName = this.taskModel.id; + if ( "manual".equals(this.taskModel.mode) ) { + lockName = this.taskModel.batchNo; + } + + var device = Device.getInstance(); + this.updateTaskStatus("WaitForLiquidPlate", "释放加液盘"); + device.liquidAddition.unlockLiquidPlate(lockName); + } + // 更新任务状态 private void updateTaskStatus(String status, String message) { LOG.info("[Digestion Task : {}] ({}) {}", taskModel.id, status, message); diff --git a/src/main/java/com/iflytop/digester/controller/HeatSlotController.java b/src/main/java/com/iflytop/digester/controller/HeatSlotController.java index 18436e5..26960a4 100644 --- a/src/main/java/com/iflytop/digester/controller/HeatSlotController.java +++ b/src/main/java/com/iflytop/digester/controller/HeatSlotController.java @@ -8,6 +8,8 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import java.util.Map; +import java.util.UUID; + @Controller public class HeatSlotController extends UfApiControllerBase { @Resource @@ -26,6 +28,7 @@ public class HeatSlotController extends UfApiControllerBase { String tubeRackNo = (String)params.get("tubeRackNo"); try { var slot = this.device.heatingTurntable.allocSlot(tubeRackNo); + this.device.liquidAddition.lockLiquidPlate(tubeRackNo); return this.success(slot); } catch ( Exception e ) { return this.error(e.getMessage()); @@ -38,6 +41,7 @@ public class HeatSlotController extends UfApiControllerBase { Integer slotIndex = (Integer)params.get("slotIndex"); try { var slot = this.device.heatingTurntable.getSlotByIndex(slotIndex); + this.device.liquidAddition.unlockLiquidPlate(slot.tubeRackNo); slot.setTubeRackNo(null); return this.success(); } catch ( Exception e ) { diff --git a/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java b/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java index 5c261b0..0455846 100644 --- a/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java +++ b/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java @@ -1,11 +1,9 @@ package com.iflytop.digester.deviceinstance; import com.iflytop.digester.underframework.UfActuatorCmdExecutor; import com.iflytop.digester.underframework.UfCmdSnippetExecutor; - import java.util.ArrayList; import java.util.List; import java.util.Map; - public class HeatingTurntableSlot { // 槽位索引 public Integer index = -1; diff --git a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java index 37d5e01..8e6167b 100644 --- a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java +++ b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java @@ -17,9 +17,12 @@ public class LiquidAdditionInstance { private List liquids; // lock for bucket empty private final Object bucketEmptyLock = new Object(); + // locks for liquid plate + private final List liquidPlateLocks = new ArrayList<>(); // setup public void setup() { + this.liquidPlateLocks.clear(); this.liquids = new ArrayList<>(); for (int i = 0; i < 8; i++) { LiquidAdditionLiquid liquid = new LiquidAdditionLiquid(); @@ -31,6 +34,43 @@ public class LiquidAdditionInstance { } } + // lock liquid plate + public void lockLiquidPlate( String lockName ) { + MdbRuntimeLog.log("LiquidPlateLock", "加液盘锁定等待 : %s", lockName); + this.liquidPlateLocks.add(lockName); + if ( 1 == this.liquidPlateLocks.size() ) { + MdbRuntimeLog.log("LiquidPlateLock", "加液盘锁定成功 : %s", lockName); + return ; + } + synchronized ( lockName ) { + try { + lockName.wait(); + MdbRuntimeLog.log("LiquidPlateLock", "加液盘锁定成功 : %s", lockName); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + // unlock liquid plate + public void unlockLiquidPlate( String lockName ) { + MdbRuntimeLog.log("LiquidPlateLock", "加液盘锁定解除 : %s", lockName); + String lock = null; + for ( String lockItem : this.liquidPlateLocks ) { + if ( lockItem.equals(lockName) ) { + lock = lockItem; + } + } + this.liquidPlateLocks.remove(lock); + if (this.liquidPlateLocks.isEmpty()) { + return ; + } + Object nextLock = this.liquidPlateLocks.remove(0); + synchronized ( nextLock ) { + nextLock.notify(); + } + } + // get liquids public List getLiquids() { return this.liquids; @@ -95,6 +135,13 @@ public class LiquidAdditionInstance { // 检查液体量 private void bucketVolumeCheck( Integer pumpIndex ) { + var env = UfApplication.getApp().getEnv(); + Boolean bucketVolumeCheckEnable = env.getProperty("app.bucketVolumeCheckEnable", Boolean.class); + assert null != bucketVolumeCheckEnable; + if ( !bucketVolumeCheckEnable ) { + return ; + } + var liquid = liquids.get((0==pumpIndex%2) ? pumpIndex/2 : (pumpIndex-1)/2); var stateStr = UfActuatorCmdExecutor.execute("LiquidBucketVolumeIO", "module_readio"); var state = Integer.parseInt(stateStr); @@ -108,7 +155,6 @@ public class LiquidAdditionInstance { liquid.setVolume(0); // 如果缺少的液体不是水, 则需要发送通知手动补充 - var env = UfApplication.getApp().getEnv(); Integer waterBucketIndex = env.getProperty("app.liquidWaterBucketIndex", Integer.class); assert waterBucketIndex != null; if (!waterBucketIndex.equals(liquid.bucketIndex)) { diff --git a/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java b/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java index ae51de4..9bd410e 100644 --- a/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java +++ b/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java @@ -28,7 +28,9 @@ public class UfActiveRecord { String tableName = UfActiveRecord.getTableNameFromModelClass(this.getClass()); Map data = UfActiveRecord.exportModelData(this); if ( this.isNewRecord ) { - this.id = UUID.randomUUID().toString(); + if ( null == this.id ) { + this.id = UUID.randomUUID().toString(); + } data.put("id", this.id); mapper.insert(tableName, data); this.isNewRecord = false;