Browse Source

recode

master
zhaohe 2 months ago
parent
commit
c0044d905a
  1. 6
      src/main/java/a8k/app/dao/type/combination/ProjBuildInInfo.java
  2. 732
      src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java
  3. 23
      src/main/java/a8k/app/hardware/type/A8kEcode.java
  4. 5
      src/main/java/a8k/app/i18n/Internationalization.java
  5. 9
      src/main/java/a8k/app/service/analyzer/A8kIdCardDataParseService.java
  6. 6
      src/main/java/a8k/app/service/analyzer/ConsumableStateAnalyzerService.java
  7. 4
      src/main/java/a8k/app/service/background/ProjIDCardCtrlAndMonitorService.java
  8. 4
      src/main/java/a8k/app/service/data/ProjIdCardInfoMgrService.java
  9. 24
      src/main/java/a8k/app/service/data/ProjInfoMgrService.java
  10. 6
      src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrService.java
  11. 6
      src/main/java/a8k/app/service/lowerctrl/OptScanModuleCtrlService.java
  12. 91
      src/main/java/a8k/app/service/lowerctrl/TubeFeedingCtrlService.java
  13. 6
      src/main/java/a8k/app/service/lowerctrl/TurnableMoveCtrlService.java
  14. 7
      src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java
  15. 94
      src/main/java/a8k/app/service/module/InFeedingCtrlModule.java
  16. 5
      src/main/java/a8k/app/service/module/IncubationPlateCtrlModule.java
  17. 7
      src/main/java/a8k/app/service/module/SamplePreProcessModule.java
  18. 34
      src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgr.java
  19. 4
      src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgr.java
  20. 35
      src/main/java/a8k/app/service/statemgr/TubeStateMgr.java
  21. 4
      src/main/java/a8k/app/service/utils/ProjInfoReader.java
  22. 8
      src/main/java/a8k/app/service/utils/ProjInfoUtils.java
  23. 3
      src/main/java/a8k/app/teststate/TestStateMgrService.java
  24. 6
      src/main/java/a8k/app/type/a8k/proj/ProjInfo.java
  25. 5
      src/main/java/a8k/app/type/a8k/state/IncubationSubTank.java
  26. 4
      src/main/java/a8k/app/type/a8k/state/OptScanModuleState.java
  27. 11
      src/main/java/a8k/app/type/a8k/state/ProjectPreProcessContext.java
  28. 6
      src/main/java/a8k/app/type/a8k/state/Tube.java
  29. 8
      src/main/java/a8k/app/type/a8k/state/TubeInfo.java
  30. 12
      src/main/java/a8k/app/type/a8k/state/enumtype/TubeState.java
  31. 22
      src/main/java/a8k/app/type/misc/TubeHolderScanResult.java
  32. 24
      src/main/java/a8k/app/type/misc/TubeScanResult.java
  33. 4
      src/main/java/a8k/extui/factory/ProjExtInfoCardFactory.java
  34. 6
      src/main/java/a8k/extui/page/debug/P01ProjInfoDebugPage.java
  35. 6
      src/main/java/a8k/extui/page/extapp/A8kOptVerification.java
  36. 4
      src/main/java/a8k/extui/page/extapp/OptModuleParamCalibration.java
  37. 25
      src/main/java/a8k/extui/page/extapp/UsrOperationSimulationPage.java
  38. 6
      src/main/java/a8k/extui/page/extapp/debug_assistant/IDCardDataGeneratorPage.java
  39. 6
      src/main/java/a8k/extui/page/extsetting/db/ProjInfoMgrPage.java
  40. 15
      src/main/java/a8k/extui/page/test/verification/P30InfeedAndPreProcessPosVerificationPage.java
  41. 5
      src/main/java/a8k/extui/page/test/verification/P50VerificationScriptPage.java

6
src/main/java/a8k/app/dao/type/combination/ProjBuildinInfo.java → src/main/java/a8k/app/dao/type/combination/ProjBuildInInfo.java

