From 8e1785ef9e9173867d04a09f89ce5a69c83df2fa Mon Sep 17 00:00:00 2001 From: sige Date: Tue, 23 Apr 2024 15:49:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E6=B6=B2=E6=A3=80=E6=9F=A5=E6=B6=B2?= =?UTF-8?q?=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.db | Bin 385024 -> 385024 bytes .../digester/controller/LiquidController.java | 8 ++ .../digester/controller/TestController.java | 10 ++ .../deviceinstance/LiquidAdditionInstance.java | 102 +++++++++++++++++---- .../deviceinstance/LiquidAdditionLiquid.java | 5 + .../digester/underframework/util/UfCommon.java | 11 +++ src/main/resources/application-dev.yml | 1 + 7 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/iflytop/digester/underframework/util/UfCommon.java diff --git a/app.db b/app.db index c97ca00e61abfcb3076bfc89a8be435d556fd87e..afaa2c70df4b9e1c507537437f355414431c4adc 100644 GIT binary patch delta 5844 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 delta 305 zcmZoTAl`65e1a5{wEILECpKw!20j1UjVTM(GcgEkWn}!tKPi9(#@uv)8j-K-c;$jcG0#ugeX zFDW?veI$!Y`^H+9?Hg-ZgN=mPx%V>gXYrlqGvJ-V^MfandoNJ^a_;SWce6UH008AL BU{nAA diff --git a/src/main/java/com/iflytop/digester/controller/LiquidController.java b/src/main/java/com/iflytop/digester/controller/LiquidController.java index 71bfc3e..a9d3e27 100644 --- a/src/main/java/com/iflytop/digester/controller/LiquidController.java +++ b/src/main/java/com/iflytop/digester/controller/LiquidController.java @@ -30,4 +30,12 @@ public class LiquidController extends UfApiControllerBase { bucket.setVolume(bucket.totalVolume); return this.success(); } + + @ResponseBody + @PostMapping("/api/liquid/new-bucket") + public UfApiResponse newBucket(@RequestBody Map params) { + Integer bucketIndex = (Integer)params.get("index"); + this.device.liquidAddition.liquidNewBucket(bucketIndex); + return this.success(); + } } diff --git a/src/main/java/com/iflytop/digester/controller/TestController.java b/src/main/java/com/iflytop/digester/controller/TestController.java index aca350a..78fc4ef 100644 --- a/src/main/java/com/iflytop/digester/controller/TestController.java +++ b/src/main/java/com/iflytop/digester/controller/TestController.java @@ -21,4 +21,14 @@ public class TestController extends UfApiControllerBase { this.device.transferArm.takeOutTubesFromErrorSlot(indexes); return this.success(); } + + @ResponseBody + @PostMapping("/api/test/liquid-add") + public UfApiResponse liquidAdd(@RequestBody Map params) { + List tubes = (List)params.get("tubes"); + String type = (String)params.get("type"); + Integer volume = (Integer)params.get("volume"); + this.device.liquidAddition.addLiquidToTubes(tubes, type, volume); + return this.success(); + } } diff --git a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java index c37cb99..1ed8fe3 100644 --- a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java +++ b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java @@ -1,7 +1,12 @@ package com.iflytop.digester.deviceinstance; +import com.iflytop.digester.model.MdbRuntimeLog; +import com.iflytop.digester.underframework.UfActuatorCmdExecutor; +import com.iflytop.digester.underframework.UfApplication; import com.iflytop.digester.underframework.UfCmdSnippetExecutor; +import com.iflytop.digester.underframework.dao.model.UfMdbNotification; import com.iflytop.digester.underframework.dao.model.UfMdbOption; import com.iflytop.digester.underframework.dao.model.UfMdbRuntimeVariable; +import com.iflytop.digester.underframework.util.UfCommon; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @@ -10,6 +15,8 @@ import java.util.Map; public class LiquidAdditionInstance { // list of liquids private List liquids; + // lock for bucket empty + private final Object bucketEmptyLock = new Object(); // setup public void setup() { @@ -38,9 +45,7 @@ public class LiquidAdditionInstance { public void addLiquidToTubes(List tubes, List pumpIndexes, int volume ) { var pumpGroupOutIndex = pumpIndexes.get(0); var pumpGroupInIndex = pumpIndexes.get(1); - var liquid = liquids.get(pumpGroupOutIndex/2); - var type = liquids.get(pumpGroupOutIndex/2).type; - var rotateDistance = this.convertVolumeToPumpRotationDistance(type, volume); + this.bucketVolumeCheck(pumpGroupOutIndex); for ( int batchIndex=0; batchIndex<4; batchIndex++ ) { // 外圈 @@ -49,16 +54,10 @@ public class LiquidAdditionInstance { if ( hasGoutTout || hasGoutTin ) { UfCmdSnippetExecutor.execute("LiquidAdditionPrepare.Out." + batchIndex); if ( hasGoutTout ) { - var snippetKey = "LiquidAdditionPump." + pumpGroupOutIndex; - Map snippetParams = Map.of("volume", rotateDistance); - UfCmdSnippetExecutor.execute(snippetKey, snippetParams); - liquid.volume -= volume; + this.pump(pumpGroupOutIndex, volume); } if ( hasGoutTin ) { - var snippetKey = "LiquidAdditionPump." + pumpGroupInIndex; - Map snippetParams = Map.of("volume", rotateDistance); - UfCmdSnippetExecutor.execute(snippetKey, snippetParams); - liquid.volume -= volume; + this.pump(pumpGroupInIndex, volume); } } @@ -68,16 +67,10 @@ public class LiquidAdditionInstance { if ( hasGinTout || hasGinTin ) { UfCmdSnippetExecutor.execute("LiquidAdditionPrepare.In." + batchIndex); if ( hasGinTout ) { - var snippetKey = "LiquidAdditionPump." + pumpGroupOutIndex; - Map snippetParams = Map.of("volume", rotateDistance); - UfCmdSnippetExecutor.execute(snippetKey, snippetParams); - liquid.volume -= volume; + this.pump(pumpGroupOutIndex, volume); } if ( hasGinTin ) { - var snippetKey = "LiquidAdditionPump." + pumpGroupInIndex; - Map snippetParams = Map.of("volume", rotateDistance); - UfCmdSnippetExecutor.execute(snippetKey, snippetParams); - liquid.volume -= volume; + this.pump(pumpGroupInIndex, volume); } } } @@ -85,6 +78,68 @@ public class LiquidAdditionInstance { UfCmdSnippetExecutor.execute("LiquidAdditionReset"); } + // add liquid to tubes by given pump indexes + private void pump( Integer pumpIndex, Integer volume ) { + var liquid = liquids.get((0==pumpIndex%2) ? pumpIndex/2 : (pumpIndex-1)/2); + var type = liquid.type; + + var snippetKey = "LiquidAdditionPump." + pumpIndex; + var rotateDistance = this.convertVolumeToPumpRotationDistance(type, volume); + Map snippetParams = Map.of("volume", rotateDistance); + UfCmdSnippetExecutor.execute(snippetKey, snippetParams); + + // update liquid volume + liquid.setVolumeByConsumed(volume); + MdbRuntimeLog.log("LiquidAdd", "酸液消耗:%s - %d [%d/%d]", type, volume, liquid.volume, liquid.totalVolume); + } + + // 检查液体量 + private void bucketVolumeCheck( Integer pumpIndex ) { + var liquid = liquids.get((0==pumpIndex%2) ? pumpIndex/2 : (pumpIndex-1)/2); + var stateStr = UfActuatorCmdExecutor.execute("LiquidBucketVolumeIO", "module_readio"); + var state = Integer.parseInt(stateStr); + MdbRuntimeLog.log("LiquidBucketVolumeIO", "液桶状态:[%s]", Integer.toString(state, 2)); + var bucketState = state >> liquid.bucketIndex & 1; + if ( 1 == bucketState ) { // 酸液足够 + return ; + } + + // 如果缺少的液体不是水, 则需要发送通知手动补充 + var env = UfApplication.getApp().getEnv(); + Integer waterBucketIndex = env.getProperty("app.liquidWaterBucketIndex", Integer.class); + assert waterBucketIndex != null; + if (!waterBucketIndex.equals(liquid.bucketIndex)) { + UfMdbNotification.action("LiquidBucketEmpty", Map.of("liquid", liquid)); + MdbRuntimeLog.log("LiquidBucketEmpty", "酸液不足,等待手动补充完成 : %s", liquid.type); + synchronized ( this.bucketEmptyLock ) { + try { + this.bucketEmptyLock.wait(); + MdbRuntimeLog.log("LiquidBucketEmpty", "酸液补充完成"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + this.bucketVolumeCheck(pumpIndex); + return; + } + + // 水桶液位不足,自动补充 + MdbRuntimeLog.log("WaterBucketEmpty", "水桶液位不足,自动补充"); + UfActuatorCmdExecutor.execute("LiquidBucketVolumeIO", "module_writeio", "8,1"); + do { + // 检查上限位是否达到 + var waterStateStr = UfActuatorCmdExecutor.execute("LiquidBucketVolumeIO", "module_readio"); + var waterState = Integer.parseInt(waterStateStr); + boolean isBucketFull = 1 == (waterState >> 12 & 1); + if ( isBucketFull ) { + break; + } + UfCommon.delay(100); + } while ( true ); + UfActuatorCmdExecutor.execute("LiquidBucketVolumeIO", "module_writeio", "8,0"); + MdbRuntimeLog.log("WaterBucketEmpty", "水桶液位补充完成"); + } + // 针对试管加液 public void addLiquidToTubes(List tubes, String type, int volume ) { var pumpIndexes = this.getPumpIndexForGroupOutAndIn(type); @@ -132,4 +187,13 @@ public class LiquidAdditionInstance { } UfCmdSnippetExecutor.execute("LiquidAddShakeStop"); } + + // 酸液更换完成 + public void liquidNewBucket( Integer index ) { + var liquid = liquids.get(index); + liquid.setVolume(liquid.totalVolume); + synchronized ( this.bucketEmptyLock ) { + this.bucketEmptyLock.notify(); + } + } } diff --git a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionLiquid.java b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionLiquid.java index aed09ad..428c4bf 100644 --- a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionLiquid.java +++ b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionLiquid.java @@ -23,4 +23,9 @@ public class LiquidAdditionLiquid { this.volume = volume; UfMdbRuntimeVariable.setInteger(String.format("LiquidBucketVolume.%d", this.bucketIndex), volume); } + + // 通过消耗量设置剩余量 + public void setVolumeByConsumed( Integer volume ) { + this.setVolume( this.volume - volume); + } } diff --git a/src/main/java/com/iflytop/digester/underframework/util/UfCommon.java b/src/main/java/com/iflytop/digester/underframework/util/UfCommon.java new file mode 100644 index 0000000..ebf3c8b --- /dev/null +++ b/src/main/java/com/iflytop/digester/underframework/util/UfCommon.java @@ -0,0 +1,11 @@ +package com.iflytop.digester.underframework.util; +public class UfCommon { + // delay for ms + public static void delay( Integer ms ) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 28d6d86..3524b01 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -36,6 +36,7 @@ app : errorSlotIndex : 4 liquidPeristalticPumpPipeSetupEnable : false liquidPipeVolumn : 1 + liquidWaterBucketIndex : 2 opencv-library-path: D:/ProgramFiles/OpenCV/opencv/build/java/x64/opencv_java490.dll pylon-library-path: D:/ProgramFiles/Pylon5/Runtime/x64/PylonC_v5_2.dll pylon-wrapper-path: D:/Sige5193/digester/src/main/java/com/iflytop/digester/camera/x64/Debug/baslerCamera.dll