Browse Source

update

master
zhaohe 2 months ago
parent
commit
e6642d5543
  1. 17
      src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java
  2. 6
      src/main/java/a8k/app/engineer/service/qatest/LiquidAbsorptionAndDistributionTestService.java
  3. 42
      src/main/java/a8k/app/hardware/driver/PipetteCtrlDriverV2.java
  4. 11
      src/main/java/a8k/app/hardware/type/pipette_module/DistribuType.java
  5. 1
      src/main/java/a8k/app/hardware/type/pipette_module/cfg/PipetteCommonConfigIndex.java
  6. 1
      src/main/java/a8k/app/hardware/type/pipette_module/cfgbean/PipetteCommonConfig.java
  7. 1
      src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/ContainerCpyId.java
  8. 2
      src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/LiquidConfigCpyIdx.java
  9. 22
      src/main/java/a8k/app/hardware/type/pipette_module/cpyidx/PlatInfoCpyIdx.java
  10. 32
      src/main/java/a8k/app/hardware/type/pipette_module/param/AspirationParam.java
  11. 25
      src/main/java/a8k/app/hardware/type/pipette_module/param/DistribuAllParam.java
  12. 8
      src/main/java/a8k/app/service/lowerctrl/DeviceMoveToZeroCtrlService.java
  13. 22
      src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java
  14. 269
      src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java
  15. 5
      src/main/java/a8k/app/service/mainctrl/mainflowctrl/MainFlowCtrlScheduler.java
  16. 22
      src/main/java/a8k/app/service/mainctrl/mainflowctrl/action/AC41ProcessSample.java
  17. 383
      src/main/java/a8k/app/service/module/LiquidOperationCtrlModule.java
  18. 18
      src/main/java/a8k/app/service/module/TipMgrModule.java
  19. 4
      src/main/java/a8k/app/service/param/exparam/HbotConsumableExParamMgr.java
  20. 12
      src/main/java/a8k/app/service/param/hbotpos/HbotLittleBSPosMgr.java
  21. 4
      src/main/java/a8k/app/service/param/hbotpos/HbotProbeSubstancePosMgr.java
  22. 2
      src/main/java/a8k/app/type/a8k/state/ProjectTaskContext.java
  23. 8
      src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunCommonConfigPage.java
  24. 12
      src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunOperationCtrlPage.java
  25. 2
      src/main/java/a8k/extui/page/test/verification/P32HbotPosVerificationPage.java
  26. 51
      src/main/java/a8k/extui/page/test/verification/P34LiquidOperationTestPage.java

17
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);

6
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;

42
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);
}

11
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();
}
}

1
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() {

1
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端均正确更新了枚举

1
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,
;

2
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();
}
}

22
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;
}
}

32
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;

25
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;

8
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();

22
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;
}
}

269
src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java

@ -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();
}
}

5
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;

22
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();
}

383
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
));
}
}

18
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);

4
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) {

12
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) {

4
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) {

2
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());
};
}

8
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);
}

12
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 {

2
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 {

51
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);
}

Loading…
Cancel
Save