diff --git a/.gitignore b/.gitignore index 76f5060..19a6885 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ tmp/ app.db !/bak/app.db /logs/* +appresource/static/app/ diff --git a/deply.bat b/sh/deply.bat similarity index 100% rename from deply.bat rename to sh/deply.bat diff --git a/mkexe.bat b/sh/mkexe.bat similarity index 100% rename from mkexe.bat rename to sh/mkexe.bat diff --git a/sh/sync_from_board.bat b/sh/sync_from_board.bat new file mode 100644 index 0000000..96ae038 --- /dev/null +++ b/sh/sync_from_board.bat @@ -0,0 +1,2 @@ + scp -r root@192.168.8.10://app/appresource/static/app .\appresource\static/ + scp root@192.168.8.10://app/appresource/db/app.db .\appresource\db/ \ No newline at end of file diff --git a/src/main/java/a8k/app/constant/AppConstant.java b/src/main/java/a8k/app/constant/AppConstant.java index a996bd4..79e11ac 100644 --- a/src/main/java/a8k/app/constant/AppConstant.java +++ b/src/main/java/a8k/app/constant/AppConstant.java @@ -2,11 +2,13 @@ package a8k.app.constant; public class AppConstant { public static final int CONSUMABLE_NUM = 25; + public static final int TUBEHOLER_SIZE = 10;//试管架中可容纳的试管的数量 public static final int CONSUMABLE_COL_NUM = 5; public static final int CONSUMABLE_ROW_NUM = 5; public static final int TIP_NUM = 120; public static final String APP_VERSION = "1.3.1"; + public static final int CONSUMABLE_CHANNEL_NUM = 6; } diff --git a/src/main/java/a8k/app/controler/api/v1/engineer/ExperimentConsistencyTestingControler.java b/src/main/java/a8k/app/controler/api/v1/engineer/ExperimentConsistencyTestingControler.java index d90eefb..eb1cb12 100644 --- a/src/main/java/a8k/app/controler/api/v1/engineer/ExperimentConsistencyTestingControler.java +++ b/src/main/java/a8k/app/controler/api/v1/engineer/ExperimentConsistencyTestingControler.java @@ -2,6 +2,7 @@ package a8k.app.controler.api.v1.engineer; import a8k.app.engineer.service.qatest.ExperimentConsistencyTestingService; +import a8k.app.engineer.service.type.TubeHolderExConfig; import a8k.app.type.exception.AppException; import a8k.app.type.ui.ApiRet; import io.swagger.v3.oas.annotations.Operation; @@ -24,9 +25,22 @@ public class ExperimentConsistencyTestingControler { @Operation(summary = "开始测试(所有配置从应用获得)") @PostMapping("/startTest") - public ApiRet startTest(Integer repeatTimes) throws AppException { - experimentConsistencyTestingService.startTest(repeatTimes); + public ApiRet startTest() throws AppException { + experimentConsistencyTestingService.startTest(); return ApiRet.success(); } + @Operation(summary = "提交配置") + @PostMapping("/submitConfig") + public ApiRet submitConfig(TubeHolderExConfig tubeHolderExConfig) { + experimentConsistencyTestingService.submitTubeExConfig(tubeHolderExConfig); + return ApiRet.success(); + } + + @Operation(summary = "获取配置") + @PostMapping("/getConfig") + public ApiRet getConfig() { + TubeHolderExConfig tubeHolderExConfig = experimentConsistencyTestingService.getTubeExConfig(); + return ApiRet.success(tubeHolderExConfig); + } } 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 b913856..5a49d11 100644 --- a/src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java +++ b/src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java @@ -1,12 +1,14 @@ package a8k.app.engineer.service.qatest; import a8k.OS; +import a8k.app.constant.AppConstant; import a8k.app.dao.type.combination.ProjBuildinInfo; import a8k.app.dao.type.db.ProjExtInfoCard; import a8k.app.dao.type.db.ReactionReport; import a8k.app.engineer.service.executor.EngineerModeActionExecutor; import a8k.app.engineer.service.state.EngineerModeStateMgrService; import a8k.app.engineer.service.type.A8kCmdRunnable; +import a8k.app.engineer.service.type.TubeHolderExConfig; import a8k.app.engineer.service.utils.BeforeDoEngineerActionChecker; import a8k.app.hardware.driver.OptModuleDriver; import a8k.app.hardware.type.A8kEcode; @@ -56,6 +58,7 @@ import java.util.Objects; @Slf4j @RequiredArgsConstructor public class ExperimentConsistencyTestingService { + final private A8kTubeHolderType expectedTubeHolderType = A8kTubeHolderType.BulletTube1P5; final private Integer expectedProjId = 1; final private Integer takeSampleUl = 10; @@ -96,18 +99,39 @@ public class ExperimentConsistencyTestingService { final private LiquidOperationCtrlService liquidOperationCtrlService; final private HbotMoveExCtrlService hbotMoveExCtrlService; private final OptModuleDriver optModuleDriver; + private final HbotMoveCtrlService hbotMoveCtrlService; + + + private TubeHolderSetting curTubeHolderSetting; + private TubeHolderExConfig tubeHolderExConfig = new TubeHolderExConfig(); + + synchronized public void submitTubeExConfig(TubeHolderExConfig tubeExTubeHolderExConfig) { + if (tubeExTubeHolderExConfig != null) { + this.tubeHolderExConfig = tubeExTubeHolderExConfig; + } + } + synchronized public TubeHolderExConfig getTubeExConfig() { + return tubeHolderExConfig; + } + + public Integer getRepeatTimes(Integer tubeoff) { + if (tubeoff < 0 || tubeoff >= AppConstant.TUBEHOLER_SIZE) { + throw new IllegalArgumentException("tubeoff is out of range"); + } + if (tubeoff >= tubeHolderExConfig.tubeExConfigs.size()) { + return 1; + } + return getTubeExConfig().tubeExConfigs.get(tubeoff).repeatTimes; + } - private TubeHolderSetting curTubeHolderSetting; - private Integer repeatTimes = 1; /** * 开始测试 - * @param repeatTimes 重复次数 + * @param * @throws AppException */ - public void startTest(Integer repeatTimes) throws AppException { - this.repeatTimes = repeatTimes; + public void startTest() throws AppException { /* * 检查当前是否有其他项目正在进行测试 */ @@ -174,15 +198,17 @@ public class ExperimentConsistencyTestingService { try { log.error("Catch exception: ", e); UISender.txErrorPrompt(e); + docmd("HBOT复位", hbotMoveCtrlService::moveToZero); + docmd("推出试管架", tubeFeedingCtrlService::ejectTubeHolder); //清空光学模组 optScanModuleStateMgrService.changeOptScanModuleStateToEmpty(); - docmd("丢反应板", () -> optScanModuleCtrlService.dropPlate()); + docmd("丢反应板", optScanModuleCtrlService::dropPlate); //清空孵育盘 List all = incubationPlateStateMgrService.getAllNotFreeIncubationSubTanks(); for (IncubationSubTank notFreeTank : all) { - docmd("拉取反应板", () -> {optScanModuleCtrlService.pullPlate(notFreeTank.pos);}); - docmd("丢反应板", () -> {optScanModuleCtrlService.dropPlate();}); + docmd("拉取反应板", () -> optScanModuleCtrlService.pullPlate(notFreeTank.pos)); + docmd("丢反应板", optScanModuleCtrlService::dropPlate); } incubationPlateStateMgrService.resetAll(); } catch (AppException ex) { @@ -228,7 +254,7 @@ public class ExperimentConsistencyTestingService { hasTubeHolder = false; docmd("入料", () -> { hasTubeHolder = tubeFeedingCtrlService.enterTubeHolder(); - }, () -> {hasTubeHolder = true;}); + }, () -> hasTubeHolder = true); if (!hasTubeHolder) { throw AppException.of(A8kEcode.ERROR_OPERATION, "入料超时,未检测到试管架"); } @@ -250,56 +276,68 @@ public class ExperimentConsistencyTestingService { verifyTubeHolderSettingAndTubeHolderScanResult(curTubeHolderSetting, scanResult); // - for (int i = 0; i < curTubeHolderSetting.tubeSettings.length; i++) { - TubeSetting tubeSetting = curTubeHolderSetting.tubeSettings[i]; + //构建试管架 + // setTubeHolderDirect + for (int tubeoff = 0; tubeoff < curTubeHolderSetting.tubeSettings.length; tubeoff++) { + TubeSetting tubeSetting = curTubeHolderSetting.tubeSettings[tubeoff]; if (tubeSetting.projId.isEmpty()) { continue; } - Assert.isTrue(scanResult.tube[i].isTubeExist, String.format("位置[%d]未放入是试管", i + 1)); + Assert.isTrue(scanResult.tube[tubeoff].isTubeExist, String.format("位置[%d]未放入是试管", tubeoff + 1)); + + + //移动试管架到预处理位置 + int finalTubeoff = tubeoff; + docmd("移动试管到处理位", () -> tubeFeedingCtrlService.moveTubeToPreProcessPos(finalTubeoff)); + + //尝试处理孵育完成的反应板 + incubationPlateProcess(false); + + //申请耗材 + var consumableInfo = consumablesMgrService.reserveConsumable(expectedProjId); + if (consumableInfo == null) { + throw AppException.of(A8kEcode.CODEERROR, "耗材不足?"); //理论上开始阶段已经核对过了耗材数量,此时应该不会不足 + } + consumablesMgrService.useReserveConsumable(consumableInfo); + + //构造项目信息 + ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(expectedProjId); + ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(consumableInfo.lotid); + ProjBriefInfo projBriefInfo = ProjInfoUtils.buildProjBrefInfo(projBuildinInfo); + + Assert.notNull(projBuildinInfo, "projBuildInInfo is null"); + Assert.notNull(projExtInfoCard, "projExtInfoCard is null"); //处理样本 - for (int j = 0; j < repeatTimes; j++) { + Tube tube = new Tube(tubeoff); + tube.setIsHighTube(false); + tube.setIsEmergency(false); + tube.setBloodType(BloodType.WHOLE_BLOOD); + tube.setSampleBarcode(tubeSetting.sampleBarcode); + tube.setUserid(tubeSetting.userid); + tube.setProjInfo(ZList.of(projBriefInfo)); + tube.setProjIds(ZList.of(expectedProjId)); + String sampleId = tubeStateMgrService.newSample(tube); + tube.setSampleId(sampleId); + + + for (int j = 0; j < getRepeatTimes(tubeoff); j++) { //处理试管 - processTube(i, tubeSetting); + processTube(tube, tubeoff, consumableInfo, tubeSetting); + if (!tube.getErrors().isEmpty()) { + log.warn("样本异常,跳过当前样本"); + break; + } } } - } - - private void processTube(Integer offset, TubeSetting tubeSetting) throws AppException { - //移动试管架到预处理位置 - docmd("移动试管到处理位", () -> { - tubeFeedingCtrlService.moveTubeToPreProcessPos(offset); - }); - //尝试处理孵育完成的反应板 - incubationPlateProcess(); + incubationPlateProcess(true); + } - //申请耗材 - var consumableInfo = consumablesMgrService.reserveConsumable(expectedProjId); - if (consumableInfo == null) { - throw AppException.of(A8kEcode.CODEERROR, "耗材不足?"); //理论上开始阶段已经核对过了耗材数量,此时应该不会不足 - } - consumablesMgrService.useReserveConsumable(consumableInfo); + private void processTube(Tube tube, Integer offset, ConsumablesMgrService.ConsumableInfo consumableInfo, TubeSetting tubeSetting) throws AppException { - //构造项目信息 ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(expectedProjId); ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(consumableInfo.lotid); - ProjBriefInfo projBriefInfo = ProjInfoUtils.buildProjBrefInfo(projBuildinInfo); - - Assert.notNull(projBuildinInfo, "projBuildInInfo is null"); - Assert.notNull(projExtInfoCard, "projExtInfoCard is null"); - - Tube tube = new Tube(offset); - tube.setIsHighTube(false); - tube.setIsEmergency(false); - tube.setBloodType(BloodType.WHOLE_BLOOD); - tube.setSampleBarcode(tubeSetting.sampleBarcode); - tube.setUserid(tubeSetting.userid); - tube.setProjInfo(ZList.of(projBriefInfo)); - tube.setProjIds(ZList.of(expectedProjId)); - - String sampleId = tubeStateMgrService.newSample(tube); - tube.setSampleId(sampleId); //拉取一个板夹到孵育盘 @@ -315,9 +353,9 @@ public class ExperimentConsistencyTestingService { // optScanModuleCtrlService.pullPlate(freeIncubationPos); // optScanModuleCtrlService.dropPlate(); - docmd("丢反应板", () -> optScanModuleCtrlService.dropPlate()); + docmd("丢反应板", optScanModuleCtrlService::dropPlate); docmd("拉取反应板", () -> optScanModuleCtrlService.pullPlate(freeIncubationPos)); - docmd("丢反应板", () -> optScanModuleCtrlService.dropPlate()); + docmd("丢反应板", optScanModuleCtrlService::dropPlate); // plateBoxCtrlService.pushPlateQuick(consumableInfo.group, freeIncubationPos); @@ -328,38 +366,58 @@ public class ExperimentConsistencyTestingService { docmd("样本处理", () -> { - liquidOperationCtrlService.setProjContext(projBuildinInfo, projExtInfoCard); - var preProcessPos = new PreReactionPos(ConsumableType.SmallBottleBuffer, consumableInfo.group, consumableInfo.pos); - //取tip - liquidOperationCtrlService.forceTakeTip(); - //刺破缓冲液 - hbotMoveExCtrlService.moveToLittleBufferPiercePos(consumableInfo.group, consumableInfo.pos); - //取样品 - Assert.isTrue(expectedTubeHolderType.equals(A8kTubeHolderType.BulletTube1P5), "expectedTubeHolderType != BulletTube1P5"); - hbotMoveExCtrlService.moveToSamplePosXY(A8kSamplePos.Bulltube1P5Pos); - liquidOperationCtrlService.takeSample(A8kSamplePos.Bulltube1P5Pos, preProcessPos, takeSampleUl); - //取混合液到预反应位 - liquidOperationCtrlService.takePreReactionLiquidToReation(preProcessPos); + try { + liquidOperationCtrlService.setProjContext(projBuildinInfo, projExtInfoCard); + var preProcessPos = new PreReactionPos(ConsumableType.SmallBottleBuffer, consumableInfo.group, consumableInfo.pos); + //取tip + liquidOperationCtrlService.forceTakeTip(); + //刺破缓冲液 + hbotMoveExCtrlService.moveToLittleBufferPiercePos(consumableInfo.group, consumableInfo.pos); + //取样品 + Assert.isTrue(expectedTubeHolderType.equals(A8kTubeHolderType.BulletTube1P5), "expectedTubeHolderType != BulletTube1P5"); + hbotMoveExCtrlService.moveToSamplePosXY(A8kSamplePos.Bulltube1P5Pos); + liquidOperationCtrlService.takeSample(A8kSamplePos.Bulltube1P5Pos, preProcessPos, takeSampleUl); + //取混合液到预反应位 + liquidOperationCtrlService.takePreReactionLiquidToReation(preProcessPos); + incubationPlateStateMgrService.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60); + } catch (AppException e) { + if (e.getError().eq(A8kEcode.APPE_TAKE_SAMPLE_FAIL)) { + hbotMoveExCtrlService.moveQuickToZero(); + tube.setErrors(ZList.of(e.getError())); + incubationPlateStateMgrService.resetIncubatorPos(freeIncubationPos); + //丢反应板 + optScanModuleCtrlService.forceDropPlate(freeIncubationPos); + UISender.txErrorMsg(log, e, "取样失败"); + } else { + throw e; + } + } + }, () -> { + incubationPlateStateMgrService.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60); }); {//开始孵育 - incubationPlateStateMgrService.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60); } } - private void incubationPlateProcess() throws AppException { + private void incubationPlateProcess(Boolean waittingForAll) throws AppException { do { IncubationSubTank tankPos = incubationPlateStateMgrService.getOneExpiredPlate(); - if (incubationPlateStateMgrService.isHasEnoughIncubationIDLEPos(1) && tankPos == null) { - break; + if (!waittingForAll) { + if (incubationPlateStateMgrService.isHasEnoughIncubationIDLEPos(1) && tankPos == null) { + break; + } + } else { + if (incubationPlateStateMgrService.isAllIncubationSubTanksFree()) { + break; + } } - //拉取反应板到光学模组 - { - //执行动作 + if (tankPos != null) { + //拉取反应板到光学模组 docmd("拉取反应板到光学模块", () -> {optScanModuleCtrlService.pullPlate(tankPos.getPos());}); //设置光学模组状态 @@ -367,21 +425,22 @@ public class ExperimentConsistencyTestingService { optScanModuleStateMgrService.syncProjInfo(tankPos.projBuildinInfo, tankPos.projExtInfoCard); //复位孵育盘状态 incubationPlateStateMgrService.resetIncubatorPos(tankPos.getPos()); - } - //光学扫描 - { + // + //光学扫描 + // + //光学扫描 optScanModuleStateMgrService.changeOptScanModuleStateToScanning(); doOptScan(); //丢板 - docmd("丢弃反应板", () -> {optScanModuleCtrlService.dropPlate();}); + docmd("丢弃反应板", optScanModuleCtrlService::dropPlate); optScanModuleStateMgrService.changeOptScanModuleStateToEmpty(); } - + actionExecutor.sleep(100); } while (true); } @@ -420,7 +479,7 @@ public class ExperimentConsistencyTestingService { private void verifyTubeHolderSettingAndTubeHolderScanResult(TubeHolderSetting tubeHolderSetting, TubeFeedingCtrlService.TubeHolderScanResult scanResult) throws AppException { A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType); - if (expectedTubeHolderType.equals(tubeHolderType)) { + if (!expectedTubeHolderType.equals(tubeHolderType)) { throw AppException.of(A8kEcode.APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT, "请使用子弹头1.5ml试管架"); } diff --git a/src/main/java/a8k/app/engineer/service/qatest/QATemperatureCtrlTestService.java b/src/main/java/a8k/app/engineer/service/qatest/QATemperatureCtrlTestService.java index 2716dfd..a35c853 100644 --- a/src/main/java/a8k/app/engineer/service/qatest/QATemperatureCtrlTestService.java +++ b/src/main/java/a8k/app/engineer/service/qatest/QATemperatureCtrlTestService.java @@ -3,6 +3,7 @@ package a8k.app.engineer.service.qatest; import a8k.app.service.background.SensorDataUpdateService; import a8k.app.service.background.TemperatureCtrlService; import a8k.app.service.setting.AppSettingsMgrService; +import a8k.app.service.statemgr.GStateMgrService; import a8k.app.type.TemperatureRecordPoint; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -22,12 +23,13 @@ public class QATemperatureCtrlTestService { private final TemperatureCtrlService temperatureCtrlService; private final AppSettingsMgrService appSettingsMgrService; private final SensorDataUpdateService sensorDataUpdateService; + private final GStateMgrService gStateMgrService; /** * 修改温度控制目标温度 */ - synchronized public void setTargetVal(Integer targetIncubatorBoxTemperature, Integer targetPlatesBoxTemperature) { + synchronized public void setTargetVal(Integer targetIncubatorBoxTemperature, Integer targetPlatesBoxTemperature) { log.info("changeTemperatureCtrlTargetVal: targetIncubatorBoxTemperature = {}, targetPlatesBoxTemperature = {}", targetIncubatorBoxTemperature, targetPlatesBoxTemperature); appSettingsMgrService.setIncubateBoxTemperature(targetIncubatorBoxTemperature); appSettingsMgrService.setPlateBoxTemperature(targetPlatesBoxTemperature); @@ -49,6 +51,14 @@ public class QATemperatureCtrlTestService { return temperatureCtrlService.getTargetPlatesBoxTemperatureSetVal(); } + synchronized public Double getIncubateBoxTemp() { + return sensorDataUpdateService.getIncubateBoxTemperature(); + } + + synchronized public Double getPlateBoxTemp() { + return sensorDataUpdateService.getPlateBoxTemperature(); + } + /** * 获取孵育盘温度曲线 * @return curve diff --git a/src/main/java/a8k/app/engineer/service/type/TubeExConfig.java b/src/main/java/a8k/app/engineer/service/type/TubeExConfig.java new file mode 100644 index 0000000..2349986 --- /dev/null +++ b/src/main/java/a8k/app/engineer/service/type/TubeExConfig.java @@ -0,0 +1,5 @@ +package a8k.app.engineer.service.type; + +public class TubeExConfig { + public Integer repeatTimes = 1; +} diff --git a/src/main/java/a8k/app/engineer/service/type/TubeHolderExConfig.java b/src/main/java/a8k/app/engineer/service/type/TubeHolderExConfig.java new file mode 100644 index 0000000..261e5d0 --- /dev/null +++ b/src/main/java/a8k/app/engineer/service/type/TubeHolderExConfig.java @@ -0,0 +1,16 @@ +package a8k.app.engineer.service.type; + +import a8k.app.constant.AppConstant; + +import java.util.ArrayList; +import java.util.List; + +public class TubeHolderExConfig { + public List tubeExConfigs = new ArrayList<>(); + + public TubeHolderExConfig() { + for (int i = 0; i < AppConstant.TUBEHOLER_SIZE; i++) { + tubeExConfigs.add(new TubeExConfig()); + } + } +} diff --git a/src/main/java/a8k/app/hardware/driver/CodeScanerDriver.java b/src/main/java/a8k/app/hardware/driver/CodeScanerDriver.java index 3df44d7..59ce537 100644 --- a/src/main/java/a8k/app/hardware/driver/CodeScanerDriver.java +++ b/src/main/java/a8k/app/hardware/driver/CodeScanerDriver.java @@ -27,7 +27,7 @@ public class CodeScanerDriver { } public String pipetteModCodeScannerScanCode() throws AppException { - return pipetteModCodeScannerScanCode(500); + return pipetteModCodeScannerScanCode(300); } public void pipetteModCodeScannerStartScan() throws AppException { diff --git a/src/main/java/a8k/app/service/background/SensorDataUpdateService.java b/src/main/java/a8k/app/service/background/SensorDataUpdateService.java index d053bd2..8b4421f 100644 --- a/src/main/java/a8k/app/service/background/SensorDataUpdateService.java +++ b/src/main/java/a8k/app/service/background/SensorDataUpdateService.java @@ -24,7 +24,6 @@ import java.util.List; public class SensorDataUpdateService { - private final GStateMgrService gStateMgrService; private final TemperatureControlDriver temperatureControlDriver; private final OptScanModuleStateMgrService optScanModuleStateMgrService; @@ -39,6 +38,9 @@ public class SensorDataUpdateService { List incubateBoxTemperatureCurve = new ArrayList<>(); List plateBoxTemperatureCurve = new ArrayList<>(); + Double incubateBoxTemperature = 0.0; + Double plateBoxTemperature = 0.0; + public void setErrorFlag(AppException e) { if (!errorFlag) { appEventBusService.pushAppExceptionEvent(e); @@ -56,11 +58,21 @@ public class SensorDataUpdateService { error = null; } + synchronized public Double getIncubateBoxTemperature() { + return incubateBoxTemperature; + } + + synchronized public Double getPlateBoxTemperature() { + return plateBoxTemperature; + } + + synchronized private void addIncubateBoxTemperatureCurve(Double temperature) { TemperatureRecordPoint point = new TemperatureRecordPoint(); point.tp = System.currentTimeMillis(); point.val = temperature; incubateBoxTemperatureCurve.add(point); + incubateBoxTemperature = temperature; if (incubateBoxTemperatureCurve.size() > 2000) { incubateBoxTemperatureCurve.remove(0); } @@ -68,8 +80,9 @@ public class SensorDataUpdateService { synchronized private void addPlateBoxTemperatureCurve(Double temperature) { TemperatureRecordPoint point = new TemperatureRecordPoint(); - point.tp = System.currentTimeMillis(); - point.val = temperature; + point.tp = System.currentTimeMillis(); + point.val = temperature; + plateBoxTemperature = temperature; plateBoxTemperatureCurve.add(point); if (plateBoxTemperatureCurve.size() > 2000) { plateBoxTemperatureCurve.remove(0); diff --git a/src/main/java/a8k/app/service/background/TemperatureCtrlService.java b/src/main/java/a8k/app/service/background/TemperatureCtrlService.java index 432541e..ce5b8fd 100644 --- a/src/main/java/a8k/app/service/background/TemperatureCtrlService.java +++ b/src/main/java/a8k/app/service/background/TemperatureCtrlService.java @@ -119,6 +119,7 @@ public class TemperatureCtrlService { } + private void startCtrlTemperature(Integer incubatorTemperature, Integer platesBoxTemperature) throws AppException { log.info("start control incubatorTemperature: {},platesBoxTemperature: {}", incubatorTemperature, platesBoxTemperature); temperatureControlDriver.startCtrlTemperature(incubatorTemperature.doubleValue(), platesBoxTemperature.doubleValue()); diff --git a/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java index a8022d7..e1f9355 100644 --- a/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java +++ b/src/main/java/a8k/app/service/lowerctrl/HbotMoveExCtrlService.java @@ -56,6 +56,12 @@ public class HbotMoveExCtrlService { Pos3d tipPos = hbotConsumableExParamMgr.getTipPos(tipGroupPos, index); hbotMoveCtrlService.hbotMoveTo(tipPos); + if (!pipetteCtrlDriver.isHasTip()) { + //TODO:单片机支持移动以mm为单位的距离的方法 + pipetteCtrlDriver.zMotorMoveByBlock(-100); + pipetteCtrlDriver.pipetteInitDeviceBlock(); + } + pipetteCtrlDriver.zMotorMoveToZeroPointQuickBlock(); } @@ -215,7 +221,6 @@ public class HbotMoveExCtrlService { } - // public void moveToProbeSubstanceSamplePos(ConsumableGroup group, Integer off) throws AppException { // hbotBaseMoveExDriver.hbotMoveTo(hbotConsumableParamMgr.getProbeSubstanceSamplePos(group, off)); // } @@ -247,14 +252,13 @@ public class HbotMoveExCtrlService { } - public void moveToSampleStartPos(A8kSamplePos pos) throws AppException { hbotMoveCtrlService.hbotMoveTo(hbotSamplePosParamMgr.getSampleStartPos(pos)); } public void moveToSampleEndPos(A8kSamplePos pos) throws AppException { - Pos3d startpos = hbotSamplePosParamMgr.getSampleStartPos(pos); - Integer endpos = hbotSamplePosParamMgr.getSampleEndPos(pos); + Pos3d startpos = hbotSamplePosParamMgr.getSampleStartPos(pos); + Integer endpos = hbotSamplePosParamMgr.getSampleEndPos(pos); startpos.z = endpos; hbotMoveCtrlService.hbotMoveTo(startpos); } diff --git a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java index ac0c026..fbd2a59 100644 --- a/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java +++ b/src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrlService.java @@ -110,6 +110,7 @@ public class LiquidOperationCtrlService { } while (true) { hbotMoveExCtrlService.takeTip(consumablesMgrService.takeNextTipPos()); + if (gstate.isInMode(DeviceRunMode.RunOnlyMode)) { break; } @@ -339,7 +340,7 @@ public class LiquidOperationCtrlService { private void ldd(Integer startpos, Integer maxpos, Integer p_threshold) throws AppException { log.info("lld: startpos={}, maxpos={}, p_threshold={}", startpos, maxpos, p_threshold); - + pipetteCtrlDriver.zMotorMoveToBlock(startpos); // pipetteCtrlDriver.liquidOperationClearParams(); diff --git a/src/main/java/a8k/app/service/lowerctrl/OptScanModuleCtrlService.java b/src/main/java/a8k/app/service/lowerctrl/OptScanModuleCtrlService.java index 7cacbde..c11aa65 100644 --- a/src/main/java/a8k/app/service/lowerctrl/OptScanModuleCtrlService.java +++ b/src/main/java/a8k/app/service/lowerctrl/OptScanModuleCtrlService.java @@ -97,6 +97,12 @@ public class OptScanModuleCtrlService { stepMotorCtrlDriver.stepMotorEasyMoveToBlock(StepMotorMId.OptModScannerM, optModuleParamsMgr.getOptScanerScandbyPos()); } + public void forceDropPlate(IncubatorPos turntablePosIndex) throws AppException { + dropPlate(); + pullPlate(turntablePosIndex); + dropPlate(); + } + public Integer[] startOptScan(A8kOptType optType, Integer lasterGain, Integer rawScanGain) throws AppException { Integer forwardScanPos = optModuleExtParamsMgr.getOptScanStartPos(optType); diff --git a/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java b/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java index dccc7fa..ed53adb 100644 --- a/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java +++ b/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java @@ -214,6 +214,15 @@ public class IncubationPlateStateMgrService { return list; } + synchronized public Boolean isAllIncubationSubTanksFree() { + for (IncubationSubTank subtank : incubationPlate.subtanks) { + if (!subtank.state.equals(IncubationSubTankState.EMPTY)) { + return false; + } + } + return true; + } + @Scheduled(fixedDelay = 500) synchronized public void updateRemainTime() { diff --git a/src/main/java/a8k/app/service/statemgr/TubeStateMgrService.java b/src/main/java/a8k/app/service/statemgr/TubeStateMgrService.java index 98f6d37..375063f 100644 --- a/src/main/java/a8k/app/service/statemgr/TubeStateMgrService.java +++ b/src/main/java/a8k/app/service/statemgr/TubeStateMgrService.java @@ -176,6 +176,11 @@ public class TubeStateMgrService { return null; } + public synchronized void setTubeHolderDirect(TubeHolder tubeHolder) throws AppException { + this.tubeHolder = tubeHolder; + } + + // // 急诊试管状态管理 // diff --git a/src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java b/src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java index efbe354..92cfbf8 100644 --- a/src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java +++ b/src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java @@ -4,7 +4,10 @@ import a8k.app.utils.ZList; import a8k.extui.page.debug.*; import a8k.extui.page.driver.*; import a8k.extui.page.extapp.*; +import a8k.extui.page.extapp.P02A8kTemperaturaVerfication; import a8k.extui.page.extapp.debug_assistant.IDCardDataGeneratorPage; +import a8k.extui.page.extapp.profession_test.ExperimentConsistencyTestingPage; +import a8k.extui.page.extapp.profession_test.P01PipetteGunVerification; import a8k.extui.page.extsetting.db.A8kSubModuleParameterInitDebugPage; import a8k.extui.page.extsetting.db.DeviceActionParameterSettingPage; import a8k.extui.page.extsetting.db.ProjInfoMgrPage; @@ -140,7 +143,8 @@ public class ExtApiPageGroupCfgMgr { )), new Menu("过检专用", ZList.of( new Menu(P01PipetteGunVerification.class, "移液枪验证"), - new Menu(P02A8kTemperaturaVerfication.class, "温度控制验证") + new Menu(P02A8kTemperaturaVerfication.class, "温度控制验证"), + new Menu(ExperimentConsistencyTestingPage.class, "一致性测试") )), new Menu("坐标测量", ZList.of( new Menu(HbotPosMeasurePage.class, "HBOT测量(电控)"), diff --git a/src/main/java/a8k/extui/page/extapp/P01PipetteGunVerification.java b/src/main/java/a8k/extui/page/extapp/P01PipetteGunVerification.java deleted file mode 100644 index 58c1576..0000000 --- a/src/main/java/a8k/extui/page/extapp/P01PipetteGunVerification.java +++ /dev/null @@ -1,228 +0,0 @@ -package a8k.extui.page.extapp; - -import a8k.app.constant.AppConstant; -import a8k.app.service.lowerctrl.LiquidOperationCtrlService; -import a8k.app.service.param.exparam.HbotConsumableExParamMgr; -import a8k.app.service.param.hbotpos.HbotTipPosMgr; -import a8k.app.service.param.pipetteparam.PipetteGunExParamMgr; -import a8k.extui.mgr.ExtApiPageMgr; -import a8k.extui.type.ExtUIPageCfg; -import a8k.app.hardware.type.LldType; -import a8k.app.service.lowerctrl.HbotMoveExCtrlService; -import a8k.app.hardware.driver.PipetteCtrlDriver; -import a8k.app.hardware.type.PipetteRegIndex; -import a8k.app.service.lowerctrl.HbotMoveCtrlService; -import a8k.app.type.a8k.ConsumableGroup; -import a8k.app.type.a8k.Pos3d; -import a8k.app.type.exception.AppException; -import a8k.app.type.a8k.pos.TipPos; -import a8k.app.type.a8k.pos.TipGroupPos; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class P01PipetteGunVerification { - @Resource - HbotTipPosMgr hbotTipPosMgr; - - @Resource - PipetteCtrlDriver pipetteCtrlDriver; - @Resource - HbotMoveCtrlService hbotMoveCtrlService; - @Resource - HbotMoveExCtrlService hbotMoveExCtrlService; - - @Resource - HbotConsumableExParamMgr hbotConsumableExParamMgr; - - @Resource - PipetteGunExParamMgr pipetteGunExParamMgr; - - @Resource - ExtApiPageMgr extApiPageMgr; - - Integer tipNum = 0; - Integer liquidPos = null; - Boolean stopFlag = false; - - @PostConstruct - void init() { - ExtUIPageCfg page = new ExtUIPageCfg(this); - page.newGroup("基础"); - page.addFunction("测试准备", this::initTestMode); - page.addFunction("停止测试", this::stopTest); - page.addFunction("设置校准系数", this::calibration) - .setParamVal("coefficientA", () -> pipetteGunExParamMgr.getCoefficientA()) - .setParamVal("coefficientB", () -> pipetteGunExParamMgr.getCoefficientB()); - page.newGroup("测试0"); - page.addFunction("取一次10ul", this::aspirate10ul); - page.addFunction("取一次75ul", this::aspirate75ul); - page.newGroup("测试1"); - page.addFunction("取一次5ul", this::aspirate5ul); - page.addFunction("取一次30ul", this::aspirate30ul); - page.addFunction("取一次50ul", this::aspirate50ul); - page.addFunction("停止测试", this::stopTest); - - extApiPageMgr.addPage(page); - } - - public void pipetteGunInit() throws AppException { - pipetteCtrlDriver.pipetteInitDeviceBlock(); - } - - public void initTestMode() throws AppException { - pipetteCtrlDriver.zMotorEnable(1); - hbotMoveCtrlService.enable(1); - pipetteCtrlDriver.zMotorMoveZeroBlock(); - hbotMoveCtrlService.moveToZero(); - hbotMoveCtrlService.hbotMoveTo(hbotTipPosMgr.getDropTipPos()); - pipetteGunInit(); - hbotMoveCtrlService.hbotMoveTo(new Pos3d(0, 0, 0)); - tipNum = AppConstant.TIP_NUM; - } - - public void stopTest() throws AppException { - pipetteCtrlDriver.zMotorEnable(0); - hbotMoveCtrlService.enable(0); - } - - public void calibration(Double coefficientA, Double coefficientB) { - pipetteGunExParamMgr.setVolumeCalibrationCoefficient(coefficientA, coefficientB); - } - - - Boolean takeOneTip() throws AppException { - hbotMoveCtrlService.hbotMoveTo(hbotTipPosMgr.getDropTipPos()); - pipetteGunInit(); - TipPos tipPos = new TipPos(); - tipPos.group = TipGroupPos.TipG1; - if (tipNum == 0) { - tipNum = 120; - } - - tipPos.index = AppConstant.TIP_NUM - tipNum; - tipNum--; - log.info(" 取TIP {}", tipPos); - return hbotMoveExCtrlService.takeTipNoCheck(tipPos.group, tipPos.index); - } - - void takeTip() throws AppException { - while (!pipetteCtrlDriver.isHasTip()) { - if (takeOneTip()) { - break; - } - } - } - - public void pumpMoveTo(Integer pumpvmax, Double ul) throws AppException { - pipetteCtrlDriver.liquidOperationClearParams(); - pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, pumpvmax); - pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipettePumpMoveTo(ul); - } - - public Integer lld() throws AppException { - liquidPos = 0; - hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG1); - pipetteCtrlDriver.zMotorMoveToBlock(0); - pumpMoveTo(8000, 0.0); - pumpMoveTo(300, 100.0); - pumpMoveTo(8000, 0.0); - pumpMoveTo(300, 50.0); - - Pos3d toPos = hbotConsumableExParamMgr.getLargeBufferSamplePos(ConsumableGroup.CG1); - Pos3d maxPos = hbotConsumableExParamMgr.getLargeBufferSamplePosEnd(ConsumableGroup.CG1); - pipetteCtrlDriver.zMotorMoveToBlock(toPos.z); - pipetteCtrlDriver.liquidOperationClearParams(); - pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 30); - pipetteCtrlDriver.liquidOperationSetZMotorRunParams(toPos.z, maxPos.z, 60 * 80 / LiquidOperationCtrlService.helicalPitch); - pipetteCtrlDriver.liquidOperationFreshParams(); - pipetteCtrlDriver.pipetteLld(LldType.kplld, 0, 30); - if (pipetteCtrlDriver.lldIsDetectLiquid()) { - liquidPos = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos); - } - pipetteCtrlDriver.zMotorMoveToBlock(0); - pumpMoveTo(8000, 0.0); - return liquidPos; - } - - public void takeLiquid(Double ul) throws AppException { - hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG1); - pipetteCtrlDriver.zMotorMoveToBlock(0); - pumpMoveTo(8000, 0.0); - pumpMoveTo(8000, 150.0); - pipetteCtrlDriver.zMotorMoveToBlock(liquidPos); - pipetteCtrlDriver.liquidOperationClearParams(); - pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 100); - pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, 300, 10 * 80 / LiquidOperationCtrlService.helicalPitch); - pipetteCtrlDriver.liquidOperationFreshParams(); - ul = pipetteGunExParamMgr.calibrateVolume(ul); - log.info("取液体 {}", ul); - pipetteCtrlDriver.pipetteAspirate(ul); - pipetteCtrlDriver.zMotorMoveToBlock(0); - } - - public void distributeLiquid() throws AppException { - hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG6); - pipetteCtrlDriver.zMotorMoveToBlock(50); - pumpMoveTo(8000, 0.0); - pipetteCtrlDriver.zMotorMoveToBlock(0); - } - - public void resetPos() throws AppException { - hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG2); - } - - public void aspirate10ul() throws AppException { - takeTip(); - lld(); - if (liquidPos == 0) - throw AppException.ofAECodeError("未检测到液体"); - takeLiquid(10.0); - distributeLiquid(); - resetPos(); - } - - public void aspirate75ul() throws AppException { - takeTip(); - lld(); - if (liquidPos == 0) - throw AppException.ofAECodeError("未检测到液体"); - takeLiquid(75.0); - distributeLiquid(); - resetPos(); - } - - public void aspirate5ul() throws AppException { - takeTip(); - lld(); - if (liquidPos == 0) - throw AppException.ofAECodeError("未检测到液体"); - takeLiquid(5.0); - distributeLiquid(); - resetPos(); - } - - public void aspirate30ul() throws AppException { - takeTip(); - lld(); - if (liquidPos == 0) - throw AppException.ofAECodeError("未检测到液体"); - takeLiquid(30.0); - distributeLiquid(); - resetPos(); - } - - public void aspirate50ul() throws AppException { - takeTip(); - lld(); - if (liquidPos == 0) - throw AppException.ofAECodeError("未检测到液体"); - takeLiquid(50.0); - distributeLiquid(); - resetPos(); - } -} diff --git a/src/main/java/a8k/extui/page/extapp/profession_test/ExperimentConsistencyTestingPage.java b/src/main/java/a8k/extui/page/extapp/profession_test/ExperimentConsistencyTestingPage.java new file mode 100644 index 0000000..0899809 --- /dev/null +++ b/src/main/java/a8k/extui/page/extapp/profession_test/ExperimentConsistencyTestingPage.java @@ -0,0 +1,97 @@ +package a8k.extui.page.extapp.profession_test; + + +import a8k.app.engineer.service.qatest.ExperimentConsistencyTestingService; +import a8k.app.engineer.service.type.TubeExConfig; +import a8k.app.engineer.service.type.TubeHolderExConfig; +import a8k.app.type.exception.AppException; +import a8k.extui.mgr.ExtApiPageMgr; +import a8k.extui.type.ExtApiStatu; +import a8k.extui.type.ExtUIPageCfg; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +@RequiredArgsConstructor +public class ExperimentConsistencyTestingPage { + + private final ExtApiPageMgr extApiPageMgr; + private final ExperimentConsistencyTestingService experimentConsistencyTestingService; + + @ExtApiStatu(name = "", group = "试管1", order = 1) + public TubeExConfig getTubeExConfig1() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(0); + } + + @ExtApiStatu(name = "", group = "试管2", order = 2) + public TubeExConfig getTubeExConfig2() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(1); + } + + @ExtApiStatu(name = "", group = "试管3", order = 3) + public TubeExConfig getTubeExConfig3() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(2); + } + + @ExtApiStatu(name = "", group = "试管4", order = 4) + public TubeExConfig getTubeExConfig4() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(3); + } + + @ExtApiStatu(name = "", group = "试管5", order = 5) + public TubeExConfig getTubeExConfig5() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(4); + } + + @ExtApiStatu(name = "", group = "试管6", order = 6) + public TubeExConfig getTubeExConfig6() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(5); + } + + @ExtApiStatu(name = "", group = "试管7", order = 7) + public TubeExConfig getTubeExConfig7() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(6); + } + + @ExtApiStatu(name = "", group = "试管8", order = 8) + public TubeExConfig getTubeExConfig8() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(7); + } + + @ExtApiStatu(name = "", group = "试管9", order = 9) + public TubeExConfig getTubeExConfig9() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(8); + } + + @ExtApiStatu(name = "", group = "试管10", order = 10) + public TubeExConfig getTubeExConfig10() { + return experimentConsistencyTestingService.getTubeExConfig().tubeExConfigs.get(9); + } + + + @PostConstruct + void init() { + ExtUIPageCfg page = new ExtUIPageCfg(this); + page.newGroup("配置"); + page.addFunction("设置配置", this::setTubeRepeatTime).setParamVal("tubeOff", () -> 1).setParamVal("repeatTimes", () -> 1); + page.newGroup("基础"); + page.addFunction("开始测试", this::startTest); + extApiPageMgr.addPage(page); + } + + public void startTest() throws AppException { + experimentConsistencyTestingService.startTest(); + } + + public void setTubeRepeatTime(Integer tubeOff, Integer repeatTimes) { + tubeOff = tubeOff + 1; + TubeHolderExConfig tubeHolderExConfig = experimentConsistencyTestingService.getTubeExConfig(); + tubeHolderExConfig.tubeExConfigs.get(tubeOff).repeatTimes = repeatTimes; + log.info("setTubeRepeatTime: tubeOff = {}, repeatTimes = {}", tubeOff, repeatTimes); + } + + +} diff --git a/src/main/java/a8k/extui/page/extapp/profession_test/P01PipetteGunVerification.java b/src/main/java/a8k/extui/page/extapp/profession_test/P01PipetteGunVerification.java new file mode 100644 index 0000000..11dd5eb --- /dev/null +++ b/src/main/java/a8k/extui/page/extapp/profession_test/P01PipetteGunVerification.java @@ -0,0 +1,80 @@ +package a8k.extui.page.extapp.profession_test; + +import a8k.app.constant.AppConstant; +import a8k.app.engineer.service.qatest.LiquidAbsorptionAndDistributionTestService; +import a8k.app.service.lowerctrl.LiquidOperationCtrlService; +import a8k.app.service.param.exparam.HbotConsumableExParamMgr; +import a8k.app.service.param.hbotpos.HbotTipPosMgr; +import a8k.app.service.param.pipetteparam.PipetteGunExParamMgr; +import a8k.extui.mgr.ExtApiPageMgr; +import a8k.extui.type.ExtUIPageCfg; +import a8k.app.hardware.type.LldType; +import a8k.app.service.lowerctrl.HbotMoveExCtrlService; +import a8k.app.hardware.driver.PipetteCtrlDriver; +import a8k.app.hardware.type.PipetteRegIndex; +import a8k.app.service.lowerctrl.HbotMoveCtrlService; +import a8k.app.type.a8k.ConsumableGroup; +import a8k.app.type.a8k.Pos3d; +import a8k.app.type.exception.AppException; +import a8k.app.type.a8k.pos.TipPos; +import a8k.app.type.a8k.pos.TipGroupPos; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +@RequiredArgsConstructor +public class P01PipetteGunVerification { + private final PipetteGunExParamMgr pipetteGunExParamMgr; + private final ExtApiPageMgr extApiPageMgr; + private final LiquidAbsorptionAndDistributionTestService liquidAbsorptionAndDistributionTestService; + + + @PostConstruct + void init() { + ExtUIPageCfg page = new ExtUIPageCfg(this); + page.newGroup("基础"); + page.addFunction("设置校准系数", this::setCalibrationParam) + .setParamVal("coefficientA", pipetteGunExParamMgr::getCoefficientA) + .setParamVal("coefficientB", pipetteGunExParamMgr::getCoefficientB); + page.newGroup("测试0"); + page.addFunction("取一次10ul", this::aspirate10ul); + page.addFunction("取一次75ul", this::aspirate75ul); + page.newGroup("测试1"); + page.addFunction("取一次5ul", this::aspirate5ul); + page.addFunction("取一次30ul", this::aspirate30ul); + page.addFunction("取一次50ul", this::aspirate50ul); + extApiPageMgr.addPage(page); + } + + + public void setCalibrationParam(Double coefficientA, Double coefficientB) { + pipetteGunExParamMgr.setVolumeCalibrationCoefficient(coefficientA, coefficientB); + } + + + public void aspirate10ul() throws AppException { + liquidAbsorptionAndDistributionTestService.absorbAndDistribute(10); + } + + public void aspirate75ul() throws AppException { + liquidAbsorptionAndDistributionTestService.absorbAndDistribute(75); + } + + public void aspirate5ul() throws AppException { + liquidAbsorptionAndDistributionTestService.absorbAndDistribute(5); + + } + + public void aspirate30ul() throws AppException { + liquidAbsorptionAndDistributionTestService.absorbAndDistribute(30); + } + + public void aspirate50ul() throws AppException { + liquidAbsorptionAndDistributionTestService.absorbAndDistribute(50); + + } +} diff --git a/src/main/java/a8k/extui/page/extapp/P02A8kTemperaturaVerfication.java b/src/main/java/a8k/extui/page/extapp/profession_test/P02A8kTemperaturaVerfication.java similarity index 100% rename from src/main/java/a8k/extui/page/extapp/P02A8kTemperaturaVerfication.java rename to src/main/java/a8k/extui/page/extapp/profession_test/P02A8kTemperaturaVerfication.java