From f9e4a13c449c7ba757fab9346ff96d32116a19da Mon Sep 17 00:00:00 2001 From: zhaohe Date: Tue, 12 Nov 2024 11:05:16 +0800 Subject: [PATCH] update --- .../appctrl/mainflowctrl/action/SEQ5_PROCESS.java | 208 ++++++++++++++-- .../app/appstate/type/ProjectTaskContext.java | 6 + .../ctrlservice/DeviceInitCtrlService.java | 12 +- .../devicectrl/ctrlservice/HbotCtrlService.java | 26 +- .../HbotLargeBottleBSPosCalibration.java | 6 +- .../ext_param_mgr/HbotConsumableParamMgr.java | 4 +- .../param/param_mgr/HbotLittleBSPosMgr.java | 4 +- .../app/devicectrl/script/DeviceCtrlScripter.java | 274 --------------------- .../app/devicectrl/script/PipeGunCtrlScripter.java | 110 +++++++++ .../java/a8k/utils/ProjProcessContextUtils.java | 4 +- 10 files changed, 337 insertions(+), 317 deletions(-) delete mode 100644 src/main/java/a8k/service/app/devicectrl/script/DeviceCtrlScripter.java create mode 100644 src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java index 1826804..7cf4973 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java @@ -1,8 +1,6 @@ package a8k.service.app.appctrl.mainflowctrl.action; import a8k.OS; -import a8k.constant.LogTopic; -import a8k.hardware.type.a8kcanprotocol.A8kEcode; import a8k.service.app.appctrl.mainflowctrl.PublicAreaResourceMgr; import a8k.service.app.appctrl.mainflowctrl.base.*; import a8k.service.app.appstate.statemgr.IncubationPlateStateMgrService; @@ -12,16 +10,29 @@ import a8k.service.app.appstate.type.ProjectTaskContext; import a8k.service.app.appstate.type.Tube; import a8k.service.app.appstate.type.TubeHolder; import a8k.service.app.appstate.type.state.TubeState; +import a8k.service.app.devicectrl.ctrlservice.HbotCtrlService; import a8k.service.app.devicectrl.ctrlservice.PlateBoxCtrlService; import a8k.service.app.devicectrl.ctrlservice.TubePreProcesCtrlService; -import a8k.service.app.devicectrl.script.DeviceCtrlScripter; +import a8k.service.app.devicectrl.ctrlservice.TurnableMoveCtrlService; +import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; +import a8k.service.app.devicectrl.exdriver.HbotBaseMoveExDriver; +import a8k.service.app.devicectrl.param.ext_param_mgr.HbotConsumableParamMgr; +import a8k.service.app.devicectrl.param.ext_param_mgr.PipetteGunParamExMgr; +import a8k.service.app.devicectrl.param.ext_param_mgr.base.PipetteGunBindActionType; +import a8k.service.app.devicectrl.param.param_mgr.HbotFixedPosParamMgr; +import a8k.service.app.devicectrl.param.param_mgr.HbotSamplePosParamMgr; +import a8k.service.app.devicectrl.param.type.A8kSamplePos; +import a8k.service.app.devicectrl.script.PipeGunCtrlScripter; import a8k.service.app.erroranalyzer.ErrorAnalyzer; +import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; import a8k.service.test.state.TestModeState; import a8k.service.test.state.VirtualDevice; +import a8k.type.ConsumableGroup; import a8k.type.IncubatorPos; import a8k.type.ecode.AppError; import a8k.type.exception.AppException; import a8k.type.exception.ZAppInterruptException; +import a8k.type.pos.Consumable; import a8k.type.type.A8kTubeHolderType; import a8k.utils.ProjInfoUtils; import a8k.utils.ProjProcessContextUtils; @@ -67,16 +78,36 @@ public class SEQ5_PROCESS extends A8kStepAction { @Resource PublicAreaResourceMgr publicAreaResourceMgr; @Resource - TubeStateMgrService tubeStateMgrService; + TubeStateMgrService tubeStateMgrService; // // CtrlService // @Resource - DeviceCtrlScripter deviceCtrlScripter; + PipeGunCtrlScripter pipeGunCtrlScripter; @Resource - PlateBoxCtrlService plateBoxCtrlService; + PlateBoxCtrlService plateBoxCtrlService; @Resource TubePreProcesCtrlService tubePreProcesCtrlService; + @Resource + PipetteCtrlDriver pipetteCtrlDriver; + @Resource + HbotBaseMoveExDriver hbotBaseMoveExDriver; + @Resource + HbotCtrlService hbotCtrlService; + @Resource + TurnableMoveCtrlService turnableMoveCtrlService; + + // + // Param + // + @Resource + HbotSamplePosParamMgr hbotSamplePosParamMgr; + @Resource + HbotConsumableParamMgr hbotConsumableParamMgr; + @Resource + HbotFixedPosParamMgr hbotFixedPosParamMgr; + @Resource + PipetteGunParamExMgr pipetteGunParamExMgr; // @@ -209,8 +240,6 @@ public class SEQ5_PROCESS extends A8kStepAction { // // REAL // - - void samplePrepare() throws AppException, ZAppInterruptException { Tube tube = tubeStateMgrService.getCurProcessingTube(); TubeHolder tubeHolder = tubeStateMgrService.getTubeHolder(); @@ -280,31 +309,162 @@ public class SEQ5_PROCESS extends A8kStepAction { List cxts = projectContextMgrService.findCxts(tube.getSampleId()); Assert.isTrue(!cxts.isEmpty(), "项目上下文不能为空"); + for (ProjectTaskContext cxt : cxts) { + try ( + var ignored = publicAreaResourceMgr.apply(this.getClass(), PublicAreaResource.HbotArea); + ) { + doSampleProcess(cxt); + } + } - try ( - var ignored = publicAreaResourceMgr.apply(this.getClass(), PublicAreaResource.HbotArea); - ) { - for (ProjectTaskContext cxt : cxts) { - deviceCtrlScripter.doSampleProcessPrepare(cxt); - sampleIsReady.waitTrue(); - deviceCtrlScripter.doSampleProcess(cxt); + sampleProcessFinished.set(); + } + + void doSampleFlowType1PreProcess(ProjectTaskContext cxt) throws AppException, ZAppInterruptException { + Consumable consumable = cxt.getConsumable(); + ConsumableGroup consumableGroup = consumable.getGroup(); + Integer consumablePos = consumable.getPos(); + + log.info(" FlowType1->取TIP {}", cxt.getTopTip()); + hbotCtrlService.takeTip(cxt.takeTip()); + log.info(" FlowType1->刺破小缓冲液 {} {}", consumableGroup, consumablePos); + hbotCtrlService.moveToLittleBufferPiercePos(consumableGroup, consumablePos); + log.info(" FlowType1->hbot归零"); + hbotCtrlService.quickResetHbot(); + } + + void doSampleFlowType2PreProcess(ProjectTaskContext cxt) throws AppException, ZAppInterruptException { + Consumable consumable = cxt.getConsumable(); + ConsumableGroup consumableGroup = consumable.getGroup(); + Integer consumablePos = consumable.getPos(); + + Integer largeBsVolume = ProjProcessContextUtils.getTakeLargeBSVolume(cxt); + log.info(" FlowType2->取TIP {}", cxt.getTopTip()); + hbotCtrlService.takeTip(cxt.takeTip());//取tip + log.info(" FlowType2->刺破探测物质 {} {}", consumableGroup, consumablePos); + hbotCtrlService.moveToProbeSubstancePiercePos(consumableGroup, consumablePos);//刺破探测物质 + log.info(" FlowType2->等待LDD准备完成"); + pipetteCtrlDriver.lldPrepareBlock(); + log.info(" FlowType2->移动到大缓冲液取液位 {}", consumableGroup); + hbotCtrlService.moveToLargeBSSamplePos(consumableGroup);//移动到取样位置 + log.info(" FlowType2->液面探测准备"); + pipeGunCtrlScripter.lld(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, cxt); //优化这个方法的接口,尽量去除掉cxt + log.info(" FlowType2->取液准备"); + pipetteCtrlDriver.aspiratePrepareBlock();//取液.准备 + log.info(" FlowType2->取液 {}", largeBsVolume); + pipeGunCtrlScripter.aspirate(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, cxt, largeBsVolume);//取液 + log.info(" FlowType2->移动到探测物质吐液位 {}", consumableGroup); + hbotCtrlService.moveToProbeSubstanceSamplePos(consumableGroup, consumablePos);//移动到吐液位 + log.info(" FlowType2->吐液 {}", largeBsVolume); + pipeGunCtrlScripter.distribute(PipetteGunBindActionType.DISTRIBUTION_LARGE_BUFFER_SOLUTION_PROBE_SUBSTANCE, cxt, largeBsVolume);//吐液 + log.info(" FlowType2->hbot归零"); + hbotCtrlService.quickResetHbot(); + } + - reactionPlateReady.waitTrue(); + void doSampleProcess(ProjectTaskContext cxt) throws AppException, ZAppInterruptException { + A8kReactionFlowType type = cxt.getProjBuildinInfo().projBaseInfo.reactionFlowType; + Consumable consumable = cxt.getConsumable(); + ConsumableGroup consumableGroup = consumable.getGroup(); + Integer consumablePos = consumable.getPos(); - try ( - var ignored1 = publicAreaResourceMgr.apply(this.getClass(), PublicAreaResource.IncubationPlateArea); - ) { - deviceCtrlScripter.doSampleProcessPostProcess(cxt); - } - cxt.setStartIncubatedTime(System.currentTimeMillis()); - cxt.setIncubatedTimeSec(cxt.getProjBuildinInfo().projBaseInfo.reactionPlateIncubationTimeMin * 60); + //TODO:可以提速的点 + // 1. 在取tip之后,就让移液枪移动到lldprepare的位置(新增一条指令,这条指令在单片机端也是非阻塞的),到lld位置时,在执行lldprepare的指令,这样即不破坏现有框架,也可以提速 + // + + + if (type.equals(A8kReactionFlowType.FlowType1)) { + log.info("FlowType1:"); + doSampleFlowType1PreProcess(cxt); + + // !!! 等待样本准备完成 !!! + sampleIsReady.waitTrue(); + + // 取样 + try ( + var ignored11 = publicAreaResourceMgr.apply(this.getClass(), PublicAreaResource.TubeSampleProcessAndTubeChannelArea); + ) { + log.info(" FlowType1->取样"); + takeSample(cxt); + log.info(" FlowType1->移动到初步反应位"); + hbotCtrlService.moveToLittleBufferSamplePos(consumableGroup, consumablePos); + } + + } else if (type.equals(A8kReactionFlowType.FlowType2)) { + log.info("FlowType2:"); + doSampleFlowType2PreProcess(cxt); + // !!! 等待样本准备完成 !!! + sampleIsReady.waitTrue(); + + // 取样 + try ( + var ignored11 = publicAreaResourceMgr.apply(this.getClass(), PublicAreaResource.TubeSampleProcessAndTubeChannelArea); + ) { + log.info(" FlowType2->取样"); + takeSample(cxt); + log.info(" FlowType2->移动到初步反应位"); + hbotCtrlService.moveToProbeSubstanceSamplePos(consumableGroup, consumablePos); } } - sampleProcessFinished.set(); + // 初步反应处理 + { + Integer sampleul = ProjProcessContextUtils.getSampleVol(cxt); + Integer reactionul = ProjProcessContextUtils.getReactionPlateDropletVolUl(cxt); + log.info(" FlowTypeX->吐液 {}", sampleul); + pipeGunCtrlScripter.aspirateNoLLF(-sampleul); + log.info(" FlowTypeX->吸吐混匀 {}ul {} times", reactionul, ProjProcessContextUtils.getBSMixingCnt(cxt)); + pipeGunCtrlScripter.mix(PipetteGunBindActionType.MIX_REACTION_LIQUOR, cxt, sampleul, ProjProcessContextUtils.getBSMixingCnt(cxt)); + } + + // 取初步反应混合液到反应板 + try ( + var ignored11 = publicAreaResourceMgr.apply(this.getClass(), PublicAreaResource.IncubationPlateArea); + ) { + Integer reactionul = ProjProcessContextUtils.getReactionPlateDropletVolUl(cxt); + log.info(" FlowTypeX->吸液 {}", reactionul); + pipeGunCtrlScripter.aspirateNoLLF(reactionul); + log.info(" FlowTypeX->吐液到反应板"); + hbotCtrlService.moveTo(hbotFixedPosParamMgr.getDropLiquidPos()); + pipeGunCtrlScripter.distributeNoLLF(reactionul); + pipetteCtrlDriver.clearHangingLiquid(2); + pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); + + //孵育 + cxt.setStartIncubatedTime(System.currentTimeMillis()); + cxt.setIncubatedTimeSec(cxt.getProjBuildinInfo().projBaseInfo.reactionPlateIncubationTimeMin * 60); + } + + log.info(" FlowTypeX->Hbot复位"); + hbotCtrlService.moveQuickToZero(); + + } + + + public void takeSample(ProjectTaskContext ctx) throws AppException { + Integer sampleul = ProjProcessContextUtils.getSampleVol(ctx); + A8kSamplePos samplePos = ProjProcessContextUtils.getSamplePos(ctx); + + log.info(" -->取样准备"); + hbotCtrlService.takeTip(ctx.takeTip()); + log.info(" -->移动到取样位置 {}", samplePos); + hbotCtrlService.moveToSamplePosXY(samplePos); + log.info(" -->液面探测准备"); + pipetteCtrlDriver.lldPrepareBlock(); + log.info(" -->液面探测"); + pipeGunCtrlScripter.lld(PipetteGunBindActionType.SAMPLE, ctx); + log.info(" -->取液准备"); + pipetteCtrlDriver.aspiratePrepareBlock(); + if (ProjProcessContextUtils.isDoMixTubeSample(ctx)) { + log.info(" -->吸吐混匀 {}", ProjProcessContextUtils.getTubeMixingCount(ctx)); + pipeGunCtrlScripter.mix(PipetteGunBindActionType.MIX_SAMPLE, ctx, sampleul, ProjProcessContextUtils.getTubeMixingCount(ctx)); + } + log.info(" -->取样 {}", sampleul); + pipeGunCtrlScripter.aspirate(PipetteGunBindActionType.SAMPLE, ctx, sampleul); + } diff --git a/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java b/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java index 51702aa..280e82d 100644 --- a/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java +++ b/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java @@ -110,6 +110,12 @@ public class ProjectTaskContext { return tipPos.remove(0); } + synchronized public TipPos getTopTip() { + if (tipPos == null || tipPos.isEmpty()) { + return null; + } + return tipPos.get(0); + } synchronized public OptScanResult getfOptScanResult(A8kOptType optType) { return switch (optType) { diff --git a/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java b/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java index c810063..c2c430c 100644 --- a/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java +++ b/src/main/java/a8k/service/app/devicectrl/ctrlservice/DeviceInitCtrlService.java @@ -1,6 +1,5 @@ package a8k.service.app.devicectrl.ctrlservice; -import a8k.constant.LogTopic; import a8k.hardware.A8kCanBusService; import a8k.hardware.type.a8kcanprotocol.IOId; import a8k.service.app.devicectrl.driver.MiniServoDriver; @@ -10,7 +9,6 @@ import a8k.service.app.devicectrl.driver.type.MiniServoMId; import a8k.service.app.devicectrl.driver.type.StepMotorMId; import a8k.service.app.devicectrl.exdriver.HbotBaseMoveExDriver; import a8k.service.app.devicectrl.exdriver.MotorEnableExDriver; -import a8k.service.app.devicectrl.script.DeviceCtrlScripter; import a8k.service.test.state.VirtualDevice; import a8k.type.CheckPointType; @@ -60,8 +58,7 @@ public class DeviceInitCtrlService { TubeFeedingCtrlService tubeFeedingCtrlService; @Resource HbotCtrlService hbotCtrlService; - @Resource - DeviceCtrlScripter deviceCtrlScripter; + @Resource HbotBaseMoveExDriver hbotBaseMoveExDriver; @@ -148,7 +145,12 @@ public class DeviceInitCtrlService { gstate.setDeviceInited(true); //弹出无效物料 - deviceCtrlScripter.dropAllPlates(); + log.error("TODO:..............................清空孵育盘"); + log.error("TODO:..............................清空孵育盘"); + log.error("TODO:..............................清空孵育盘"); + log.error("TODO:..............................清空孵育盘"); + log.error("TODO:..............................清空孵育盘"); + //弹出试管架 tubeFeedingCtrlService.ejectTubeHolder(); //丢弃tip头 diff --git a/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java b/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java index 7803a07..3d614cf 100644 --- a/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java +++ b/src/main/java/a8k/service/app/devicectrl/ctrlservice/HbotCtrlService.java @@ -9,6 +9,7 @@ import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; import a8k.service.app.devicectrl.param.ext_param_mgr.HbotConsumableParamMgr; import a8k.service.app.devicectrl.param.param_mgr.HbotFixedPosParamMgr; import a8k.service.app.devicectrl.param.param_mgr.HbotSamplePosParamMgr; +import a8k.service.app.devicectrl.param.type.A8kSamplePos; import a8k.type.ConsumableGroup; import a8k.service.app.devicectrl.param.type.HbotSamplePos; import a8k.type.pos.TipPos; @@ -96,6 +97,14 @@ public class HbotCtrlService { } } + public void quickResetHbot() throws AppException { + hbotBaseMoveExDriver.hbotMoveTo(hbotTipPosMgr.getDropTipPos()); + pipetteCtrlDriver.pipetteInitDeviceBlock(); + hbotBaseMoveExDriver.hbotMoveTo(new Pos3d(0, 0, 0)); + hbotBaseMoveExDriver.moveToZero(); + } + + public Boolean isHasTip() throws AppException { return pipetteCtrlDriver.isHasTip(); } @@ -123,7 +132,7 @@ public class HbotCtrlService { } public void moveToLittleBufferSamplePos(ConsumableGroup group, Integer off) throws AppException { - hbotBaseMoveExDriver.hbotMoveTo(hbotConsumableParamMgr.getLittleBufferSamplePosEnd(group, off)); + hbotBaseMoveExDriver.hbotMoveTo(hbotConsumableParamMgr.getLittleBufferSamplePos(group, off)); } // public void moveToProbeSubstanceSamplePos(ConsumableGroup group, Integer off) throws AppException { @@ -139,12 +148,12 @@ public class HbotCtrlService { } - public void moveToLargeBufferPos(ConsumableGroup group) throws AppException { + public void moveToLargeBSSamplePos(ConsumableGroup group) throws AppException { Pos3d toPos = hbotConsumableParamMgr.getLargeBufferSamplePos(group); hbotBaseMoveExDriver.hbotMoveTo(toPos); } - public void moveToLargeBufferPosEnd(ConsumableGroup group) throws AppException { + public void moveToLargeBSSampleEndPos(ConsumableGroup group) throws AppException { Pos3d toPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(group); hbotBaseMoveExDriver.hbotMoveTo(toPos); } @@ -154,6 +163,17 @@ public class HbotCtrlService { hbotBaseMoveExDriver.hbotMoveTo(hbotSamplePosParamMgr.getSamplePos(pos)); } + public void moveToSampleStartPos(A8kSamplePos pos) throws AppException { + hbotBaseMoveExDriver.hbotMoveTo(hbotSamplePosParamMgr.getSampleStartPos(pos)); + } + + public void moveToSamplePosXY(A8kSamplePos pos) throws AppException { + var topos = hbotSamplePosParamMgr.getSampleStartPos(pos); + topos.z = 0; + hbotBaseMoveExDriver.hbotMoveTo(topos); + } + + public void moveTo(Pos3d pos) throws AppException { hbotBaseMoveExDriver.hbotMoveTo(pos); } diff --git a/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotLargeBottleBSPosCalibration.java b/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotLargeBottleBSPosCalibration.java index c58fef7..83eb65e 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotLargeBottleBSPosCalibration.java +++ b/src/main/java/a8k/service/app/devicectrl/param/calibration/HbotLargeBottleBSPosCalibration.java @@ -12,18 +12,14 @@ import a8k.service.app.devicectrl.ctrlservice.HbotCtrlService; import a8k.service.app.devicectrl.param.param_mgr.HbotLargeBottleBSPosMgr; import a8k.type.*; import a8k.type.cfg.Pos2d; -import a8k.type.cfg.Pos3d; import a8k.type.exception.AppException; import a8k.utils.ZJsonHelper; -import a8k.utils.ZSimplAlgo; import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.annotation.Resource; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.springframework.stereotype.Component; -import java.util.List; - @ExtApiTab(cfg = ExtApiTabConfig.HbotLargeBottleBSPosCalibration) @Component @Aspect @@ -230,7 +226,7 @@ public class HbotLargeBottleBSPosCalibration { enableModule(); pipetteCtrlDriver.zMotorMoveZeroBlock(); for (ConsumableGroup group : ConsumableGroup.values()) { - hbotCtrlService.moveToLargeBufferPosEnd(group); + hbotCtrlService.moveToLargeBSSampleEndPos(group); pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); if (checkStopFlag()) break; diff --git a/src/main/java/a8k/service/app/devicectrl/param/ext_param_mgr/HbotConsumableParamMgr.java b/src/main/java/a8k/service/app/devicectrl/param/ext_param_mgr/HbotConsumableParamMgr.java index 45403e0..57bd347 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/ext_param_mgr/HbotConsumableParamMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/ext_param_mgr/HbotConsumableParamMgr.java @@ -37,8 +37,8 @@ public class HbotConsumableParamMgr { return hbotLittleBSPosMgr.getPiercePos(group, off); } - public Pos3d getLittleBufferSamplePosEnd(ConsumableGroup group, Integer off) { - return hbotLittleBSPosMgr.getSampleEndPos(group, off); + public Pos3d getLittleBufferSamplePos(ConsumableGroup group, Integer off) { + return hbotLittleBSPosMgr.getSamplePos(group, off); } diff --git a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotLittleBSPosMgr.java b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotLittleBSPosMgr.java index 90c28b4..3eec6c8 100644 --- a/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotLittleBSPosMgr.java +++ b/src/main/java/a8k/service/app/devicectrl/param/param_mgr/HbotLittleBSPosMgr.java @@ -29,7 +29,7 @@ public class HbotLittleBSPosMgr extends ParamMgr { for (int i = 0; i < 25; i++) { getConsumablePos(group, i); getPiercePos(group, i); - getSampleEndPos(group, i); + getSamplePos(group, i); } } } @@ -70,7 +70,7 @@ public class HbotLittleBSPosMgr extends ParamMgr { return pos; } - public Pos3d getSampleEndPos(ConsumableGroup group, Integer off) { + public Pos3d getSamplePos(ConsumableGroup group, Integer off) { Pos3d pos = getConsumablePos(group, off); pos.z = getParam(HbotLittleBSPos.LittleBSSampleZPos, Integer.class); return pos; diff --git a/src/main/java/a8k/service/app/devicectrl/script/DeviceCtrlScripter.java b/src/main/java/a8k/service/app/devicectrl/script/DeviceCtrlScripter.java deleted file mode 100644 index ec485b0..0000000 --- a/src/main/java/a8k/service/app/devicectrl/script/DeviceCtrlScripter.java +++ /dev/null @@ -1,274 +0,0 @@ -package a8k.service.app.devicectrl.script; - -import a8k.service.app.appstate.type.ProjectTaskContext; -import a8k.service.app.devicectrl.ctrlservice.HbotCtrlService; -import a8k.service.app.devicectrl.ctrlservice.OptScanModuleCtrlService; -import a8k.service.app.devicectrl.ctrlservice.TurnableMoveCtrlService; -import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; -import a8k.service.app.devicectrl.exdriver.HbotBaseMoveExDriver; -import a8k.service.app.devicectrl.param.ext_param_mgr.HbotConsumableParamMgr; -import a8k.service.app.devicectrl.param.ext_param_mgr.base.PipetteGunBindActionType; -import a8k.service.app.devicectrl.param.ext_param_mgr.base.LLDParamPack; -import a8k.service.app.devicectrl.param.ext_param_mgr.PipetteGunParamExMgr; -import a8k.service.app.devicectrl.param.ext_param_mgr.base.LLFParamPack; -import a8k.service.app.devicectrl.param.param_mgr.HbotFixedPosParamMgr; -import a8k.service.app.devicectrl.param.param_mgr.HbotSamplePosParamMgr; -import a8k.service.app.devicectrl.param.type.A8kSamplePos; -import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; -import a8k.type.cfg.Pos3d; -import a8k.type.exception.AppException; -import a8k.type.pos.Consumable; -import a8k.type.pos.TipPos; -import a8k.utils.ProjProcessContextUtils; -import a8k.utils.ZAppChecker; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; - -@Component -@Slf4j -public class DeviceCtrlScripter { - - - @Resource - PipetteCtrlDriver pipetteCtrlDriver; - @Resource - HbotBaseMoveExDriver hbotBaseMoveExDriver; - @Resource - HbotCtrlService hbotCtrlService; - @Resource - TurnableMoveCtrlService turnableMoveCtrlService; - - @Resource - HbotSamplePosParamMgr hbotSamplePosParamMgr; - @Resource - HbotConsumableParamMgr hbotConsumableParamMgr; - @Resource - HbotFixedPosParamMgr hbotFixedPosParamMgr; - @Resource - PipetteGunParamExMgr pipetteGunParamExMgr; - - @Resource - ZAppChecker zAppChecker; - - - @Resource - OptScanModuleCtrlService optScanModuleCtrlService; - - - public void dropAllPlates() throws AppException { - log.info("清空孵育盘"); - //TODO:测试模式下不执行 - // actionReactor.dosome("丢板", () -> optScanModuleCtrlService.dropPlate()); - // for (var incubatorPos : IncubatorPos.values()) { - // actionReactor.dosome("拉板" + incubatorPos.name(), () -> optScanModuleCtrlService.pullPlate(incubatorPos)); - // actionReactor.dosome("丢板", () -> optScanModuleCtrlService.dropPlate()); - // } - } - - - void aspirateNoLLF(Integer ul) throws AppException { - pipetteCtrlDriver.aspirateSetLlfVelocity(0); - pipetteCtrlDriver.aspirateBlock(ul); - } - - void distributeNoLLF(Integer ul) throws AppException { - pipetteCtrlDriver.aspirateSetLlfVelocity(0); - pipetteCtrlDriver.aspirateBlock(-ul); - } - - - void distribute(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul) throws AppException { - LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); - pipetteCtrlDriver.aspirateSetLlfVelocity(llfParamPack.llfVel); - pipetteCtrlDriver.setLlfStartZ(llfParamPack.llfStartPos); - pipetteCtrlDriver.setLlfEndZ(llfParamPack.llfEndPos); - pipetteCtrlDriver.aspirateBlock(-ul); - } - - void mix(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul, Integer times) throws AppException { - LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); - pipetteCtrlDriver.aspirateSetLlfVelocity(llfParamPack.llfVel); - pipetteCtrlDriver.setLlfStartZ(llfParamPack.llfStartPos); - pipetteCtrlDriver.setLlfEndZ(llfParamPack.llfEndPos); - pipetteCtrlDriver.shakeUpBlock(ul, times); - } - - - void aspirate(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul) throws AppException { - LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); - log.info("吸液 {} , llfvel {} , llfStartPos {} , llfEndPos {}", ul, llfParamPack.llfVel, llfParamPack.llfStartPos, llfParamPack.llfEndPos); - - pipetteCtrlDriver.aspirateSetLlfVelocity(llfParamPack.llfVel); - pipetteCtrlDriver.setLlfStartZ(llfParamPack.llfStartPos); - pipetteCtrlDriver.setLlfEndZ(llfParamPack.llfEndPos); - pipetteCtrlDriver.aspirateBlock(ul); - } - - - void lld(PipetteGunBindActionType actionType, ProjectTaskContext ctx) throws AppException { - pipetteCtrlDriver.lldPrepareBlock(); - - log.info("液面探测 {}", actionType); - LLDParamPack lldparm = pipetteGunParamExMgr.getLLDParam(actionType, ctx); - Pos3d sampleStartPos = null; - Pos3d sampleEndPos = null; - - //取tip,移动到样本所在的位置,并液面探测 - switch (actionType) { - case SAMPLE -> { - A8kSamplePos samplePos = ProjProcessContextUtils.getSamplePos(ctx); - sampleStartPos = hbotSamplePosParamMgr.getSampleStartPos(samplePos); - sampleEndPos = hbotSamplePosParamMgr.getSampleEndPos(samplePos); - } - case TAKE_LARGE_BUFFER_SOLUTION -> { //取大瓶缓冲液 - var group = ctx.getConsumable().getGroup(); - sampleStartPos = hbotConsumableParamMgr.getLargeBufferSamplePos(group); - sampleEndPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(group); - } - } - - Assert.notNull(sampleStartPos, "sampleStartPos is null"); - Assert.notNull(sampleEndPos, "sampleEndPos is null"); - - pipetteCtrlDriver.setStartZ(sampleStartPos.z); - pipetteCtrlDriver.setEndZ(sampleEndPos.z); - pipetteCtrlDriver.setLldType(lldparm.type); - pipetteCtrlDriver.setLldCThreshold(lldparm.cThreshold); - pipetteCtrlDriver.setLldPThreshold(lldparm.pThreshold); - pipetteCtrlDriver.lldBlock(); - } - - - public void doSampleProcessPrepare(ProjectTaskContext ctx) throws AppException { - A8kReactionFlowType type = ctx.getProjBuildinInfo().projBaseInfo.reactionFlowType; - if (type.equals(A8kReactionFlowType.FlowType1)) { - log.info("样本预处理,刺破小瓶缓冲液"); - /* - * 刺破小瓶缓冲液 - */ - TipPos tip = ctx.takeTip(); - Assert.isTrue(tip != null, "tip is null"); - - Consumable consumable = ctx.getConsumable(); - - //取tip - hbotCtrlService.takeTip(tip); - //刺破 - hbotCtrlService.moveToLittleBufferPiercePos(consumable.getGroup(), consumable.getPos()); - //丢tip - hbotCtrlService.dropTip(); - //待机 - hbotCtrlService.moveQuickToZero(); - - //提前.取tip, - hbotCtrlService.takeTip(ctx.takeTip()); - } else if (type.equals(A8kReactionFlowType.FlowType2)) { - log.info("样本预处理,取大瓶缓冲液液到探测物质中"); - /* - * 取大瓶缓冲液液到探测物质中 - */ - //ldd准备 - - //取tip, - hbotCtrlService.takeTip(ctx.takeTip()); - - //移动到取样位置 - Pos3d pos = hbotConsumableParamMgr.getLargeBufferSamplePos(ctx.getConsumable().getGroup()); - pos.z = 0; - hbotCtrlService.moveTo(pos); - - //移动到目标位置,并液面探测 - lld(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, ctx); - - //取液.准备 - pipetteCtrlDriver.aspiratePrepareBlock(); - - //取液 - Integer takeul = ProjProcessContextUtils.getTakeLargeBSVolume(ctx); - aspirate(PipetteGunBindActionType.TAKE_LARGE_BUFFER_SOLUTION, ctx, takeul); - - //移动到吐液位 - hbotCtrlService.moveTo(hbotConsumableParamMgr.getProbeSubstanceSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos())); - - //吐液 - distribute(PipetteGunBindActionType.DISTRIBUTION_LARGE_BUFFER_SOLUTION_PROBE_SUBSTANCE, ctx, takeul); - - - //丢tip - hbotCtrlService.dropTip(); - - //归零,待机 - hbotCtrlService.moveQuickToZero(); - } else { - Assert.isTrue(false, "不支持的反应流程类型"); - } - } - - public void doSampleProcess(ProjectTaskContext ctx) throws AppException { - Integer sampleul = ProjProcessContextUtils.getSampleVol(ctx); - Integer reactionul = ProjProcessContextUtils.getReactionPlateDropletVolUl(ctx); - - A8kReactionFlowType type = ctx.getProjBuildinInfo().projBaseInfo.reactionFlowType; - if (type.equals(A8kReactionFlowType.FlowType1)) { - // hbotCtrlService.takeTip(ctx.takeTip()); - } else { - hbotCtrlService.takeTip(ctx.takeTip()); - } - - //移动到取样位置 - A8kSamplePos samplePos = ProjProcessContextUtils.getSamplePos(ctx); - log.info("移动到 {}", samplePos); - Pos3d pos = hbotSamplePosParamMgr.getSampleStartPos(samplePos); - pos.z = 0; - hbotCtrlService.moveTo(pos); - - //ldd准备 - lld(PipetteGunBindActionType.SAMPLE, ctx); - - //取液准备 - pipetteCtrlDriver.aspiratePrepareBlock(); - - //吸吐混匀 - if (ProjProcessContextUtils.isDoMixTubeSample(ctx)) - mix(PipetteGunBindActionType.MIX_SAMPLE, ctx, sampleul, ProjProcessContextUtils.getTubeMixingCount(ctx)); - - //取样 - aspirate(PipetteGunBindActionType.SAMPLE, ctx, sampleul); - - //移动到吐液位, - hbotCtrlService.moveTo(ProjProcessContextUtils.getReactionEndPos(ctx)); - } - - - public void doSampleProcessPostProcess(ProjectTaskContext ctx) throws AppException { - Integer sampleul = ProjProcessContextUtils.getSampleVol(ctx); - Integer reactionul = ProjProcessContextUtils.getReactionPlateDropletVolUl(ctx); - - //吐液 - aspirateNoLLF(-sampleul); - - //吸吐混匀 - mix(PipetteGunBindActionType.MIX_REACTION_LIQUOR, ctx, sampleul, ProjProcessContextUtils.getBSMixingCnt(ctx)); - - //吸液 - aspirateNoLLF(reactionul); - - //旋转转盘 - turnableMoveCtrlService.trunableMoveToDropLiquidPos(ctx.getIncubatorPos()); - - //吐液到反应板 - hbotCtrlService.moveTo(hbotFixedPosParamMgr.getDropLiquidPos()); - distributeNoLLF(reactionul); - pipetteCtrlDriver.clearHangingLiquid(2); - - - //丢tip - hbotCtrlService.dropTip(); - //归零,待机 - hbotCtrlService.moveQuickToZero(); - } - - -} diff --git a/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java b/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java new file mode 100644 index 0000000..8e97857 --- /dev/null +++ b/src/main/java/a8k/service/app/devicectrl/script/PipeGunCtrlScripter.java @@ -0,0 +1,110 @@ +package a8k.service.app.devicectrl.script; + +import a8k.service.app.appstate.type.ProjectTaskContext; +import a8k.service.app.devicectrl.ctrlservice.HbotCtrlService; +import a8k.service.app.devicectrl.ctrlservice.OptScanModuleCtrlService; +import a8k.service.app.devicectrl.ctrlservice.TurnableMoveCtrlService; +import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; +import a8k.service.app.devicectrl.exdriver.HbotBaseMoveExDriver; +import a8k.service.app.devicectrl.param.ext_param_mgr.HbotConsumableParamMgr; +import a8k.service.app.devicectrl.param.ext_param_mgr.base.PipetteGunBindActionType; +import a8k.service.app.devicectrl.param.ext_param_mgr.base.LLDParamPack; +import a8k.service.app.devicectrl.param.ext_param_mgr.PipetteGunParamExMgr; +import a8k.service.app.devicectrl.param.ext_param_mgr.base.LLFParamPack; +import a8k.service.app.devicectrl.param.param_mgr.HbotFixedPosParamMgr; +import a8k.service.app.devicectrl.param.param_mgr.HbotSamplePosParamMgr; +import a8k.service.app.devicectrl.param.type.A8kSamplePos; +import a8k.type.cfg.Pos3d; +import a8k.type.exception.AppException; +import a8k.utils.ProjProcessContextUtils; +import a8k.utils.ZAppChecker; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +@Component +@Slf4j +public class PipeGunCtrlScripter { + + + @Resource + PipetteCtrlDriver pipetteCtrlDriver; + @Resource + HbotSamplePosParamMgr hbotSamplePosParamMgr; + @Resource + HbotConsumableParamMgr hbotConsumableParamMgr; + @Resource + PipetteGunParamExMgr pipetteGunParamExMgr; + + public void aspirateNoLLF(Integer ul) throws AppException { + pipetteCtrlDriver.aspirateSetLlfVelocity(0); + pipetteCtrlDriver.aspirateBlock(ul); + } + + public void distributeNoLLF(Integer ul) throws AppException { + pipetteCtrlDriver.aspirateSetLlfVelocity(0); + pipetteCtrlDriver.aspirateBlock(-ul); + } + + + public void distribute(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul) throws AppException { + LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); + pipetteCtrlDriver.aspirateSetLlfVelocity(llfParamPack.llfVel); + pipetteCtrlDriver.setLlfStartZ(llfParamPack.llfStartPos); + pipetteCtrlDriver.setLlfEndZ(llfParamPack.llfEndPos); + pipetteCtrlDriver.aspirateBlock(-ul); + } + + public void mix(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul, Integer times) throws AppException { + LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); + pipetteCtrlDriver.aspirateSetLlfVelocity(llfParamPack.llfVel); + pipetteCtrlDriver.setLlfStartZ(llfParamPack.llfStartPos); + pipetteCtrlDriver.setLlfEndZ(llfParamPack.llfEndPos); + pipetteCtrlDriver.shakeUpBlock(ul, times); + } + + + public void aspirate(PipetteGunBindActionType actionType, ProjectTaskContext ctx, Integer ul) throws AppException { + LLFParamPack llfParamPack = pipetteGunParamExMgr.getLLFParam(actionType, ctx); + log.info("吸液 {} , llfvel {} , llfStartPos {} , llfEndPos {}", ul, llfParamPack.llfVel, llfParamPack.llfStartPos, llfParamPack.llfEndPos); + + pipetteCtrlDriver.aspirateSetLlfVelocity(llfParamPack.llfVel); + pipetteCtrlDriver.setLlfStartZ(llfParamPack.llfStartPos); + pipetteCtrlDriver.setLlfEndZ(llfParamPack.llfEndPos); + pipetteCtrlDriver.aspirateBlock(ul); + } + + + public void lld(PipetteGunBindActionType actionType, ProjectTaskContext ctx) throws AppException { + log.info("液面探测 {}", actionType); + LLDParamPack lldparm = pipetteGunParamExMgr.getLLDParam(actionType, ctx); + Pos3d sampleStartPos = null; + Pos3d sampleEndPos = null; + + //取tip,移动到样本所在的位置,并液面探测 + switch (actionType) { + case SAMPLE -> { + A8kSamplePos samplePos = ProjProcessContextUtils.getSamplePos(ctx); + sampleStartPos = hbotSamplePosParamMgr.getSampleStartPos(samplePos); + sampleEndPos = hbotSamplePosParamMgr.getSampleEndPos(samplePos); + } + case TAKE_LARGE_BUFFER_SOLUTION -> { //取大瓶缓冲液 + var group = ctx.getConsumable().getGroup(); + sampleStartPos = hbotConsumableParamMgr.getLargeBufferSamplePos(group); + sampleEndPos = hbotConsumableParamMgr.getLargeBufferSamplePosEnd(group); + } + } + + Assert.notNull(sampleStartPos, "sampleStartPos is null"); + Assert.notNull(sampleEndPos, "sampleEndPos is null"); + + pipetteCtrlDriver.setStartZ(sampleStartPos.z); + pipetteCtrlDriver.setEndZ(sampleEndPos.z); + pipetteCtrlDriver.setLldType(lldparm.type); + pipetteCtrlDriver.setLldCThreshold(lldparm.cThreshold); + pipetteCtrlDriver.setLldPThreshold(lldparm.pThreshold); + pipetteCtrlDriver.lldBlock(); + } + +} diff --git a/src/main/java/a8k/utils/ProjProcessContextUtils.java b/src/main/java/a8k/utils/ProjProcessContextUtils.java index 5c36f85..d84f124 100644 --- a/src/main/java/a8k/utils/ProjProcessContextUtils.java +++ b/src/main/java/a8k/utils/ProjProcessContextUtils.java @@ -154,11 +154,11 @@ public class ProjProcessContextUtils { } - static public Pos3d getReactionEndPos(ProjectTaskContext ctx) { + static public Pos3d getFirstStepReactionPos(ProjectTaskContext ctx) { HbotConsumableParamMgr hbotConsumableParamMgr = SpringBootBeanUtil.getBean(HbotConsumableParamMgr.class); A8kReactionFlowType type = ctx.getProjBuildinInfo().projBaseInfo.reactionFlowType; return switch (type) { - case FlowType1 -> hbotConsumableParamMgr.getLittleBufferSamplePosEnd(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos()); + case FlowType1 -> hbotConsumableParamMgr.getLittleBufferSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos()); case FlowType2 -> hbotConsumableParamMgr.getProbeSubstanceSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos()); }; }