From e6642d5543764ae69eb54845fd75fc83fa86b241 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Wed, 28 May 2025 20:45:10 +0800 Subject: [PATCH] update --- .../ExperimentConsistencyTestingService.java | 17 +- ...LiquidAbsorptionAndDistributionTestService.java | 6 +- .../app/hardware/driver/PipetteCtrlDriverV2.java | 42 ++- .../hardware/type/pipette_module/DistribuType.java | 11 + .../cfg/PipetteCommonConfigIndex.java | 1 + .../cfgbean/PipetteCommonConfig.java | 1 + .../type/pipette_module/cpyidx/ContainerCpyId.java | 1 + .../pipette_module/cpyidx/LiquidConfigCpyIdx.java | 2 + .../type/pipette_module/cpyidx/PlatInfoCpyIdx.java | 22 +- .../type/pipette_module/param/AspirationParam.java | 32 +- .../pipette_module/param/DistribuAllParam.java | 25 ++ .../lowerctrl/DeviceMoveToZeroCtrlService.java | 8 +- .../service/lowerctrl/HbotMoveExCtrlService.java | 22 +- .../lowerctrl/LiquidOperationCtrlService.java | 269 --------------- .../mainflowctrl/MainFlowCtrlScheduler.java | 5 - .../mainflowctrl/action/AC41ProcessSample.java | 22 +- .../service/module/LiquidOperationCtrlModule.java | 383 +++++++++++++++++++++ .../java/a8k/app/service/module/TipMgrModule.java | 18 +- .../param/exparam/HbotConsumableExParamMgr.java | 4 +- .../service/param/hbotpos/HbotLittleBSPosMgr.java | 12 +- .../param/hbotpos/HbotProbeSubstancePosMgr.java | 4 +- .../a8k/app/type/a8k/state/ProjectTaskContext.java | 2 +- .../pipette_module/PipetteGunCommonConfigPage.java | 8 +- .../PipetteGunOperationCtrlPage.java | 12 +- .../verification/P32HbotPosVerificationPage.java | 2 +- .../verification/P34LiquidOperationTestPage.java | 51 ++- 26 files changed, 594 insertions(+), 388 deletions(-) create mode 100644 src/main/java/a8k/app/hardware/type/pipette_module/DistribuType.java delete mode 100644 src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java create mode 100644 src/main/java/a8k/app/service/module/LiquidOperationCtrlModule.java diff --git a/src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java b/src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java index a3ca4f9..ade0a69 100644 --- a/src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java +++ b/src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java @@ -17,12 +17,12 @@ import a8k.app.service.data.ProjInfoMgrService; import a8k.app.service.data.ReactionRecordMgrService; import a8k.app.service.lowerctrl.*; import a8k.app.service.mainctrl.TubeHolderSettingMgrService; +import a8k.app.service.module.LiquidOperationCtrlModule; import a8k.app.service.module.TipMgrModule; import a8k.app.service.statemgr.*; import a8k.app.service.utils.ProjInfoUtils; import a8k.app.service.utils.UISender; import a8k.app.type.a8k.A8kTubeHolderType; -import a8k.app.type.a8k.BloodType; import a8k.app.type.a8k.ConsumableType; import a8k.app.type.a8k.opt.A8kOptType; import a8k.app.type.a8k.opt.OptScanResult; @@ -98,9 +98,9 @@ public class ExperimentConsistencyTestingService { final private TubePreProcesModuleExCtrlService tubePreProcesModuleExCtrlService; final private OptScanModuleCtrlService optScanModuleCtrlService; final private PlateBoxCtrlService plateBoxCtrlService; - final private TurnableMoveCtrlService turnableMoveCtrlService; - final private LiquidOperationCtrlService liquidOperationCtrlService; - final private HbotMoveExCtrlService hbotMoveExCtrlService; + final private TurnableMoveCtrlService turnableMoveCtrlService; + final private LiquidOperationCtrlModule liquidOperationCtrlModule; + final private HbotMoveExCtrlService hbotMoveExCtrlService; private final OptModuleDriver optModuleDriver; private final HbotMoveCtrlService hbotMoveCtrlService; private final TipMgrModule tipMgrModule; @@ -397,10 +397,10 @@ public class ExperimentConsistencyTestingService { docmd("样本处理", () -> { try { - liquidOperationCtrlService.setProjContext(projBuildinInfo, projExtInfoCard); + liquidOperationCtrlModule.setProjContext(projBuildinInfo, projExtInfoCard); var preProcessPos = new PreReactionPos(ConsumableType.SmallBottleBuffer, consumableInfo.group, consumableInfo.pos); //取tip - tipMgrModule.takeTip(() -> !actionExecutor.isStopping()); + tipMgrModule.tryTakeTip(() -> !actionExecutor.isStopping()); actionExecutor.sleep(1); //刺破缓冲液 hbotMoveExCtrlService.moveToLittleBufferPiercePos(consumableInfo.group, consumableInfo.pos); @@ -408,10 +408,11 @@ public class ExperimentConsistencyTestingService { Assert.isTrue(!samplePos.equals(A8kSamplePos.EmergencyTubePos), "samplePos cannot be EmergencyTubePos"); Assert.isTrue(!samplePos.equals(A8kSamplePos.BloodHTubePos), "samplePos cannot be BloodHTubePos"); Assert.isTrue(!samplePos.equals(A8kSamplePos.BloodSTubePos), "samplePos cannot be BloodSTubePos"); - liquidOperationCtrlService.takeSample(samplePos, preProcessPos, takeSampleUl); + liquidOperationCtrlModule.takeSampleToPreReactionPos(samplePos, preProcessPos, takeSampleUl); actionExecutor.sleep(1); //取混合液到预反应位 - liquidOperationCtrlService.takePreReactionLiquidToReation(preProcessPos); + liquidOperationCtrlModule.takePreReactionLiquid(preProcessPos); + liquidOperationCtrlModule.dropLiquidToReactionPlate(); actionExecutor.sleep(1); incubationPlateStateMgrService.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60); actionExecutor.sleep(1); diff --git a/src/main/java/a8k/app/engineer/service/qatest/LiquidAbsorptionAndDistributionTestService.java b/src/main/java/a8k/app/engineer/service/qatest/LiquidAbsorptionAndDistributionTestService.java index 80e1e85..0f3f08f 100644 --- a/src/main/java/a8k/app/engineer/service/qatest/LiquidAbsorptionAndDistributionTestService.java +++ b/src/main/java/a8k/app/engineer/service/qatest/LiquidAbsorptionAndDistributionTestService.java @@ -3,10 +3,10 @@ package a8k.app.engineer.service.qatest; import a8k.app.engineer.service.executor.EngineerModeActionExecutor; import a8k.app.engineer.service.utils.BeforeDoEngineerActionChecker; import a8k.app.service.lowerctrl.*; +import a8k.app.service.module.LiquidOperationCtrlModule; import a8k.app.service.module.TipMgrModule; import a8k.app.service.param.exparam.HbotConsumableExParamMgr; import a8k.app.service.utils.UISender; -import a8k.app.type.a8k.*; import a8k.app.type.exception.AppException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -34,8 +34,8 @@ public class LiquidAbsorptionAndDistributionTestService { /* * 状态管理器 */ - final private LiquidOperationCtrlService liquidOperationCtrlService; - final private HbotMoveExCtrlService hbotMoveExCtrlService; + final private LiquidOperationCtrlModule liquidOperationCtrlModule; + final private HbotMoveExCtrlService hbotMoveExCtrlService; final private TipMgrModule tipMgrModule; final private HbotMoveCtrlService hbotMoveCtrlService; diff --git a/src/main/java/a8k/app/hardware/driver/PipetteCtrlDriverV2.java b/src/main/java/a8k/app/hardware/driver/PipetteCtrlDriverV2.java index 0a25d5d..178cf3c 100644 --- a/src/main/java/a8k/app/hardware/driver/PipetteCtrlDriverV2.java +++ b/src/main/java/a8k/app/hardware/driver/PipetteCtrlDriverV2.java @@ -13,6 +13,7 @@ import a8k.app.hardware.type.pipette_module.cfg.*; import a8k.app.hardware.type.pipette_module.param.AspirationParam; import a8k.app.hardware.type.pipette_module.param.DistribuAllParam; import a8k.app.type.exception.AppException; +import a8k.app.utils.ZJsonHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -306,8 +307,8 @@ public class PipetteCtrlDriverV2 { waitForMod(CmdId.pipette_pump_init_device); } - public void initPumpDeviceBlock(PlatformInfoIndex platInfoCpyId) throws AppException { - initPumpDeviceBlock(platInfoCpyId.toInteger()); + public void initPumpDeviceBlock() throws AppException { + initPumpDeviceBlock(-1); } public void takeTipBlock() throws AppException { @@ -335,6 +336,7 @@ public class PipetteCtrlDriverV2 { } public void aspirateSetParam(AspirationParam param) throws AppException { + log.info("aspirateSetParam :\n{}", ZJsonHelper.objToPrettyJson(param)); param.serialization(this::aspirateSetParam); } @@ -343,6 +345,29 @@ public class PipetteCtrlDriverV2 { waitForMod(CmdId.pipette_pump_aspirate); } + public void aspirateBlock(AspirationParam aspirationParam) throws AppException { + aspirateSetParam(aspirationParam); + aspirateBlock(); + } + + public void distributeAllSetParam(DistribuAllParamId param, Integer val) throws AppException { + callcmd(MId.PipetteMod, CmdId.pipette_pump_distribu_all_set_param, param.toInteger(), val); + } + + public void distributeAllSetParam(DistribuAllParam param) throws AppException { + log.info("distributeAllSetParam :\n{}", ZJsonHelper.objToPrettyJson(param)); + param.serialization(this::distributeAllSetParam); + } + + public void distributeAllBlock() throws AppException { + callcmd(MId.PipetteMod, CmdId.pipette_pump_distribu_all); + waitForMod(CmdId.pipette_pump_distribu_all); + } + + public void distributeAllBlock(DistribuAllParam distribuAllParam) throws AppException { + distributeAllSetParam(distribuAllParam); + distributeAllBlock(); + } public void pipetteTestPumpMoveToX100nl(Integer x100nl, Integer vcfgIndex) throws AppException { callcmd(MId.PipetteMod, CmdId.pipette_test_pump_move_to_x100nl, x100nl, vcfgIndex); @@ -395,19 +420,6 @@ public class PipetteCtrlDriverV2 { } - public void pipettePumpDistributeAllSetParam(DistribuAllParamId param, Integer val) throws AppException { - callcmd(MId.PipetteMod, CmdId.pipette_pump_distribu_all_set_param, param.toInteger(), val); - } - - public void pipettePumpDistributeAllSetParam(DistribuAllParam param) throws AppException { - param.serialization(this::pipettePumpDistributeAllSetParam); - } - - public void pipettePumpDistributeAllBlock() throws AppException { - callcmd(MId.PipetteMod, CmdId.pipette_pump_distribu_all); - waitForMod(CmdId.pipette_pump_distribu_all); - } - public Integer readState(PipetteStateIndex index) throws AppException { return callcmd(MId.PipetteMod, CmdId.pipette_read_state, index.toInteger()).getContentI32(0); } diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/DistribuType.java b/src/main/java/a8k/app/hardware/type/pipette_module/DistribuType.java new file mode 100644 index 0000000..5b4e1f7 --- /dev/null +++ b/src/main/java/a8k/app/hardware/type/pipette_module/DistribuType.java @@ -0,0 +1,11 @@ +package a8k.app.hardware.type.pipette_module; + +public enum DistribuType { + JET_DIST, //液面上分配 + SURFACE_DIST, //液体表面分配 + ; + + public Integer toInteger() { + return this.ordinal(); + } +} diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/cfg/PipetteCommonConfigIndex.java b/src/main/java/a8k/app/hardware/type/pipette_module/cfg/PipetteCommonConfigIndex.java index 798138e..6a4bdef 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/cfg/PipetteCommonConfigIndex.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/cfg/PipetteCommonConfigIndex.java @@ -2,6 +2,7 @@ package a8k.app.hardware.type.pipette_module.cfg; public enum PipetteCommonConfigIndex { pressureRecordEnable, + platformInfoCpyid, mark; public Integer toInteger() { diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/cfgbean/PipetteCommonConfig.java b/src/main/java/a8k/app/hardware/type/pipette_module/cfgbean/PipetteCommonConfig.java index 51f11fd..ea9c7b5 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/cfgbean/PipetteCommonConfig.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/cfgbean/PipetteCommonConfig.java @@ -24,6 +24,7 @@ public class PipetteCommonConfig { // lld // public Integer pressureRecordEnable = 0; // 是否记录压力数据 + public Integer platformInfoCpyid = 0; // 平台信息配置索引,当调用initPumpDevice时,如果传入的参数为-1,则使用platformInfoCpyid public Integer mark = 0; // 结构体最后一个数值,设置9973,用于保证单片机端和java端均正确更新了枚举 diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/ContainerCpyId.java b/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/ContainerCpyId.java index 6148744..4d535ad 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/ContainerCpyId.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/ContainerCpyId.java @@ -11,6 +11,7 @@ public enum ContainerCpyId { BulletTube1P5,//子弹头1.5ml BulletTube0P5,//子弹头0.5ml StoolTestTube,//粪便试管 + ReactionPlate, NotSet, ; diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/LiquidConfigCpyIdx.java b/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/LiquidConfigCpyIdx.java index c185e33..c63ac57 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/LiquidConfigCpyIdx.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/LiquidConfigCpyIdx.java @@ -37,6 +37,8 @@ public enum LiquidConfigCpyIdx { } public Integer toInteger() { + if (this.equals(NotSet)) + return -1; return ordinal(); } } diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/PlatInfoCpyIdx.java b/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/PlatInfoCpyIdx.java index 1f31c2f..6809ba1 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/PlatInfoCpyIdx.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/PlatInfoCpyIdx.java @@ -2,5 +2,25 @@ package a8k.app.hardware.type.pipette_module.cpyidx; public enum PlatInfoCpyIdx { Default, - TestTip, + TransparentTip, + NotSet, + ; + + public Integer toInteger() { + if (this.equals(NotSet)) + return -1; + return ordinal(); + } + + static public PlatInfoCpyIdx of(Integer val) { + if (val < 0) + return NotSet; + for (PlatInfoCpyIdx idx : PlatInfoCpyIdx.values()) { + if (idx.ordinal() == val) { + return idx; + } + } + + return NotSet; + } } diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/param/AspirationParam.java b/src/main/java/a8k/app/hardware/type/pipette_module/param/AspirationParam.java index 3e33a79..85efa36 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/param/AspirationParam.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/param/AspirationParam.java @@ -1,6 +1,8 @@ package a8k.app.hardware.type.pipette_module.param; import a8k.app.hardware.type.pipette_module.AspirationParamId; +import a8k.app.hardware.type.pipette_module.cpyidx.ContainerCpyId; +import a8k.app.hardware.type.pipette_module.cpyidx.LiquidConfigCpyIdx; import a8k.app.type.exception.AppException; public class AspirationParam { @@ -16,7 +18,7 @@ public class AspirationParam { // // 液体类型 // - public Integer liquidCfgIdx = 0; + public Integer liquidCfgIdx = 0; // // 吸取模式 // @@ -38,6 +40,34 @@ public class AspirationParam { public Integer mixVolume = 0; public Integer mixTimes = 0; + public AspirationParam() {} + + public AspirationParam(Integer volumex100nl, + Integer containerPos, + ContainerCpyId containerInfoCpyId, + LiquidConfigCpyIdx liquidCfgIdx, + Integer aspirationMode, + Integer lldEnable, + Integer lldType, + Integer lldEnableProtect, + Integer mixLlfEnable, + Integer llfEnable, + Integer mixVolume, + Integer mixTimes) { + this.volume = volumex100nl; + this.containerPos = containerPos; + this.containerInfoCpyId = containerInfoCpyId.toInteger(); + this.liquidCfgIdx = liquidCfgIdx.toInteger(); + this.aspirationMode = aspirationMode; + this.lldEnable = lldEnable; + this.lldType = lldType; + this.lldEnableProtect = lldEnableProtect; + this.mixLlfEnable = mixLlfEnable; + this.llfEnable = llfEnable; + this.mixVolume = mixVolume; + this.mixTimes = mixTimes; + } + @FunctionalInterface public interface AssignObjectItemFn { Integer assignVal(AspirationParamId index) throws AppException; diff --git a/src/main/java/a8k/app/hardware/type/pipette_module/param/DistribuAllParam.java b/src/main/java/a8k/app/hardware/type/pipette_module/param/DistribuAllParam.java index 6baa03c..c8122bb 100644 --- a/src/main/java/a8k/app/hardware/type/pipette_module/param/DistribuAllParam.java +++ b/src/main/java/a8k/app/hardware/type/pipette_module/param/DistribuAllParam.java @@ -1,6 +1,9 @@ package a8k.app.hardware.type.pipette_module.param; import a8k.app.hardware.type.pipette_module.DistribuAllParamId; +import a8k.app.hardware.type.pipette_module.DistribuType; +import a8k.app.hardware.type.pipette_module.cpyidx.ContainerCpyId; +import a8k.app.hardware.type.pipette_module.cpyidx.LiquidConfigCpyIdx; import a8k.app.type.exception.AppException; public class DistribuAllParam { @@ -31,6 +34,28 @@ public class DistribuAllParam { // public Integer zmAutoMoveToZero = 0; // zm自动归零 + public DistribuAllParam() { + // 默认构造函数 + } + + public DistribuAllParam(Integer containerPos, + ContainerCpyId destContainerCpyid, + LiquidConfigCpyIdx destLiquidCfgIndex, + Boolean destContainerIsEmpty, + DistribuType distribuType, + Integer mixVolume, + Integer mixTimes, + Boolean zmAutoMoveToZero) { + this.containerPos = containerPos; + this.destContainerCpyid = destContainerCpyid.toInteger(); + this.destContainerIsEmpty = destContainerIsEmpty ? 1 : 0; + this.destLiquidCfgIndex = destLiquidCfgIndex.toInteger(); + this.distribuType = distribuType.toInteger(); + this.mixVolume = mixVolume; + this.mixTimes = mixTimes; + this.zmAutoMoveToZero = zmAutoMoveToZero ? 1 : 0; + } + @FunctionalInterface public interface SerializationObjectItemFn { void serializeObject(DistribuAllParamId index, Integer itermVal) throws AppException; diff --git a/src/main/java/a8k/app/service/lowerctrl/DeviceMoveToZeroCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/DeviceMoveToZeroCtrlService.java index 155e691..baad7c9 100644 --- a/src/main/java/a8k/app/service/lowerctrl/DeviceMoveToZeroCtrlService.java +++ b/src/main/java/a8k/app/service/lowerctrl/DeviceMoveToZeroCtrlService.java @@ -27,6 +27,8 @@ import java.util.List; public class DeviceMoveToZeroCtrlService { + private final PipetteCtrlDriverV2 pipetteCtrlDriverV2; + public static class Checkpoint { public enum Type { CHECK_TUBE_XCHANNEL_IS_EMPTY,//入料通道是否为空 @@ -86,7 +88,6 @@ public class DeviceMoveToZeroCtrlService { private final PipetteCtrlDriverV2 pipetteCtrlDriver; - // // ExDriver // @@ -241,8 +242,9 @@ public class DeviceMoveToZeroCtrlService { //弹出试管架 tubeFeedingCtrlService.ejectTubeHolder(); tubeFeedingCtrlService.moveTubeRackMoveToEnterPos(); - //丢弃tip头 - hbotMoveExCtrlService.initPipetterGun(); + //初始化tip + hbotMoveExCtrlService.moveToDropTipXYPos(); + pipetteCtrlDriverV2.initPumpDeviceBlock(); //hbot快速归零 hbotMoveExCtrlService.moveQuickToZero(); diff --git a/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java index 69e88be..5153c78 100644 --- a/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java +++ b/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java @@ -7,8 +7,6 @@ import a8k.app.type.a8k.ConsumableGroup; import a8k.app.type.a8k.pos.TipGroupPos; import a8k.app.type.a8k.Pos2d; import a8k.app.type.a8k.Pos3d; -import a8k.app.constant.AppConstant; -import a8k.app.hardware.type.A8kEcode; import a8k.app.hardware.driver.HbotDriver; import a8k.app.service.param.hbotpos.HbotTipPosMgr; import a8k.app.service.param.exparam.HbotConsumableExParamMgr; @@ -71,7 +69,6 @@ public class HbotMoveExCtrlService { if (nowPos.z.equals(observePos.z)) { hbotDriver.moveToBlock(observePos.x - GearBacklashConstant.HBOT_GEAR_BACKLASH, observePos.y); hbotDriver.moveToBlock(observePos.x, observePos.y); - return; } else { hbotMoveCtrlService.hbotMoveTo(observePos); } @@ -79,13 +76,11 @@ public class HbotMoveExCtrlService { - - public void initPipetterGun() throws AppException { + public void moveToDropTipPos() throws AppException { + log.info("moveToDropTipPos"); hbotMoveCtrlService.hbotMoveTo(hbotTipPosMgr.getDropTipPos()); - pipetteCtrlDriver.initPumpDeviceBlock(0); } - //************************************************************************************************* // //************************************************************************************************* @@ -97,7 +92,7 @@ public class HbotMoveExCtrlService { public void initializePipette() throws AppException { log.info("initializePipette"); - pipetteCtrlDriver.initPumpDeviceBlock(0); + pipetteCtrlDriver.initPumpDeviceBlock(); } @@ -136,7 +131,7 @@ public class HbotMoveExCtrlService { public void moveToProbeSubstanceSamplePos(ConsumableGroup group, Integer off) throws AppException { - hbotMoveCtrlService.hbotMoveTo(hbotConsumableExParamMgr.getProbeSubstanceSamplePos(group, off)); + hbotMoveCtrlService.hbotMoveTo(hbotConsumableExParamMgr.getProbeSubstanceContainerPos(group, off)); } public void moveToProbeSubstancePiercePos(ConsumableGroup group, Integer off) throws AppException { @@ -194,13 +189,4 @@ public class HbotMoveExCtrlService { return pos; } - - public Boolean isPosEq(Pos3d pos) throws AppException { - Pos3d curPos = getPos(); - if (Math.abs(curPos.x - pos.x) < 5 && Math.abs(curPos.y - pos.y) < 5 && Math.abs(curPos.z - pos.z) < 2) { - return true; - } - return false; - } - } diff --git a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java deleted file mode 100644 index 9098da2..0000000 --- a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java +++ /dev/null @@ -1,269 +0,0 @@ -package a8k.app.service.lowerctrl; - - -import a8k.app.dao.type.combination.ProjBuildinInfo; -import a8k.app.dao.type.db.ProjExtInfoCard; -import a8k.app.hardware.driver.PipetteCtrlDriverV2; -import a8k.app.hardware.type.A8kEcode; -import a8k.app.service.param.exparam.HbotConsumableExParamMgr; -import a8k.app.service.param.hbotpos.HbotSamplePosParamMgr; -import a8k.app.service.statemgr.ConsumablesMgrService; -import a8k.app.service.statemgr.GStateMgrService; -import a8k.app.service.utils.ZAppChecker; -import a8k.app.type.DeviceRunMode; -import a8k.app.type.JudgeFn; -import a8k.app.type.a8k.ConsumableType; -import a8k.app.type.a8k.Pos3d; -import a8k.app.type.a8k.pos.LargeBufferPos; -import a8k.app.type.a8k.pos.PreReactionPos; -import a8k.app.type.a8k.pos.TipGroupPos; -import a8k.app.type.a8k.pos.TipPos; -import a8k.app.type.exception.AppException; -import a8k.app.type.param.type.A8kSamplePos; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -@RequiredArgsConstructor -public class LiquidOperationCtrlService { - static public final Integer MIX_VOLUME_UL = 200; - - - private final GStateMgrService gstate; - - /* - * CTRL-SERVICE - */ - private final HbotMoveExCtrlService hbotMoveExCtrlService; - private final PipetteCtrlDriverV2 pipetteCtrlDriverV2; - - /* - * PARAM-MGR - */ - private final HbotConsumableExParamMgr hbotConsumableExParamMgr; - /** - * StateMgr - */ - private final ConsumablesMgrService consumablesMgrService; - private final HbotSamplePosParamMgr hbotSamplePosParamMgr; - - - ProjBuildinInfo projBuildinInfo; - ProjExtInfoCard projExtInfo; - - - synchronized public void setProjContext(ProjBuildinInfo projBuildinInfo, ProjExtInfoCard projExtInfo) { - this.projBuildinInfo = projBuildinInfo; - this.projExtInfo = projExtInfo; - } - - - /** - * 取大瓶缓冲液到探测物质位置 - * @param from 大瓶缓冲液 - * @param topos 探测物质位置 - * @param ul 吸取量 - */ - public void takeLargeBottleBufferLiquidToProbeSubstance(LargeBufferPos from, PreReactionPos topos, Integer ul) throws AppException { - // 取TIP - // forceTakeTip(); - - // 检查是否有TIP - ZAppChecker.check(pipetteCtrlDriverV2.readTipState(), A8kEcode.CODEERROR, "未检测到TIP"); - // Pos3d largeBottleEndPos = hbotConsumableExParamMgr.getLargeBufferSamplePosEnd(from.group); - // Pos3d largeBottlePos = hbotConsumableExParamMgr.getLargeBufferSamplePos(from.group); - Integer liquidLevel = 0; - - - // - // 刺破探测物质 - // - Pos3d piercePos = hbotConsumableExParamMgr.getProbeSubstancePiercePos(topos.group, topos.index); - hbotMoveExCtrlService.moveTo(piercePos); - pipetteCtrlDriverV2.zMotorMoveToBlock(0); - - - // - // 移动到取样位 - // - // hbotMoveExCtrlService.moveToXY(largeBottlePos); - - // - //取样 - // - //清空tip中的液体和空气,同时预先吸入部分空气,以便后续清空由于lld吸入的液体,提高lld的准确性 - { - //TODO: 取样 - - } - // lddprepare(); - // ldd(largeBottlePos.z, largeBottleEndPos.z, LLD_P_THRESHOLD); - // if (!pipetteCtrlDriverV2.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { - // throw AppException.of(A8kEcode.APPE_TAKE_LARGE_BUFFER_LIQUID_FAIL); - // } - // liquidLevel = pipetteCtrlDriverV2.getReg(PipetteRegIndex.kreg_pipette_zm_pos); - // pipetteCtrlDriverV2.zMotorMoveToBlock(0); - // pumpMoveTo(8000, 0.0); - // - // // - // //取样 - // // - // pipetteCtrlDriverV2.zMotorMoveToBlock(liquidLevel); - // if (ul < 100) { - // pumpMoveTo(8000, 50.0);//预先吸入部分空气 - // } else { - // pumpMoveTo(8000, 25.0);//预先吸入部分空气 - // } - // - // aspirate(largeBottleEndPos.z, pipetteGunExParamMgr.getLargeBSBottleLlfVel(), ul * 1.0); - // pipetteCtrlDriverV2.zMotorMoveToBlock(0); - - // - // 移动到探测物质的位置 - // - Pos3d toCPos = hbotConsumableExParamMgr.getProbeSubstanceSamplePos(topos.group, topos.index); - hbotMoveExCtrlService.moveTo(toCPos); - // pumpMoveTo(8000, 0.0); - pipetteCtrlDriverV2.zMotorMoveToBlock(0); - - // - // 丢弃TIP - // - hbotMoveExCtrlService.initPipetterGun(); - hbotMoveExCtrlService.moveQuickToZero(); - } - - private Pos3d getPreReactionPos(PreReactionPos pos) { - Pos3d toCPos = null; - if (pos.type.equals(ConsumableType.ProbeSubstance)) { - toCPos = hbotConsumableExParamMgr.getProbeSubstanceSamplePos(pos.group, pos.index); - } else { - toCPos = hbotConsumableExParamMgr.getLittleBufferSamplePos(pos.group, pos.index); - } - return toCPos; - } - - /** - * 取样本 - * @param from 样本位置 - * @param ul 吸取量 - * @throws AppException 异常 - */ - public void takeSampleOnly(A8kSamplePos from, Integer ul) throws AppException { - log.info("takeSampleOnly: from={},ul={}ul", from, ul); - - // 取TIP - // forceTakeTip(); - ZAppChecker.check(pipetteCtrlDriverV2.readTipState(), A8kEcode.CODEERROR, "未检测到TIP"); - - // - // 取样位 - // - - // 取样 - // Pos3d sampleStartPos = hbotSamplePosParamMgr.getSampleStartPos(from); - // Integer sampleEndZPos = hbotSamplePosParamMgr.getSampleEndPos(from); - Integer liquidLevel = 0; - // 移动到取样位 - // hbotMoveExCtrlService.moveToXY(sampleStartPos); - - //TODO:取样 - { - - } - //lld - //清空tip中的液体和空气,同时预先吸入部分空气,以便后续清空由于lld吸入的液体,提高lld的准确性 - // lddprepare(); - // ldd(sampleStartPos.z, sampleEndZPos, LLD_P_THRESHOLD); - // if (!pipetteCtrlDriverV2.lldIsDetectLiquid() && gstate.isInMode(DeviceRunMode.RealMode)) { - // throw AppException.of(A8kEcode.APPE_TAKE_SAMPLE_FAIL); - // } - // - // //获取当前液面高度 - // liquidLevel = pipetteCtrlDriverV2.getReg(PipetteRegIndex.kreg_pipette_zm_pos); - // liquidLevel += 10;//保证液面高度 - // - // //取样准备 - // pipetteCtrlDriverV2.zMotorMoveToBlock(sampleStartPos.z); //回到0 - // pumpMoveTo(8000, 0.0); //排空 - // pumpMoveTo(PRE_ASPIRATE_PUMP_VMAX, ASPIRATE_PRE_TAKE); //预先吸入部分空气 - // - // //取样 - // pipetteCtrlDriverV2.zMotorMoveToBlock(liquidLevel); - // aspirate(sampleEndZPos, pipetteGunExParamMgr.getSampleLLFVel(ul * 1.0, from), ul * 1.0); - // pipetteCtrlDriverV2.zMotorMoveToBlock(0); - - - } - - - /** - * 取样本到探测物质 - * @param from 样本位置 - * @param pos 预先反应位置P - * @param ul 吸取量 - * @throws AppException 异常 - */ - public void takeSample(A8kSamplePos from, PreReactionPos pos, Integer ul) throws AppException { - log.info("takeSampleToPreReactionPos: from={}, pos={}, ul={}ul", from, pos, ul); - - takeSampleOnly(from, ul); - - - // - // 移动到反应位 - // - log.info("move to pre reaction pos: {}", pos); - hbotMoveExCtrlService.moveTo(getPreReactionPos(pos)); - - Integer shakeUl = MIX_VOLUME_UL; - Integer shakeTimes = 5; - if (projBuildinInfo != null) { - shakeUl = projBuildinInfo.mixedLiquidMixingVolUl; - shakeTimes = projBuildinInfo.mixedLiquidMixingTimes; - } - //TODO: 吐样&&摇匀 - { - - } - - //z轴回0 - pipetteCtrlDriverV2.zMotorMoveToZeroPointQuickBlock(); - } - - public void pirceLittleBuffer(PreReactionPos pos) throws AppException { - // forceTakeTip(); - - hbotMoveExCtrlService.moveToLittleBufferPiercePos(pos.group, pos.index); - pipetteCtrlDriverV2.zMotorMoveToBlock(0); - } - - - /** - * 取反应液到反应板上 - * @param pos 反应板位置 - * @throws AppException 异常 - */ - public void takePreReactionLiquidToReation(PreReactionPos pos) throws AppException { - log.info("takePreReactionLiquidToReactionPos: from pos={}", pos); - // forceTakeTip(); - // Pos3d reactionPos = getPreReactionPos(pos); - // - // hbotMoveExCtrlService.moveToXY(reactionPos); - // pipetteCtrlDriverV2.zMotorMoveByBlock(0); - // makeReserveAir(100); - // - // hbotMoveExCtrlService.moveToZ(reactionPos); - // aspirate(reactionPos.z, 0, (double) REACTION_VOLUME_UL); - // - // hbotMoveExCtrlService.moveToDropLiquidPos(); - // pumpMoveTo(8000, 0.0); - // - // hbotMoveExCtrlService.initPipetterGun(); - // hbotMoveExCtrlService.moveQuickToZero(); - } - - -} diff --git a/src/main/java/a8k/app/service/mainctrl/mainflowctrl/MainFlowCtrlScheduler.java b/src/main/java/a8k/app/service/mainctrl/mainflowctrl/MainFlowCtrlScheduler.java index d6cce56..c8e5203 100644 --- a/src/main/java/a8k/app/service/mainctrl/mainflowctrl/MainFlowCtrlScheduler.java +++ b/src/main/java/a8k/app/service/mainctrl/mainflowctrl/MainFlowCtrlScheduler.java @@ -2,14 +2,11 @@ package a8k.app.service.mainctrl.mainflowctrl; import a8k.OS; import a8k.SpringBootBeanUtil; -import a8k.app.engineer.service.qatest.EngineerModeActionCtrlService; import a8k.app.engineer.service.state.EngineerModeStateMgrService; import a8k.app.engineer.service.type.EngineerWorkState; import a8k.app.service.module.TipMgrModule; import a8k.app.type.DeviceRunMode; //import a8k.app.a8ktype.appevent.A8kErrorsPromptEvent; -import a8k.app.type.a8k.pos.TipGroupPos; -import a8k.app.type.a8k.pos.TipPos; import a8k.app.type.a8k.state.enumtype.A8kWorkTaskType; import a8k.app.type.error.AECodeError; import a8k.app.type.error.AppError; @@ -20,14 +17,12 @@ import a8k.app.hardware.driver.ModuleEnableCtrlDriver; import a8k.app.hardware.type.A8kEcode; import a8k.app.service.background.AppEventBusService; import a8k.app.service.utils.UISender; -import a8k.app.service.lowerctrl.LiquidOperationCtrlService; import a8k.app.service.mainctrl.TubeHolderSettingMgrService; import a8k.app.service.mainctrl.mainflowctrl.base.*; import a8k.app.service.statemgr.ConsumablesMgrService; import a8k.app.service.statemgr.DeviceWorkStateMgrService; import a8k.app.service.statemgr.GStateMgrService; import a8k.app.utils.ZStringUtils; -import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/a8k/app/service/mainctrl/mainflowctrl/action/AC41ProcessSample.java b/src/main/java/a8k/app/service/mainctrl/mainflowctrl/action/AC41ProcessSample.java index d48f9ee..9699315 100644 --- a/src/main/java/a8k/app/service/mainctrl/mainflowctrl/action/AC41ProcessSample.java +++ b/src/main/java/a8k/app/service/mainctrl/mainflowctrl/action/AC41ProcessSample.java @@ -1,5 +1,6 @@ package a8k.app.service.mainctrl.mainflowctrl.action; +import a8k.app.service.module.LiquidOperationCtrlModule; import a8k.app.service.module.TipMgrModule; import a8k.app.type.a8k.A8kTubeHolderType; import a8k.app.type.a8k.pos.IncubatorPos; @@ -55,11 +56,11 @@ public class AC41ProcessSample extends A8kActionTask { @Resource TubePreProcesModuleExCtrlService tubePreProcesCtrlService; @Resource - TurnableMoveCtrlService turnableMoveCtrlService; + TurnableMoveCtrlService turnableMoveCtrlService; @Resource - LiquidOperationCtrlService liquidOperationCtrlService; + LiquidOperationCtrlModule liquidOperationCtrlModule; @Resource - OptScanModuleCtrlService optScanModuleCtrlService; + OptScanModuleCtrlService optScanModuleCtrlService; @Resource HbotMoveCtrlService hbotMoveCtrlService; @@ -315,7 +316,7 @@ public class AC41ProcessSample extends A8kActionTask { void preProcessSample(ProjectTaskContext cxt) throws AppException { //取探测物质 A8kReactionFlowType type = cxt.getProjBuildinInfo().reactionFlowType; - liquidOperationCtrlService.setProjContext(cxt.projBuildinInfo, cxt.projExtInfoCard); + liquidOperationCtrlModule.setProjContext(cxt.projBuildinInfo, cxt.projExtInfoCard); // @@ -323,7 +324,7 @@ public class AC41ProcessSample extends A8kActionTask { // if (type.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) { UISender.txInfoMsg(log, "取大瓶缓冲液到探测物质中"); - liquidOperationCtrlService.takeLargeBottleBufferLiquidToProbeSubstance( // + liquidOperationCtrlModule.takeLargeBottleBufferLiquidToProbeSubstance( // cxt.getLargeBufferPos(), cxt.getPreReactionPos(), cxt.getTakeLargeBSVolume()); } @@ -347,7 +348,7 @@ public class AC41ProcessSample extends A8kActionTask { void doSampleProcess(ProjectTaskContext cxt, Boolean finalCxt) throws AppException, ZAppInterruptException { log.info("开始处理样本 cxtid:{} sampleId:{}", cxt.cxtId, cxt.sampleInfo.sampleId); A8kReactionFlowType type = cxt.getProjBuildinInfo().reactionFlowType; - liquidOperationCtrlService.setProjContext(cxt.projBuildinInfo, cxt.projExtInfoCard); + liquidOperationCtrlModule.setProjContext(cxt.projBuildinInfo, cxt.projExtInfoCard); // !!! 等待样本准备完成 !!! // @@ -355,14 +356,14 @@ public class AC41ProcessSample extends A8kActionTask { // if (type.equals(A8kReactionFlowType.SampleAndBS)) { UISender.txInfoMsg(log, "刺破小瓶缓冲液"); - liquidOperationCtrlService.pirceLittleBuffer(cxt.getPreReactionPos()); + liquidOperationCtrlModule.pirceLittleBuffer(cxt.getPreReactionPos()); UISender.txInfoMsg(log, "取样"); - liquidOperationCtrlService.takeSample(cxt.getSamplePos(), cxt.getPreReactionPos(), cxt.getSampleVol()); + liquidOperationCtrlModule.takeSampleToPreReactionPos(cxt.getSamplePos(), cxt.getPreReactionPos(), cxt.getSampleVol()); } else if (type.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) { UISender.txInfoMsg(log, "取样"); - liquidOperationCtrlService.takeSample(cxt.getSamplePos(), cxt.getPreReactionPos(), cxt.getSampleVol()); + liquidOperationCtrlModule.takeSampleToPreReactionPos(cxt.getSamplePos(), cxt.getPreReactionPos(), cxt.getSampleVol()); } if (finalCxt) { @@ -379,7 +380,8 @@ public class AC41ProcessSample extends A8kActionTask { //吐液到反应板上 turnableMoveCtrlService.trunableMoveToDropLiquidPos(cxt.getIncubatorPos()); - liquidOperationCtrlService.takePreReactionLiquidToReation(cxt.getPreReactionPos()); + liquidOperationCtrlModule.takePreReactionLiquid(cxt.getPreReactionPos()); + liquidOperationCtrlModule.dropLiquidToReactionPlate(); } diff --git a/src/main/java/a8k/app/service/module/LiquidOperationCtrlModule.java b/src/main/java/a8k/app/service/module/LiquidOperationCtrlModule.java new file mode 100644 index 0000000..d7ee565 --- /dev/null +++ b/src/main/java/a8k/app/service/module/LiquidOperationCtrlModule.java @@ -0,0 +1,383 @@ +package a8k.app.service.module; + + +import a8k.app.dao.type.combination.ProjBuildinInfo; +import a8k.app.dao.type.db.ProjExtInfoCard; +import a8k.app.hardware.driver.PipetteCtrlDriverV2; +import a8k.app.hardware.type.A8kEcode; +import a8k.app.hardware.type.pipette_module.DistribuType; +import a8k.app.hardware.type.pipette_module.cpyidx.ContainerCpyId; +import a8k.app.hardware.type.pipette_module.cpyidx.LiquidConfigCpyIdx; +import a8k.app.hardware.type.pipette_module.param.AspirationParam; +import a8k.app.hardware.type.pipette_module.param.DistribuAllParam; +import a8k.app.service.lowerctrl.HbotMoveExCtrlService; +import a8k.app.service.param.exparam.HbotConsumableExParamMgr; +import a8k.app.service.param.hbotpos.HbotFixedPosParamMgr; +import a8k.app.service.param.hbotpos.HbotSamplePosParamMgr; +import a8k.app.service.statemgr.ConsumablesMgrService; +import a8k.app.service.statemgr.GStateMgrService; +import a8k.app.service.utils.UISender; +import a8k.app.service.utils.ZAppChecker; +import a8k.app.type.a8k.ConsumableType; +import a8k.app.type.a8k.Pos3d; +import a8k.app.type.a8k.pos.LargeBufferPos; +import a8k.app.type.a8k.pos.PreReactionPos; +import a8k.app.type.exception.AppException; +import a8k.app.type.param.type.A8kSamplePos; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +@RequiredArgsConstructor +public class LiquidOperationCtrlModule { + static public final Integer MIX_VOLUME_UL = 200; + + + private final GStateMgrService gstate; + + /* + * CTRL-SERVICE + */ + private final HbotMoveExCtrlService hbotMoveExCtrlService; + private final PipetteCtrlDriverV2 pipetteCtrlDriverV2; + + /* + * PARAM-MGR + */ + private final HbotConsumableExParamMgr hbotConsumableExParamMgr; + /** + * StateMgr + */ + private final ConsumablesMgrService consumablesMgrService; + private final HbotSamplePosParamMgr hbotSamplePosParamMgr; + private final HbotFixedPosParamMgr hbotFixedPosParamMgr; + + private final TipMgrModule tipMgrModule; + + + ProjBuildinInfo projBuildinInfo; + ProjExtInfoCard projExtInfo; + + + synchronized public void setProjContext(ProjBuildinInfo projBuildinInfo, ProjExtInfoCard projExtInfo) { + this.projBuildinInfo = projBuildinInfo; + this.projExtInfo = projExtInfo; + } + + + /** + * 取大瓶缓冲液到探测物质位置 + * @param from 大瓶缓冲液 + * @param topos 探测物质位置 + * @param ul 吸取量 + */ + public void takeLargeBottleBufferLiquidToProbeSubstance(LargeBufferPos from, PreReactionPos topos, Integer ul) throws AppException { + // 取TIP + tipMgrModule.tryTakeTip(); + ZAppChecker.check(pipetteCtrlDriverV2.readTipState(), A8kEcode.CODEERROR, "未检测到TIP"); + + Pos3d largeBSContainerPos = hbotConsumableExParamMgr.getLargeBuffer(from.group);//大瓶缓冲液位置 + Pos3d probeSubstanceContainerPos = hbotConsumableExParamMgr.getProbeSubstanceContainerPos(topos.group, topos.index);//探测物质位置 + Pos3d probeSubstancePiercePos = hbotConsumableExParamMgr.getProbeSubstancePiercePos(topos.group, topos.index);//探测物质刺破位置 + + + // 刺破探测物质 + UISender.txInfoMsg(log, "刺破探测物质:%s" + topos); + hbotMoveExCtrlService.moveToXY(probeSubstancePiercePos); + pipetteCtrlDriverV2.pierceThroughBlock(ContainerCpyId.DetectSubstancesCup, probeSubstanceContainerPos.z); + + // 移动到取样位 && 取样 + UISender.txInfoMsg(log, "移动到大瓶缓冲液位置:%s", largeBSContainerPos); + hbotMoveExCtrlService.moveToXY(largeBSContainerPos); + // 预吸取 + UISender.txInfoMsg(log, "预吸取大瓶缓冲液:%dul", ul); + pipetteCtrlDriverV2.aspirateBlock(new AspirationParam( + ul * 10, + largeBSContainerPos.z, + ContainerCpyId.LargeBufferCup, + LiquidConfigCpyIdx.BufferSolution, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0 + )); + + // 移动到探测物质位置,吐液 + + + // 移动到取样位 + UISender.txInfoMsg(log, "移动到探测物质位置:%s", probeSubstanceContainerPos); + hbotMoveExCtrlService.moveToXY(probeSubstanceContainerPos); + // 吐液 + UISender.txInfoMsg(log, "吐液到探测物质位置:%dul", ul); + pipetteCtrlDriverV2.distributeAllBlock(new DistribuAllParam( + probeSubstanceContainerPos.z, + ContainerCpyId.DetectSubstancesCup, + LiquidConfigCpyIdx.NotSet, + true, + DistribuType.JET_DIST, + 0, + 0, + true + )); + // 丢弃TIP + UISender.txInfoMsg(log, "丢弃TIP"); + tipMgrModule.dropTip(); + + hbotMoveExCtrlService.moveQuickToZero(); + } + + + ContainerCpyId a8kSamplePosToContainerCpyId(A8kSamplePos a8kSamplePos) { + return switch (a8kSamplePos) { + case EmergencyTubePos, BloodSTubePos -> ContainerCpyId.ShortWholeBufferTube; + case BloodHTubePos -> ContainerCpyId.HighWholeBufferTube; + case MiniBloodPos -> ContainerCpyId.MiniBlood; + case Bulltube1P5Pos -> ContainerCpyId.BulletTube1P5; + case Bulltube0P5Pos -> ContainerCpyId.BulletTube0P5; + case StoolTestTubePos -> ContainerCpyId.StoolTestTube; + }; + } + + /** + * 取样本 + * @param from 样本位置 + * @param ul 吸取量 + * @throws AppException 异常 + */ + public void takeSampleOnly(A8kSamplePos from, Integer ul) throws AppException { + log.info("takeSampleOnly: from={},ul={}ul", from, ul); + + Pos3d sampleContainerPos = hbotSamplePosParamMgr.getSampleContainerPos(from);//样本位置 + + + // 取TIP + tipMgrModule.tryTakeTip(); + ZAppChecker.check(pipetteCtrlDriverV2.readTipState(), A8kEcode.CODEERROR, "未检测到TIP"); + + //移动到取样位 + UISender.txInfoMsg(log, "移动到样本位置:%s", sampleContainerPos); + hbotMoveExCtrlService.moveToXY(sampleContainerPos); + + //取样 + UISender.txInfoMsg(log, "取样:%dul", ul); + pipetteCtrlDriverV2.aspirateBlock(new AspirationParam( + ul * 10, + sampleContainerPos.z, + a8kSamplePosToContainerCpyId(from), + LiquidConfigCpyIdx.NotSet, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0 + )); + } + + + public void pirceLittleBuffer(PreReactionPos pos) throws AppException { + // 取TIP + tipMgrModule.tryTakeTip(); + ZAppChecker.check(pipetteCtrlDriverV2.readTipState(), A8kEcode.CODEERROR, "未检测到TIP"); + + Pos3d pircePos; + ContainerCpyId containerCpyId; + + if (pos.type.equals(ConsumableType.ProbeSubstance)) { + pircePos = hbotConsumableExParamMgr.getProbeSubstancePiercePos(pos.group, pos.index); + containerCpyId = ContainerCpyId.DetectSubstancesCup; + } else { + pircePos = hbotConsumableExParamMgr.getLittleBufferPiercePos(pos.group, pos.index); + containerCpyId = ContainerCpyId.LittleBufferCup; + } + + pipetteCtrlDriverV2.pierceThroughBlock(containerCpyId, pircePos.z); + } + + + /** + * 取样本到探测物质 + * @param from 样本位置 + * @param pos 预先反应位置P + * @param ul 吸取量 + * @throws AppException 异常 + */ + public void takeSampleToPreReactionPos(A8kSamplePos from, PreReactionPos pos, Integer ul) throws AppException { + log.info("takeSampleToPreReactionPos: from={}, pos={}, ul={}ul", from, pos, ul); + takeSampleOnly(from, ul); + + Pos3d reactionPos; + ContainerCpyId containerCpyId; + Integer shakeUl = MIX_VOLUME_UL; + Integer shakeTimes = 5; + + if (pos.type.equals(ConsumableType.ProbeSubstance)) { + reactionPos = hbotConsumableExParamMgr.getProbeSubstanceContainerPos(pos.group, pos.index); + containerCpyId = ContainerCpyId.DetectSubstancesCup; + } else { + reactionPos = hbotConsumableExParamMgr.getLittleBufferSamplePos(pos.group, pos.index); + containerCpyId = ContainerCpyId.LittleBufferCup; + } + if (projBuildinInfo != null) { + shakeUl = projBuildinInfo.mixedLiquidMixingVolUl; + shakeTimes = projBuildinInfo.mixedLiquidMixingTimes; + } + + // 移动到反应位 + UISender.txInfoMsg(log, "移动到预先反应位置:%s", reactionPos); + hbotMoveExCtrlService.moveToXY(reactionPos); + + //z轴移动到反应位 + UISender.txInfoMsg(log, "分配样本"); + pipetteCtrlDriverV2.distributeAllBlock(new DistribuAllParam( + reactionPos.z, + containerCpyId, + LiquidConfigCpyIdx.BufferSolution, + false, + DistribuType.SURFACE_DIST, + shakeUl * 10, // 预先反应位置的液体量 + shakeTimes, + true + )); + } + + /** + * 取样本液到预反应位,混合后,再取样 + * @param from + * @param pos + * @param ul + * @throws AppException + */ + public void takeSampleToPreReactionPosAndAspirate(A8kSamplePos from, PreReactionPos pos, Integer ul) throws AppException { + log.info("takeSampleToPreReactionPosAndTakeToReactionPlate: from={}, pos={}, ul={}ul", from, pos, ul); + takeSampleOnly(from, ul); + + Pos3d reactionPos; + ContainerCpyId containerCpyId; + Integer shakeUl = MIX_VOLUME_UL; + Integer shakeTimes = 5; + + if (pos.type.equals(ConsumableType.ProbeSubstance)) { + reactionPos = hbotConsumableExParamMgr.getProbeSubstanceContainerPos(pos.group, pos.index); + containerCpyId = ContainerCpyId.DetectSubstancesCup; + } else { + reactionPos = hbotConsumableExParamMgr.getLittleBufferSamplePos(pos.group, pos.index); + containerCpyId = ContainerCpyId.LittleBufferCup; + } + if (projBuildinInfo != null) { + shakeUl = projBuildinInfo.mixedLiquidMixingVolUl; + shakeTimes = projBuildinInfo.mixedLiquidMixingTimes; + } + + // 移动到反应位 + UISender.txInfoMsg(log, "移动到预先反应位置:%s", reactionPos); + hbotMoveExCtrlService.moveToXY(reactionPos); + + //z轴移动到反应位 + UISender.txInfoMsg(log, "分配样本"); + pipetteCtrlDriverV2.distributeAllBlock(new DistribuAllParam( + reactionPos.z, + containerCpyId, + LiquidConfigCpyIdx.BufferSolution, + false, + DistribuType.SURFACE_DIST, + shakeUl * 10, // 预先反应位置的液体量 + shakeTimes, + false + )); + + UISender.txInfoMsg(log, "取混合液"); + pipetteCtrlDriverV2.aspirateBlock(new AspirationParam( + 750, // 预先反应位置的液体量 + reactionPos.z, + containerCpyId, + LiquidConfigCpyIdx.BufferSolution, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + )); + } + + + /** + * 取反应液到反应板上 + * @param pos 反应板位置 + * @throws AppException 异常 + */ + public void takePreReactionLiquid(PreReactionPos pos) throws AppException { + log.info("takePreReactionLiquidToReactionPos: from pos={}", pos); + + tipMgrModule.tryTakeTip(); + + Pos3d reactionPos; + ContainerCpyId containerCpyId; + + if (pos.type.equals(ConsumableType.ProbeSubstance)) { + reactionPos = hbotConsumableExParamMgr.getProbeSubstanceContainerPos(pos.group, pos.index); + containerCpyId = ContainerCpyId.DetectSubstancesCup; + } else { + reactionPos = hbotConsumableExParamMgr.getLittleBufferSamplePos(pos.group, pos.index); + containerCpyId = ContainerCpyId.LittleBufferCup; + } + + + UISender.txInfoMsg(log, "移动到预先反应位置:%s", reactionPos); + hbotMoveExCtrlService.moveToXY(reactionPos); + + UISender.txInfoMsg(log, "取混合液"); + pipetteCtrlDriverV2.aspirateBlock(new AspirationParam( + 750, // 预先反应位置的液体量 + reactionPos.z, + containerCpyId, + LiquidConfigCpyIdx.BufferSolution, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + )); + + + } + + public void dropLiquidToReactionPlate() throws AppException { + log.info("dropLiquidToReactionPlate"); + + Pos3d dropLiquidPos = hbotFixedPosParamMgr.getDropLiquidPos(); + + + UISender.txInfoMsg(log, "移动到预先反应位置:%s", dropLiquidPos); + hbotMoveExCtrlService.moveToXY(dropLiquidPos); + + UISender.txInfoMsg(log, "分配到反应板位置"); + pipetteCtrlDriverV2.distributeAllBlock(new DistribuAllParam( + dropLiquidPos.z, + ContainerCpyId.ReactionPlate, + LiquidConfigCpyIdx.BufferSolution, + false, + DistribuType.JET_DIST, + 0, + 0, + true + )); + } + + +} diff --git a/src/main/java/a8k/app/service/module/TipMgrModule.java b/src/main/java/a8k/app/service/module/TipMgrModule.java index 872e85b..923cb37 100644 --- a/src/main/java/a8k/app/service/module/TipMgrModule.java +++ b/src/main/java/a8k/app/service/module/TipMgrModule.java @@ -36,11 +36,6 @@ public class TipMgrModule { private final PipetteCtrlDriverV2 pipetteCtrlDriver; - //********************************************************* - // TIP OPERATION - //********************************************************* - - public void checkTipNumSetting() throws AppException { for (TipGroupPos group : TipGroupPos.values()) { UISender.txInfoMsg(log, "核对TIP-%s数量设置", group); @@ -59,7 +54,9 @@ public class TipMgrModule { } } } - + public void testDoTakeTipAction(TipGroupPos tipGroupPos, Integer index) throws AppException { + doTakeTipAction(tipGroupPos, index); + } public Boolean isHasTip() throws AppException { return pipetteCtrlDriver.readTipState(); } @@ -90,8 +87,8 @@ public class TipMgrModule { * 循环遍历所有的TIP位置,直到取到TIP为止 * @throws AppException TIP数量不足时,抛出APPE_TIP_NOT_ENOUGH。其他异常一般均为硬件异常。 */ - public void takeTip() throws AppException { - takeTip(null); + public void tryTakeTip() throws AppException { + tryTakeTip(null); } /** @@ -99,7 +96,7 @@ public class TipMgrModule { * @param breakCondJudgeFn 一般用于结束条件判定,例如上层应用如果期望打断取TIP操作,可以传入一个函数来判断是否继续取TIP * @throws AppException TIP数量不足时,抛出APPE_TIP_NOT_ENOUGH。其他异常一般均为硬件异常。 */ - public void takeTip(JudgeFn breakCondJudgeFn) throws AppException { + public void tryTakeTip(JudgeFn breakCondJudgeFn) throws AppException { if (pipetteCtrlDriver.readTipState()) { return; } @@ -131,6 +128,7 @@ public class TipMgrModule { } } + //******************************************************************************** // 私有方法 //******************************************************************************** @@ -142,7 +140,7 @@ public class TipMgrModule { * @param index TIP索引 * @throws AppException 异常 */ - public void doTakeTipAction(TipGroupPos tipGroupPos, Integer index) throws AppException { + private void doTakeTipAction(TipGroupPos tipGroupPos, Integer index) throws AppException { log.info("takeTip groupId:{} index:{}", tipGroupPos.ordinal(), index); checkTipIndex(tipGroupPos, index); hbotMoveExCtrlService.moveToTakeTipXYPos(tipGroupPos, index); diff --git a/src/main/java/a8k/app/service/param/exparam/HbotConsumableExParamMgr.java b/src/main/java/a8k/app/service/param/exparam/HbotConsumableExParamMgr.java index 8956c76..5959091 100644 --- a/src/main/java/a8k/app/service/param/exparam/HbotConsumableExParamMgr.java +++ b/src/main/java/a8k/app/service/param/exparam/HbotConsumableExParamMgr.java @@ -43,8 +43,8 @@ public class HbotConsumableExParamMgr { } - public Pos3d getProbeSubstanceSamplePos(ConsumableGroup group, Integer off) { - return hbotProbeSubstancePosMgr.getSamplePos(group, off); + public Pos3d getProbeSubstanceContainerPos(ConsumableGroup group, Integer off) { + return hbotProbeSubstancePosMgr.getContainerPos(group, off); } public Pos3d getProbeSubstancePiercePos(ConsumableGroup group, Integer off) { diff --git a/src/main/java/a8k/app/service/param/hbotpos/HbotLittleBSPosMgr.java b/src/main/java/a8k/app/service/param/hbotpos/HbotLittleBSPosMgr.java index d4d4669..aa33607 100644 --- a/src/main/java/a8k/app/service/param/hbotpos/HbotLittleBSPosMgr.java +++ b/src/main/java/a8k/app/service/param/hbotpos/HbotLittleBSPosMgr.java @@ -3,7 +3,6 @@ package a8k.app.service.param.hbotpos; import a8k.app.type.a8k.ConsumableGroup; import a8k.app.service.param.base.ParamMgr; import a8k.app.type.param.hbotpos.HbotLittleBSPos; -import a8k.app.type.a8k.Pos2d; import a8k.app.type.a8k.Pos3d; import jakarta.annotation.PostConstruct; import org.slf4j.Logger; @@ -106,15 +105,10 @@ public class HbotLittleBSPosMgr extends ParamMgr { return getParam(HbotLittleBSPos.GroupDY, Double.class); } - // public Pos3d getSamplePos(ConsumableGroup group, Integer off) { - // Pos3d pos = getXYPos(group, off); - // pos.z = getParam(HbotProbeSubstancePos.ProbeSubstanceSampleZPos, Double.class).intValue(); - // return pos; - // } - public Pos3d getProbeSubstanceSamplePos(ConsumableGroup group, Integer off) { - Pos3d pos = getProbeSubstanceXYPos(group, off); - return pos; + + public Pos3d getProbeSubstanceContainerPos(ConsumableGroup group, Integer off) { + return getProbeSubstanceXYPos(group, off); } public Pos3d getProbeSubstancePiercePos(ConsumableGroup group, Integer off) { diff --git a/src/main/java/a8k/app/service/param/hbotpos/HbotProbeSubstancePosMgr.java b/src/main/java/a8k/app/service/param/hbotpos/HbotProbeSubstancePosMgr.java index 64642a2..059636b 100644 --- a/src/main/java/a8k/app/service/param/hbotpos/HbotProbeSubstancePosMgr.java +++ b/src/main/java/a8k/app/service/param/hbotpos/HbotProbeSubstancePosMgr.java @@ -16,8 +16,8 @@ public class HbotProbeSubstancePosMgr extends ParamMgr { @Resource HbotLittleBSPosMgr hbotLittleBSPosMgr; - public Pos3d getSamplePos(ConsumableGroup group, Integer off) { - return hbotLittleBSPosMgr.getProbeSubstanceSamplePos(group, off); + public Pos3d getContainerPos(ConsumableGroup group, Integer off) { + return hbotLittleBSPosMgr.getProbeSubstanceContainerPos(group, off); } public Pos3d getPiercePos(ConsumableGroup group, Integer off) { diff --git a/src/main/java/a8k/app/type/a8k/state/ProjectTaskContext.java b/src/main/java/a8k/app/type/a8k/state/ProjectTaskContext.java index e9c2458..edbe31c 100644 --- a/src/main/java/a8k/app/type/a8k/state/ProjectTaskContext.java +++ b/src/main/java/a8k/app/type/a8k/state/ProjectTaskContext.java @@ -304,7 +304,7 @@ public class ProjectTaskContext { A8kReactionFlowType type = this.getProjBuildinInfo().reactionFlowType; return switch (type) { case SampleAndBS -> hbotConsumableExParamMgr.getLittleBufferSamplePos(this.getConsumable().getGroup(), this.getConsumable().getPos()); - case SampleAndBSAndProbeSubstance -> hbotConsumableExParamMgr.getProbeSubstanceSamplePos(this.getConsumable().getGroup(), this.getConsumable().getPos()); + case SampleAndBSAndProbeSubstance -> hbotConsumableExParamMgr.getProbeSubstanceContainerPos(this.getConsumable().getGroup(), this.getConsumable().getPos()); }; } diff --git a/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunCommonConfigPage.java b/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunCommonConfigPage.java index 0f3e559..882aaa4 100644 --- a/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunCommonConfigPage.java +++ b/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunCommonConfigPage.java @@ -4,6 +4,7 @@ package a8k.extui.page.driver.pipette_module; import a8k.app.hardware.driver.PipetteCtrlDriverV2; import a8k.app.hardware.type.pipette_module.cfg.PipetteCommonConfigIndex; import a8k.app.hardware.type.pipette_module.cfg.PlatformInfoIndex; +import a8k.app.hardware.type.pipette_module.cpyidx.PlatInfoCpyIdx; import a8k.app.type.exception.AppException; import a8k.extui.mgr.ExtApiPageMgr; import jakarta.annotation.PostConstruct; @@ -35,6 +36,9 @@ public class PipetteGunCommonConfigPage { pipetteCtrlDriverV2.setCommonConfig(PipetteCommonConfigIndex.pressureRecordEnable, enable ? 1 : 0); } + public void setPlatformInfo(PlatInfoCpyIdx platInfoCpyIdx) throws AppException { + pipetteCtrlDriverV2.setCommonConfig(PipetteCommonConfigIndex.platformInfoCpyid, platInfoCpyIdx.toInteger()); + } @PostConstruct void init() { @@ -42,7 +46,9 @@ public class PipetteGunCommonConfigPage { page.newGroup("基础操作"); page.addFunction("设置压力记录开关", this::setPressureRecordEnable) .setParamVal("enable", () -> getVal(PipetteCommonConfigIndex.pressureRecordEnable) == 1); - + page.addFunction("设置平台信息", this::setPlatformInfo) + .setParamVal("platInfoCpyIdx", + () -> PlatInfoCpyIdx.of(getVal(PipetteCommonConfigIndex.platformInfoCpyid))); extApiPageMgr.addPage(page); } diff --git a/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunOperationCtrlPage.java b/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunOperationCtrlPage.java index 2f8009b..79a5fdb 100644 --- a/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunOperationCtrlPage.java +++ b/src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunOperationCtrlPage.java @@ -77,14 +77,6 @@ public class PipetteGunOperationCtrlPage { aspirateParam.mixTimes = mixTimes; } - // containerPos - //destContainerCpyid - //destContainerIsEmpty - //destLiquidCfgIndex - //distribuType - //mixVolume - //mixTimes - //zmAutoMoveToZero public void setDistributeParam_containerPos(Integer containerPos) { distributeParam.containerPos = containerPos; } @@ -124,8 +116,8 @@ public class PipetteGunOperationCtrlPage { } public void execDistribute() throws AppException { - pipetteCtrlDriverV2.pipettePumpDistributeAllSetParam(distributeParam); - pipetteCtrlDriverV2.pipettePumpDistributeAllBlock(); + pipetteCtrlDriverV2.distributeAllSetParam(distributeParam); + pipetteCtrlDriverV2.distributeAllBlock(); } public void pipettePumpInitDeviceBlock(Integer cpyId) throws AppException { diff --git a/src/main/java/a8k/extui/page/test/verification/P32HbotPosVerificationPage.java b/src/main/java/a8k/extui/page/test/verification/P32HbotPosVerificationPage.java index cecb94b..fd624f1 100644 --- a/src/main/java/a8k/extui/page/test/verification/P32HbotPosVerificationPage.java +++ b/src/main/java/a8k/extui/page/test/verification/P32HbotPosVerificationPage.java @@ -21,7 +21,7 @@ public class P32HbotPosVerificationPage { public void takeTip(TipGroupPos tipGroupPos, Integer index) throws AppException { - tipMgrModule.doTakeTipAction(tipGroupPos, index); + tipMgrModule.testDoTakeTipAction(tipGroupPos, index); } public void moveToTakeTipObservationPos(TipGroupPos tipGroupPos, Integer index, Integer zpos) throws AppException { diff --git a/src/main/java/a8k/extui/page/test/verification/P34LiquidOperationTestPage.java b/src/main/java/a8k/extui/page/test/verification/P34LiquidOperationTestPage.java index d1a5535..521a56a 100644 --- a/src/main/java/a8k/extui/page/test/verification/P34LiquidOperationTestPage.java +++ b/src/main/java/a8k/extui/page/test/verification/P34LiquidOperationTestPage.java @@ -1,13 +1,14 @@ package a8k.extui.page.test.verification; +import a8k.app.service.lowerctrl.TurnableMoveCtrlService; import a8k.app.service.module.TipMgrModule; import a8k.app.type.a8k.*; +import a8k.app.type.a8k.pos.IncubatorPos; import a8k.app.type.a8k.pos.LargeBufferPos; import a8k.app.type.a8k.pos.PreReactionPos; -import a8k.app.type.a8k.pos.TipGroupPos; import a8k.app.type.exception.AppException; import a8k.app.type.param.type.A8kSamplePos; -import a8k.app.service.lowerctrl.LiquidOperationCtrlService; +import a8k.app.service.module.LiquidOperationCtrlModule; import a8k.extui.mgr.ExtApiPageMgr; import a8k.extui.type.ExtUIPageCfg; import jakarta.annotation.PostConstruct; @@ -20,18 +21,20 @@ import org.springframework.stereotype.Component; public class P34LiquidOperationTestPage { @Resource - LiquidOperationCtrlService liquidOperationCtrlService; + LiquidOperationCtrlModule liquidOperationCtrlModule; @Resource - TipMgrModule tipMgrModule; + TurnableMoveCtrlService turnableMoveCtrlService; @Resource - ExtApiPageMgr extApiPageMgr; + TipMgrModule tipMgrModule; + @Resource + ExtApiPageMgr extApiPageMgr; // // 液体操作 // public void takeTip() throws AppException { - tipMgrModule.takeTip(); + tipMgrModule.tryTakeTip(); } public void dropTip() throws AppException { @@ -40,36 +43,41 @@ public class P34LiquidOperationTestPage { public void takeLargeBottleBufferLiquidToProbeSubstance(LargeBufferPos from, ConsumableGroup group, Integer index, Integer ul) throws AppException { PreReactionPos topos = new PreReactionPos(ConsumableType.ProbeSubstance, group, index); - liquidOperationCtrlService.takeLargeBottleBufferLiquidToProbeSubstance(from, topos, ul); + liquidOperationCtrlModule.takeLargeBottleBufferLiquidToProbeSubstance(from, topos, ul); } public void takeSampleToProbeSubstance(A8kSamplePos from, ConsumableGroup toGroup, Integer toIndex, Integer ul) throws AppException { PreReactionPos topos = new PreReactionPos(ConsumableType.ProbeSubstance, toGroup, toIndex); - liquidOperationCtrlService.takeSample(from, topos, ul); + liquidOperationCtrlModule.takeSampleToPreReactionPos(from, topos, ul); + } + + public void takePreReactionLiquidFromProbeSubstance(ConsumableGroup toGroup, Integer toIndex) throws AppException { + PreReactionPos pos = new PreReactionPos(ConsumableType.ProbeSubstance, toGroup, toIndex); + liquidOperationCtrlModule.takePreReactionLiquid(pos); } public void takeSampleOnly(A8kSamplePos from, Integer ul) throws AppException { - liquidOperationCtrlService.takeSampleOnly(from, ul); + liquidOperationCtrlModule.takeSampleOnly(from, ul); } public void takeSampleToLittleBuffer(A8kSamplePos from, ConsumableGroup toGroup, Integer toIndex, Integer ul) throws AppException { PreReactionPos topos = new PreReactionPos(ConsumableType.SmallBottleBuffer, toGroup, toIndex); - liquidOperationCtrlService.takeSample(from, topos, ul); + liquidOperationCtrlModule.takeSampleToPreReactionPos(from, topos, ul); } public void pirceLittleBuffer(ConsumableGroup toGroup, Integer toIndex) throws AppException { PreReactionPos pos = new PreReactionPos(ConsumableType.SmallBottleBuffer, toGroup, toIndex); - liquidOperationCtrlService.pirceLittleBuffer(pos); + liquidOperationCtrlModule.pirceLittleBuffer(pos); } - public void takePreReactionLiquidFromLittleBufferToLiquid(ConsumableGroup toGroup, Integer toIndex) throws AppException { + public void takePreReactionLiquidFromSmallBottleBuffer(ConsumableGroup toGroup, Integer toIndex) throws AppException { PreReactionPos pos = new PreReactionPos(ConsumableType.SmallBottleBuffer, toGroup, toIndex); - liquidOperationCtrlService.takePreReactionLiquidToReation(pos); + liquidOperationCtrlModule.takePreReactionLiquid(pos); } - public void takePreReactionLiquidFromProbeSubstanceToLiquid(ConsumableGroup toGroup, Integer toIndex) throws AppException { - PreReactionPos pos = new PreReactionPos(ConsumableType.ProbeSubstance, toGroup, toIndex); - liquidOperationCtrlService.takePreReactionLiquidToReation(pos); + public void dropLiquidToReactionPlate(IncubatorPos pos) throws AppException { + turnableMoveCtrlService.trunableMoveToDropLiquidPos(pos); + liquidOperationCtrlModule.dropLiquidToReactionPlate(); } @PostConstruct @@ -81,12 +89,17 @@ public class P34LiquidOperationTestPage { cfg.newGroup("液体操作-大瓶缓冲液/探测物质"); cfg.addFunction("取大瓶缓冲液到探测物质位置", this::takeLargeBottleBufferLiquidToProbeSubstance); cfg.addFunction("取样品到探测物质位置", this::takeSampleToProbeSubstance); - cfg.addFunction("取反应液到反应位", this::takePreReactionLiquidFromProbeSubstanceToLiquid); + cfg.addFunction("取反应液", this::takePreReactionLiquidFromProbeSubstance); + cfg.addFunction("滴反应液到反应板上", this::dropLiquidToReactionPlate); cfg.newGroup("液体操作-小瓶缓冲液"); cfg.addFunction("刺小瓶缓冲液", this::pirceLittleBuffer); cfg.addFunction("取样品到小瓶缓冲液", this::takeSampleToLittleBuffer); - cfg.addFunction("取反应液到反应位", this::takePreReactionLiquidFromLittleBufferToLiquid); - cfg.addFunction("取样本", this::takeSampleOnly); + cfg.addFunction("取反应液", this::takePreReactionLiquidFromSmallBottleBuffer); + cfg.addFunction("滴反应液到反应板上", this::dropLiquidToReactionPlate); + cfg.newGroup("其他"); + cfg.addFunction("取样本(Only)", this::takeSampleOnly); + + extApiPageMgr.addPage(cfg); }