@ -19,7 +19,7 @@ import java.util.List;
*/
@Slf4j
@Data
public class ProjBuildinInfo implements Serializable {
public class ProjBuildInInfo implements Serializable {
/*基础配置*/
public Integer projId; //项目index
public String projName; //项目名称
@ -49,7 +49,7 @@ public class ProjBuildinInfo implements Serializable {
public List<OptCfg> optcfg;
public ProjBuildinInfo() {} //for json
public ProjBuildInInfo() {} //for json
public A8kOptType getOptType(Integer subProjIndex) {
for (OptCfg optCfg : optcfg) {
@ -81,7 +81,7 @@ public class ProjBuildinInfo implements Serializable {
}
public ProjBuildinInfo(ProjectBaseInfo baseInfo, List<OptCfg> optInfos) {
public ProjBuildInInfo(ProjectBaseInfo baseInfo, List<OptCfg> optInfos) {
//遍历所有ProjectBaseInfo字段赋值给ProjBuildinInfo
for (var field : baseInfo.getClass().getDeclaredFields()) {
if (field.getName().equals("id")) {

732
src/main/java/a8k/app/engineer/service/qatest/ExperimentConsistencyTestingService.java

@ -2,7 +2,7 @@ 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.combination.ProjBuildInInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.dao.type.db.ReactionReport;
import a8k.app.engineer.service.executor.EngineerModeActionExecutor;
@ -37,6 +37,8 @@ import a8k.app.type.a8k.state.Tube;
import a8k.app.type.error.AppError;
import a8k.app.type.exception.AppException;
import a8k.app.type.exception.EngineerTaskBreakException;
import a8k.app.type.misc.TubeHolderScanResult;
import a8k.app.type.misc.TubeScanResult;
import a8k.app.type.param.type.A8kSamplePos;
import a8k.app.type.ui.TubeHolderSetting;
import a8k.app.type.ui.TubeSetting;
@ -94,17 +96,17 @@ public class ExperimentConsistencyTestingService {
/*
* 控制器
*/
final private TubePreProcesModuleCtrlService tubePreProcesModuleCtrlService;
final private TubePreProcesModuleCtrlService tubePreProcesModuleCtrlService;
final private TubeFeedingCtrlService tubeFeedingCtrlService;
final private TubePreProcessModuleExCtrlService tubePreProcessModuleExCtrlService;
final private OptScanModuleCtrlService optScanModuleCtrlService;
final private PlateBoxCtrlService plateBoxCtrlService;
final private TurnableMoveCtrlService turnableMoveCtrlService;
final private LiquidOperationCtrService liquidOperationCtrService;
final private HbotMoveExCtrlService hbotMoveExCtrlService;
private final OptModuleDriver optModuleDriver;
private final HbotMoveCtrlService hbotMoveCtrlService;
private final TipOperationCtrlModule tipOperationCtrlModule;
final private PlateBoxCtrlService plateBoxCtrlService;
final private TurnableMoveCtrlService turnableMoveCtrlService;
final private LiquidOperationCtrService liquidOperationCtrService;
final private HbotMoveExCtrlService hbotMoveExCtrlService;
private final OptModuleDriver optModuleDriver;
private final HbotMoveCtrlService hbotMoveCtrlService;
private final TipOperationCtrlModule tipOperationCtrlModule;
private TubeHolderSetting curTubeHolderSetting;
private A8kSamplePos samplePos;
@ -179,362 +181,362 @@ public class ExperimentConsistencyTestingService {
log.info("开始试剂实验一致性检测");
curTubeHolderSetting = tubeHolderSetting;
actionExecutor.start(this::action);
}
void docmd(String mark, A8kCmdRunnable runnable, A8kCmdRunnable virtualRunable) throws AppException {
actionExecutor.sleep(2);
actionExecutor.docmd(mark, runnable, virtualRunable);
}
void docmd(String mark, A8kCmdRunnable runnable) throws AppException {
UISender.txInfoMsg(log, mark);
actionExecutor.docmd(mark, runnable);
}
public void action() {
try {
doAction();
} catch (Exception e) {
processException(e);
}
}
public void processException(Exception e) {
try {
log.error("Catch exception: ", e);
if (!(e instanceof EngineerTaskBreakException)) {
UISender.txErrorPrompt(e);
}
//
// Action
//
if (actionExecutor.isInRealMode()) {
optScanModuleCtrlService.dropPlate();
tipOperationCtrlModule.dropTip();
tubeFeedingCtrlService.ejectTubeHolder();
List<IncubationSubTank> all = incubationPlateStateMgr.getAllNotFreeIncubationSubTanks();
for (IncubationSubTank notFreeTank : all) {
optScanModuleCtrlService.pullPlate(notFreeTank.pos);
optScanModuleCtrlService.dropPlate();
}
}
//
// State
//
optScanModuleStateMgr.changeOptScanModuleStateToEmpty();
incubationPlateStateMgr.resetAll();
} catch (AppException ex) {
log.error("Catch exception: ", e);
UISender.txErrorPrompt(e);
gStateMgrService.setFatalError(ex.error);
} catch (Exception ex) {
log.error("Catch exception: ", e);
UISender.txErrorPrompt(e);
gStateMgrService.setFatalError(new AppError(A8kEcode.SYS_EXCEPTION, ex.getMessage()));
}
}
Boolean hasTubeHolder;
TubeFeedingCtrlService.TubeHolderScanResult scanResult;
public void doAction() throws AppException {
/*
* 1. 核对是否存在试管配置是否只有一个
* 2. 核对耗材是否充足
*
*
* 1. 入料
* 2. 核对试管架类型
*
* Loop
* 1. 样本准备
*
* Loop
* 1. 检查孵育盘是否有空闲位没有空闲位则等待空闲位
* 2. 检查是否有孵育完成的样本 有孵育完成的样本则进行光学扫描
* 3. 入板
* 4. 取样
* 5. 预反应
* 6. 滴定
*
* End:
* 1. 等待所有反应板孵育完成
*/
//入料
hasTubeHolder = false;
docmd("入料", () -> {
hasTubeHolder = tubeFeedingCtrlService.enterTubeHolder();
}, () -> hasTubeHolder = true);
if (!hasTubeHolder) {
throw AppException.of(A8kEcode.ERROR_OPERATION, "入料超时,未检测到试管架");
}
//扫描试管架
scanResult = null;
docmd("扫描试管架", () -> {
scanResult = tubeFeedingCtrlService.scanTubeHodler();
}, () -> {
scanResult = new TubeFeedingCtrlService.TubeHolderScanResult();
for (int i = 0; i < curTubeHolderSetting.tubeSettings.length; i++) {
scanResult.tube[i] = new TubeFeedingCtrlService.TubesScanResult();
if (!curTubeHolderSetting.tubeSettings[i].projId.isEmpty()) {
scanResult.tube[i].isTubeExist = true;
}
}
});
//核对试管架信息
verifyTubeHolderSettingAndTubeHolderScanResult(curTubeHolderSetting, scanResult);
//
A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType);
if (A8kTubeHolderType.BulletTube1P5.equals(tubeHolderType)) {
samplePos = A8kSamplePos.Bulltube1P5Pos;
} else if (A8kTubeHolderType.BulletTube0P5.equals(tubeHolderType)) {
samplePos = A8kSamplePos.Bulltube0P5Pos;
} else {
throw AppException.of(A8kEcode.APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT, "请使用子弹头1.5ml或者子弹头0.5ml试管架");
}
//构建试管架
// setTubeHolderDirect
for (int tubeoff = 0; tubeoff < curTubeHolderSetting.tubeSettings.length; tubeoff++) {
TubeSetting tubeSetting = curTubeHolderSetting.tubeSettings[tubeoff];
if (tubeSetting.projId.isEmpty()) {
continue;
}
Assert.isTrue(scanResult.tube[tubeoff].isTubeExist, String.format("位置[%d]未放入是试管", tubeoff + 1));
//移动试管架到预处理位置
int finalTubeoff = tubeoff;
UISender.txInfoMsg(log, "开始处理第%d个试管", finalTubeoff + 1);
docmd("移动试管到处理位", () -> tubeFeedingCtrlService.moveTubeToPreProcessPos(finalTubeoff));
for (int j = 0; j < getRepeatTimes(tubeoff); j++) {
//尝试处理孵育完成的反应板
incubationPlateProcess(false);
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(expectedProjId);
//申请耗材
var consumableInfo = consumablesMgrService.reserveConsumable(projBuildinInfo.reactionFlowType, expectedProjId);
if (consumableInfo == null) {
throw AppException.of(A8kEcode.CODEERROR, "耗材不足?"); //理论上开始阶段已经核对过了耗材数量此时应该不会不足
}
consumablesMgrService.useReserveConsumable(consumableInfo);
//构造项目信息
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(tubeoff);
tube.setIsHighTube(false);
tube.setIsEmergency(false);
tube.setBloodType(tubeSetting.bloodType);
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);
//处理试管
processTube(tube, tubeoff, consumableInfo, tubeSetting);
if (!tube.getErrors().isEmpty()) {
log.warn("样本异常,跳过当前样本");
UISender.txErrorMsg(log, tube.getErrors().getFirst(), "样本异常,跳过当前样本");
break;
}
docmd("HBOT复位", hbotMoveExCtrlService::moveQuickToZero);
}
}
tubeFeedingCtrlService.ejectTubeHolder();
incubationPlateProcess(true);
incubationPlateStateMgr.resetAll();
UISender.txInfoPrompt(log, "试剂实验一致性检测完成");
}
private void processTube(Tube tube, Integer offset, ConsumableInfo consumableInfo, TubeSetting tubeSetting) throws AppException {
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(expectedProjId);
ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(consumableInfo.lotid);
//拉取一个板夹到孵育盘
var freeIncubationPos = incubationPlateStateMgr.takeOneIncubationIDLEPos(
(IncubatorPos pos) -> {
incubationPlateStateMgr.syncProjInfo(pos, projBuildinInfo, projExtInfoCard);
incubationPlateStateMgr.syncSampleInfo(pos, tube.getSampleInfo());
}
);
//强制清空一下光学模组和孵育盘
// optScanModuleCtrlService.dropPlate();
// optScanModuleCtrlService.pullPlate(freeIncubationPos);
// optScanModuleCtrlService.dropPlate();
docmd("丢反应板", optScanModuleCtrlService::dropPlate);
docmd("拉取反应板", () -> optScanModuleCtrlService.pullPlate(freeIncubationPos));
docmd("丢反应板", optScanModuleCtrlService::dropPlate);
// plateBoxCtrlService.pushPlateQuick(consumableInfo.group, freeIncubationPos);
docmd("推入新的反应板", () -> plateBoxCtrlService.pushPlateQuick(consumableInfo.group, freeIncubationPos));
//移动当前板夹到滴定位
// turnableMoveCtrlService.trunableMoveToDropLiquidPos(freeIncubationPos);
docmd("移动到滴定位", () -> turnableMoveCtrlService.trunableMoveToDropLiquidPos(freeIncubationPos));
docmd("样本处理", () -> {
try {
liquidOperationCtrService.setProjContext(projBuildinInfo, projExtInfoCard);
var preProcessPos = new PreReactionPos(ConsumableType.SmallBottleBuffer, consumableInfo.group, consumableInfo.pos);
//取tip
tipOperationCtrlModule.tryTakeTip(() -> !actionExecutor.isStopping());
actionExecutor.sleep(1);
//刺破缓冲液
hbotMoveExCtrlService.moveToLittleBufferPiercePos(consumableInfo.group, consumableInfo.pos);
//取样品
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");
liquidOperationCtrService.takeSampleToPreReactionPos(samplePos, preProcessPos, takeSampleUl);
actionExecutor.sleep(1);
//取混合液到预反应位
liquidOperationCtrService.takePreReactionLiquid(preProcessPos);
liquidOperationCtrService.dropLiquidToReactionPlate();
actionExecutor.sleep(1);
incubationPlateStateMgr.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60);
actionExecutor.sleep(1);
} catch (AppException e) {
if (e.getError().eq(A8kEcode.APPE_TAKE_SAMPLE_FAIL)) {
hbotMoveExCtrlService.moveQuickToZero();
tube.setErrors(ZList.of(e.getError()));
incubationPlateStateMgr.resetIncubatorPos(freeIncubationPos);
//丢反应板
optScanModuleCtrlService.forceDropPlate(freeIncubationPos);
UISender.txErrorMsg(log, e, "取样失败");
} else {
throw e;
}
}
}, () -> {
incubationPlateStateMgr.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60);
});
{//开始孵育
}
}
private void incubationPlateProcess(Boolean waittingForAll) throws AppException {
do {
IncubationSubTank tankPos = incubationPlateStateMgr.getOneExpiredPlate();
if (!waittingForAll) {
if (incubationPlateStateMgr.isHasEnoughIncubationIDLEPos(1) && tankPos == null) {
break;
}
} else {
if (incubationPlateStateMgr.isAllIncubationSubTanksFree()) {
break;
}
}
if (tankPos != null) {
//拉取反应板到光学模组
docmd("拉取反应板到光学模块", () -> {optScanModuleCtrlService.pullPlate(tankPos.getPos());});
//设置光学模组状态
optScanModuleStateMgr.changeOptScanModuleStateToPlateIsReady(tankPos.projInfo, tankPos.toSampleInfo());
optScanModuleStateMgr.syncProjInfo(tankPos.projBuildinInfo, tankPos.projExtInfoCard);
//复位孵育盘状态
incubationPlateStateMgr.resetIncubatorPos(tankPos.getPos());
//
//光学扫描
//
//光学扫描
optScanModuleStateMgr.changeOptScanModuleStateToScanning();
doOptScan();
//丢板
docmd("丢弃反应板", optScanModuleCtrlService::dropPlate);
optScanModuleStateMgr.changeOptScanModuleStateToEmpty();
}
actionExecutor.sleep(100);
} while (true);
}
private void doOptScan() throws AppException {
/*
* HsCrp只有一个项目
*/
Assert.isTrue(Objects.equals(expectedProjId, 1), "1 != expectedProjId");
int subProjIndex = 0;
A8kOptType optType = optScanModuleStateMgr.getOptScanModule().getProjBuildinInfo().getOptType(subProjIndex);
var buildInInfo = optScanModuleStateMgr.getOptScanModule().getProjBuildinInfo();
SampleInfo sampleInfo = optScanModuleStateMgr.getOptScanModule().getSampleInfo();
ProjInfo projInfo = optScanModuleStateMgr.getOptScanModule().getProjInfo();
// a8kOptPeakInfo
docmd("光学扫描", () -> {
OptScanResult optScanResult = optScanModuleCtrlService.optScan(buildInInfo, subProjIndex);
ReactionReport.ReactionResult result = A8kPeakAnalyzer.analysisPeakInfo(sampleInfo, projInfo, subProjIndex, optScanResult.analysResult);
log.info("光学扫描结果: {}", result);
reactionRecordMgrService.addRecord(optScanModuleStateMgr.getOptScanModule().getSampleInfo(), projInfo, ZList.of(optScanResult), ZList.of(result));
}
, () -> {
OS.hsleep(1000);
}
);
}
/*
* Utils
*/
private void verifyTubeHolderSettingAndTubeHolderScanResult(TubeHolderSetting tubeHolderSetting, TubeFeedingCtrlService.TubeHolderScanResult scanResult) throws AppException {
A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType);
if (!tubeHolderType.equals(A8kTubeHolderType.BulletTube1P5) && !tubeHolderType.equals(A8kTubeHolderType.BulletTube0P5)) {
throw AppException.of(A8kEcode.APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT, "请使用子弹头1.5ml或者子弹头0.5ml试管架");
}
for (int i = 0; i < tubeHolderSetting.tubeSettings.length; i++) {
TubeSetting tubeSetting = tubeHolderSetting.tubeSettings[i];
if (tubeSetting.projId.isEmpty() && !scanResult.tube[i].isTubeExist) {
continue;
}
if (tubeSetting.projId.isEmpty()) {
throw AppException.of(A8kEcode.APPE_TUBEHOLDER_SETTING_ERROR, String.format("试管[%d]缺少项目配置", i + 1));
}
if (!scanResult.tube[i].isTubeExist) {
throw AppException.of(A8kEcode.APPE_TUBEHOLDER_SETTING_ERROR, String.format("位置[%d]未放入是试管", i + 1));
}
}
// actionExecutor.start(this::action);
}
//
// void docmd(String mark, A8kCmdRunnable runnable, A8kCmdRunnable virtualRunable) throws AppException {
// actionExecutor.sleep(2);
// actionExecutor.docmd(mark, runnable, virtualRunable);
//
// }
//
// void docmd(String mark, A8kCmdRunnable runnable) throws AppException {
// UISender.txInfoMsg(log, mark);
// actionExecutor.docmd(mark, runnable);
// }
//
//
// public void action() {
//
// try {
// doAction();
// } catch (Exception e) {
// processException(e);
// }
// }
//
// public void processException(Exception e) {
// try {
// log.error("Catch exception: ", e);
// if (!(e instanceof EngineerTaskBreakException)) {
// UISender.txErrorPrompt(e);
// }
// //
// // Action
// //
// if (actionExecutor.isInRealMode()) {
// optScanModuleCtrlService.dropPlate();
// tipOperationCtrlModule.dropTip();
// tubeFeedingCtrlService.ejectTubeHolder();
// List<IncubationSubTank> all = incubationPlateStateMgr.getAllNotFreeIncubationSubTanks();
// for (IncubationSubTank notFreeTank : all) {
// optScanModuleCtrlService.pullPlate(notFreeTank.pos);
// optScanModuleCtrlService.dropPlate();
// }
// }
// //
// // State
// //
// optScanModuleStateMgr.changeOptScanModuleStateToEmpty();
// incubationPlateStateMgr.resetAll();
// } catch (AppException ex) {
// log.error("Catch exception: ", e);
// UISender.txErrorPrompt(e);
// gStateMgrService.setFatalError(ex.error);
// } catch (Exception ex) {
// log.error("Catch exception: ", e);
// UISender.txErrorPrompt(e);
// gStateMgrService.setFatalError(new AppError(A8kEcode.SYS_EXCEPTION, ex.getMessage()));
// }
//
// }
//
// Boolean hasTubeHolder;
// TubeHolderScanResult scanResult;
//
// public void doAction() throws AppException {
// /*
// * 1. 核对是否存在试管配置是否只有一个
// * 2. 核对耗材是否充足
// *
// *
// * 1. 入料
// * 2. 核对试管架类型
// *
// * Loop
// * 1. 样本准备
// *
// * Loop
// * 1. 检查孵育盘是否有空闲位没有空闲位则等待空闲位
// * 2. 检查是否有孵育完成的样本 有孵育完成的样本则进行光学扫描
// * 3. 入板
// * 4. 取样
// * 5. 预反应
// * 6. 滴定
// *
// * End:
// * 1. 等待所有反应板孵育完成
// */
//
// //入料
// hasTubeHolder = false;
// docmd("入料", () -> {
// hasTubeHolder = tubeFeedingCtrlService.enterTubeHolder();
// }, () -> hasTubeHolder = true);
// if (!hasTubeHolder) {
// throw AppException.of(A8kEcode.ERROR_OPERATION, "入料超时,未检测到试管架");
// }
//
// //扫描试管架
// scanResult = null;
// docmd("扫描试管架", () -> {
// scanResult = tubeFeedingCtrlService.scanTubeHodler();
// }, () -> {
// scanResult = new TubeHolderScanResult();
// for (int i = 0; i < curTubeHolderSetting.tubeSettings.length; i++) {
// scanResult.tube[i] = new TubeScanResult();
// if (!curTubeHolderSetting.tubeSettings[i].projId.isEmpty()) {
// scanResult.tube[i].isTubeExist = true;
// }
// }
// });
// //核对试管架信息
// verifyTubeHolderSettingAndTubeHolderScanResult(curTubeHolderSetting, scanResult);
// //
// A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType);
// if (A8kTubeHolderType.BulletTube1P5.equals(tubeHolderType)) {
// samplePos = A8kSamplePos.Bulltube1P5Pos;
// } else if (A8kTubeHolderType.BulletTube0P5.equals(tubeHolderType)) {
// samplePos = A8kSamplePos.Bulltube0P5Pos;
// } else {
// throw AppException.of(A8kEcode.APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT, "请使用子弹头1.5ml或者子弹头0.5ml试管架");
// }
//
//
// //构建试管架
// // setTubeHolderDirect
// for (int tubeoff = 0; tubeoff < curTubeHolderSetting.tubeSettings.length; tubeoff++) {
// TubeSetting tubeSetting = curTubeHolderSetting.tubeSettings[tubeoff];
// if (tubeSetting.projId.isEmpty()) {
// continue;
// }
// Assert.isTrue(scanResult.tube[tubeoff].isTubeExist, String.format("位置[%d]未放入是试管", tubeoff + 1));
//
// //移动试管架到预处理位置
// int finalTubeoff = tubeoff;
// UISender.txInfoMsg(log, "开始处理第%d个试管", finalTubeoff + 1);
// docmd("移动试管到处理位", () -> tubeFeedingCtrlService.moveTubeToPreProcessPos(finalTubeoff));
//
// for (int j = 0; j < getRepeatTimes(tubeoff); j++) {
//
// //尝试处理孵育完成的反应板
// incubationPlateProcess(false);
// ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(expectedProjId);
//
// //申请耗材
// var consumableInfo = consumablesMgrService.reserveConsumable(projBuildinInfo.reactionFlowType, expectedProjId);
// if (consumableInfo == null) {
// throw AppException.of(A8kEcode.CODEERROR, "耗材不足?"); //理论上开始阶段已经核对过了耗材数量此时应该不会不足
// }
// consumablesMgrService.useReserveConsumable(consumableInfo);
//
// //构造项目信息
// 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(tubeoff);
// tube.setIsHighTube(false);
// tube.setIsEmergency(false);
// tube.setBloodType(tubeSetting.bloodType);
// 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);
//
//
// //处理试管
// processTube(tube, tubeoff, consumableInfo, tubeSetting);
// if (!tube.getErrors().isEmpty()) {
// log.warn("样本异常,跳过当前样本");
// UISender.txErrorMsg(log, tube.getErrors().getFirst(), "样本异常,跳过当前样本");
// break;
// }
// docmd("HBOT复位", hbotMoveExCtrlService::moveQuickToZero);
// }
// }
// tubeFeedingCtrlService.ejectTubeHolder();
//
// incubationPlateProcess(true);
// incubationPlateStateMgr.resetAll();
// UISender.txInfoPrompt(log, "试剂实验一致性检测完成");
// }
//
// private void processTube(Tube tube, Integer offset, ConsumableInfo consumableInfo, TubeSetting tubeSetting) throws AppException {
//
// ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(expectedProjId);
// ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(consumableInfo.lotid);
//
//
// //拉取一个板夹到孵育盘
// var freeIncubationPos = incubationPlateStateMgr.takeOneIncubationIDLEPos(
// (IncubatorPos pos) -> {
// incubationPlateStateMgr.syncProjInfo(pos, projBuildinInfo, projExtInfoCard);
// incubationPlateStateMgr.syncSampleInfo(pos, tube.getSampleInfo());
// }
// );
//
// //强制清空一下光学模组和孵育盘
// // optScanModuleCtrlService.dropPlate();
// // optScanModuleCtrlService.pullPlate(freeIncubationPos);
// // optScanModuleCtrlService.dropPlate();
//
// docmd("丢反应板", optScanModuleCtrlService::dropPlate);
// docmd("拉取反应板", () -> optScanModuleCtrlService.pullPlate(freeIncubationPos));
// docmd("丢反应板", optScanModuleCtrlService::dropPlate);
//
//
// // plateBoxCtrlService.pushPlateQuick(consumableInfo.group, freeIncubationPos);
// docmd("推入新的反应板", () -> plateBoxCtrlService.pushPlateQuick(consumableInfo.group, freeIncubationPos));
// //移动当前板夹到滴定位
// // turnableMoveCtrlService.trunableMoveToDropLiquidPos(freeIncubationPos);
// docmd("移动到滴定位", () -> turnableMoveCtrlService.trunableMoveToDropLiquidPos(freeIncubationPos));
//
//
// docmd("样本处理", () -> {
// try {
// liquidOperationCtrService.setProjContext(projBuildinInfo, projExtInfoCard);
// var preProcessPos = new PreReactionPos(ConsumableType.SmallBottleBuffer, consumableInfo.group, consumableInfo.pos);
// //取tip
// tipOperationCtrlModule.tryTakeTip(() -> !actionExecutor.isStopping());
// actionExecutor.sleep(1);
// //刺破缓冲液
// hbotMoveExCtrlService.moveToLittleBufferPiercePos(consumableInfo.group, consumableInfo.pos);
// //取样品
// 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");
// liquidOperationCtrService.takeSampleToPreReactionPos(samplePos, preProcessPos, takeSampleUl);
// actionExecutor.sleep(1);
// //取混合液到预反应位
// liquidOperationCtrService.takePreReactionLiquid(preProcessPos);
// liquidOperationCtrService.dropLiquidToReactionPlate();
// actionExecutor.sleep(1);
// incubationPlateStateMgr.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60);
// actionExecutor.sleep(1);
// } catch (AppException e) {
// if (e.getError().eq(A8kEcode.APPE_TAKE_SAMPLE_FAIL)) {
// hbotMoveExCtrlService.moveQuickToZero();
// tube.setErrors(ZList.of(e.getError()));
// incubationPlateStateMgr.resetIncubatorPos(freeIncubationPos);
// //丢反应板
// optScanModuleCtrlService.forceDropPlate(freeIncubationPos);
// UISender.txErrorMsg(log, e, "取样失败");
// } else {
// throw e;
// }
// }
// }, () -> {
// incubationPlateStateMgr.startIncubating(freeIncubationPos, System.currentTimeMillis(), projBuildinInfo.reactionPlateIncubationTimeMin * 60);
// });
//
//
// {//开始孵育
// }
// }
//
//
// private void incubationPlateProcess(Boolean waittingForAll) throws AppException {
// do {
// IncubationSubTank tankPos = incubationPlateStateMgr.getOneExpiredPlate();
// if (!waittingForAll) {
// if (incubationPlateStateMgr.isHasEnoughIncubationIDLEPos(1) && tankPos == null) {
// break;
// }
// } else {
// if (incubationPlateStateMgr.isAllIncubationSubTanksFree()) {
// break;
// }
// }
//
// if (tankPos != null) {
//
// //拉取反应板到光学模组
// docmd("拉取反应板到光学模块", () -> {optScanModuleCtrlService.pullPlate(tankPos.getPos());});
//
// //设置光学模组状态
// optScanModuleStateMgr.changeOptScanModuleStateToPlateIsReady(tankPos.projInfo, tankPos.toSampleInfo());
// optScanModuleStateMgr.syncProjInfo(tankPos.projBuildinInfo, tankPos.projExtInfoCard);
// //复位孵育盘状态
// incubationPlateStateMgr.resetIncubatorPos(tankPos.getPos());
//
// //
// //光学扫描
// //
//
// //光学扫描
// optScanModuleStateMgr.changeOptScanModuleStateToScanning();
// doOptScan();
// //丢板
//
// docmd("丢弃反应板", optScanModuleCtrlService::dropPlate);
//
// optScanModuleStateMgr.changeOptScanModuleStateToEmpty();
// }
//
// actionExecutor.sleep(100);
// } while (true);
// }
//
// private void doOptScan() throws AppException {
// /*
// * HsCrp只有一个项目
// */
// Assert.isTrue(Objects.equals(expectedProjId, 1), "1 != expectedProjId");
//
// int subProjIndex = 0;
//
// A8kOptType optType = optScanModuleStateMgr.getOptScanModule().getProjBuildinInfo().getOptType(subProjIndex);
// var buildInInfo = optScanModuleStateMgr.getOptScanModule().getProjBuildinInfo();
// SampleInfo sampleInfo = optScanModuleStateMgr.getOptScanModule().getSampleInfo();
// ProjInfo projInfo = optScanModuleStateMgr.getOptScanModule().getProjInfo();
//
// // a8kOptPeakInfo
// docmd("光学扫描", () -> {
// OptScanResult optScanResult = optScanModuleCtrlService.optScan(buildInInfo, subProjIndex);
// ReactionReport.ReactionResult result = A8kPeakAnalyzer.analysisPeakInfo(sampleInfo, projInfo, subProjIndex, optScanResult.analysResult);
//
// log.info("光学扫描结果: {}", result);
// reactionRecordMgrService.addRecord(optScanModuleStateMgr.getOptScanModule().getSampleInfo(), projInfo, ZList.of(optScanResult), ZList.of(result));
// }
// , () -> {
// OS.hsleep(1000);
// }
// );
// }
//
//
//
// /*
// * Utils
// */
//
// private void verifyTubeHolderSettingAndTubeHolderScanResult(TubeHolderSetting tubeHolderSetting, TubeHolderScanResult scanResult) throws AppException {
// A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType);
// if (!tubeHolderType.equals(A8kTubeHolderType.BulletTube1P5) && !tubeHolderType.equals(A8kTubeHolderType.BulletTube0P5)) {
// throw AppException.of(A8kEcode.APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT, "请使用子弹头1.5ml或者子弹头0.5ml试管架");
// }
//
// for (int i = 0; i < tubeHolderSetting.tubeSettings.length; i++) {
// TubeSetting tubeSetting = tubeHolderSetting.tubeSettings[i];
// if (tubeSetting.projId.isEmpty() && !scanResult.tube[i].isTubeExist) {
// continue;
// }
//
// if (tubeSetting.projId.isEmpty()) {
// throw AppException.of(A8kEcode.APPE_TUBEHOLDER_SETTING_ERROR, String.format("试管[%d]缺少项目配置", i + 1));
// }
//
// if (!scanResult.tube[i].isTubeExist) {
// throw AppException.of(A8kEcode.APPE_TUBEHOLDER_SETTING_ERROR, String.format("位置[%d]未放入是试管", i + 1));
// }
//
// }
// }
}

23
src/main/java/a8k/app/hardware/type/A8kEcode.java

@ -90,6 +90,7 @@ public enum A8kEcode {
APPE_SCAN_TUBEHOLDER_TYPE_TIMEOUT(200),//扫描试管架类型超时
APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT(201),//试管架类型不支持
APPE_INFEED_OVERTIME_FAIL(202),//入料超时失败
APPE_TUBEHOLDER_IS_EMPTY(203),//试管架中没有试管
//样本处理过程中的错误
APPE_PUT_TIP_FAIL(210),//丢弃Tip失败
@ -110,8 +111,8 @@ public enum A8kEcode {
APPE_A8K_PROJ_CARD_EXPIRYED(301), //ID卡过期
APPE_A8K_PROJ_ID_IS_EMPTY(302), //项目ID为空
PROJ_CARD_ERROR_WRONG_UNSUPPORTED(303), //项目不支持
APPE_PULLERM_INIT_POS_ERROR(305), //初始化阶段拉板电机没有处于零点位置
APPE_PUSHERM_INIT_POS_ERROR(306), //初始化阶段推板电机没有处于零点位置
APPE_PULLER_MOTOR_INIT_POS_ERROR(305), //初始化阶段拉板电机没有处于零点位置
APPE_PUSHER_MOTOR_INIT_POS_ERROR(306), //初始化阶段推板电机没有处于零点位置
APPE_PLATE_STUCK_DETECTOR_SENSOR_TRIGGER(307), //卡板检测传感器触发
APPE_TUBE_X_CHANNEL_IS_NOT_EMPTY(308), //试管架通道有异物
APPE_PLATE_BOX_NOT_COVER(309), //板夹仓未盖
@ -154,8 +155,8 @@ public enum A8kEcode {
LOW_ERROR_DEVICE_IS_BUSY(1104),
LOW_ERROR_DEVICE_IS_OFFLINE(1105),
LOW_ERROR_OVERTIME(1106),
LOW_ERROR_NOACK(1107),
LOW_ERROR_ERRORACK(1108),
LOW_ERROR_NO_ACK(1107),
LOW_ERROR_ERROR_ACK(1108),
LOW_ERROR_DEVICE_OFFLINE(1109),
LOW_ERROR_SUBDEVICE_OVERTIME(1111),
LOW_ERROR_BUFFER_NOT_ENOUGH(1112),
@ -163,12 +164,12 @@ public enum A8kEcode {
LOW_ERROR_CHECKCODE_IS_ERROR(1115),
LOW_ERROR_ILLEGAL_OPERATION(1116),
LOW_ERROR_ACTION_OVERTIME(1117),
LOW_ERROR_MODULE_OPEATION_BREAK_BY_USER(1202),
LOW_ERROR_MODULE_OPERATION_BREAK_BY_USER(1202),
LOW_ERROR_MODULE_NOT_FIND_REG(1207),
LOW_ERROR_XYMOTOR_X_FIND_ZERO_EDGE_FAIL(1306),
LOW_ERROR_XYMOTOR_Y_FIND_ZERO_EDGE_FAIL(1307),
LOW_ERROR_XYMOTOR_NOT_ENABLE(1308),
LOW_ERROR_XYMOTOR_TARGET_POS_OUTOF_RANGE(1309),
LOW_ERROR_XYMOTOR_TARGET_POS_OUT_OF_RANGE(1309),
LOW_ERROR_XYMOTOR_NOT_MOVE_TO_ZERO(1310),
LOW_ERROR_PIPETTE_ERROR_NO_ERROR(1400),
LOW_ERROR_PIPETTE_ERROR_INIT_FAIL(1401),
@ -195,7 +196,7 @@ public enum A8kEcode {
LOW_ERROR_PIPETTE_ERROR_NO_TIP_WHEN_LLD(1422),
LOW_ERROR_PIPETTE_ERROR_TIPISLOAD_WHEN_LLD_PREPARE(1500),
LOW_ERROR_PIPETTE_ERROR_UNINITED(1501),
LOW_ERROR_PIPETTE_ERROR_UNINITIALIZED(1501),
LOW_ERROR_PIPETTE_ERROR_NOT_LLD_PREPARE(1502),
LOW_ERROR_PIPETTE_ERROR_PUMP_LOAD_VAL_IS_NOT_EMPTY(1503),
LOW_ERROR_PIPETTE_LLD_ERROR_NO_LIQUID_DETECTED(1504),
@ -210,7 +211,7 @@ public enum A8kEcode {
LOW_ERROR_STEP_MOTOR_OVER_VOLTAGE(1603),
LOW_ERROR_STEP_MOTOR_RUN_OVERTIME(1604),
LOW_ERROR_STEP_MOTOR_NOT_ENABLE(1605),
LOW_ERROR_STEP_MOTOR_IOINDEX_OUT_OF_RANGE(1606),
LOW_ERROR_STEP_MOTOR_IO_INDEX_OUT_OF_RANGE(1606),
LOW_ERROR_STEP_MOTOR_SUBIC_RESET(1607),
LOW_ERROR_STEP_MOTOR_DRV_ERR(1608),
LOW_ERROR_STEP_MOTOR_UV_CP(1609),
@ -233,7 +234,7 @@ public enum A8kEcode {
//
// 底层扩展错误码由java定义
//
LOW_EXT_ERROR_UNKOWN_INDEX_ERROR(5000), //代码错误,未知错误
LOW_EXT_ERROR_UNKNOWN_INDEX_ERROR(5000), //代码错误,未知错误
LOW_EXT_ERROR_CMD_NOT_SUPPORT(5001), //代码错误,未知错误
LOW_EXT_ERROR_MOTOR_AT_WRONG_POS(5002),//电机在错误的位置
;
@ -253,8 +254,8 @@ public enum A8kEcode {
}
}
log.error("未知错误码:{}", index);
A8kEcode.LOW_EXT_ERROR_UNKOWN_INDEX_ERROR.rawindex = index;
return A8kEcode.LOW_EXT_ERROR_UNKOWN_INDEX_ERROR;
A8kEcode.LOW_EXT_ERROR_UNKNOWN_INDEX_ERROR.rawindex = index;
return A8kEcode.LOW_EXT_ERROR_UNKNOWN_INDEX_ERROR;
}

5
src/main/java/a8k/app/i18n/Internationalization.java

@ -20,6 +20,7 @@ public class Internationalization {
case APPE_ADD_EMERGENCY_ACTION_IS_NOT_ALLOWED_WHEN_WORKING -> "添加急诊样本失败,设备正在运行中";
case APPE_DEVICE_IS_IN_FATAL_ERROR -> "设备处于严重错误,请关闭电源重启设备";
case APPE_SCAN_TUBEHOLDER_TYPE_TIMEOUT -> "扫描试管架类型超时";
case APPE_TUBEHOLDER_IS_EMPTY -> "试管架是空的";
case APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT -> "试管架类型不支持";
case APPE_INFEED_OVERTIME_FAIL -> "入料超时失败";
case APPE_PUT_TIP_FAIL -> "丢弃Tip失败";
@ -32,8 +33,8 @@ public class Internationalization {
case APPE_A8K_PROJ_CARD_EXPIRYED -> "ID卡过期";
case APPE_A8K_PROJ_ID_IS_EMPTY -> "项目ID为空";
case PROJ_CARD_ERROR_WRONG_UNSUPPORTED -> "项目不支持";
case APPE_PULLERM_INIT_POS_ERROR -> "初始化阶段,拉板电机没有处于零点位置";
case APPE_PUSHERM_INIT_POS_ERROR -> "初始化阶段,推板电机没有处于零点位置";
case APPE_PULLER_MOTOR_INIT_POS_ERROR -> "初始化阶段,拉板电机没有处于零点位置";
case APPE_PUSHER_MOTOR_INIT_POS_ERROR -> "初始化阶段,推板电机没有处于零点位置";
case APPE_PLATE_STUCK_DETECTOR_SENSOR_TRIGGER -> "卡板检测传感器触发";
case APPE_TUBE_X_CHANNEL_IS_NOT_EMPTY -> "试管架通道有异物";
case APPE_PLATE_BOX_NOT_COVER -> "板夹仓未盖";

9
src/main/java/a8k/app/service/analyzer/A8kIdCardDataParseService.java

@ -1,12 +1,10 @@
package a8k.app.service.analyzer;
import a8k.app.dao.ProjectBaseInfoDao;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.type.a8k.optfn.A8kNormalFn;
import a8k.app.hardware.type.A8kEcode;
import a8k.app.type.a8k.optfn.A8kOptX;
import a8k.app.dao.type.db.ProjectBaseInfo;
import a8k.app.type.a8k.optfn.A8kPiecewiseFn;
import a8k.app.type.a8k.optfn.A8kFnType;
import a8k.app.type.a8k.proj.A8kResultUnit;
@ -14,7 +12,6 @@ import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.type.error.AppError;
import a8k.app.type.exception.AppException;
import a8k.app.utils.ZDateUtils;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -244,7 +241,7 @@ public class A8kIdCardDataParseService {
ASSERT_IS_TRUE(idcard.lotId.length() == 8, "PARSE LOTID IS ERROR");
ASSERT_IS_TRUE(!idcard.projName.isEmpty(), "PARSE PROJNAME IS ERROR");
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(idcard.projId);
ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(idcard.projId);
ASSERT_IS_TRUE(projBuildinInfo != null, A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED, "PROJECT ID %d NOT SUPPORTED", idcard.projId);
if (idcard.projShortName == null || idcard.projShortName.isEmpty()) {
idcard.projShortName = projBuildinInfo.getProjShortName();
@ -367,7 +364,7 @@ public class A8kIdCardDataParseService {
private void parseAndCheckFn(ProjExtInfoCard idcard) throws AppException {
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(idcard.projId);
ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(idcard.projId);
ASSERT_IS_TRUE(projBuildinInfo != null, A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED, "PROJECT ID %d NOT FOUND", idcard.projId);

6
src/main/java/a8k/app/service/analyzer/ConsumableStateAnalyzerService.java

@ -5,10 +5,8 @@ import a8k.app.service.statemgr.ConsumablesMgrService;
import a8k.app.type.a8k.state.TubeHolderInfo;
import a8k.app.type.a8k.state.TubeInfo;
import a8k.app.type.exception.AppException;
import a8k.app.type.a8k.state.Tube;
import a8k.app.type.a8k.state.TubeHolder;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.utils.ZJsonHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -37,7 +35,7 @@ public class ConsumableStateAnalyzerService {
void assginProjInfo(ConsumableStatInfo info) {
ProjInfoMgrService projInfoMgrService = SpringBootBeanUtil.getBean(ProjInfoMgrService.class);
ProjBuildinInfo projBuildinInfo = null;
ProjBuildInInfo projBuildinInfo = null;
try {
projBuildinInfo = projInfoMgrService.getProjBuildInInfo(info.projId);
info.projShortName = projBuildinInfo.projShortName;

4
src/main/java/a8k/app/service/background/ProjIDCardCtrlAndMonitorService.java

@ -13,7 +13,7 @@ import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.type.exception.AppException;
import a8k.app.hardware.channel.A8kCanBusService;
import a8k.app.service.analyzer.A8kIdCardDataParseService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.utils.ZWorkQueue;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
@ -111,7 +111,7 @@ public class ProjIDCardCtrlAndMonitorService {
//解析ID卡信息
try {
mountedIdCardInfo = idCardDataParseService.parseAndCheck(data);
ProjBuildinInfo buildinInfo = projInfoMgrService.getProjBuildInInfo(mountedIdCardInfo.projId);
ProjBuildInInfo buildinInfo = projInfoMgrService.getProjBuildInInfo(mountedIdCardInfo.projId);
mountedIdCardInfo.color = buildinInfo.color;
eventBus.pushEvent(new AppIDCardMountEvent(mountedIdCardInfo));

4
src/main/java/a8k/app/service/data/ProjIdCardInfoMgrService.java

@ -14,7 +14,7 @@ import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.type.a8k.proj.A8kProjInfoCardBreif;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.dao.type.common.CommonPage;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.utils.ZAppChecker;
import a8k.app.utils.DoubleUtils;
import jakarta.annotation.Resource;
@ -120,7 +120,7 @@ public class ProjIdCardInfoMgrService {
//
public List<A8kEcode> verifyProjExtInfoCard(ProjExtInfoCard projExtInfoCard) throws AppException {
ProjBuildinInfo projBuildinInfo;
ProjBuildInInfo projBuildinInfo;
List<A8kEcode> ecodeList = new ArrayList<>();
try {

24
src/main/java/a8k/app/service/data/ProjInfoMgrService.java

@ -10,7 +10,7 @@ import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.dao.type.db.ProjectBaseInfo;
import a8k.app.type.exception.AppException;
import a8k.app.service.background.ProjIDCardCtrlAndMonitorService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.utils.ZAppChecker;
import a8k.app.utils.ZJsonHelper;
import jakarta.annotation.PostConstruct;
@ -34,32 +34,32 @@ public class ProjInfoMgrService {
ProjOptInfoDao projOptInfoDao;
public ProjBuildinInfo getProjBuildInInfo(Integer projId) throws AppException {
public ProjBuildInInfo getProjBuildInInfo(Integer projId) throws AppException {
var projBaseInfo = projectBaseInfoDao.findByProjId(projId);
var projOptInfos = projOptInfoDao.findByProjIndex(projId);
ZAppChecker.notNull(projBaseInfo, A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED, "PROJ:%d IS NOT SUPPORTED", projId);
ZAppChecker.notEmpty(projOptInfos, A8kEcode.PROJ_CARD_ERROR_BUILD_IN_PROJ_INFO_ERROR, "PROJ:%d OPT CONFIG IS NOT EXIST", projId);
ZAppChecker.check(projOptInfos.size() == projBaseInfo.subProjNum, A8kEcode.PROJ_CARD_ERROR_BUILD_IN_PROJ_INFO_ERROR, "PROJ:%d OPT CONFIG IS NOT MATCH", projId);
return new ProjBuildinInfo(projBaseInfo, projOptInfos);
return new ProjBuildInInfo(projBaseInfo, projOptInfos);
}
public List<ProjBuildinInfo> getProjBuildInInfo(List<Integer> projIds) throws AppException {
List<ProjBuildinInfo> projBuildinInfos = new ArrayList<>();
public List<ProjBuildInInfo> getProjBuildInInfo(List<Integer> projIds) throws AppException {
List<ProjBuildInInfo> projBuildInInfos = new ArrayList<>();
for (Integer projId : projIds) {
projBuildinInfos.add(getProjBuildInInfo(projId));
projBuildInInfos.add(getProjBuildInInfo(projId));
}
return projBuildinInfos;
return projBuildInInfos;
}
public List<ProjBuildinInfo> getAllProjBuildInInfo() throws AppException {
List<ProjBuildinInfo> projBuildinInfos = new ArrayList<>();
public List<ProjBuildInInfo> getAllProjBuildInInfo() throws AppException {
List<ProjBuildInInfo> projBuildInInfos = new ArrayList<>();
List<ProjectBaseInfo> projBInfos = projectBaseInfoDao.getAll();
for (ProjectBaseInfo projBInfo : projBInfos) {
projBuildinInfos.add(getProjBuildInInfo(projBInfo.projId));
projBuildInInfos.add(getProjBuildInInfo(projBInfo.projId));
}
return projBuildinInfos;
return projBuildInInfos;
}
public ProjExtInfoCard getProjExtInfoCard(String lotid) {
@ -70,7 +70,7 @@ public class ProjInfoMgrService {
var service = SpringBootBeanUtil.getBean(ProjIDCardCtrlAndMonitorService.class);
return service.getMountedIdCardInfo();
}
public ProjBuildinInfo getProjBuildInInfoByMountedCard() throws AppException {
public ProjBuildInInfo getProjBuildInInfoByMountedCard() throws AppException {
var mountedIdCardInfo = getMountedProjInfoCard();
if(mountedIdCardInfo == null){
return null;

6
src/main/java/a8k/app/service/lowerctrl/LiquidOperationCtrService.java

@ -1,7 +1,7 @@
package a8k.app.service.lowerctrl;
import a8k.app.dao.type.combination.ProjBuildinInfo;
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;
@ -49,11 +49,11 @@ public class LiquidOperationCtrService {
private final TipOperationCtrlModule tipOperationCtrlModule;
ProjBuildinInfo projBuildinInfo;
ProjBuildInInfo projBuildinInfo;
ProjExtInfoCard projExtInfo;
synchronized public void setProjContext(ProjBuildinInfo projBuildinInfo, ProjExtInfoCard projExtInfo) {
synchronized public void setProjContext(ProjBuildInInfo projBuildinInfo, ProjExtInfoCard projExtInfo) {
this.projBuildinInfo = projBuildinInfo;
this.projExtInfo = projExtInfo;
}

6
src/main/java/a8k/app/service/lowerctrl/OptScanModuleCtrlService.java

@ -15,7 +15,7 @@ import a8k.app.dao.type.db.OptRawScanData;
import a8k.app.type.a8k.opt.A8kOptType;
import a8k.app.type.a8k.pos.IncubatorPos;
import a8k.app.type.exception.AppException;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.hardware.utils.OptGainConvert;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -206,7 +206,7 @@ public class OptScanModuleCtrlService {
return rawData;
}
public OptScanResult optScan(ProjBuildinInfo projBuildinInfo, Integer subProjIndex, Boolean autoAmpl) throws AppException {
public OptScanResult optScan(ProjBuildInInfo projBuildinInfo, Integer subProjIndex, Boolean autoAmpl) throws AppException {
UISender.txInfoMsg(log, "光学扫描");
A8kOptCurveAnalyzer a8KOptCurveAnalyzer = new A8kOptCurveAnalyzer();
@ -223,7 +223,7 @@ public class OptScanModuleCtrlService {
return result;
}
public OptScanResult optScan(ProjBuildinInfo projBuildinInfo, Integer subProjIndex) throws AppException {
public OptScanResult optScan(ProjBuildInInfo projBuildinInfo, Integer subProjIndex) throws AppException {
return optScan(projBuildinInfo, subProjIndex, true);
}
}

91
src/main/java/a8k/app/service/lowerctrl/TubeFeedingCtrlService.java

@ -16,66 +16,23 @@ import a8k.app.hardware.channel.A8kCanBusService;
import a8k.app.hardware.type.A8kEcode;
import a8k.app.hardware.type.InputIOId;
import a8k.app.hardware.type.MId;
import a8k.app.type.misc.TubeHolderScanResult;
import a8k.app.type.misc.TubeScanResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@RequiredArgsConstructor
@Slf4j
public class TubeFeedingCtrlService {
public static class TubeHolderScanResult {
public TubesScanResult[] tube = new TubesScanResult[10];
public String tubeHolderType = "";
public Boolean isVirtual = false;
public String toString() {
return String.format("%s %s", tubeHolderType, Arrays.toString(tube));
}
public Boolean isHasTubeInIt() {
for (TubesScanResult tubesScanResult : tube) {
if (tubesScanResult.isTubeExist) {
return true;
}
}
return false;
}
}
public static class TubesScanResult {
public Boolean isTubeExist = false;
public Boolean isHighTube = false;
public String tubeCode = null;
public TubesScanResult() {
}
public TubesScanResult(Boolean isTubeExist, Boolean isHighTube, String tubeCode) {
this.isTubeExist = isTubeExist;
this.isHighTube = isHighTube;
this.tubeCode = tubeCode;
}
public String toString() {
if (isTubeExist) {
return String.format("%s(%s)", tubeCode, isHighTube ? "High" : "Low");
} else {
return "Null";
}
}
}
static Integer tubeScanOvertime = 3000;
static Integer tubeHolderScanOvertime = 5000;
static Integer tubeScanOvertime = 3000; // 试管扫码超时
static Integer tubeHolderScanOvertime = 3000; // 试管架类型扫码超时
private final AppEventBusService ebus;
private final A8kCanBusService canBus;
private final TubeFeedingModuleParamMgr stp;
private final CodeScanerDriver codeScaner;
private final CodeScanerDriver codeScanner;
private final TubeFeedingExCtrlService tubeFeedingExCtrlService;
private final MiniServoDriver miniServoDriver;
private final StepMotorCtrlDriver stepMotorCtrlDriver;
@ -176,7 +133,7 @@ public class TubeFeedingCtrlService {
try {
tubeFeedingExCtrlService.scanClampModClamp();
miniServoDriver.miniServoRotateWithTorque(MiniServoMId.ShakeModTubeScanerRotateSV, stp.getTubeScanServoTorque());
return codeScaner.feedingModScannerModCodeScannerScanCode(tubeScanOvertime);
return codeScanner.feedingModScannerModCodeScannerScanCode(tubeScanOvertime);
} finally {
miniServoDriver.moduleStop(MiniServoMId.ShakeModTubeScanerRotateSV);
tubeFeedingExCtrlService.scanClampModRelease();
@ -192,7 +149,7 @@ public class TubeFeedingCtrlService {
moveTubeRackToScanPos();
tubeFeedingExCtrlService.scanClampModClamp();
result = codeScaner.feedingModScannerModCodeScannerScanCode(tubeHolderScanOvertime);
result = codeScanner.feedingModScannerModCodeScannerScanCode(tubeHolderScanOvertime);
tubeFeedingExCtrlService.scanClampModRelease();
if (result == null || result.isEmpty()) {
return "";
@ -247,43 +204,43 @@ public class TubeFeedingCtrlService {
}
//逐个扫描试管
TubesScanResult[] tubesScanResult = new TubesScanResult[10];
boolean hasTube = false;
for (int i = 0; i < tubesScanResult.length; i++) {
tubesScanResult[i] = new TubesScanResult();
TubeScanResult[] tubeScanResult = new TubeScanResult[10];
boolean hasTube = false;
for (int i = 0; i < tubeScanResult.length; i++) {
tubeScanResult[i] = new TubeScanResult();
Boolean isTubeExist = moveAndjudgeTubeExist(i);
if (isTubeExist) {
hasTube = true;
tubesScanResult[i].isTubeExist = true;
hasTube = true;
tubeScanResult[i].isTubeExist = true;
if (tubeHolderType == A8kTubeHolderType.BloodTube) {
tubesScanResult[i].isHighTube = moveAndJudgeTubeAltit(i);
tubesScanResult[i].tubeCode = moveToTubeScanPosAndScan(i);
tubeScanResult[i].isHighTube = moveAndJudgeTubeAltit(i);
tubeScanResult[i].tubeCode = moveToTubeScanPosAndScan(i);
} else {
tubesScanResult[i].isHighTube = false;
tubesScanResult[i].tubeCode = "";
tubeScanResult[i].isHighTube = false;
tubeScanResult[i].tubeCode = "";
}
} else {
tubesScanResult[i].isTubeExist = false;
tubeScanResult[i].isTubeExist = false;
}
log.info("扫描试管{}完成,{}", i, tubesScanResult[i]);
log.info("扫描试管{}完成,{}", i, tubeScanResult[i]);
}
//处理扫描结果
if (!hasTube) {
log.error("试管架中没有试管");
ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT));
ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.APPE_TUBEHOLDER_IS_EMPTY));
return null;
}
result.tubeHolderType = tubeType;
result.tube = tubesScanResult;
result.tube = tubeScanResult;
return result;
}
public TubeHolderScanResult enterAndScanTubeHodler() throws AppException {
public TubeHolderScanResult enterAndScanTubeholder() throws AppException {
//清空试管架
if (!tubeXChannelIsEmpty()) {
log.warn("试管架通道有试管,弹出试管架");
ejectTubeHolder();
}
//入料
@ -291,12 +248,10 @@ public class TubeFeedingCtrlService {
Boolean enterSuc = enterTubeHolder();
if (!enterSuc) {
log.warn("进料超时");
// ejectTubeHolderInEnterPos();
ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.APPE_INFEED_OVERTIME_FAIL));
return null;
}
return scanTubeHodler();
}
//

6
src/main/java/a8k/app/service/lowerctrl/TurnableMoveCtrlService.java

@ -38,20 +38,20 @@ public class TurnableMoveCtrlService {
//检查钩板电机是否处于终点位置
if (!inputDetectDriver.getIOState(InputIOId.PullerMZeroPPS)) {
log.error("PullerM is not in zero pos");
throw new AppException(A8kEcode.APPE_PULLERM_INIT_POS_ERROR);
throw new AppException(A8kEcode.APPE_PULLER_MOTOR_INIT_POS_ERROR);
}
//检查板夹仓光电是否处于起点位置
if (!inputDetectDriver.getIOState(InputIOId.PusherMZeroPPS)) {
log.error("PusherM is not in zero pos");
throw new AppException(A8kEcode.APPE_PUSHERM_INIT_POS_ERROR);
throw new AppException(A8kEcode.APPE_PUSHER_MOTOR_INIT_POS_ERROR);
}
}
private void checkBeforeMovePlateBox() throws AppException {
if (!inputDetectDriver.getIOState(InputIOId.PusherMZeroPPS)) {
log.error("PusherM is not in zero pos ");
throw new AppException(A8kEcode.APPE_PUSHERM_INIT_POS_ERROR);
throw new AppException(A8kEcode.APPE_PUSHER_MOTOR_INIT_POS_ERROR);
}
}

7
src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java

@ -1,9 +1,8 @@
package a8k.app.service.mainctrl;
import a8k.app.constant.AppConstant;
import a8k.app.hardware.type.A8kEcode;
import a8k.app.i18n.Internationalization;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.service.statemgr.ConsumablesMgrService;
@ -131,7 +130,7 @@ public class AppConsumablesScanService {
return ret;
}
ProjBuildinInfo projBuildinInfo = null;
ProjBuildInInfo projBuildinInfo = null;
try {
projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projExtInfoCard.projId);
} catch (AppException e) {
@ -204,7 +203,7 @@ public class AppConsumablesScanService {
Assert.isTrue(result.projId != 0, "result.projId!=0");
ProjBuildinInfo projCfg = null;
ProjBuildInInfo projCfg = null;
try {
projCfg = projInfoMgrService.getProjBuildInInfo(projExtInfoCard.projId);
} catch (AppException e) {

94
src/main/java/a8k/app/service/module/InFeedingCtrlModule.java

@ -1,7 +1,6 @@
package a8k.app.service.module;
import a8k.OS;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.db.ReactionReport;
import a8k.app.engineer.service.type.A8kCmdRunnable;
import a8k.app.factory.AppErrorFactory;
@ -23,10 +22,11 @@ import a8k.app.type.a8k.A8kTubeHolderType;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.state.TubeHolderInfo;
import a8k.app.type.a8k.state.TubeInfo;
import a8k.app.type.a8k.state.enumtype.TubeHolderState;
import a8k.app.type.appevent.AppWarningNotifyEvent;
import a8k.app.type.error.AETubeError;
import a8k.app.type.error.AppError;
import a8k.app.type.exception.AppException;
import a8k.app.type.misc.TubeHolderScanResult;
import a8k.app.type.ui.TubeHolderSetting;
import a8k.app.utils.ZWorkThread;
import cn.hutool.core.util.ObjectUtil;
@ -110,17 +110,21 @@ public class InFeedingCtrlModule {
continue;
}
//入料
if (isReady()) {
TubeHolderSetting tubeSetting = tubeHolderSettingMgrService.getThelastActiveTubeHolderSetting();
priDoAction(tubeSetting);
tubeHolderSettingMgrService.removeLockTubeHolderSetting(tubeSetting);
//如果Tubeholder处于空的状态则弹入新的试管架
if (tubeStateMgr.getTubeholderState().equals(TubeHolderState.IDLE)) {
//如果入料通道光电被触发
// 或者软件推测有新的试管架
if (getTubeholderEnterPosPPS() ||
deviceWorkStateMgrService.isMayHaveNewTubeHolder()) {
TubeHolderSetting tubeSetting = tubeHolderSettingMgrService.getThelastActiveTubeHolderSetting();
scanTubeHolder(tubeSetting);
tubeHolderSettingMgrService.removeLockTubeHolderSetting(tubeSetting);
}
}
//出料
if (tubeStateMgr.isTubeHolderInProcessing()
&& tubeStateMgr.isTubeholderHasBeenProcessed()
) {
if (!tubeStateMgr.getTubeholderState().equals(TubeHolderState.IDLE) &&
tubeStateMgr.isAllTubeInTubeholderHasBeenProcessed()) {
docmd("弹出试管架", () -> {
tubeFeedingCtrlService.ejectTubeHolder();
tubeFeedingCtrlService.moveTubeRackMoveToEnterPos();
@ -137,13 +141,9 @@ public class InFeedingCtrlModule {
state.isWorking = false;
}
private Boolean isReady() {
if (tubeStateMgr.isTubeHolderProcessCompleted()) {
return getTubeholderEnterPosPPS() || deviceWorkStateMgrService.isMayHaveNewTubeHolder();
}
return false;
}
//**********************************************************************************************
// PRIVATE
//**********************************************************************************************
private Boolean getTubeholderEnterPosPPS() { // 入料通道是否为空
if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.RealMode)) {
@ -158,13 +158,13 @@ public class InFeedingCtrlModule {
}
A8kEcode initOneTube(TubeInfo tube, Integer i, TubeFeedingCtrlService.TubeHolderScanResult scanResult,
TubeHolderSetting setting) {
private A8kEcode initOneTube(TubeInfo tube, Integer i, TubeHolderScanResult scanResult, TubeHolderSetting setting) {
if (!scanResult.tube[i].isTubeExist) {
tube.isHasTube = false;
return A8kEcode.SUC;
}
tube.isHasTube = (scanResult.tube[i].isHighTube);
tube.isHasTube = true;
tube.isHighTube = (scanResult.tube[i].isHighTube);
// 首先赋值默认值
tube.bloodType = (BloodType.WHOLE_BLOOD);
@ -174,19 +174,10 @@ public class InFeedingCtrlModule {
// 然后赋值用户配置的数值
if (setting != null) {
List<ProjBuildinInfo> projBuildinInfos = null;
try {
projBuildinInfos = projInfoMgrService.getProjBuildInInfo(setting.tubeSettings[i].projId);
} catch (AppException e) {
log.error("项目信息不存在,{}", setting.tubeSettings[i].projId);
return A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED;
}
tube.bloodType = (setting.tubeSettings[i].bloodType);
tube.sampleBarcode = (setting.tubeSettings[i].sampleBarcode);
tube.userid = (setting.tubeSettings[i].userid);
tube.projIds = (setting.tubeSettings[i].projId);
}
// TODO:添加请求后台的代码
if (tube.projIds.isEmpty()) {
@ -195,11 +186,8 @@ public class InFeedingCtrlModule {
return A8kEcode.SUC;
}
TubeHolderInfo parseScanResult(TubeFeedingCtrlService.TubeHolderScanResult scanResult, TubeHolderSetting setting) {
private TubeHolderInfo parseScanResult(TubeHolderScanResult scanResult, TubeHolderSetting setting) {
log.info("解析试管架扫描结果");
log.info("扫描结果 {}", scanResult);
log.info("试管架配置 {}", setting);
TubeHolderInfo tubeholderInfo = new TubeHolderInfo();
// 获取试管架类型
@ -214,6 +202,7 @@ public class InFeedingCtrlModule {
for (int i = 0; i < tubeholderInfo.tubeInfos.length; i++) {
A8kEcode ecode = initOneTube(tubeholderInfo.tubeInfos[i], i, scanResult, setting);
if (!ecode.equals(A8kEcode.SUC)) {
log.error("解析试管架扫描结果失败,试管{}错误码:{}", i, ecode);
appEventBusService.pushEvent(new AppWarningNotifyEvent(new AETubeError(ecode, i)));
return null;
}
@ -221,7 +210,7 @@ public class InFeedingCtrlModule {
return tubeholderInfo;
}
TubeFeedingCtrlService.TubeHolderScanResult doScanHolder() throws AppException {
private TubeHolderScanResult doScanHolder() throws AppException {
/*
* 如果使能了虚拟设备那么直接返回虚拟设备的扫描结果
*/
@ -229,7 +218,7 @@ public class InFeedingCtrlModule {
if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.RealMode)) {
return stc.scanTubeHodler();
} else if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.RunOnlyMode)) {
TubeFeedingCtrlService.TubeHolderScanResult result = stc.scanTubeHodler();
TubeHolderScanResult result = stc.scanTubeHodler();
ZAppChecker.check(result == null, A8kEcode.CODEERROR, "试管架中有试管,但是测试模式中设置了虚拟试管扫描结果");
return stc.takeVirtualTubeScanResult();
} else if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.VirtualMode)) {
@ -238,25 +227,19 @@ public class InFeedingCtrlModule {
return null;
}
Boolean doEnterTubeHolder() throws AppException {
private void scanTubeHolder(TubeHolderSetting tubeHolderSetting) throws AppException {
log.info("推入试管架");
Boolean enterTubeHolderSuc = false;
if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.RealMode)) {
return stc.enterTubeHolder();
enterTubeHolderSuc = stc.enterTubeHolder();
} else if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.RunOnlyMode)) {
stc.enterTubeHolder();
return true;
enterTubeHolderSuc = stc.enterTubeHolder();
} else if (gStateMgrService.getDeviceRunMode().equals(DeviceRunMode.VirtualMode)) {
return true;
enterTubeHolderSuc = false;
}
return false;
}
void doEjectHodler() throws AppException {
docmd("弹出试管架", stc::ejectTubeHolder);
}
public void priDoAction(TubeHolderSetting tubeHolderSetting) throws AppException {
if (!doEnterTubeHolder()) {
if (!enterTubeHolderSuc) {
if (deviceWorkStateMgrService.isMayHaveNewTubeHolder()) {
deviceWorkStateMgrService.setMayHaveNewTubeHolder(false);
log.warn("尝试推入试管架忽略");
@ -270,18 +253,19 @@ public class InFeedingCtrlModule {
deviceWorkStateMgrService.setMayHaveNewTubeHolder(true);
// 扫描试管架
TubeFeedingCtrlService.TubeHolderScanResult scanResult;
scanResult = doScanHolder();
TubeHolderScanResult scanResult = doScanHolder();
if (scanResult == null) {
log.error("扫描试管架失败");
doEjectHodler();
docmd("弹出试管架", stc::ejectTubeHolder);
return;
}
// 解析试管架扫描结果
log.info("扫描结果 {}", scanResult);
log.info("试管架配置 {}", tubeHolderSetting);
TubeHolderInfo tubeholderInfo = parseScanResult(scanResult, tubeHolderSetting);
if (tubeholderInfo == null) {
doEjectHodler();
docmd("弹出试管架", stc::ejectTubeHolder);
return;
}
@ -292,11 +276,15 @@ public class InFeedingCtrlModule {
if (e.getError().eq(A8kEcode.APPE_CONSUME_NOT_ENOUGH, A8kEcode.APPE_TIP_NOT_ENOUGH)) {
deviceWorkStateMgrService.setConsumeNotEnoughErrorFlag();
}
log.error("添加试管架到系统中失败", e);
appEventBusService.pushEvent(new AppWarningNotifyEvent(e.error));
doEjectHodler();
docmd("弹出试管架", stc::ejectTubeHolder);
}
}
//***************************************************************************************************
// BASE UTILS //
//***************************************************************************************************
private void docmd(String mark, A8kCmdRunnable runnable, A8kCmdRunnable virtualAction) throws AppException {
log.info("DO {}", mark);

5
src/main/java/a8k/app/service/module/IncubationPlateCtrlModule.java

@ -1,8 +1,6 @@
package a8k.app.service.module;
import a8k.OS;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.engineer.service.type.A8kCmdRunnable;
import a8k.app.factory.AppErrorFactory;
import a8k.app.service.lowerctrl.OptScanModuleCtrlService;
@ -13,10 +11,8 @@ import a8k.app.service.statemgr.IncubationPlateStateMgr;
import a8k.app.service.statemgr.OptScanModuleStateMgr;
import a8k.app.service.utils.UISender;
import a8k.app.type.DeviceRunMode;
import a8k.app.type.a8k.ConsumableGroup;
import a8k.app.type.a8k.pos.IncubatorPos;
import a8k.app.type.a8k.state.IncubationSubTank;
import a8k.app.type.a8k.state.SampleInfo;
import a8k.app.type.a8k.state.enumtype.IncubationSubTankState;
import a8k.app.type.error.AppError;
import a8k.app.type.exception.AppException;
@ -28,7 +24,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.List;
/**
*

7
src/main/java/a8k/app/service/module/SamplePreProcessModule.java

@ -154,11 +154,8 @@ public class SamplePreProcessModule {
// 预定孵育盘位置
for (var cxt : tube.getPreProcessContexts()) {
//预定孵育盘位置
cxt.incubatorPos = incubationPlateStateMgr.takeOneIncubationIDLEPos(
(IncubatorPos pos) -> {
incubationPlateStateMgr.syncProjInfo(pos, cxt.projBuildinInfo, cxt.projExtInfoCard);
incubationPlateStateMgr.syncSampleInfo(pos, cxt.sampleInfo);
}
cxt.incubatorPos = incubationPlateStateMgr.takeOneIncubationIDLEPos((IncubatorPos pos) ->
incubationPlateStateMgr.syncCxtInfo(pos, cxt.sampleInfo, cxt.projBuildinInfo, cxt.projExtInfoCard, cxt.consumableInfo)
);
//使用耗材
consumablesMgrService.useReserveConsumable(cxt.consumableInfo);

34
src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgr.java

@ -2,6 +2,7 @@ package a8k.app.service.statemgr;
import a8k.app.type.DeviceRunMode;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.pos.ConsumableInfo;
import a8k.app.type.a8k.state.IncubationPlate;
import a8k.app.type.a8k.state.IncubationSubTank;
import a8k.app.type.a8k.state.SampleInfo;
@ -10,7 +11,7 @@ import a8k.app.type.a8k.pos.IncubatorPos;
import a8k.app.type.a8k.proj.ProjBriefInfo;
import a8k.app.type.error.AppError;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.utils.ProjInfoUtils;
import a8k.app.utils.ZTimeUtils;
import cn.hutool.core.util.ObjectUtil;
@ -74,7 +75,7 @@ public class IncubationPlateStateMgr {
synchronized public Boolean isHasEnoughIncubationIDLEPos(Integer num) {
var subtanks = incubationPlate.subtanks;
int count = 0;
int count = 0;
for (IncubationSubTank subtank : subtanks) {
if (subtank.state.equals(IncubationSubTankState.EMPTY) && subtank.getHasCleared()) {
count++;
@ -181,9 +182,6 @@ public class IncubationPlateStateMgr {
}
synchronized public void setIncubationToErrorState(IncubatorPos pos, List<AppError> errors) {
if (pos == null) {
return;
@ -206,25 +204,43 @@ public class IncubationPlateStateMgr {
}
}
synchronized public void syncSampleInfo(IncubatorPos pos, SampleInfo sampleInfo) {
// synchronized public void syncSampleInfo(IncubatorPos pos,) {
// var subtanks = incubationPlate.subtanks;
// subtanks[pos.off].sampleId = sampleInfo.sampleId;
// subtanks[pos.off].bloodType = sampleInfo.bloodType;
// subtanks[pos.off].sampleBarcode = sampleInfo.sampleBarcode;
// subtanks[pos.off].userid = sampleInfo.userid;
// subtanks[pos.off].isEmergency = sampleInfo.isEmergency;
// }
//
// synchronized public void syncProjInfo(IncubatorPos pos, ProjBuildInInfo projBuildinInfo, ProjExtInfoCard projExtInfoCard) {
// var subtanks = incubationPlate.subtanks;
// subtanks[pos.off].projBuildinInfo = projBuildinInfo;
// subtanks[pos.off].projExtInfoCard = projExtInfoCard;
// subtanks[pos.off].lotId = projExtInfoCard.lotId;
// subtanks[pos.off].projId = projBuildinInfo.projId;
// subtanks[pos.off].projInfo = ProjInfoUtils.buildProjBrefInfo(projBuildinInfo);
// }
synchronized public void syncCxtInfo(IncubatorPos pos, SampleInfo sampleInfo, ProjBuildInInfo projBuildinInfo, ProjExtInfoCard projExtInfoCard, ConsumableInfo consumableInfo) {
var subtanks = incubationPlate.subtanks;
subtanks[pos.off].sampleId = sampleInfo.sampleId;
subtanks[pos.off].bloodType = sampleInfo.bloodType;
subtanks[pos.off].sampleBarcode = sampleInfo.sampleBarcode;
subtanks[pos.off].userid = sampleInfo.userid;
subtanks[pos.off].isEmergency = sampleInfo.isEmergency;
}
synchronized public void syncProjInfo(IncubatorPos pos, ProjBuildinInfo projBuildinInfo, ProjExtInfoCard projExtInfoCard) {
var subtanks = incubationPlate.subtanks;
subtanks[pos.off].projBuildinInfo = projBuildinInfo;
subtanks[pos.off].projExtInfoCard = projExtInfoCard;
subtanks[pos.off].lotId = projExtInfoCard.lotId;
subtanks[pos.off].projId = projBuildinInfo.projId;
subtanks[pos.off].projInfo = ProjInfoUtils.buildProjBrefInfo(projBuildinInfo);
subtanks[pos.off].consumableInfo = consumableInfo;
}
synchronized public void setIncubationToWaitingForDropState(IncubatorPos pos) {
var subtanks = incubationPlate.subtanks;
subtanks[pos.off].state = IncubationSubTankState.WAITING_FOR_DROP;

4
src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgr.java

@ -8,7 +8,7 @@ import a8k.app.type.a8k.state.enumtype.OptScanModuleStateEnum;
import a8k.app.type.a8k.proj.ProjBriefInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.service.data.UtilsProjectColorAllocer;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import cn.hutool.core.util.ObjectUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -78,7 +78,7 @@ public class OptScanModuleStateMgr {
log.info("光学模块:状态->反应板准备就绪 {}", sampleInfo);
}
synchronized public void syncProjInfo(ProjBuildinInfo projBuildinInfo, ProjExtInfoCard projExtInfoCard) {
synchronized public void syncProjInfo(ProjBuildInInfo projBuildinInfo, ProjExtInfoCard projExtInfoCard) {
optScanModule.setProjBuildinInfo(projBuildinInfo);
optScanModule.setProjExtInfoCard(projExtInfoCard);
optScanModule.setLotId(projExtInfoCard.lotId);

35
src/main/java/a8k/app/service/statemgr/TubeStateMgr.java

@ -20,12 +20,11 @@ import a8k.app.type.error.AppError;
import a8k.app.type.exception.AppException;
import a8k.app.type.a8k.BloodType;
import a8k.app.service.data.UtilsProjectColorAllocer;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.utils.ProjInfoUtils;
import a8k.app.service.utils.ZAppChecker;
import a8k.app.utils.ZJsonHelper;
import cn.hutool.core.util.ObjectUtil;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -118,7 +117,7 @@ public class TubeStateMgr {
private ProjectPreProcessContext newProjectPreProcessContext(Tube tube, Integer projId, Integer off) throws AppException {
SampleInfo sampleInfo = tube.getSampleInfo();
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projId);
ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projId);
ConsumableInfo consumableInfo = consumablesMgrService.reserveConsumable(projBuildinInfo.reactionFlowType, projId);
ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(consumableInfo.lotid);
@ -183,8 +182,8 @@ public class TubeStateMgr {
tube.setUserid(tubeInfo.userid);
tube.setState(TubeState.TO_BE_PROCESSED);
tube.setProjIds(new ArrayList<>(tubeInfo.projIds));
tube.setProjBuildinInfos(projInfoMgrService.getProjBuildInInfo(tubeInfo.projIds));
tube.setProjInfo(ProjInfoUtils.buidProjBriefInfoList(tube.getProjBuildinInfos()));
tube.setProjBuildInInfos(projInfoMgrService.getProjBuildInInfo(tubeInfo.projIds));
tube.setProjInfo(ProjInfoUtils.buidProjBriefInfoList(tube.getProjBuildInInfos()));
String sampleId = newSample(tube);
tube.setSampleId(sampleId);
@ -222,7 +221,7 @@ public class TubeStateMgr {
synchronized public void commitEmergencySampleSetting(String userid, String sampleBarcode, BloodType bloodType,//
List<Integer> projIds, Boolean isVirtual) throws AppException {
Tube tube = emergencyTubePos.tube;
List<ProjBuildinInfo> projBuildInInfos = new ArrayList<>();
List<ProjBuildInInfo> projBuildInInfos = new ArrayList<>();
if (projIds.isEmpty()) {
throw new AppException(A8kEcode.APPE_A8K_PROJ_ID_IS_EMPTY);
}
@ -265,7 +264,7 @@ public class TubeStateMgr {
tube.setIsEmergency(true);
tube.setProjInfo(ProjInfoUtils.buidProjBriefInfoList(projBuildInInfos));
tube.setProjIds(projIds);
tube.setProjBuildinInfos(projBuildInInfos);
tube.setProjBuildInInfos(projBuildInInfos);
//!! 这行代码后续代码需要保证无异常发生
Integer off = 0;
for (Integer projId : projIds) {
@ -429,11 +428,11 @@ public class TubeStateMgr {
return nextTubeIndex;
}
synchronized public Boolean isTubeHolderProcessCompleted() {
return tubeHolder.getState().equals(TubeHolderState.IDLE);
synchronized public TubeHolderState getTubeholderState() {
return tubeHolder.getState();
}
synchronized public Boolean isHasSomeToBeProcessedTube() {
for (Tube tube : tubeHolder.getTubes()) {
if (tube.getState().equals(TubeState.TO_BE_PROCESSED)) {
@ -443,23 +442,19 @@ public class TubeStateMgr {
return emergencyTubePos.tube.getState().equals(TubeState.TO_BE_PROCESSED);
}
synchronized public Boolean isTubeholderHasBeenProcessed() {
/**
* 检查试管架中所有试管是否都已经被处理完成
* @return 如果所有试管都已经被处理完成则返回true否则返回false
*/
synchronized public Boolean isAllTubeInTubeholderHasBeenProcessed() {
for (Tube tube : tubeHolder.getTubes()) {
if ((!tube.getState().equals(TubeState.EMPTY) &&
!tube.getState().equals(TubeState.PROCESS_COMPLETE) &&
!tube.getState().equals(TubeState.ERROR)
)) {
if(tube.getState().isNotEq(TubeState.EMPTY, TubeState.PROCESS_COMPLETE, TubeState.ERROR)) {
return false;
}
}
return true;
}
synchronized public Boolean isTubeHolderInProcessing() {
return !tubeHolder.getState().equals(TubeHolderState.IDLE);
}
synchronized public Boolean isHasEmergencyTubeToBeProcessed() {
return emergencyTubePos.tube.getState().equals(TubeState.TO_BE_PROCESSED);
}

4
src/main/java/a8k/app/service/utils/ProjInfoReader.java

@ -1,14 +1,14 @@
package a8k.app.service.utils;
import a8k.app.type.a8k.BloodType;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ProjInfoReader {
static public Integer getSampleVol(ProjBuildinInfo buildinInfo, ProjExtInfoCard extInfoCard, BloodType bloodType) {
static public Integer getSampleVol(ProjBuildInInfo buildinInfo, ProjExtInfoCard extInfoCard, BloodType bloodType) {
if (bloodType.equals(BloodType.WHOLE_BLOOD)) {
if (isEffectiveValue(extInfoCard.wBloodSampleVolUl)) {

8
src/main/java/a8k/app/service/utils/ProjInfoUtils.java

@ -1,6 +1,6 @@
package a8k.app.service.utils;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.type.a8k.proj.ProjBriefInfo;
@ -9,7 +9,7 @@ import java.util.List;
public class ProjInfoUtils {
static public ProjBriefInfo buildProjBrefInfo(ProjBuildinInfo buildinInfo) {
static public ProjBriefInfo buildProjBrefInfo(ProjBuildInInfo buildinInfo) {
ProjBriefInfo projBriefInfo = new ProjBriefInfo();
projBriefInfo.projId = buildinInfo.projId;
projBriefInfo.projName = buildinInfo.projName;
@ -18,9 +18,9 @@ public class ProjInfoUtils {
return projBriefInfo;
}
static public List<ProjBriefInfo> buidProjBriefInfoList(List<ProjBuildinInfo> projBuildinInfos) {
static public List<ProjBriefInfo> buidProjBriefInfoList(List<ProjBuildInInfo> projBuildInInfos) {
List<ProjBriefInfo> projBriefInfos = new ArrayList<>();
for (ProjBuildinInfo projBuildinInfo : projBuildinInfos) {
for (ProjBuildInInfo projBuildinInfo : projBuildInInfos) {
ProjBriefInfo projBriefInfo = buildProjBrefInfo(projBuildinInfo);
projBriefInfos.add(projBriefInfo);
}

3
src/main/java/a8k/app/teststate/TestStateMgrService.java

@ -4,6 +4,7 @@ package a8k.app.teststate;
import a8k.app.service.lowerctrl.ConsumablesScanCtrlService;
import a8k.app.service.lowerctrl.TubeFeedingCtrlService;
import a8k.app.service.utils.ReactionPlate2DCodeHelper;
import a8k.app.type.misc.TubeHolderScanResult;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
@ -18,7 +19,7 @@ public class TestStateMgrService {
* 插入虚拟的试管架扫描结果
* @param scanResult 试管架扫描结果
*/
public void insertVirtualBloodTubeHolder(TubeFeedingCtrlService.TubeHolderScanResult scanResult) {
public void insertVirtualBloodTubeHolder(TubeHolderScanResult scanResult) {
tubeFeedingCtrlService.setVirtualTubeScanResult(scanResult);
}

6
src/main/java/a8k/app/type/a8k/proj/ProjInfo.java

@ -1,15 +1,15 @@
package a8k.app.type.a8k.proj;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import java.io.Serializable;
public class ProjInfo implements Serializable {
public ProjBuildinInfo buildIn;
public ProjBuildInInfo buildIn;
public ProjExtInfoCard ext;
public ProjInfo(ProjBuildinInfo buildIn, ProjExtInfoCard ext) {
public ProjInfo(ProjBuildInInfo buildIn, ProjExtInfoCard ext) {
this.buildIn = buildIn;
this.ext = ext;
}

5
src/main/java/a8k/app/type/a8k/state/IncubationSubTank.java

@ -1,6 +1,5 @@
package a8k.app.type.a8k.state;
import a8k.app.service.statemgr.ConsumablesMgrService;
import a8k.app.type.a8k.pos.ConsumableInfo;
import a8k.app.type.a8k.state.enumtype.IncubationSubTankState;
import a8k.app.type.a8k.pos.IncubatorPos;
@ -8,7 +7,7 @@ import a8k.app.type.error.AppError;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.proj.ProjBriefInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
@ -42,7 +41,7 @@ public class IncubationSubTank implements Serializable {
public ProjExtInfoCard projExtInfoCard = null;
@JsonIgnore
public ProjBuildinInfo projBuildinInfo = null;
public ProjBuildInInfo projBuildinInfo = null;
public String lotId = ""; //批次号

4
src/main/java/a8k/app/type/a8k/state/OptScanModuleState.java

@ -5,7 +5,7 @@ import a8k.app.type.a8k.state.enumtype.OptScanModuleStateEnum;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.proj.ProjBriefInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -39,7 +39,7 @@ public class OptScanModuleState implements Serializable {
@JsonIgnore
ProjExtInfoCard projExtInfoCard;
@JsonIgnore
ProjBuildinInfo projBuildinInfo;
ProjBuildInInfo projBuildinInfo;
Boolean cleared = false; //是否被清空过

11
src/main/java/a8k/app/type/a8k/state/ProjectPreProcessContext.java

@ -1,19 +1,20 @@
package a8k.app.type.a8k.state;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.service.statemgr.ConsumablesMgrService;
import a8k.app.type.a8k.pos.ConsumableInfo;
import a8k.app.type.a8k.pos.IncubatorPos;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class ProjectPreProcessContext {
import java.io.Serializable;
public class ProjectPreProcessContext implements Serializable {
public String cxtId = "";
public SampleInfo sampleInfo = null;
public ConsumableInfo consumableInfo = null; //耗材信息
public Integer projId = 0; //项目ID
@JsonIgnore
public ProjBuildinInfo projBuildinInfo;
public ProjBuildInInfo projBuildinInfo;
@JsonIgnore
public ProjExtInfoCard projExtInfoCard;
public IncubatorPos incubatorPos = null; //孵育盘位置
@ -21,7 +22,7 @@ public class ProjectPreProcessContext {
public ProjectPreProcessContext(SampleInfo sampleInfo,
ConsumableInfo consumableInfo,
Integer projId,
ProjBuildinInfo projBuildinInfo,
ProjBuildInInfo projBuildinInfo,
ProjExtInfoCard projExtInfoCard, Integer off) {
this.cxtId = String.format("{}-{}-{}", sampleInfo.sampleId, projId, off);
this.sampleInfo = sampleInfo;

6
src/main/java/a8k/app/type/a8k/state/Tube.java

@ -5,7 +5,7 @@ import a8k.app.type.a8k.state.enumtype.TubeState;
import a8k.app.type.error.AppError;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.proj.ProjBriefInfo;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -45,12 +45,10 @@ public class Tube implements Serializable {
List<AppError> errors = new ArrayList<>(); //错误信息
List<ProjectPreProcessContext> preProcessContexts = new ArrayList<>(); //预处理上下文
@JsonIgnore
A8kTubeHolderType tubeHolderType = null;
@JsonIgnore
List<ProjBuildinInfo> projBuildinInfos = new ArrayList<>();
List<ProjBuildInInfo> projBuildInInfos = new ArrayList<>();
public Tube(Integer pos) {
this.pos = pos;

8
src/main/java/a8k/app/type/a8k/state/TubeInfo.java

@ -1,14 +1,6 @@
package a8k.app.type.a8k.state;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.type.a8k.A8kTubeHolderType;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.proj.ProjBriefInfo;
import a8k.app.type.a8k.state.enumtype.TubeState;
import a8k.app.type.error.AppError;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;

12
src/main/java/a8k/app/type/a8k/state/enumtype/TubeState.java

@ -12,8 +12,7 @@ public enum TubeState {
;
public Boolean isEq(TubeState ... states) {
public Boolean isEq(TubeState... states) {
for (TubeState state : states) {
if (this.equals(state)) {
return true;
@ -21,4 +20,13 @@ public enum TubeState {
}
return false;
}
public Boolean isNotEq(TubeState... states) {
for (TubeState state : states) {
if (this.equals(state)) {
return false;
}
}
return true;
}
}

22
src/main/java/a8k/app/type/misc/TubeHolderScanResult.java

@ -0,0 +1,22 @@
package a8k.app.type.misc;
import java.util.Arrays;
public class TubeHolderScanResult {
public TubeScanResult[] tube = new TubeScanResult[10];
public String tubeHolderType = "";
public Boolean isVirtual = false;
public String toString() {
return String.format("%s %s", tubeHolderType, Arrays.toString(tube));
}
public Boolean isHasTubeInIt() {
for (TubeScanResult tubeScanResult : tube) {
if (tubeScanResult.isTubeExist) {
return true;
}
}
return false;
}
}

24
src/main/java/a8k/app/type/misc/TubeScanResult.java

@ -0,0 +1,24 @@
package a8k.app.type.misc;
public class TubeScanResult {
public Boolean isTubeExist = false;
public Boolean isHighTube = false;
public String tubeCode = null;
public TubeScanResult() {
}
public TubeScanResult(Boolean isTubeExist, Boolean isHighTube, String tubeCode) {
this.isTubeExist = isTubeExist;
this.isHighTube = isHighTube;
this.tubeCode = tubeCode;
}
public String toString() {
if (isTubeExist) {
return String.format("Has(Code:%s IsH:%s)", tubeCode, isHighTube ? "High" : "Low");
} else {
return "None";
}
}
}

4
src/main/java/a8k/extui/factory/ProjExtInfoCardFactory.java

@ -7,7 +7,7 @@ import a8k.app.type.a8k.optfn.A8kNormalFn;
import a8k.app.type.a8k.optfn.A8kPiecewiseFn;
import a8k.app.type.a8k.optfn.A8kFnType;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import java.util.Date;
@ -18,7 +18,7 @@ public class ProjExtInfoCardFactory {
ProjInfoMgrService projInfoMgrService = SpringBootBeanUtil.getBean(ProjInfoMgrService.class);
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projId);
ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projId);
if (lotId == null || lotId.isEmpty()) {
lotId = String.format("%s000000", projBuildinInfo.projShortName);

6
src/main/java/a8k/extui/page/debug/P01ProjInfoDebugPage.java

@ -7,7 +7,7 @@ import a8k.extui.factory.ProjExtInfoCardFactory;
import a8k.app.service.data.ProjIdCardInfoMgrService;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.utils.ZDateUtils;
import a8k.extui.mgr.ExtApiPageMgr;
import a8k.extui.type.ExtApiStatu;
@ -49,8 +49,8 @@ public class P01ProjInfoDebugPage {
}
public String addAllProjFakeProjInfoCard() throws AppException {
List<ProjBuildinInfo> projBuildinInfos = projInfoMgrService.getAllProjBuildInInfo();
for (ProjBuildinInfo projBuildinInfo : projBuildinInfos) {
List<ProjBuildInInfo> projBuildInInfos = projInfoMgrService.getAllProjBuildInInfo();
for (ProjBuildInInfo projBuildinInfo : projBuildInInfos) {
ProjExtInfoCard projExtInfoCard = ProjExtInfoCardFactory.buildProjExtInfoCard(projBuildinInfo.projId, null);
projIdCardInfoMgrService.saveProjExtInfoCard(projExtInfoCard);
}

6
src/main/java/a8k/extui/page/extapp/A8kOptVerification.java

@ -23,7 +23,7 @@ import a8k.app.type.a8k.opt.A8kOptType;
import a8k.app.type.a8k.ConsumableGroup;
import a8k.app.type.a8k.pos.IncubatorPos;
import a8k.app.type.exception.AppException;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
@ -127,7 +127,7 @@ public class A8kOptVerification {
public A8kOptType optType;
public A8kScanCurve optScanCurve;
public OptScanResult optScanResult;
public ProjBuildinInfo projInfo;
public ProjBuildInInfo projInfo;
public Integer subProjIndex;
}
@ -142,7 +142,7 @@ public class A8kOptVerification {
return null;
}
public void generateOptReport(ProjBuildinInfo info, Integer subProjIndex, OptScanResult optScanResult)
public void generateOptReport(ProjBuildInInfo info, Integer subProjIndex, OptScanResult optScanResult)
throws IOException {
OptScanReport report = new OptScanReport();
report.optScanCurve = A8kScanCurveFactory.createScanCurve1200Point(optScanResult.rawData.rawData);

4
src/main/java/a8k/extui/page/extapp/OptModuleParamCalibration.java

@ -1,6 +1,6 @@
package a8k.extui.page.extapp;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.optalgo.type.A8kOptPeakInfo;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.type.a8k.ConsumableGroup;
@ -180,7 +180,7 @@ public class OptModuleParamCalibration {
A8kScanCurve optScanCurve = null;
public A8kOptPeakInfo doOptScan(Integer projId, Integer subProjIndex) throws AppException {
ProjBuildinInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projId);
ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projId);
var result = optScanModuleCtrlService.optScan(projBuildinInfo, subProjIndex);
optScanCurve = A8kScanCurveFactory.createScanCurve1200Point(result.rawData.rawData);
return result.analysResult;

25
src/main/java/a8k/extui/page/extapp/UsrOperationSimulationPage.java

@ -1,10 +1,11 @@
package a8k.extui.page.extapp;
import a8k.app.service.lowerctrl.TubeFeedingCtrlService;
import a8k.app.type.a8k.A8kTubeHolderType;
import a8k.app.type.a8k.ConsumableGroup;
import a8k.app.type.exception.AppException;
import a8k.app.dao.type.db.ProjExtInfoCard;
import a8k.app.type.misc.TubeHolderScanResult;
import a8k.app.type.misc.TubeScanResult;
import a8k.extui.factory.ProjExtInfoCardFactory;
import a8k.app.service.data.ProjIdCardInfoMgrService;
import a8k.app.service.data.ProjInfoMgrService;
@ -66,18 +67,18 @@ public class UsrOperationSimulationPage {
public void putInVirtualBloodTubeHolder() throws AppException {
gstate.checkIfIsInVirtualModeOrRunOnlyMode();
TubeFeedingCtrlService.TubeHolderScanResult scanResult = new TubeFeedingCtrlService.TubeHolderScanResult();
TubeHolderScanResult scanResult = new TubeHolderScanResult();
scanResult.tubeHolderType = A8kTubeHolderType.BloodTube.scanCode;
scanResult.tube[0] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[1] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[2] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[3] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[4] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[5] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[6] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[7] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[8] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[9] = new TubeFeedingCtrlService.TubesScanResult(true, true, "");
scanResult.tube[0] = new TubeScanResult(true, true, "");
scanResult.tube[1] = new TubeScanResult(true, true, "");
scanResult.tube[2] = new TubeScanResult(true, true, "");
scanResult.tube[3] = new TubeScanResult(true, true, "");
scanResult.tube[4] = new TubeScanResult(true, true, "");
scanResult.tube[5] = new TubeScanResult(true, true, "");
scanResult.tube[6] = new TubeScanResult(true, true, "");
scanResult.tube[7] = new TubeScanResult(true, true, "");
scanResult.tube[8] = new TubeScanResult(true, true, "");
scanResult.tube[9] = new TubeScanResult(true, true, "");
testStateMgrService.insertVirtualBloodTubeHolder(scanResult);
}

6
src/main/java/a8k/extui/page/extapp/debug_assistant/IDCardDataGeneratorPage.java

@ -6,7 +6,7 @@ import a8k.extui.factory.ProjExtInfoCardFactory;
import a8k.app.service.data.ProjIdCardInfoMgrService;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.extui.mgr.ExtApiPageMgr;
import a8k.extui.type.ExtApiStatu;
import jakarta.annotation.PostConstruct;
@ -44,8 +44,8 @@ public class IDCardDataGeneratorPage {
}
public String addAllProjFakeProjInfoCard() throws AppException {
List<ProjBuildinInfo> projBuildinInfos = projInfoMgrService.getAllProjBuildInInfo();
for (ProjBuildinInfo projBuildinInfo : projBuildinInfos) {
List<ProjBuildInInfo> projBuildInInfos = projInfoMgrService.getAllProjBuildInInfo();
for (ProjBuildInInfo projBuildinInfo : projBuildInInfos) {
ProjExtInfoCard projExtInfoCard = ProjExtInfoCardFactory.buildProjExtInfoCard(projBuildinInfo.projId, null);
projIdCardInfoMgrService.saveProjExtInfoCard(projExtInfoCard);
}

6
src/main/java/a8k/extui/page/extsetting/db/ProjInfoMgrPage.java

@ -5,7 +5,7 @@ import a8k.app.controler.filemgr.StorageControler;
import a8k.app.dao.ProjectBaseInfoDao;
import a8k.app.service.data.ProjIdCardInfoMgrService;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.dao.type.combination.ProjBuildinInfo;
import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.extui.mgr.ExtApiPageMgr;
import a8k.extui.type.ExtUIPageCfg;
import a8k.extui.type.ExtUiTable;
@ -49,11 +49,11 @@ public class ProjInfoMgrPage {
public ExtUiTable getProjInfoBreifList() throws AppException {
var allproj = projInfoMgrService.getAllProjBuildInInfo();
return new ExtUiTable(ProjBuildinInfo.class, allproj);
return new ExtUiTable(ProjBuildInInfo.class, allproj);
}
public ProjBuildinInfo getProjInfoById(Integer projId) throws AppException {
public ProjBuildInInfo getProjInfoById(Integer projId) throws AppException {
return projInfoMgrService.getProjBuildInInfo(projId);
}

15
src/main/java/a8k/extui/page/test/verification/P30InfeedAndPreProcessPosVerificationPage.java

@ -2,6 +2,7 @@ package a8k.extui.page.test.verification;
import a8k.app.type.exception.AppException;
import a8k.app.service.lowerctrl.*;
import a8k.app.type.misc.TubeHolderScanResult;
import a8k.extui.mgr.ExtApiPageMgr;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
@ -21,7 +22,7 @@ public class P30InfeedAndPreProcessPosVerificationPage {
}
//移动到试管架存在检测位置
public String moveAndjudgeTubeExist(Integer tubeIndex) throws AppException {
public String moveAndJudgeTubeExist(Integer tubeIndex) throws AppException {
boolean exit = tubeFeedingCtrlService.moveAndjudgeTubeExist(tubeIndex - 1);
return exit ? "存在" : "不存在";
}
@ -32,13 +33,11 @@ public class P30InfeedAndPreProcessPosVerificationPage {
}
public String moveToTubeScanPosAndScan(Integer tubeIndex) throws AppException {
String code = tubeFeedingCtrlService.moveToTubeScanPosAndScan(tubeIndex - 1);
return code;
return tubeFeedingCtrlService.moveToTubeScanPosAndScan(tubeIndex - 1);
}
public String moveToTubeRackScanPosAndScan() throws AppException {
var code = tubeFeedingCtrlService.moveToTubeRackScanPosAndScan();
return code;
return tubeFeedingCtrlService.moveToTubeRackScanPosAndScan();
}
@ -47,8 +46,8 @@ public class P30InfeedAndPreProcessPosVerificationPage {
* @return 管架扫描结果
* @throws AppException ae
*/
public TubeFeedingCtrlService.TubeHolderScanResult scanTubeHolder() throws AppException {
TubeFeedingCtrlService.TubeHolderScanResult result = tubeFeedingCtrlService.enterAndScanTubeHodler();
public TubeHolderScanResult scanTubeHolder() throws AppException {
TubeHolderScanResult result = tubeFeedingCtrlService.enterAndScanTubeholder();
tubeFeedingCtrlService.ejectTubeHolder();
return result;
}
@ -114,7 +113,7 @@ public class P30InfeedAndPreProcessPosVerificationPage {
page.newGroup("入料操作");
page.addFunction("入料", this::enterTubeHolder);
page.addFunction("移动到[试管]扫描位置,并扫描", this::moveToTubeScanPosAndScan).setParamVal("tubeIndex",()-> 1);
page.addFunction("移动到[试管]存在检测位置,并判断", this::moveAndjudgeTubeExist).setParamVal("tubeIndex", ()->1);
page.addFunction("移动到[试管]存在检测位置,并判断", this::moveAndJudgeTubeExist).setParamVal("tubeIndex", ()->1);
page.addFunction("移动到[试管]高低检测位置,并判断", this::moveAndJudgeTubeAltit).setParamVal("tubeIndex", ()->1);
page.addFunction("移动到[试管]预处理位置", this::moveTubeToPreProcessPos).setParamVal("tubeIndex",()-> 1);
page.addFunction("移动到[试管架]扫描位置,并扫描", this::moveToTubeRackScanPosAndScan);

5
src/main/java/a8k/extui/page/test/verification/P50VerificationScriptPage.java

@ -11,6 +11,7 @@ import a8k.app.hardware.driver.*;
import a8k.app.service.lowerctrl.TubeFeedingCtrlService;
import a8k.app.service.lowerctrl.TubePreProcessModuleExCtrlService;
import a8k.app.service.lowerctrl.*;
import a8k.app.type.misc.TubeHolderScanResult;
import a8k.extui.mgr.ExtApiPageMgr;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
@ -26,7 +27,7 @@ public class P50VerificationScriptPage {
@Resource
TubePreProcessModuleExCtrlService tubePreProcessModuleExCtrlService;
TubeFeedingCtrlService.TubeHolderScanResult tubeHolderScanResult;
TubeHolderScanResult tubeHolderScanResult;
@Resource
@ -51,7 +52,7 @@ public class P50VerificationScriptPage {
throw AppException.ofAECodeError("入料失败");
}
tubeHolderScanResult = tubeFeedingCtrlService.enterAndScanTubeHodler();
tubeHolderScanResult = tubeFeedingCtrlService.enterAndScanTubeholder();
if (tubeHolderScanResult == null) {
tubeFeedingCtrlService.ejectTubeHolder();
throw AppException.ofAECodeError("扫描试管架失败");

Loading…
Cancel
Save