From c1147166fdee0af9460b85d0284e563b3db41b9a Mon Sep 17 00:00:00 2001 From: zhaohe Date: Mon, 16 Jun 2025 13:52:58 +0800 Subject: [PATCH] fix some bug --- .../a8k/app/constant/ActionOvertimeConstant.java | 6 +- .../java/a8k/app/dao/AppStatePersistenceDao.java | 84 +++++++++++++++++++- .../java/a8k/app/dao/type/db/ReactionReport.java | 28 +++++-- .../java/a8k/app/optalgo/A8kOptCurveAnalyzer.java | 8 +- src/main/java/a8k/app/optalgo/A8kPeakAnalyzer.java | 10 +-- .../a8k/app/service/data/ProjInfoMgrService.java | 20 +++-- .../app/service/data/ReactionRecordMgrService.java | 4 +- .../mainctrl/AppConsumablesScanService.java | 68 +--------------- .../service/mainctrl/AppDeviceInitCtrlService.java | 22 ++++-- .../service/statemgr/ConsumablesMgrService.java | 91 ++++++++++++++++++++++ .../a8k/app/service/statemgr/GStateMgrService.java | 1 + .../ReactionPlateContainerStateMgr.java | 12 +++ .../statemgr/consumables_mgr/TipStateMgr.java | 8 +- .../java/a8k/app/type/SimpleReactionReport.java | 52 +++++++++++++ src/main/java/a8k/app/type/a8k/opt/A8kOptPeak.java | 5 +- src/main/java/a8k/app/utils/ZSqliteJdbcHelper.java | 5 +- .../extsetting/db/ReactionRecordMgrDebugPage.java | 9 ++- .../extui/page/optalgotest/OptAlgoTestPage.java | 3 +- 18 files changed, 326 insertions(+), 110 deletions(-) create mode 100644 src/main/java/a8k/app/type/SimpleReactionReport.java diff --git a/src/main/java/a8k/app/constant/ActionOvertimeConstant.java b/src/main/java/a8k/app/constant/ActionOvertimeConstant.java index ca8a1fa..fe2a89b 100644 --- a/src/main/java/a8k/app/constant/ActionOvertimeConstant.java +++ b/src/main/java/a8k/app/constant/ActionOvertimeConstant.java @@ -33,10 +33,10 @@ public class ActionOvertimeConstant { pushNewConfig(StepMotorMId.FeedingModXM, CmdId.step_motor_easy_move_to_zero, 15 * 1000); pushNewConfig(StepMotorMId.FeedingModXM, CmdId.step_motor_easy_move_to_end_point, 15 * 1000); - pushNewConfig(MId.PipetteMod, CmdId.pipette_pump_distribu_all, 30 * 1000); - pushNewConfig(MId.PipetteMod, CmdId.pipette_pump_aspirate, 30 * 1000); + pushNewConfig(MId.PipetteMod, CmdId.pipette_pump_distribu_all, 60 * 1000); + pushNewConfig(MId.PipetteMod, CmdId.pipette_pump_aspirate, 60 * 1000); pushNewConfig(MId.PipetteMod, CmdId.pipette_test_lld, 30 * 1000); - pushNewConfig(MId.PipetteMod, CmdId.pipette_test_pump_move_to_x100nl, 30 * 1000); + pushNewConfig(MId.PipetteMod, CmdId.pipette_test_pump_move_to_x100nl, 60 * 1000); } diff --git a/src/main/java/a8k/app/dao/AppStatePersistenceDao.java b/src/main/java/a8k/app/dao/AppStatePersistenceDao.java index 25e8320..ac76362 100644 --- a/src/main/java/a8k/app/dao/AppStatePersistenceDao.java +++ b/src/main/java/a8k/app/dao/AppStatePersistenceDao.java @@ -1,29 +1,109 @@ package a8k.app.dao; import a8k.app.dao.type.db.KeyVal; +import a8k.app.type.a8k.ConsumableGroup; +import a8k.app.type.a8k.container.LarBottleContainer; +import a8k.app.type.a8k.container.ReactionPlateContainer; +import a8k.app.type.a8k.pos.TipGroupPos; +import a8k.app.utils.ZJsonHelper; import a8k.app.utils.ZSqlite; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; @Component @Slf4j +@RequiredArgsConstructor public class AppStatePersistenceDao extends ZSqlite { @Resource JdbcTemplate jdbcTemplate; @PostConstruct void init() { - init(jdbcTemplate, "zapp_state_persistence_dao", KeyVal.class, false); + init(jdbcTemplate, "zapp_state_persistence", KeyVal.class, false); } - void storage(String key, String val) { + + public void setTipGroupNum(TipGroupPos pos, Integer num) { + if (pos == null || num == null) { + log.error("pos or num is null, pos: {}, num: {}", pos, num); + return; + } + String key = pos.name() + "/tipNum"; + String val = String.valueOf(num); + storage(key, val); + } + + public Integer getTipGroupNum(TipGroupPos pos) { + if (pos == null) { + log.error("pos is null"); + return 0; + } + String key = pos.name() + "/tipNum"; + KeyVal keyVal = get(key); + if (keyVal == null || keyVal.val == null) { + log.warn("No value found for key: {}", key); + return 0; + } + try { + return Integer.valueOf(keyVal.val); + } catch (NumberFormatException e) { + return 0; + } + } + + public void syncReactionPlateContainerState(ConsumableGroup group, ReactionPlateContainer reactionPlateContainer) { + if (group == null || reactionPlateContainer == null) { + log.error("group or reactionPlateContainer is null, group: {}, reactionPlateContainer: {}", group, reactionPlateContainer); + return; + } + String key = group.name() + "/reactionPlateContainer"; + String val = ZJsonHelper.objectToJson(reactionPlateContainer); + storage(key, val); + } + + public ReactionPlateContainer getReactionPlateContainer(ConsumableGroup group) { + if (group == null) { + return null; + } + String key = group.name() + "/reactionPlateContainer"; + KeyVal keyVal = get(key); + if (keyVal == null || keyVal.val == null) { + return null; + } + try { + return ZJsonHelper.objectFromJson(keyVal.val, ReactionPlateContainer.class); + } catch (Exception e) { + log.error("Failed to parse ReactionPlateContainer from JSON: {}", keyVal.val, e); + return null; + } + } + + private void storage(String key, String val) { if (key == null || val == null) { log.error("key or val is null, key: {}, val: {}", key, val); return; } + KeyVal keyVal = get(key); + if (keyVal == null) { + keyVal = new KeyVal(); + keyVal.key = key; + keyVal.val = val; + add(keyVal); + } else { + keyVal.val = val; + update(keyVal); + } } + private KeyVal get(String key) { + if (key == null) { + log.error("key is null"); + return null; + } + return queryOne("select * from " + tableName + " where key = ?", key); + } } diff --git a/src/main/java/a8k/app/dao/type/db/ReactionReport.java b/src/main/java/a8k/app/dao/type/db/ReactionReport.java index ab755c9..ede2e7e 100644 --- a/src/main/java/a8k/app/dao/type/db/ReactionReport.java +++ b/src/main/java/a8k/app/dao/type/db/ReactionReport.java @@ -36,6 +36,10 @@ import java.util.List; */ @Data public class ReactionReport implements Serializable { //记录单个反应板的反应结果 + + //**************************************************************************** + // INTER CLASS + //**************************************************************************** public static class ReactionResult { @Schema(description = "反应结果状态") public ReactionResultStatus status = ReactionResultStatus.DISABLED; @@ -74,8 +78,17 @@ public class ReactionReport implements Serializable { //记录单个反应板的 public String toString() { return ZJsonHelper.objectToJson(this); } + + public String toBriefString() { + if (!status.equals(ReactionResultStatus.SUCCESS)) { + return String.format("%s", status); + } + return String.format("%s %s", resultConverters.get(0).convert(result), resultConverters.get(0).uintstr); + } + } + public int id = 0; @Schema(description = "记录创建时间(ms)") @@ -89,8 +102,8 @@ public class ReactionReport implements Serializable { //记录单个反应板的 public String sampleUserid = ""; //用户输入的样本ID,不做逻辑,只做展示 @Schema(description = "样本ID(系统生成用于追溯)") public String sampleId = ""; // 样本ID,由系统生成 -// @Schema(description = "是否是急诊", example = "false") -// public Boolean sampleIsEmergency = false; // 是否急诊 + @Schema(description = "是否是急诊", example = "false") + public Boolean sampleIsEmergency = false; // 是否急诊 //项目信息 @Schema(description = "项目名称", example = "Tn-I/CK-MB/Myoglobin") @@ -125,15 +138,16 @@ public class ReactionReport implements Serializable { //记录单个反应板的 public Integer subProjNum = 0; //子项目数量 - - @Schema(description = "详细结果") - public List results = new java.util.ArrayList<>(); //结果 - @Schema(description = "扫描结果") @JsonIgnore public List detailOptData = new ArrayList<>();// 扫描上下文数据(包含原始结果,扫描参数,扫描原始数据) -// public ProjExtInfoCard projExtInfoCard; + @JsonIgnore + public ProjExtInfoCard projExtInfoCard; + + + @Schema(description = "详细结果") + public List results = new java.util.ArrayList<>(); //结果 public OptScanResult getOptData(int subProjIndex) { diff --git a/src/main/java/a8k/app/optalgo/A8kOptCurveAnalyzer.java b/src/main/java/a8k/app/optalgo/A8kOptCurveAnalyzer.java index 1b2620a..2dc5ae2 100644 --- a/src/main/java/a8k/app/optalgo/A8kOptCurveAnalyzer.java +++ b/src/main/java/a8k/app/optalgo/A8kOptCurveAnalyzer.java @@ -6,13 +6,11 @@ import a8k.app.optalgo.algo.LinearRegressionCalculator; import a8k.app.optalgo.algo.SubSampling; import a8k.app.optalgo.algo.SupperSampling; import a8k.app.optalgo.type.A8kOptPeakInfo; -import a8k.app.optalgo.type.PeakPresetPosConfig; import a8k.app.optalgo.version.OptAlogVersion; import a8k.app.type.a8k.container.A8kOptPeakContainer; import a8k.app.type.a8k.opt.A8kOptPeak; import a8k.app.type.a8k.opt.PeakName; import a8k.app.type.a8k.opt.PeakQuotient; -import a8k.app.utils.ZJsonHelper; import cn.hutool.core.util.ArrayUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.util.Assert; @@ -85,7 +83,7 @@ public class A8kOptCurveAnalyzer { //计算峰的面积 for (int i = 0; i < 5; i++) { A8kOptPeak peak = peaks.getPeak(i); - if (peak.isFindPeak()) { + if (peak.judgeIsFindPeak()) { peak.area = computePeakArea(afSubSampling, peak.peakStartPos, peak.peakEndPos); } } @@ -100,8 +98,8 @@ public class A8kOptCurveAnalyzer { if (!curPeak.peakName.equals(PeakName.N)) { findPeak(avg, (off + 1) * 40, 40, curPeak); - if (curPeak.isFindPeak()) { - if (prePeak == null || prePeak.peakName.equals(PeakName.N) || !prePeak.isFindPeak()) { + if (curPeak.judgeIsFindPeak()) { + if (prePeak == null || prePeak.peakName.equals(PeakName.N) || !prePeak.judgeIsFindPeak()) { curPeak.peakStartPos = curPeak.peakPos - 20; // 20个点的中间位置 } else { curPeak.peakStartPos = (prePeak.peakPos + curPeak.peakPos) / 2; diff --git a/src/main/java/a8k/app/optalgo/A8kPeakAnalyzer.java b/src/main/java/a8k/app/optalgo/A8kPeakAnalyzer.java index 6fda628..f515f27 100644 --- a/src/main/java/a8k/app/optalgo/A8kPeakAnalyzer.java +++ b/src/main/java/a8k/app/optalgo/A8kPeakAnalyzer.java @@ -299,23 +299,23 @@ public class A8kPeakAnalyzer { for (var peak : optCfg.peakConfig) { switch (peak) { case T4 -> { - if (!a8kOptPeakInfo.T4.isFindPeak()) + if (!a8kOptPeakInfo.T4.judgeIsFindPeak()) throw A8kOptProcessExceptionFactory.create(ReactionResultStatus.ERROR_LOST_PEAK_T4); } case R -> { - if (!a8kOptPeakInfo.R.isFindPeak()) + if (!a8kOptPeakInfo.R.judgeIsFindPeak()) throw A8kOptProcessExceptionFactory.create(ReactionResultStatus.ERROR_LOST_PEAK_R); } case H -> { - if (!a8kOptPeakInfo.H.isFindPeak()) + if (!a8kOptPeakInfo.H.judgeIsFindPeak()) throw A8kOptProcessExceptionFactory.create(ReactionResultStatus.ERROR_LOST_PEAK_H); } case T -> { - if (!a8kOptPeakInfo.T.isFindPeak()) + if (!a8kOptPeakInfo.T.judgeIsFindPeak()) throw A8kOptProcessExceptionFactory.create(ReactionResultStatus.ERROR_LOST_PEAK_T); } case C -> { - if (!a8kOptPeakInfo.C.isFindPeak()) + if (!a8kOptPeakInfo.C.judgeIsFindPeak()) throw A8kOptProcessExceptionFactory.create(ReactionResultStatus.ERROR_LOST_PEAK_C); } case N -> { diff --git a/src/main/java/a8k/app/service/data/ProjInfoMgrService.java b/src/main/java/a8k/app/service/data/ProjInfoMgrService.java index 591fea3..95cdde2 100644 --- a/src/main/java/a8k/app/service/data/ProjInfoMgrService.java +++ b/src/main/java/a8k/app/service/data/ProjInfoMgrService.java @@ -27,11 +27,11 @@ import java.util.List; public class ProjInfoMgrService { @Resource - A8kProjExtInfoCardDao a8KProjExtInfoCardDao; + A8kProjExtInfoCardDao a8KProjExtInfoCardDao; @Resource - ProjectBaseInfoDao projectBaseInfoDao; + ProjectBaseInfoDao projectBaseInfoDao; @Resource - ProjOptInfoDao projOptInfoDao; + ProjOptInfoDao projOptInfoDao; public ProjBuildInInfo getProjBuildInInfo(Integer projId) throws AppException { @@ -63,16 +63,24 @@ public class ProjInfoMgrService { } public ProjExtInfoCard getProjExtInfoCard(String lotid) { + if (getMountedProjInfoCard() != null && getMountedProjInfoCard().lotId.equals(lotid)) { + return getMountedProjInfoCard(); + } return a8KProjExtInfoCardDao.getByLotId(lotid); } public ProjExtInfoCard getMountedProjInfoCard() { - var service = SpringBootBeanUtil.getBean(ProjIDCardCtrlAndMonitorService.class); - return service.getMountedIdCardInfo(); + try { + var service = SpringBootBeanUtil.getBean(ProjIDCardCtrlAndMonitorService.class); + return service.getMountedIdCardInfo(); + } catch (Exception e) { + return null; + } } + public ProjBuildInInfo getProjBuildInInfoByMountedCard() throws AppException { var mountedIdCardInfo = getMountedProjInfoCard(); - if(mountedIdCardInfo == null){ + if (mountedIdCardInfo == null) { return null; } return getProjBuildInInfo(mountedIdCardInfo.projId); diff --git a/src/main/java/a8k/app/service/data/ReactionRecordMgrService.java b/src/main/java/a8k/app/service/data/ReactionRecordMgrService.java index 630c49d..80ddd31 100644 --- a/src/main/java/a8k/app/service/data/ReactionRecordMgrService.java +++ b/src/main/java/a8k/app/service/data/ReactionRecordMgrService.java @@ -48,11 +48,11 @@ public class ReactionRecordMgrService { record.sampleBarcode = sampleInfo.sampleBarcode; record.sampleUserid = sampleInfo.userid; record.sampleId = sampleInfo.sampleId; -// record.sampleIsEmergency = sampleInfo.isEmergency; + record.sampleIsEmergency = sampleInfo.isEmergency; record.projName = projInfo.buildIn.projName; record.lotId = projInfo.ext.lotId; record.projId = projInfo.ext.projId; -// record.projExtInfoCard = projInfo.ext;//TODO:添加配置 支持保存和不保存ID卡信息 + record.projExtInfoCard = projInfo.ext;// record.setExpiryDate(projInfo.ext.expiryDate); record.operator = operator; record.projShortName = projInfo.ext.projShortName; diff --git a/src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java b/src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java index 8e53b4a..ae8cbab 100644 --- a/src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java +++ b/src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java @@ -214,74 +214,12 @@ public class AppConsumablesScanService { return ret; } - void loadingConsumables(Integer ch, ConsumablesScanReport result) { + void loadingConsumables(Integer ch, ConsumablesScanReport result) throws AppException { if (result.state != ConsumablesScanReportErrorType.PASS) { return; } - - ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(result.lotId); - Assert.isTrue(ch.equals(result.chNum), "ch.equals(result.chNum)"); - Assert.isTrue(projExtInfoCard != null, "projExtInfoCard != null"); - Assert.isTrue(result.projId != null, "result.projId!=null"); - Assert.isTrue(result.projId != 0, "result.projId!=0"); - - - ProjBuildInInfo projCfg = null; - try { - projCfg = projInfoMgrService.getProjBuildInInfo(projExtInfoCard.projId); - } catch (AppException e) { - throw new RuntimeException(e); - } - - - var reactionType = projCfg.reactionFlowType; - - ReactionPlateContainerInfo reactionPlateContainer = null; - LittBottleConsumablesInfo littBottleConsumablesInfo = null; - LargeBottleConsumablesInfo largeBottleConsumablesInfo = null; - - if (reactionType.equals(A8kReactionFlowType.SampleAndBS)) { - reactionPlateContainer = new ReactionPlateContainerInfo( - result.projId, - projExtInfoCard.projName, - projCfg.projShortName, - result.lotId, - projExtInfoCard.color); - - littBottleConsumablesInfo = new LittBottleConsumablesInfo( - LittleBottleConsumableType.BufferSolution, - result.projId, - projExtInfoCard.projName, - projCfg.projShortName, - result.lotId, - projExtInfoCard.color); - - } else if (reactionType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) { - reactionPlateContainer = new ReactionPlateContainerInfo( - result.projId, - projExtInfoCard.projName, - projCfg.projShortName, - result.lotId, - projExtInfoCard.color); - littBottleConsumablesInfo = new LittBottleConsumablesInfo( - LittleBottleConsumableType.ProbeSubstance, - result.projId, - projExtInfoCard.projName, - projCfg.projShortName, - result.lotId, - projExtInfoCard.color); - largeBottleConsumablesInfo = new LargeBottleConsumablesInfo( - result.projId, - projExtInfoCard.projName, - projCfg.projShortName, - result.lotId, - projExtInfoCard.color); - } else { - throw new RuntimeException("未知的反应流程类型"); - } - //更新耗材 - consumablesMgrService.installConsumable(ch, reactionPlateContainer, littBottleConsumablesInfo, largeBottleConsumablesInfo); + consumablesMgrService.installConsumable(ch, result.projId, result.lotId); } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -320,7 +258,7 @@ public class AppConsumablesScanService { // For Test Only - public void loadingConsumablesDirectly(ConsumablesScanReport result) { + public void loadingConsumablesDirectly(ConsumablesScanReport result) throws AppException { loadingConsumables(result.chNum, result); } diff --git a/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java b/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java index 76f7731..3898b43 100644 --- a/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java +++ b/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java @@ -7,6 +7,7 @@ import a8k.app.service.lowerctrl.HbotMoveCtrlService; import a8k.app.service.lowerctrl.HbotMoveExCtrlService; import a8k.app.service.lowerctrl.TubeFeedingCtrlService; import a8k.app.service.lowerctrl.TubePreProcessModuleCtrlService; +import a8k.app.service.statemgr.DeviceWorkStateMgrService; import a8k.app.type.exception.AppException; import a8k.app.type.ui.ZAppPromopt; import a8k.app.type.ui.ZAppPromoptFormsItem; @@ -87,8 +88,9 @@ public class AppDeviceInitCtrlService { private final TubeFeedingCtrlService tubeFeedingCtrlService; private final TubePreProcessModuleCtrlService tubePreProcessModuleCtrlService; private final HbotMoveExCtrlService hbotMoveExCtrlService; - private final HbotMoveCtrlService hbotMoveCtrlService; - private final A8kSubModuleRegInitService a8kSubModuleRegInitService; + private final HbotMoveCtrlService hbotMoveCtrlService; + private final A8kSubModuleRegInitService a8kSubModuleRegInitService; + private final DeviceWorkStateMgrService deviceWorkStateMgrService; private final List checkPoints = new ArrayList<>(); @@ -244,18 +246,14 @@ public class AppDeviceInitCtrlService { tubeFeedingCtrlService.ejectTubeHolder(); tubeFeedingCtrlService.moveTubeRackMoveToEnterPos(); tubeFeedingCtrlService.infeedMotorRotateBak(1000); - //初始化tip - hbotMoveExCtrlService.moveToDropTipXYPos(); - pipetteCtrlDriverV2.zMotorMoveToTipDepositBlock(); - pipetteCtrlDriverV2.initPumpDeviceBlock(); - //hbot快速归零 - hbotMoveExCtrlService.moveQuickToZero(); + //打开废料仓满溢检测光栅 outputIOCtrlDriver.setIOState(OutputIOId.RecycleBinOverflowPPSPowerCtrl, true); gstate.setDeviceInited(true); gstate.clearFatalError(); + deviceWorkStateMgrService.clearFatalErrorFlag(); return results; } @@ -267,6 +265,14 @@ public class AppDeviceInitCtrlService { pipetteCtrlDriverV2.zMotorMoveZeroBlock(); log.info("HBot回零"); hbotMoveCtrlService.moveToZero(); + + //初始化tip + hbotMoveExCtrlService.moveToDropTipXYPos(); + pipetteCtrlDriverV2.zMotorMoveToTipDepositBlock(); + pipetteCtrlDriverV2.initPumpDeviceBlock(); + //hbot快速归零 + hbotMoveExCtrlService.moveQuickToZero(); + //进出料初始化 log.info("摇匀模组扫码夹紧舵机回零"); miniServoDriver.miniServoMoveToZeroBlock(MiniServoMId.ShakeModTubeScanerClampingSV); diff --git a/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java b/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java index 4218316..95e245a 100644 --- a/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java +++ b/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java @@ -1,12 +1,16 @@ package a8k.app.service.statemgr; +import a8k.app.dao.AppStatePersistenceDao; import a8k.app.dao.type.combination.ProjBuildInInfo; +import a8k.app.dao.type.db.ProjExtInfoCard; import a8k.app.factory.FakeA8kConsumableContainerFactory; +import a8k.app.service.data.ProjInfoMgrService; import a8k.app.service.statemgr.consumables_mgr.LarBottleContainerStateMgr; import a8k.app.service.statemgr.consumables_mgr.LittBottleContainerStateMgr; import a8k.app.service.statemgr.consumables_mgr.ReactionPlateContainerStateMgr; import a8k.app.service.statemgr.consumables_mgr.TipStateMgr; import a8k.app.type.DeviceRunMode; +import a8k.app.type.a8k.LittleBottleConsumableType; import a8k.app.type.a8k.container.*; import a8k.app.type.a8k.pos.ConsumableInfo; import a8k.app.type.a8k.pos.TipPos; @@ -15,6 +19,7 @@ import a8k.app.type.exception.AppException; import a8k.app.type.a8k.ConsumableGroup; import a8k.app.type.a8k.pos.TipGroupPos; import a8k.app.hardware.type.A8kEcode; +import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -58,6 +63,27 @@ public class ConsumablesMgrService { private final TipStateMgr tipStateMgr; private final PreReactionStateMgr preReactionStateMgr; + private final AppStatePersistenceDao appStatePersistenceDao; + private final ProjInfoMgrService projInfoMgrService; + + @PostConstruct + void init() { +// for (var ch : ConsumableGroup.values()) { +// ReactionPlateContainer reactionPlateContainer = appStatePersistenceDao.getReactionPlateContainer(ch); +// if (reactionPlateContainer == null) +// continue; +// +// if (!reactionPlateContainer.isInstall) +// continue; +// +// try { +// installConsumable(ch.off, reactionPlateContainer.projId, reactionPlateContainer.lotId); +// } catch (AppException ignored) { +// } +// } + + } + //耗材状态 // private final A8kConsumableContainer cState = new A8kConsumableContainer(); @@ -171,6 +197,71 @@ public class ConsumablesMgrService { stateVersion++; } + synchronized public void installConsumable(Integer ch, Integer projId, String lotid) throws AppException { + + ProjExtInfoCard projExtInfoCard = projInfoMgrService.getProjExtInfoCard(lotid); + if (projExtInfoCard == null) { + log.error("安装耗材失败,未找到对应的项目扩展信息卡: {}", lotid); + throw AppException.of(A8kEcode.APPE_A8K_ID_CARD_NOT_MOUNTED); + } + + ProjBuildInInfo projCfg = null; + try { + projCfg = projInfoMgrService.getProjBuildInInfo(projExtInfoCard.projId); + } catch (AppException e) { + throw new RuntimeException(e); + } + + var reactionType = projCfg.reactionFlowType; + + ReactionPlateContainerInfo reactionPlateContainer = null; + LittBottleConsumablesInfo littBottleConsumablesInfo = null; + LargeBottleConsumablesInfo largeBottleConsumablesInfo = null; + + if (reactionType.equals(A8kReactionFlowType.SampleAndBS)) { + reactionPlateContainer = new ReactionPlateContainerInfo( + projId, + projExtInfoCard.projName, + projCfg.projShortName, + lotid, + projExtInfoCard.color); + + littBottleConsumablesInfo = new LittBottleConsumablesInfo( + LittleBottleConsumableType.BufferSolution, + projId, + projExtInfoCard.projName, + projCfg.projShortName, + lotid, + projExtInfoCard.color); + + } else if (reactionType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) { + reactionPlateContainer = new ReactionPlateContainerInfo( + projId, + projExtInfoCard.projName, + projCfg.projShortName, + lotid, + projExtInfoCard.color); + littBottleConsumablesInfo = new LittBottleConsumablesInfo( + LittleBottleConsumableType.ProbeSubstance, + projId, + projExtInfoCard.projName, + projCfg.projShortName, + lotid, + projExtInfoCard.color); + largeBottleConsumablesInfo = new LargeBottleConsumablesInfo( + projId, + projExtInfoCard.projName, + projCfg.projShortName, + lotid, + projExtInfoCard.color); + } else { + throw new RuntimeException("未知的反应流程类型"); + } + + //更新耗材 + installConsumable(ch, reactionPlateContainer, littBottleConsumablesInfo, largeBottleConsumablesInfo); + } + /** * 更新耗材数量(useByUI) diff --git a/src/main/java/a8k/app/service/statemgr/GStateMgrService.java b/src/main/java/a8k/app/service/statemgr/GStateMgrService.java index ed6e68b..928ca67 100644 --- a/src/main/java/a8k/app/service/statemgr/GStateMgrService.java +++ b/src/main/java/a8k/app/service/statemgr/GStateMgrService.java @@ -18,6 +18,7 @@ import org.springframework.stereotype.Component; @RequiredArgsConstructor public class GStateMgrService { private final GState gState; + private final DeviceWorkStateMgrService deviceWorkStateMgrService; public synchronized Boolean isDeviceInited() { diff --git a/src/main/java/a8k/app/service/statemgr/consumables_mgr/ReactionPlateContainerStateMgr.java b/src/main/java/a8k/app/service/statemgr/consumables_mgr/ReactionPlateContainerStateMgr.java index e5b63c9..33062c1 100644 --- a/src/main/java/a8k/app/service/statemgr/consumables_mgr/ReactionPlateContainerStateMgr.java +++ b/src/main/java/a8k/app/service/statemgr/consumables_mgr/ReactionPlateContainerStateMgr.java @@ -1,6 +1,7 @@ package a8k.app.service.statemgr.consumables_mgr; import a8k.app.constant.AppConstant; +import a8k.app.dao.AppStatePersistenceDao; import a8k.app.type.a8k.ConsumableGroup; import a8k.app.type.a8k.container.ReactionPlateContainer; import a8k.app.type.a8k.container.ReactionPlateContainerInfo; @@ -16,6 +17,7 @@ import org.springframework.util.Assert; @RequiredArgsConstructor public class ReactionPlateContainerStateMgr { + private final AppStatePersistenceDao appStatePersistenceDao; public ReactionPlateContainer[] containers = new ReactionPlateContainer[AppConstant.CONSUMABLE_CHANNEL_NUM]; @PostConstruct @@ -36,6 +38,7 @@ public class ReactionPlateContainerStateMgr { container.num = AppConstant.CONSUMABLE_NUM; container.isInstall = true; container.reserveNum = 0; + appStatePersistenceDao.syncReactionPlateContainerState(group, container); } synchronized public Boolean isAllowToBeUninstalled(ConsumableGroup group) { @@ -48,6 +51,7 @@ public class ReactionPlateContainerStateMgr { ReactionPlateContainer container = containers[group.off]; Assert.isTrue(isAllowToBeUninstalled(group), "ReactionPlateContainer is in use, cannot uninstall for group: " + group); container.reset(); + appStatePersistenceDao.syncReactionPlateContainerState(group, container); } public synchronized Boolean isInstall(ConsumableGroup group) { @@ -62,6 +66,7 @@ public class ReactionPlateContainerStateMgr { } else { log.warn("setReactionPlateNum: Reaction plate container is not installed for group: {}", group); } + appStatePersistenceDao.syncReactionPlateContainerState(group, container); } synchronized public Integer getConsumableNum(Integer projId) { @@ -86,6 +91,7 @@ public class ReactionPlateContainerStateMgr { log.debug("getOneByProjId: group={}, projId={}", group, projId); container.reserveNum++; Assert.isTrue(container.reserveNum <= container.num, "Reserve number cannot exceed total number"); + appStatePersistenceDao.syncReactionPlateContainerState(group, container); return new ConsumableInfo(container.lotId, group, AppConstant.CONSUMABLE_NUM - (container.num - (container.reserveNum - 1))); } } @@ -98,6 +104,7 @@ public class ReactionPlateContainerStateMgr { ReactionPlateContainer container = containers[group.off]; if (container.isInstall && container.num > 0) { container.num--; + appStatePersistenceDao.syncReactionPlateContainerState(group, container); return true; } else { return false; @@ -115,6 +122,7 @@ public class ReactionPlateContainerStateMgr { } container.reserveNum++; Assert.isTrue(container.reserveNum <= container.num, "Reserve number cannot exceed total number"); + appStatePersistenceDao.syncReactionPlateContainerState(group, container); return group; } @@ -125,6 +133,7 @@ public class ReactionPlateContainerStateMgr { container.reserveNum--; Assert.isTrue(container.isInstall, "ReactionPlateContainer is not installed for group: " + group); Assert.isTrue(container.reserveNum >= 0, "Reserve number cannot be negative"); + appStatePersistenceDao.syncReactionPlateContainerState(group, container); } synchronized public void bak(ConsumableInfo consumable) { @@ -132,6 +141,7 @@ public class ReactionPlateContainerStateMgr { return; } bak(consumable.group); + } synchronized public void usedOne(ConsumableInfo consumable) { @@ -141,12 +151,14 @@ public class ReactionPlateContainerStateMgr { Assert.isTrue(container.reserveNum > 0, "Reserve number cannot be negative"); container.num--; container.reserveNum--; + appStatePersistenceDao.syncReactionPlateContainerState(consumable.group, container); log.info("usedOne: group={}, remaining num={}", consumable.group, container.num); } synchronized public void bakAll() { for (ReactionPlateContainer container : containers) { if (container.isInstall && container.reserveNum > 0) { + appStatePersistenceDao.syncReactionPlateContainerState(container.group, container); container.reserveNum = 0; } } diff --git a/src/main/java/a8k/app/service/statemgr/consumables_mgr/TipStateMgr.java b/src/main/java/a8k/app/service/statemgr/consumables_mgr/TipStateMgr.java index 1e029af..9521678 100644 --- a/src/main/java/a8k/app/service/statemgr/consumables_mgr/TipStateMgr.java +++ b/src/main/java/a8k/app/service/statemgr/consumables_mgr/TipStateMgr.java @@ -1,6 +1,7 @@ package a8k.app.service.statemgr.consumables_mgr; import a8k.app.constant.AppConstant; +import a8k.app.dao.AppStatePersistenceDao; import a8k.app.hardware.type.A8kEcode; import a8k.app.service.statemgr.DeviceWorkStateMgrService; import a8k.app.type.a8k.container.TipContainer; @@ -17,14 +18,15 @@ import org.springframework.stereotype.Component; @RequiredArgsConstructor public class TipStateMgr { private final DeviceWorkStateMgrService deviceWorkStateMgrService; + private final AppStatePersistenceDao appStatePersistenceDao; public TipContainer[] tips = new TipContainer[3]; @PostConstruct void init() { for (int i = 0; i < tips.length; i++) { - tips[i] = new TipContainer(); - tips[i].tipNum = 0; + tips[i] = new TipContainer(); + tips[i].tipNum = appStatePersistenceDao.getTipGroupNum(TipGroupPos.fromInt(i)); tips[i].tipGroupPos = TipGroupPos.fromInt(i); } } @@ -38,6 +40,7 @@ public class TipStateMgr { if (tips[i].tipNum > 0) { int tipPos = 120 - tips[i].tipNum; tips[i].tipNum--; + appStatePersistenceDao.setTipGroupNum(TipGroupPos.fromInt(i), tips[i].tipNum); TipPos ret = new TipPos(); ret.group = TipGroupPos.fromInt(i); ret.index = tipPos; @@ -67,6 +70,7 @@ public class TipStateMgr { } log.info("setTipNum: group={}, num={}", group, num); tips[group.ordinal()].tipNum = num; + appStatePersistenceDao.setTipGroupNum(group, num); } synchronized public TipPos getFirstTipPos(TipGroupPos group) { diff --git a/src/main/java/a8k/app/type/SimpleReactionReport.java b/src/main/java/a8k/app/type/SimpleReactionReport.java new file mode 100644 index 0000000..c9a689d --- /dev/null +++ b/src/main/java/a8k/app/type/SimpleReactionReport.java @@ -0,0 +1,52 @@ +package a8k.app.type; + +import a8k.app.dao.type.db.ReactionReport; +import a8k.app.type.a8k.BloodType; + +import java.util.Date; + +public class SimpleReactionReport { + public int id = 0; + + public Date creatDate = new Date(); + + public BloodType sampleBloodType = BloodType.WHOLE_BLOOD; //血液类型 + public String sampleUserid = ""; //用户输入的样本ID,不做逻辑,只做展示 + public Boolean sampleIsEmergency = false; // 是否急诊 + + //项目信息 + public String projName = ""; // 项目名称 + public String projShortName = ""; // 项目名称 + public String lotId = ""; // 批次名称 + public Integer projId = 0; // 项目名称代码 + + public String result0; + public String result1; + public String result2; + + public SimpleReactionReport(ReactionReport report) { + this.id = report.id; + this.creatDate = report.creatDate; + this.sampleBloodType = report.sampleBloodType; + this.sampleUserid = report.sampleUserid; + this.sampleIsEmergency = report.sampleIsEmergency; + + this.projName = report.projName; + this.projShortName = report.projShortName; + this.lotId = report.lotId; + this.projId = report.projId; + + if (report.results.size() == 1) { + this.result0 = report.results.get(0).toBriefString(); + } + if (report.results.size() == 2) { + this.result0 = report.results.get(0).toBriefString(); + this.result1 = report.results.get(1).toBriefString(); + } + if (report.results.size() == 3) { + this.result0 = report.results.get(0).toBriefString(); + this.result1 = report.results.get(1).toBriefString(); + this.result2 = report.results.get(2).toBriefString(); + } + } +} diff --git a/src/main/java/a8k/app/type/a8k/opt/A8kOptPeak.java b/src/main/java/a8k/app/type/a8k/opt/A8kOptPeak.java index d5174ba..e42c85b 100644 --- a/src/main/java/a8k/app/type/a8k/opt/A8kOptPeak.java +++ b/src/main/java/a8k/app/type/a8k/opt/A8kOptPeak.java @@ -1,5 +1,7 @@ package a8k.app.type.a8k.opt; +import com.fasterxml.jackson.annotation.JsonIgnore; + public class A8kOptPeak { public enum State { FIND_PEAK, @@ -32,7 +34,8 @@ public class A8kOptPeak { return val; } - public Boolean isFindPeak() { + @JsonIgnore + public Boolean judgeIsFindPeak() { return state == State.FIND_PEAK; } diff --git a/src/main/java/a8k/app/utils/ZSqliteJdbcHelper.java b/src/main/java/a8k/app/utils/ZSqliteJdbcHelper.java index 2b1ed09..f1f8ea0 100644 --- a/src/main/java/a8k/app/utils/ZSqliteJdbcHelper.java +++ b/src/main/java/a8k/app/utils/ZSqliteJdbcHelper.java @@ -3,6 +3,7 @@ package a8k.app.utils; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -130,7 +131,9 @@ public class ZSqliteJdbcHelper { } else { try { ObjectMapper objectMapper = new ObjectMapper(); - String json = rs.getString(field.getName()); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + String json = rs.getString(field.getName()); if (json == null || json.isEmpty()) { field.set(obj, null); } else { diff --git a/src/main/java/a8k/extui/page/extsetting/db/ReactionRecordMgrDebugPage.java b/src/main/java/a8k/extui/page/extsetting/db/ReactionRecordMgrDebugPage.java index f34fe0e..d3bfa24 100644 --- a/src/main/java/a8k/extui/page/extsetting/db/ReactionRecordMgrDebugPage.java +++ b/src/main/java/a8k/extui/page/extsetting/db/ReactionRecordMgrDebugPage.java @@ -1,6 +1,7 @@ package a8k.extui.page.extsetting.db; import a8k.app.service.peripheral_ctrl.PrinterService; +import a8k.app.type.SimpleReactionReport; import a8k.app.type.exception.AppException; import a8k.app.optalgo.type.ReactionResultStatus; import a8k.app.controler.filemgr.StorageControler; @@ -23,6 +24,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; @Slf4j @Component @@ -47,7 +50,11 @@ public class ReactionRecordMgrDebugPage { public ExtUiTable getReactionRecordList() { var results = reactionRecordMgrService.getAllDesc(); - return new ExtUiTable(ReactionReport.class, results); + List simpleResults = new ArrayList<>(); + for (ReactionReport report : results) { + simpleResults.add(new SimpleReactionReport(report)); + } + return new ExtUiTable(SimpleReactionReport.class, simpleResults); } public Object getReactionResult(Integer id) { diff --git a/src/main/java/a8k/extui/page/optalgotest/OptAlgoTestPage.java b/src/main/java/a8k/extui/page/optalgotest/OptAlgoTestPage.java index ad47fa4..63eb179 100644 --- a/src/main/java/a8k/extui/page/optalgotest/OptAlgoTestPage.java +++ b/src/main/java/a8k/extui/page/optalgotest/OptAlgoTestPage.java @@ -43,8 +43,7 @@ public class OptAlgoTestPage { record.detailOptData.get(subProjIndex).rawData.rawData ); -// ProjExtInfoCard projExtInfoCard = record.projExtInfoCard; - ProjExtInfoCard projExtInfoCard = null; + ProjExtInfoCard projExtInfoCard = record.projExtInfoCard; if (projExtInfoCard == null) { projExtInfoCard = projInfoMgrService.getProjExtInfoCard(record.lotId); }