From 9c92bce435060e1ced237a5204b8c6b9146e6452 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Wed, 9 Oct 2024 09:58:21 +0800 Subject: [PATCH] update --- .../appevent/A8kEcodeContextListPromptEvent.java | 2 +- .../appeventbus/appevent/DoA8kStepActionEvent.java | 2 +- .../a8k/service/appctrl/AppDeviceCtrlService.java | 5 +- .../service/appctrl/AppTubeSettingMgrService.java | 180 -------------- .../a8k/service/appctrl/CondtionMgrService.java | 151 ------------ .../service/appctrl/ConsumablesScanService.java | 31 ++- .../a8k/service/appctrl/MainFlowCtrlService.java | 11 +- .../a8k/service/appctrl/TubeSettingMgrService.java | 180 ++++++++++++++ .../appctrl/action/base/A8kActionStepType.java | 29 --- .../service/appctrl/action/base/A8kStepAction.java | 40 --- .../a8k/service/appctrl/action/ctrl/DO_PAUSE.java | 51 ---- .../a8k/service/appctrl/action/ctrl/DO_RESUME.java | 50 ---- .../a8k/service/appctrl/action/ctrl/DO_START.java | 55 ----- .../a8k/service/appctrl/action/ctrl/DO_STOP.java | 50 ---- .../errorhandler/DO_CLEAR_ERROR_BEFORE_WORK.java | 76 ------ .../errorhandler/DO_PROCESS_ERROR_PLATE.java | 82 ------- .../action/errorhandler/DO_PROCESS_ERROR_TUBE.java | 84 ------- .../incubate/PROCESS_INCUBATE_COMPLETED_PLATE.java | 82 ------- .../mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java | 254 ------------------- .../mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java | 106 -------- .../action/mainflow/SEQ3_APPLAY_RESOURCE.java | 126 ---------- .../appctrl/action/mainflow/SEQ4_PRE_PROCESS.java | 229 ----------------- .../appctrl/action/mainflow/SEQ5_PROCESS.java | 96 -------- .../appctrl/action/mainflow/SEQ6_POST_PROCESS.java | 92 ------- .../action/mainflow/SEQ7_EJECT_TUBEHOLDER.java | 60 ----- .../service/appctrl/action/opt/PLATE_OPT_SCAN.java | 85 ------- .../appctrl/mainflowctrl/CondtionMgrService.java | 149 +++++++++++ .../mainflowctrl/MainFlowCtrlScheduler.java | 238 ++++++++++++++++++ .../action/DO_CLEAR_ERROR_BEFORE_WORK.java | 72 ++++++ .../appctrl/mainflowctrl/action/DO_PAUSE.java | 50 ++++ .../action/DO_PROCESS_ERROR_PLATE.java | 81 ++++++ .../mainflowctrl/action/DO_PROCESS_ERROR_TUBE.java | 83 +++++++ .../appctrl/mainflowctrl/action/DO_RESUME.java | 50 ++++ .../appctrl/mainflowctrl/action/DO_START.java | 55 +++++ .../appctrl/mainflowctrl/action/DO_STOP.java | 50 ++++ .../mainflowctrl/action/PLATE_OPT_SCAN.java | 81 ++++++ .../action/PROCESS_INCUBATE_COMPLETED_PLATE.java | 80 ++++++ .../action/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java | 254 +++++++++++++++++++ .../action/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java | 106 ++++++++ .../mainflowctrl/action/SEQ3_APPLAY_RESOURCE.java | 126 ++++++++++ .../mainflowctrl/action/SEQ4_PRE_PROCESS.java | 229 +++++++++++++++++ .../appctrl/mainflowctrl/action/SEQ5_PROCESS.java | 96 ++++++++ .../mainflowctrl/action/SEQ6_POST_PROCESS.java | 92 +++++++ .../mainflowctrl/action/SEQ7_EJECT_TUBEHOLDER.java | 60 +++++ .../mainflowctrl/base/A8kActionStepType.java | 29 +++ .../appctrl/mainflowctrl/base/A8kErrorContext.java | 21 ++ .../appctrl/mainflowctrl/base/A8kStepAction.java | 40 +++ .../appctrl/scheduler/MainFlowCtrlScheduler.java | 273 --------------------- .../a8k/service/appctrl/type/A8kErrorContext.java | 22 -- .../ConsumableState.java | 30 --- .../ConsumablesScanResult.java | 8 - .../app_consumables_mgr_service/LarBSGroup.java | 22 -- .../app_consumables_mgr_service/LittBSGroup.java | 23 -- .../ReactionPlateGroup.java | 22 -- .../ScanResultState.java | 17 -- .../type/app_consumables_mgr_service/Tips.java | 5 - .../java/a8k/service/appstate/GStateService.java | 2 +- .../service/appstate/type/MainFlowCtrlState.java | 2 +- .../java/a8k/type/consumables/ConsumableState.java | 30 +++ src/main/java/a8k/type/consumables/LarBSGroup.java | 22 ++ .../java/a8k/type/consumables/LittBSGroup.java | 23 ++ .../a8k/type/consumables/ReactionPlateGroup.java | 22 ++ .../java/a8k/type/consumables/ScanResultState.java | 17 ++ src/main/java/a8k/type/consumables/Tips.java | 5 + 64 files changed, 2371 insertions(+), 2425 deletions(-) delete mode 100644 src/main/java/a8k/service/appctrl/AppTubeSettingMgrService.java delete mode 100644 src/main/java/a8k/service/appctrl/CondtionMgrService.java create mode 100644 src/main/java/a8k/service/appctrl/TubeSettingMgrService.java delete mode 100644 src/main/java/a8k/service/appctrl/action/base/A8kActionStepType.java delete mode 100644 src/main/java/a8k/service/appctrl/action/base/A8kStepAction.java delete mode 100644 src/main/java/a8k/service/appctrl/action/ctrl/DO_PAUSE.java delete mode 100644 src/main/java/a8k/service/appctrl/action/ctrl/DO_RESUME.java delete mode 100644 src/main/java/a8k/service/appctrl/action/ctrl/DO_START.java delete mode 100644 src/main/java/a8k/service/appctrl/action/ctrl/DO_STOP.java delete mode 100644 src/main/java/a8k/service/appctrl/action/errorhandler/DO_CLEAR_ERROR_BEFORE_WORK.java delete mode 100644 src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_PLATE.java delete mode 100644 src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_TUBE.java delete mode 100644 src/main/java/a8k/service/appctrl/action/incubate/PROCESS_INCUBATE_COMPLETED_PLATE.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ3_APPLAY_RESOURCE.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ4_PRE_PROCESS.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ5_PROCESS.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ6_POST_PROCESS.java delete mode 100644 src/main/java/a8k/service/appctrl/action/mainflow/SEQ7_EJECT_TUBEHOLDER.java delete mode 100644 src/main/java/a8k/service/appctrl/action/opt/PLATE_OPT_SCAN.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/CondtionMgrService.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/MainFlowCtrlScheduler.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_CLEAR_ERROR_BEFORE_WORK.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PAUSE.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_PLATE.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_TUBE.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_RESUME.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_START.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_STOP.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ3_APPLAY_RESOURCE.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ5_PROCESS.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ7_EJECT_TUBEHOLDER.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kActionStepType.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kErrorContext.java create mode 100644 src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kStepAction.java delete mode 100644 src/main/java/a8k/service/appctrl/scheduler/MainFlowCtrlScheduler.java delete mode 100644 src/main/java/a8k/service/appctrl/type/A8kErrorContext.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumableState.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumablesScanResult.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LarBSGroup.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LittBSGroup.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ReactionPlateGroup.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ScanResultState.java delete mode 100644 src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/Tips.java create mode 100644 src/main/java/a8k/type/consumables/ConsumableState.java create mode 100644 src/main/java/a8k/type/consumables/LarBSGroup.java create mode 100644 src/main/java/a8k/type/consumables/LittBSGroup.java create mode 100644 src/main/java/a8k/type/consumables/ReactionPlateGroup.java create mode 100644 src/main/java/a8k/type/consumables/ScanResultState.java create mode 100644 src/main/java/a8k/type/consumables/Tips.java diff --git a/src/main/java/a8k/baseservice/appeventbus/appevent/A8kEcodeContextListPromptEvent.java b/src/main/java/a8k/baseservice/appeventbus/appevent/A8kEcodeContextListPromptEvent.java index 339897d..db74cee 100644 --- a/src/main/java/a8k/baseservice/appeventbus/appevent/A8kEcodeContextListPromptEvent.java +++ b/src/main/java/a8k/baseservice/appeventbus/appevent/A8kEcodeContextListPromptEvent.java @@ -1,6 +1,6 @@ package a8k.baseservice.appeventbus.appevent; -import a8k.service.appctrl.type.A8kErrorContext; +import a8k.service.appctrl.mainflowctrl.base.A8kErrorContext; import java.util.List; diff --git a/src/main/java/a8k/baseservice/appeventbus/appevent/DoA8kStepActionEvent.java b/src/main/java/a8k/baseservice/appeventbus/appevent/DoA8kStepActionEvent.java index 4811fcc..a7bd5d2 100644 --- a/src/main/java/a8k/baseservice/appeventbus/appevent/DoA8kStepActionEvent.java +++ b/src/main/java/a8k/baseservice/appeventbus/appevent/DoA8kStepActionEvent.java @@ -1,6 +1,6 @@ package a8k.baseservice.appeventbus.appevent; -import a8k.service.appctrl.action.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; public class DoA8kStepActionEvent extends AppEvent { public A8kActionStepType actionStep; diff --git a/src/main/java/a8k/service/appctrl/AppDeviceCtrlService.java b/src/main/java/a8k/service/appctrl/AppDeviceCtrlService.java index a61b3b7..0e57436 100644 --- a/src/main/java/a8k/service/appctrl/AppDeviceCtrlService.java +++ b/src/main/java/a8k/service/appctrl/AppDeviceCtrlService.java @@ -3,16 +3,13 @@ package a8k.service.appctrl; import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; import a8k.controler.extapi.utils.ExtApiFn; import a8k.controler.extapi.utils.ExtApiTab; -import a8k.service.appctrl.action.base.A8kStepAction; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; import a8k.service.appstate.type.MainFlowCtrlState; import a8k.service.appstate.type.TubeHolder; import a8k.type.ConsumableGroup; import a8k.type.checkpoint.CheckResult; import a8k.service.appstate.GStateService; -import a8k.service.appstate.type.state.A8kWorkState; import a8k.type.exception.AppException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; diff --git a/src/main/java/a8k/service/appctrl/AppTubeSettingMgrService.java b/src/main/java/a8k/service/appctrl/AppTubeSettingMgrService.java deleted file mode 100644 index 31cce2a..0000000 --- a/src/main/java/a8k/service/appctrl/AppTubeSettingMgrService.java +++ /dev/null @@ -1,180 +0,0 @@ -package a8k.service.appctrl; - -import a8k.baseservice.appeventbus.AppEventBusService; -import a8k.baseservice.appeventbus.appevent.AppTubeholderSettingUpdateEvent; -import a8k.service.appstate.GStateService; -import a8k.controler.extapi.utils.ExtApiTab; -import a8k.controler.extapi.utils.ExtApiFn; -import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; -import a8k.type.exception.AppException; -import a8k.type.type.A8kTubeHolderType; -import a8k.type.type.BloodType; -import a8k.type.tube_setting.TubeSetting; -import a8k.type.tube_setting.TubeHolderSetting; -import a8k.hardware.type.a8kcanprotocol.A8kEcode; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -@Component -@ExtApiTab(cfg = ExtApiTabConfig.AppTubeSettingMgrService) -public class AppTubeSettingMgrService { - static Logger logger = LoggerFactory.getLogger(AppTubeSettingMgrService.class); - - static class ORDER { - static final int getA8kDeviceCfg = 1; - static final int addCfg = 2; - static final int removeCfg = 3; - static final int activeCfg = 4; - static final int setTubeSettingU = 5; - static final int clearTubeProjectCfg = 6; - static final int setTubeSetting = 7; - } - - @Resource - GStateService gState; - - @Resource - AppEventBusService ebus; - - - TubeHolderSetting getTubeHolderSetting(String uuid) { - for (TubeHolderSetting setting : gState.getTubeHolderSettings()) { - if (setting.uuid.equals(uuid)) { - return setting; - } - } - return null; - } - - - TubeHolderSetting getTubeHolderSettingAndCheckIsEditable(String uuid) throws AppException { - TubeHolderSetting setting = getTubeHolderSetting(uuid); - if (setting == null) { - throw new AppException(A8kEcode.TubeHolderSettingNotFound); - } - if (setting.lock) { - throw new AppException(A8kEcode.TubeHolderSettingIsLocked); - } - return setting; - } - - - // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // EXTERNAL API - // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - @ExtApiFn(name = "获取试管架配置", group = "配置读取", order = ORDER.getA8kDeviceCfg) - synchronized public List getTubeHolderSettings() { - return gState.getTubeHolderSettings(); - } - - @ExtApiFn(name = "添加<试管架>配置", group = "试管架", order = ORDER.addCfg) - synchronized public List newTubeHolderSetting() { - var newSetting = new TubeHolderSetting(); - logger.info("newTubeHolderSetting {}", newSetting.uuid); - - gState.getTubeHolderSettings().add(newSetting); - return getTubeHolderSettings(); - } - - @ExtApiFn(name = "删除<试管架>配置", group = "试管架", order = ORDER.removeCfg) - synchronized public List removeTubeHolderSetting(String uuid) throws AppException { - logger.info("removeTubeHolderSetting {}", uuid); - getTubeHolderSettingAndCheckIsEditable(uuid); - gState.getTubeHolderSettings().removeIf(setting -> setting.uuid.equals(uuid)); - return getTubeHolderSettings(); - } - - synchronized public void removeTubeHolderSetting(TubeHolderSetting setting) throws AppException { - if (setting == null) { - return; - } - removeTubeHolderSetting(setting.uuid); - } - - @ExtApiFn(name = "设置<试管架>激活状态", group = "试管架", order = ORDER.activeCfg) - synchronized public List tubeHodlerSettingSetActiveState(String uuid, Boolean active) throws AppException { - logger.info("tubeHodlerSettingSetActiveState {} {}", uuid, active); - TubeHolderSetting setting = getTubeHolderSettingAndCheckIsEditable(uuid); - - setting.active = active; - return getTubeHolderSettings(); - } - - @ExtApiFn(name = "设置<试管架>类型", group = "试管架", order = ORDER.activeCfg) - synchronized public List tubeHodlerSettingSetTubeHolderType(String uuid, A8kTubeHolderType type) throws AppException { - logger.info("tubeHodlerSettingSetTubeHolderType {} {}", uuid, type); - TubeHolderSetting setting = getTubeHolderSettingAndCheckIsEditable(uuid); - setting.tubeHolderType = type; - return getTubeHolderSettings(); - } - - @ExtApiFn(name = "复位<试管>配置", group = "试管", order = ORDER.clearTubeProjectCfg) - synchronized public List resetTubeSetting(String uuid, Integer tubeIndex) throws AppException { - logger.info("resetTubeSetting {} {}", uuid, tubeIndex); - TubeHolderSetting thSetting = getTubeHolderSettingAndCheckIsEditable(uuid); - thSetting.tubeSettings[tubeIndex].reset(); - return getTubeHolderSettings(); - - } - - @ExtApiFn(name = "修改<试管>用户信息配置", group = "试管", order = ORDER.setTubeSettingU) - synchronized public List setTubeSettingUserIdAndSampleBarcode(String uuid, Integer tubeIndex, String userid, String sampleBarcode) throws AppException { - logger.info("setTubeSettingUserIdAndSampleBarcode {} {} {} {}", uuid, tubeIndex, userid, sampleBarcode); - TubeHolderSetting thSetting = getTubeHolderSettingAndCheckIsEditable(uuid); - TubeSetting tSetting = thSetting.tubeSettings[tubeIndex]; - tSetting.userid = userid; - tSetting.sampleBarcode = sampleBarcode; - return getTubeHolderSettings(); - } - - @ExtApiFn(name = "修改<试管>配置(ps:projIndex格式为逗号分割的数字)", group = "试管", order = ORDER.setTubeSetting) - synchronized public List setTubeSetting(String uuid, Integer tubeIndex, BloodType bloodType, String projIndex) throws AppException { - logger.info("setTubeSetting {} {} {} {}", uuid, tubeIndex, bloodType, projIndex); - TubeHolderSetting thSetting = getTubeHolderSettingAndCheckIsEditable(uuid); - - List projIndexList = new ArrayList<>(); - String[] projIndexArr = projIndex.split(","); - for (String s : projIndexArr) { - projIndexList.add(Integer.parseInt(s)); - } - var tubeSetting = thSetting.tubeSettings[tubeIndex]; - tubeSetting.bloodType = bloodType; - tubeSetting.projIndex = projIndexList; - return getTubeHolderSettings(); - } - - /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * internal use - *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - - //锁定第一个激活的试管架配置 - synchronized public TubeHolderSetting getThelastActiveTubeHolderSettingAndLock() { - for (int i = gState.getTubeHolderSettings().size() - 1; i >= 0; i--) { - TubeHolderSetting setting = gState.getTubeHolderSettings().get(i); - if (setting.active) { - setting.lock = true; - ebus.pushEvent(new AppTubeholderSettingUpdateEvent()); - return setting; - } - } - return null; - } - - synchronized public void unlockTubeHolderSetting(String uuid) { - for (TubeHolderSetting setting : gState.getTubeHolderSettings()) { - if (setting.uuid.equals(uuid)) { - setting.lock = false; - ebus.pushEvent(new AppTubeholderSettingUpdateEvent()); - return; - } - } - } - - -} diff --git a/src/main/java/a8k/service/appctrl/CondtionMgrService.java b/src/main/java/a8k/service/appctrl/CondtionMgrService.java deleted file mode 100644 index 5e589ee..0000000 --- a/src/main/java/a8k/service/appctrl/CondtionMgrService.java +++ /dev/null @@ -1,151 +0,0 @@ -package a8k.service.appctrl; - -import a8k.hardware.A8kCanBusService; -import a8k.hardware.type.a8kcanprotocol.IOId; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.IncubationPlateMgrService; -import a8k.service.appstate.OptScanModuleStateMgrService; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.service.appstate.type.state.IncubationSubTankState; -import a8k.service.appstate.type.state.TubeHolderState; -import a8k.service.appstate.type.state.TubeState; -import a8k.type.exception.AppException; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - - -@Component -public class CondtionMgrService { - static Logger logger = LoggerFactory.getLogger(CondtionMgrService.class); - - @Resource - GStateService gstate; - - @Resource - A8kCanBusService canBus; - - @Resource - IncubationPlateMgrService incubationPlateMgrService; - - @Resource - OptScanModuleStateMgrService optScanModuleStateMgrService; - - Boolean getTubeholderEnterPosPPS() { //入料通道是否为空 - try { - return canBus.getIOState(IOId.InfeedPPS); - } catch (Exception e) { - logger.error("getTubeholderEnterPosPPS error", e); - return false; - } - } - - public Boolean isNoMoreTubeToBeProcessed() { - return !gstate.getTubeHolder().isHasTubeToBeProcessed(); - } - - public Boolean isCanDoAction() { - return gstate.mainFlowCtrlState.workState.equals(A8kWorkState.WORKING) && !gstate.mainFlowCtrlState.errorFlag && !gstate.mainFlowCtrlState.workStateChangeFlag; - } - - - public Boolean isHasSometubesToBeProcessed() { - return gstate.getTubeHolder().isHasTubeToBeProcessed() || gstate.getEmergencyTubePos().tube.state.equals(TubeState.TO_BE_PROCESSED); - } - - public Boolean isCurTubeProcessCompleted() { - return gstate.getCurProcessingTube() == null || gstate.getCurProcessingTube().state.equals(TubeState.PROCESS_COMPLETE); - } - - public Boolean isOptModuleEmpty() { - return optScanModuleStateMgrService.isEmpty(); - } - - public Boolean isTimeToEnterNewTubeHolder() { - Boolean cond0 = isCanDoAction(); - //试管架处于空闲状态 - Boolean cond1 = gstate.getTubeHolder().state.equals(TubeHolderState.IDLE); - //入料通道是否为空 - Boolean cond2 = getTubeholderEnterPosPPS(); - return cond0 && cond1 && cond2; - } - - public Boolean isTimeToSwitchNextTube() { - Boolean cond0 = isCanDoAction(); - //当前试管处理完成 - Boolean cond1 = isCurTubeProcessCompleted(); - //有待处理的试管 - Boolean cond2 = isHasSometubesToBeProcessed(); - return cond0 && cond1 && cond2; - } - - public Boolean isTimeToProcessPendingTube() { - Tube tube = gstate.getCurProcessingTube(); - if (tube == null) - return false; - - //当前正在工作 - Boolean cond1 = isCanDoAction(); - //没有试管在处理 或者 当前试管处理完成 - Boolean cond2 = tube.state.equals(TubeState.PENDING); - //急诊有待处理的试管,或者试管架正在处理 - Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); - return cond1 && cond2 && cond3; - } - - public Boolean isTimeToPreProcessTube() { - Tube tube = gstate.getCurProcessingTube(); - if (tube == null) - return false; - - //当前正在工作 - Boolean cond1 = isCanDoAction(); - //没有试管在处理 或者 当前试管处理完成 - Boolean cond2 = tube.state.equals(TubeState.RESOURCE_IS_READY); - //急诊有待处理的试管,或者试管架正在处理 - Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); - return cond1 && cond2 && cond3; - } - - public Boolean isTimeToProcessTube() { - Tube tube = gstate.getCurProcessingTube(); - if (tube == null) - return false; - - //当前正在工作 - Boolean cond1 = isCanDoAction(); - //没有试管在处理 或者 当前试管处理完成 - Boolean cond2 = tube.state.equals(TubeState.PRE_PROCESSED); - //急诊有待处理的试管,或者试管架正在处理 - Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); - return cond1 && cond2 && cond3; - } - - public Boolean isTimeToPostProcessTube() { - Tube tube = gstate.getCurProcessingTube(); - if (tube == null) - return false; - - //当前正在工作 - Boolean cond1 = isCanDoAction(); - //没有试管在处理 或者 当前试管处理完成 - Boolean cond2 = tube.state.equals(TubeState.PROCESSED); - //急诊有待处理的试管,或者试管架正在处理 - Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); - return cond1 && cond2 && cond3; - } - - public Boolean isHasSomeErrorPlatesToBeProcessed() { - return incubationPlateMgrService.isHasSomeErrorPlate(); - } - - public Boolean isHasSomeErrorTubeToBeProcessed() { - Tube tube = gstate.getCurProcessingTube(); - if (tube == null) - return false; - return gstate.getEmergencyTubePos().tube.state.equals(TubeState.ERROR); - } - -} diff --git a/src/main/java/a8k/service/appctrl/ConsumablesScanService.java b/src/main/java/a8k/service/appctrl/ConsumablesScanService.java index 49a07e3..d9a8f19 100644 --- a/src/main/java/a8k/service/appctrl/ConsumablesScanService.java +++ b/src/main/java/a8k/service/appctrl/ConsumablesScanService.java @@ -1,11 +1,15 @@ package a8k.service.appctrl; +import a8k.constant.AppConstant; import a8k.hardware.type.a8kcanprotocol.A8kEcode; import a8k.service.appdata.AppProjInfoMgrService; -import a8k.service.appctrl.type.app_consumables_mgr_service.*; import a8k.service.appstate.GStateService; import a8k.service.devicedriver.ctrl.ConsumablesScanCtrl; import a8k.type.ConsumableGroup; +import a8k.type.consumables.LarBSGroup; +import a8k.type.consumables.LittBSGroup; +import a8k.type.consumables.ReactionPlateGroup; +import a8k.type.consumables.ScanResultState; import a8k.type.exception.AppException; import a8k.type.projecttype.A8kReactionFlowType; import a8k.type.projecttype.a8kidcard.A8kIdCardInfo; @@ -21,17 +25,22 @@ import java.util.Map; @Component public class ConsumablesScanService { - static Logger logger = org.slf4j.LoggerFactory.getLogger(ConsumablesScanService.class); - static final Integer EachConsumableNum = 20; + static Logger logger = org.slf4j.LoggerFactory.getLogger(ConsumablesScanService.class); + + public static class ConsumablesScanResult { + public Integer chNum; + public ScanResultState state; + public Integer projIndex; + public String lotId; + } - @Resource - GStateService gstate; @Resource + GStateService gstate; + @Resource AppProjInfoMgrService appProjMgr; - @Resource - ConsumablesScanCtrl scanCtrlService; + ConsumablesScanCtrl scanCtrlService; /** * 解析扫描结果,返回耗材扫描结果 @@ -111,13 +120,13 @@ public class ConsumablesScanService { assert a8kIdCardInfo != null; assert reactionType != null; - cState.reactionPlateGroup[ch] = new ReactionPlateGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum); + cState.reactionPlateGroup[ch] = new ReactionPlateGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, AppConstant.CONSUMABLE_NUM); if (reactionType.equals(A8kReactionFlowType.ReactionWithLittBS)) { - cState.littBSGroup[ch] = new LittBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum); + cState.littBSGroup[ch] = new LittBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, AppConstant.CONSUMABLE_NUM); cState.larBSGroup[ch] = new LarBSGroup(); } else if (reactionType.equals(A8kReactionFlowType.ReactionWithLarBsAndDetection)) { - cState.littBSGroup[ch] = new LittBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum); - cState.larBSGroup[ch] = new LarBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum); + cState.littBSGroup[ch] = new LittBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, AppConstant.CONSUMABLE_NUM); + cState.larBSGroup[ch] = new LarBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, AppConstant.CONSUMABLE_NUM); } else { throw new RuntimeException("未知的反应流程类型"); } diff --git a/src/main/java/a8k/service/appctrl/MainFlowCtrlService.java b/src/main/java/a8k/service/appctrl/MainFlowCtrlService.java index 30d08cd..58d72fc 100644 --- a/src/main/java/a8k/service/appctrl/MainFlowCtrlService.java +++ b/src/main/java/a8k/service/appctrl/MainFlowCtrlService.java @@ -1,10 +1,10 @@ package a8k.service.appctrl; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appctrl.action.ctrl.DO_STOP; -import a8k.service.appctrl.scheduler.MainFlowCtrlScheduler; -import a8k.service.appctrl.type.A8kErrorContext; +import a8k.service.appctrl.mainflowctrl.MainFlowCtrlScheduler; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kErrorContext; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appctrl.mainflowctrl.action.DO_STOP; import a8k.service.appstate.GStateService; import a8k.service.appstate.type.MainFlowCtrlState; import a8k.service.appstate.type.state.A8kWorkState; @@ -40,7 +40,6 @@ public class MainFlowCtrlService { @PostConstruct void init() { - scheduler.regClearErrorProcesser(this::clearErrorcodeBeforeContinueDo); scheduler.regEcodePostProcesser(this::postPorcessA8kEcode); scheduler.regCheckBeforeGuess(this::checkBeforeGuess); diff --git a/src/main/java/a8k/service/appctrl/TubeSettingMgrService.java b/src/main/java/a8k/service/appctrl/TubeSettingMgrService.java new file mode 100644 index 0000000..a68bfef --- /dev/null +++ b/src/main/java/a8k/service/appctrl/TubeSettingMgrService.java @@ -0,0 +1,180 @@ +package a8k.service.appctrl; + +import a8k.baseservice.appeventbus.AppEventBusService; +import a8k.baseservice.appeventbus.appevent.AppTubeholderSettingUpdateEvent; +import a8k.service.appstate.GStateService; +import a8k.controler.extapi.utils.ExtApiTab; +import a8k.controler.extapi.utils.ExtApiFn; +import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; +import a8k.type.exception.AppException; +import a8k.type.type.A8kTubeHolderType; +import a8k.type.type.BloodType; +import a8k.type.tube_setting.TubeSetting; +import a8k.type.tube_setting.TubeHolderSetting; +import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +@ExtApiTab(cfg = ExtApiTabConfig.AppTubeSettingMgrService) +public class TubeSettingMgrService { + static Logger logger = LoggerFactory.getLogger(TubeSettingMgrService.class); + + static class ORDER { + static final int getA8kDeviceCfg = 1; + static final int addCfg = 2; + static final int removeCfg = 3; + static final int activeCfg = 4; + static final int setTubeSettingU = 5; + static final int clearTubeProjectCfg = 6; + static final int setTubeSetting = 7; + } + + @Resource + GStateService gState; + + @Resource + AppEventBusService ebus; + + + TubeHolderSetting getTubeHolderSetting(String uuid) { + for (TubeHolderSetting setting : gState.getTubeHolderSettings()) { + if (setting.uuid.equals(uuid)) { + return setting; + } + } + return null; + } + + + TubeHolderSetting getTubeHolderSettingAndCheckIsEditable(String uuid) throws AppException { + TubeHolderSetting setting = getTubeHolderSetting(uuid); + if (setting == null) { + throw new AppException(A8kEcode.TubeHolderSettingNotFound); + } + if (setting.lock) { + throw new AppException(A8kEcode.TubeHolderSettingIsLocked); + } + return setting; + } + + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // EXTERNAL API + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + @ExtApiFn(name = "获取试管架配置", group = "配置读取", order = ORDER.getA8kDeviceCfg) + synchronized public List getTubeHolderSettings() { + return gState.getTubeHolderSettings(); + } + + @ExtApiFn(name = "添加<试管架>配置", group = "试管架", order = ORDER.addCfg) + synchronized public List newTubeHolderSetting() { + var newSetting = new TubeHolderSetting(); + logger.info("newTubeHolderSetting {}", newSetting.uuid); + + gState.getTubeHolderSettings().add(newSetting); + return getTubeHolderSettings(); + } + + @ExtApiFn(name = "删除<试管架>配置", group = "试管架", order = ORDER.removeCfg) + synchronized public List removeTubeHolderSetting(String uuid) throws AppException { + logger.info("removeTubeHolderSetting {}", uuid); + getTubeHolderSettingAndCheckIsEditable(uuid); + gState.getTubeHolderSettings().removeIf(setting -> setting.uuid.equals(uuid)); + return getTubeHolderSettings(); + } + + synchronized public void removeTubeHolderSetting(TubeHolderSetting setting) throws AppException { + if (setting == null) { + return; + } + removeTubeHolderSetting(setting.uuid); + } + + @ExtApiFn(name = "设置<试管架>激活状态", group = "试管架", order = ORDER.activeCfg) + synchronized public List tubeHodlerSettingSetActiveState(String uuid, Boolean active) throws AppException { + logger.info("tubeHodlerSettingSetActiveState {} {}", uuid, active); + TubeHolderSetting setting = getTubeHolderSettingAndCheckIsEditable(uuid); + + setting.active = active; + return getTubeHolderSettings(); + } + + @ExtApiFn(name = "设置<试管架>类型", group = "试管架", order = ORDER.activeCfg) + synchronized public List tubeHodlerSettingSetTubeHolderType(String uuid, A8kTubeHolderType type) throws AppException { + logger.info("tubeHodlerSettingSetTubeHolderType {} {}", uuid, type); + TubeHolderSetting setting = getTubeHolderSettingAndCheckIsEditable(uuid); + setting.tubeHolderType = type; + return getTubeHolderSettings(); + } + + @ExtApiFn(name = "复位<试管>配置", group = "试管", order = ORDER.clearTubeProjectCfg) + synchronized public List resetTubeSetting(String uuid, Integer tubeIndex) throws AppException { + logger.info("resetTubeSetting {} {}", uuid, tubeIndex); + TubeHolderSetting thSetting = getTubeHolderSettingAndCheckIsEditable(uuid); + thSetting.tubeSettings[tubeIndex].reset(); + return getTubeHolderSettings(); + + } + + @ExtApiFn(name = "修改<试管>用户信息配置", group = "试管", order = ORDER.setTubeSettingU) + synchronized public List setTubeSettingUserIdAndSampleBarcode(String uuid, Integer tubeIndex, String userid, String sampleBarcode) throws AppException { + logger.info("setTubeSettingUserIdAndSampleBarcode {} {} {} {}", uuid, tubeIndex, userid, sampleBarcode); + TubeHolderSetting thSetting = getTubeHolderSettingAndCheckIsEditable(uuid); + TubeSetting tSetting = thSetting.tubeSettings[tubeIndex]; + tSetting.userid = userid; + tSetting.sampleBarcode = sampleBarcode; + return getTubeHolderSettings(); + } + + @ExtApiFn(name = "修改<试管>配置(ps:projIndex格式为逗号分割的数字)", group = "试管", order = ORDER.setTubeSetting) + synchronized public List setTubeSetting(String uuid, Integer tubeIndex, BloodType bloodType, String projIndex) throws AppException { + logger.info("setTubeSetting {} {} {} {}", uuid, tubeIndex, bloodType, projIndex); + TubeHolderSetting thSetting = getTubeHolderSettingAndCheckIsEditable(uuid); + + List projIndexList = new ArrayList<>(); + String[] projIndexArr = projIndex.split(","); + for (String s : projIndexArr) { + projIndexList.add(Integer.parseInt(s)); + } + var tubeSetting = thSetting.tubeSettings[tubeIndex]; + tubeSetting.bloodType = bloodType; + tubeSetting.projIndex = projIndexList; + return getTubeHolderSettings(); + } + + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * internal use + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + //锁定第一个激活的试管架配置 + synchronized public TubeHolderSetting getThelastActiveTubeHolderSettingAndLock() { + for (int i = gState.getTubeHolderSettings().size() - 1; i >= 0; i--) { + TubeHolderSetting setting = gState.getTubeHolderSettings().get(i); + if (setting.active) { + setting.lock = true; + ebus.pushEvent(new AppTubeholderSettingUpdateEvent()); + return setting; + } + } + return null; + } + + synchronized public void unlockTubeHolderSetting(String uuid) { + for (TubeHolderSetting setting : gState.getTubeHolderSettings()) { + if (setting.uuid.equals(uuid)) { + setting.lock = false; + ebus.pushEvent(new AppTubeholderSettingUpdateEvent()); + return; + } + } + } + + +} diff --git a/src/main/java/a8k/service/appctrl/action/base/A8kActionStepType.java b/src/main/java/a8k/service/appctrl/action/base/A8kActionStepType.java deleted file mode 100644 index 7a023e4..0000000 --- a/src/main/java/a8k/service/appctrl/action/base/A8kActionStepType.java +++ /dev/null @@ -1,29 +0,0 @@ -package a8k.service.appctrl.action.base; - -public enum A8kActionStepType { - DO_START,//启动 - DO_PAUSE,//暂停 - DO_STOP, //停止 - DO_RESUME,//恢复 - - //mainflow - SEQ1_ENTER_TUBEHOLDER_AND_SCAN, //入料并扫描 - SEQ2_SWITCH_TO_THE_NEXT_TUBE,// 切换到下一个试管 - SEQ3_APPLAY_RESOURCE,//申请资源 - SEQ4_PRE_PROCESS, - SEQ5_PROCESS, - SEQ6_POST_PROCESS, - SEQ7_EJECT_TUBEHOLDER, //弹出试管架 - - //incubate - PROCESS_INCUBATE_COMPLETED_PLATE,//处理孵育完成的板 - - //OPT - PLATE_OPT_SCAN, - PLATE_OPT_DROP, - - //Error - DO_CLEAR_ERROR_BEFORE_WORK,//在启动前,清除错误 - DO_PROCESS_ERROR_TUBE, - DO_PROCESS_ERROR_PLATE, -} diff --git a/src/main/java/a8k/service/appctrl/action/base/A8kStepAction.java b/src/main/java/a8k/service/appctrl/action/base/A8kStepAction.java deleted file mode 100644 index c5796af..0000000 --- a/src/main/java/a8k/service/appctrl/action/base/A8kStepAction.java +++ /dev/null @@ -1,40 +0,0 @@ -package a8k.service.appctrl.action.base; - - -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.type.exception.AppException; - -import java.util.List; - -public class A8kStepAction { - - public A8kActionStepType step = null; - - public A8kStepAction(A8kActionStepType step) { - this.step = step; - } - - public Boolean checkCondition() { - return false; - } - - public Boolean getCondition() { - return checkCondition(); - } - - public List getResourceList() { - return null; - } - - public void doaction() throws AppException { - } - - public Boolean isMutiLineAction() { - return false; - } - - public Boolean isAllowsParallelRunning() { - return true; - } - -} diff --git a/src/main/java/a8k/service/appctrl/action/ctrl/DO_PAUSE.java b/src/main/java/a8k/service/appctrl/action/ctrl/DO_PAUSE.java deleted file mode 100644 index 235aac3..0000000 --- a/src/main/java/a8k/service/appctrl/action/ctrl/DO_PAUSE.java +++ /dev/null @@ -1,51 +0,0 @@ -package a8k.service.appctrl.action.ctrl; - -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class DO_PAUSE extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_PAUSE.class); - - DO_PAUSE() { - super(A8kActionStepType.DO_PAUSE); - } - - @Resource - GStateService gstate; - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - mfcs.workStateChangeFlag = false; - } - - @Override public Boolean checkCondition() { - Boolean cond1 = mfcs.workStateChangeFlag && !mfcs.errorFlag; - Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.WORKING); - Boolean cond3 = mfcs.workState.equals(A8kWorkState.PAUSE); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of(); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/ctrl/DO_RESUME.java b/src/main/java/a8k/service/appctrl/action/ctrl/DO_RESUME.java deleted file mode 100644 index 51bf333..0000000 --- a/src/main/java/a8k/service/appctrl/action/ctrl/DO_RESUME.java +++ /dev/null @@ -1,50 +0,0 @@ -package a8k.service.appctrl.action.ctrl; - -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class DO_RESUME extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_RESUME.class); - - DO_RESUME() { - super(A8kActionStepType.DO_RESUME); - } - - @Resource - GStateService gstate; - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - mfcs.workStateChangeFlag = false; - } - - @Override public Boolean checkCondition() { - Boolean cond1 = mfcs.workStateChangeFlag; - Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.PAUSE); - Boolean cond3 = mfcs.workState.equals(A8kWorkState.WORKING); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of(); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/ctrl/DO_START.java b/src/main/java/a8k/service/appctrl/action/ctrl/DO_START.java deleted file mode 100644 index 25d1fad..0000000 --- a/src/main/java/a8k/service/appctrl/action/ctrl/DO_START.java +++ /dev/null @@ -1,55 +0,0 @@ -package a8k.service.appctrl.action.ctrl; - -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class DO_START extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_START.class); - - DO_START() { - super(A8kActionStepType.DO_START); - } - - @Resource - GStateService gstate; - - @Resource - SampleScanTransportCtrl sampleScanTransportCtrl; - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - mfcs.workStateChangeFlag = false; - sampleScanTransportCtrl.ejectTubeHolder(); - } - - @Override public Boolean checkCondition() { - Boolean cond1 = mfcs.workStateChangeFlag; - Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.IDLE); - Boolean cond3 = mfcs.workState.equals(A8kWorkState.WORKING); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of(A8kPublicResourceType.ShakeModule); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/ctrl/DO_STOP.java b/src/main/java/a8k/service/appctrl/action/ctrl/DO_STOP.java deleted file mode 100644 index d203e0e..0000000 --- a/src/main/java/a8k/service/appctrl/action/ctrl/DO_STOP.java +++ /dev/null @@ -1,50 +0,0 @@ -package a8k.service.appctrl.action.ctrl; - -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class DO_STOP extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_STOP.class); - - DO_STOP() { - super(A8kActionStepType.DO_STOP); - } - - @Resource - GStateService gstate; - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - mfcs.workStateChangeFlag = false; - } - - @Override public Boolean checkCondition() { - Boolean cond1 = mfcs.workStateChangeFlag; - Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.WORKING) || mfcs.lastWorkState.equals(A8kWorkState.PAUSE); - Boolean cond3 = mfcs.workState.equals(A8kWorkState.IDLE); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of(); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/errorhandler/DO_CLEAR_ERROR_BEFORE_WORK.java b/src/main/java/a8k/service/appctrl/action/errorhandler/DO_CLEAR_ERROR_BEFORE_WORK.java deleted file mode 100644 index e1a5495..0000000 --- a/src/main/java/a8k/service/appctrl/action/errorhandler/DO_CLEAR_ERROR_BEFORE_WORK.java +++ /dev/null @@ -1,76 +0,0 @@ -package a8k.service.appctrl.action.errorhandler; - -import a8k.OS; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.IncubationPlateMgrService; -import a8k.service.appstate.OptScanModuleStateMgrService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.IncubationSubTank; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.service.appstate.type.state.IncubationSubTankState; -import a8k.service.appstate.type.state.TubeState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class DO_CLEAR_ERROR_BEFORE_WORK extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_CLEAR_ERROR_BEFORE_WORK.class); - - DO_CLEAR_ERROR_BEFORE_WORK() { - super(A8kActionStepType.DO_CLEAR_ERROR_BEFORE_WORK); - } - - @Resource - GStateService gstate; - @Resource - CondtionMgrService cms; - @Resource - IncubationPlateMgrService incubationPlateMgrService; - @Resource - OptScanModuleStateMgrService optScanModuleStateMgrService; - - MainFlowCtrlState mfcs; - - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - - @Override public void doaction() throws AppException { - - //ProcessErrorBeforeContinue - - - mfcs.errorFlag = false; - mfcs.ecodeList.clear(); - - } - - @Override public Boolean checkCondition() { - Boolean cond1 = mfcs.workStateChangeFlag; - Boolean cond2 = mfcs.errorFlag; - Boolean cond3 = mfcs.workState.equals(A8kWorkState.WORKING); - Boolean cond4 = mfcs.lastWorkState.equals(A8kWorkState.PAUSE) || mfcs.lastWorkState.equals(A8kWorkState.IDLE); - return cond1 && cond2 && cond3 && cond4; - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.IncubationPlateModule, - A8kPublicResourceType.OPTModule, - A8kPublicResourceType.PlatesBoxModule - ); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_PLATE.java b/src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_PLATE.java deleted file mode 100644 index d8b635f..0000000 --- a/src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_PLATE.java +++ /dev/null @@ -1,82 +0,0 @@ -package a8k.service.appctrl.action.errorhandler; - -import a8k.OS; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.IncubationPlateMgrService; -import a8k.service.appstate.OptScanModuleStateMgrService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.IncubationSubTank; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.service.appstate.type.state.IncubationSubTankState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * 处理错误的孵育盘 - */ -@Component -public class DO_PROCESS_ERROR_PLATE extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_PROCESS_ERROR_PLATE.class); - - DO_PROCESS_ERROR_PLATE() { - super(A8kActionStepType.DO_PROCESS_ERROR_PLATE); - } - - @Resource - GStateService gstate; - @Resource - CondtionMgrService cms; - @Resource - IncubationPlateMgrService incubationPlateMgrService; - @Resource - OptScanModuleStateMgrService optScanModuleStateMgrService; - - MainFlowCtrlState mfcs; - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - - - @Override public void doaction() throws AppException { - //ProcessErrorBeforeContinue - - while (true) { - IncubationSubTank errorTank = incubationPlateMgrService.getErrorPlate(); - if (errorTank == null) { - break; - } - logger.info("处理错误板夹:{}", errorTank.pos); - //TODO:推出板夹到光学模组,同时丢弃板夹 - logger.info("推出板夹到光学模组"); - logger.info("丢弃板夹"); - OS.forceSleep(3000); - // - optScanModuleStateMgrService.newPlateToOptScanPos(errorTank); - optScanModuleStateMgrService.dropPlate(); - incubationPlateMgrService.setIncubationPlateState(errorTank.pos, IncubationSubTankState.EMPTY); - } - } - - @Override public Boolean checkCondition() { - Boolean cond1 = cms.isCanDoAction(); - Boolean cond2 = cms.isHasSomeErrorPlatesToBeProcessed(); - Boolean cond3 = cms.isOptModuleEmpty(); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of(); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_TUBE.java b/src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_TUBE.java deleted file mode 100644 index 90baf71..0000000 --- a/src/main/java/a8k/service/appctrl/action/errorhandler/DO_PROCESS_ERROR_TUBE.java +++ /dev/null @@ -1,84 +0,0 @@ -package a8k.service.appctrl.action.errorhandler; - -import a8k.OS; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.IncubationPlateMgrService; -import a8k.service.appstate.OptScanModuleStateMgrService; -import a8k.service.appstate.TubeProcessStateMgrService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.service.appstate.type.state.TubeState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * 处理错误的试管 - */ -@Component -public class DO_PROCESS_ERROR_TUBE extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(DO_PROCESS_ERROR_TUBE.class); - - DO_PROCESS_ERROR_TUBE() { - super(A8kActionStepType.DO_PROCESS_ERROR_TUBE); - } - - @Resource - GStateService gstate; - @Resource - CondtionMgrService cms; - @Resource - IncubationPlateMgrService incubationPlateMgrService; - @Resource - OptScanModuleStateMgrService optScanModuleStateMgrService; - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - - @Override public void doaction() throws AppException { - //ProcessErrorBeforeContinue - - Tube tube = gstate.getCurProcessingTube(); - assert tube != null; - - logger.info("处理错误试管:{}", tube.sampleid); - logger.info("复位摇匀模组"); - OS.forceSleep(4000); - //复位摇匀模组 - logger.info("复位HBOT"); - //复位HBOT - OS.forceSleep(4000); - tubeProcessStateMgrService.setCurTubeState(TubeState.PROCESS_COMPLETE); - } - - @Override public Boolean checkCondition() { - Boolean cond1 = cms.isCanDoAction(); - Boolean cond2 = cms.isHasSometubesToBeProcessed(); - return cond1 && cond2; - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.ShakeModule, - A8kPublicResourceType.HBOT - ); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/incubate/PROCESS_INCUBATE_COMPLETED_PLATE.java b/src/main/java/a8k/service/appctrl/action/incubate/PROCESS_INCUBATE_COMPLETED_PLATE.java deleted file mode 100644 index 7f070d5..0000000 --- a/src/main/java/a8k/service/appctrl/action/incubate/PROCESS_INCUBATE_COMPLETED_PLATE.java +++ /dev/null @@ -1,82 +0,0 @@ -package a8k.service.appctrl.action.incubate; - -import a8k.OS; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.IncubationPlateMgrService; -import a8k.service.appstate.OptScanModuleStateMgrService; -import a8k.service.appstate.TubeProcessStateMgrService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.IncubationSubTank; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.IncubationSubTankState; -import a8k.service.appstate.type.state.TubeState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * 处理错误的试管 - */ -@Component -public class PROCESS_INCUBATE_COMPLETED_PLATE extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(PROCESS_INCUBATE_COMPLETED_PLATE.class); - - PROCESS_INCUBATE_COMPLETED_PLATE() { - super(A8kActionStepType.PROCESS_INCUBATE_COMPLETED_PLATE); - } - - @Resource - GStateService gstate; - @Resource - CondtionMgrService cms; - @Resource - IncubationPlateMgrService incubationPlateMgrService; - @Resource - OptScanModuleStateMgrService optScanModuleStateMgrService; - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - - @Override public void doaction() throws AppException { - IncubationSubTank tank = incubationPlateMgrService.getOneExpiredPlate(); - if (tank == null) { - return; - } - logger.info("推出板夹到光学模组,{}", tank.pos); - OS.forceSleep(3000); - - optScanModuleStateMgrService.newPlateToOptScanPos(tank); - incubationPlateMgrService.setIncubationPlateState(tank.pos, IncubationSubTankState.EMPTY); - } - - @Override public Boolean checkCondition() { - Boolean cond1 = cms.isCanDoAction(); - Boolean cond2 = incubationPlateMgrService.isHasExpiredPlate(); - Boolean cond3 = optScanModuleStateMgrService.isEmpty(); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.OPTModule, - A8kPublicResourceType.IncubationPlateModule - ); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java deleted file mode 100644 index eee8b55..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java +++ /dev/null @@ -1,254 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.baseservice.appeventbus.AppEventBusService; -import a8k.baseservice.appeventbus.appevent.AppWarningNotifyEvent; -import a8k.hardware.A8kCanBusService; -import a8k.hardware.type.a8kcanprotocol.A8kEcode; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.AppTubeSettingMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.TubeProcessContextMgrService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.TubeHolder; -import a8k.service.appstate.type.state.TubeHolderState; -import a8k.service.appstate.type.state.TubeState; -import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; -import a8k.type.exception.AppException; -import a8k.type.tube_setting.TubeHolderSetting; -import a8k.type.type.A8kTubeHolderType; -import a8k.type.type.BloodType; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * - * TubeHolderState - * IDLE --> PROCESSING - * - * TUBES STATE - * EMPTY --> TO_BE_PROCESSED - */ -@Component -public class SEQ1_ENTER_TUBEHOLDER_AND_SCAN extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ1_ENTER_TUBEHOLDER_AND_SCAN.class); - - SEQ1_ENTER_TUBEHOLDER_AND_SCAN() { - super(A8kActionStepType.SEQ1_ENTER_TUBEHOLDER_AND_SCAN); - } - - static public class TubesScanResult { - public Boolean isTubeExist = false; - public Boolean isHighTube = false; - public String tubeCode = null; - - public String toString() { - return String.format("isTubeExist:%s,isHighTube:%s,tubeCode:%s", isTubeExist, isHighTube, tubeCode); - } - } - - static public class SampleScanResult { - public TubesScanResult[] tubesScanResults; - public String tubeHolderType; - } - - - @Resource - GStateService gstate; - @Resource - CondtionMgrService cmgr; - @Resource - SampleScanTransportCtrl stc; - @Resource - AppEventBusService ebus; - @Resource - A8kCanBusService canBus; - @Resource - AppTubeSettingMgrService appTubeSettingMgrService; - @Resource - TubeProcessContextMgrService tubeProcessContextMgrService; - - - SampleScanResult scanTubeHodler() throws AppException { - SampleScanResult result = new SampleScanResult(); - - //清空试管架 - if (!stc.tubeXChannelIsEmpty()) { - stc.ejectTubeHolder(); - } - //入料 - logger.info("开始进料"); - Boolean enterSuc = stc.enterTubeHolder(); - if (!enterSuc) { - logger.warn("进料超时,从入料口,弹出试管架"); - stc.ejectTubeHolderInEnterPos(); - throw new AppException(A8kEcode.InfeedOvertimeFail); - } - //扫描试管架类型 - String tubeType = stc.moveTubeRackToScanPosAndScan(); - if (tubeType.isEmpty()) { - logger.warn("扫描试管架类型失败,弹出试管架"); - stc.ejectTubeHolder(); - ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.ScanTubeholderTypeTimeout)); - return null; - } - logger.info("扫描试管架类型成功,{}", tubeType); - //逐个扫描试管 - TubesScanResult[] tubesScanResult = new TubesScanResult[10]; - boolean hasTube = false; - for (int i = 0; i < tubesScanResult.length; i++) { - tubesScanResult[i] = new TubesScanResult(); - Boolean isTubeExist = stc.moveAndjudgeTubeExist(i); - if (isTubeExist) { - hasTube = true; - tubesScanResult[i].isTubeExist = true; - tubesScanResult[i].isHighTube = stc.moveAndJudgeTubeAltit(i); - tubesScanResult[i].tubeCode = stc.moveTubeToScanPosAndScan(i); - } else { - tubesScanResult[i].isTubeExist = false; - } - logger.info("扫描试管{}完成,{}", i, tubesScanResult[i]); - } - //处理扫描结果 - if (!hasTube) { - logger.error("试管架中没有试管"); - ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.TubeHolderTypeIsNotSupport)); - stc.ejectTubeHolder(); - return null; - } - result.tubeHolderType = tubeType; - result.tubesScanResults = tubesScanResult; - return result; - } - - TubeHolder parseScanResult(SampleScanResult scanResult) throws AppException { - TubeHolder state = new TubeHolder(); - TubeHolderSetting setting = appTubeSettingMgrService.getThelastActiveTubeHolderSettingAndLock(); - try { - //获取试管架类型 - A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType); - if (tubeHolderType == null) { - logger.error("不支持的试管架类型"); - ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.TubeHolderTypeIsNotSupport)); - stc.ejectTubeHolder(); - return null; - } - - assert setting == null || setting.tubeSettings.length == state.tubes.length; - - //逐个赋值试管配置信息 - updaetGroupId(); - for (int i = 0; i < state.tubes.length; i++) { - - if (!scanResult.tubesScanResults[i].isTubeExist) { - state.tubes[i].state = TubeState.EMPTY; - continue; - } - - state.tubes[i].state = TubeState.TO_BE_PROCESSED; - state.tubes[i].isHighTube = scanResult.tubesScanResults[i].isHighTube; - - - //首先赋值默认值 - state.tubes[i].bloodType = BloodType.WHOLE_BLOOD; - state.tubes[i].sampleBarcode = ""; - state.tubes[i].userid = ""; - state.tubes[i].projIndex = List.of();//不做任何项目 - - //然后赋值用户配置的数值 - if (setting != null) { - state.tubes[i].bloodType = setting.tubeSettings[i].bloodType; - state.tubes[i].sampleBarcode = setting.tubeSettings[i].sampleBarcode; - state.tubes[i].userid = setting.tubeSettings[i].userid; - state.tubes[i].projIndex = setting.tubeSettings[i].projIndex; - } - - if (state.tubes[i].userid.isEmpty()) { - state.tubes[i].userid = genUserId(i); - } - - //最后赋值扫描到的数值 - // - //TODO:添加请求后台的代码 - // - // state.tubeStates[i].bloodType = ; - // state.tubeStates[i].sampleBarcode = setting.tubeSettings[i].sampleBarcode; - // state.tubeStates[i].userid = setting.tubeSettings[i].userid; - // state.tubeStates[i].projIndex = setting.tubeSettings[i].projIndex; - } - //设置试管架状态 - state.state = TubeHolderState.PROCESSING; - //删除之前的试管架配置 - appTubeSettingMgrService.removeTubeHolderSetting(setting); - return state; - - } catch (AppException e) { - //回滚部分状态 - appTubeSettingMgrService.removeTubeHolderSetting(setting); - throw e; - } - } - - - @Override public void doaction() throws AppException { - logger.info("开始扫描试管架"); - var scanResult = scanTubeHodler(); - if (scanResult == null) { - return; - } - - logger.info("解析扫描结果"); - TubeHolder state = parseScanResult(scanResult); - if (state == null) { - return; - } - - logger.info("将样本信息写入数据库"); - tubeProcessContextMgrService.createNewTubeContexts(state.tubes); - - logger.info("更新试管架状态"); - gstate.setTubeHolder(state); - } - - @Override public Boolean checkCondition() { - return cmgr.isTimeToEnterNewTubeHolder(); - } - - @Override public List getResourceList() { - return List.of(A8kPublicResourceType.ShakeModule); - } - - // - // UTILS - // - - static Integer usrgroupidoff = 10; - static Boolean tryUpdateGroupId = false; - - String genUserId(Integer tubeoff) { - if (tryUpdateGroupId) { - usrgroupidoff++; - if (usrgroupidoff >= 100) { - usrgroupidoff = 10; - } - tryUpdateGroupId = false; - } - //构造用户ID, 年月日时分秒_试管偏移量 - int usrReadableOff = tubeoff + 1; - if (usrReadableOff >= 10) { - usrReadableOff = 0; - } - return String.format("%2d%d", usrgroupidoff, usrReadableOff); - } - - void updaetGroupId() { - tryUpdateGroupId = true; - } - - -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java deleted file mode 100644 index 48bfebf..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java +++ /dev/null @@ -1,106 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.*; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.TubeHolder; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.TubeState; -import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * - * 核对物料资源是否足够 - * - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -@Component -public class SEQ2_SWITCH_TO_THE_NEXT_TUBE extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ2_SWITCH_TO_THE_NEXT_TUBE.class); - - SEQ2_SWITCH_TO_THE_NEXT_TUBE() { - super(A8kActionStepType.SEQ2_SWITCH_TO_THE_NEXT_TUBE); - } - - @Resource - GStateService gstate; - @Resource - SampleScanTransportCtrl sstc; - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - @Resource - CondtionMgrService cms; - - - MainFlowCtrlState state; - - @PostConstruct - void init() { - state = gstate.mainFlowCtrlState; - } - - int moveToNextTube() { - TubeHolder state = gstate.getTubeHolder(); - assert state.tubes.length == 10; - int nextTubeIndex = -1; - for (int i = 0; i < 10; i++) { - Tube tube = state.tubes[i]; - if (tube.state.equals(TubeState.TO_BE_PROCESSED)) { - nextTubeIndex = i; - break; - } - } - //没有下一个试管 - return nextTubeIndex; - } - - @Override public void doaction() throws AppException { - /* - * 1. 将下一个试管移动到预处理位 - * 2. 如果当前试管是最后一个试管,则设置试管架状态为处理完成。 - * 3. 检查反应板是否有空位 - */ - //当前是否有有急诊试管需要处理 - Tube nextProcessTube = null; - boolean isEmergencyTube = false; - int nextTubeIndex = -1; - - if (gstate.getEmergencyTubePos().tube.state.equals(TubeState.TO_BE_PROCESSED)) { - nextProcessTube = gstate.getEmergencyTubePos().tube; - isEmergencyTube = true; - } else { - nextTubeIndex = moveToNextTube(); - assert nextTubeIndex != -1; - nextProcessTube = gstate.getTubeHolder().tubes[nextTubeIndex]; - } - //设置状态 - if (isEmergencyTube) { - logger.info("处理急诊试管:{}", nextProcessTube.sampleid); - } else { - logger.info("处理下一个试管:{}", nextProcessTube.sampleid); - sstc.moveTubeToPreProcessPos(nextTubeIndex); - } - - tubeProcessStateMgrService.pendingTube(nextProcessTube); - } - - @Override public Boolean checkCondition() { - return cms.isTimeToSwitchNextTube(); - } - - @Override public List getResourceList() { - return List.of(A8kPublicResourceType.ShakeModule); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ3_APPLAY_RESOURCE.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ3_APPLAY_RESOURCE.java deleted file mode 100644 index 32d3be6..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ3_APPLAY_RESOURCE.java +++ /dev/null @@ -1,126 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.baseservice.AppExceptionBuilder; -import a8k.hardware.type.a8kcanprotocol.A8kEcode; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appdata.AppProjInfoMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.*; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.Tube; -import a8k.type.Consumable; -import a8k.type.IncubatorPos; -import a8k.type.TipPos; -import a8k.type.exception.AppException; -import a8k.type.projecttype.A8kReactionFlowType; -import a8k.type.projecttype.a8kidcard.A8kIdCardInfo; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * 核对物料资源是否足够 - * - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -@Component -public class SEQ3_APPLAY_RESOURCE extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ3_APPLAY_RESOURCE.class); - - SEQ3_APPLAY_RESOURCE() { - super(A8kActionStepType.SEQ3_APPLAY_RESOURCE); - } - - @Resource - GStateService gstate; - @Resource - ConsumablesMgrService consumablesMgrService; //耗材管理 - @Resource - AppExceptionBuilder ebuilder; //异常构造器 - @Resource - IncubationPlateMgrService incubationPlateMgrService; //孵育盘管理 - @Resource - AppProjInfoMgrService appProjInfoMgrService; //项目信息管理 - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; //试管处理状态管理 - @Resource - CondtionMgrService cms; - - - MainFlowCtrlState state; - - @PostConstruct - void init() { - state = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - Tube tube = gstate.getCurProcessingTube(); - assert tube != null; - List projs = gstate.getCurProcessingTube().projIndex; - - //检查是否有足够的耗材 - for (Integer projin : projs) { - if (!consumablesMgrService.isHasEnoughConsumables(projs)) { - throw ebuilder.buildConsumeNotEnoughError(projin); - } - } - logger.info("check consumables ok"); - - //检查tip是否足够 - int tipNum = 0; - for (Integer proj : projs) { - A8kReactionFlowType flow = appProjInfoMgrService.getA8kReactionFlowTypeByProjIndex(proj); - assert flow != null; //由于先核对的耗材,这里就一定有对应的项目 - tipNum += flow.tipUseNum; - } - if (!consumablesMgrService.isHasEnoughTips(tipNum)) { - throw ebuilder.buildAppException(A8kEcode.TipNotEnough); - } - logger.info("check tips ok"); - - assert incubationPlateMgrService.isHasEnoughIncubationIDLEPos(projs.size()); - logger.info("check incubationPlate ok"); - - //申请项目耗材 - List consumables = consumablesMgrService.takeConsumables(projs); - //申请孵育盘位置 - List incubatorPoss = incubationPlateMgrService.takeIncubationIDLEPos(projs.size()); - assert consumables != null; - assert incubatorPoss != null; - //找到项目对应的A8kIdCardInfo - List a8kIdCardInfo = new ArrayList<>(); - for (Consumable consumable : consumables) { - A8kIdCardInfo idcardInfo = appProjInfoMgrService.getA8kIdCardInfoByLotId(consumable.lotId); - assert idcardInfo != null; - a8kIdCardInfo.add(idcardInfo); - } - //申请tip头 - List> tipPos = new ArrayList<>(); - for (int i = 0; i < projs.size(); i++) { - List tips = consumablesMgrService.takeTip(a8kIdCardInfo.get(i).reactionFlowType); - assert tips != null; - tipPos.add(tips); - } - //创建项目处理上下文 - tubeProcessStateMgrService.setTubeResourceIsReady(a8kIdCardInfo, consumables, tipPos, incubatorPoss); - logger.info("apply resource ok"); - } - - @Override public Boolean checkCondition() { - return cms.isTimeToProcessPendingTube(); - } - - @Override public List getResourceList() { - return List.of(A8kPublicResourceType.CurTubeProcessToken); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ4_PRE_PROCESS.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ4_PRE_PROCESS.java deleted file mode 100644 index a9986fc..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ4_PRE_PROCESS.java +++ /dev/null @@ -1,229 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.OS; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appdata.AppProjInfoMgrService; -import a8k.baseservice.AppExceptionBuilder; -import a8k.baseservice.appeventbus.AppEventBusService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.*; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.TubeState; -import a8k.service.devicedriver.ctrl.HbotControlService; -import a8k.service.devicedriver.ctrl.ReactionPlatesTransmitCtrl; -import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; -import a8k.service.devicedriver.ctrl.SamplesPreProcesCtrl; -import a8k.type.ecode.AppError; -import a8k.type.exception.AppException; -import a8k.utils.ZFnCall; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Objects; -import java.util.concurrent.*; - -/** - * - * 核对物料资源是否足够 - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -@Component -public class SEQ4_PRE_PROCESS extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ4_PRE_PROCESS.class); - - SEQ4_PRE_PROCESS() { - super(A8kActionStepType.SEQ4_PRE_PROCESS); - } - - @Resource - GStateService gstate; - - @Resource - SampleScanTransportCtrl sstc; - - - @Resource - ConsumablesMgrService consumablesMgrService; - - - @Resource - AppProjInfoMgrService appProjInfoMgrService; - - @Resource - AppEventBusService ebus; - - @Resource - AppExceptionBuilder ebuilder; - - @Resource - TubeProcessContextMgrService tubeProcessContextMgrService; - - @Resource - ReactionPlatesTransmitCtrl reactionPlatesTransmitCtrl; - - @Resource - SamplesPreProcesCtrl samplesPreProcesCtrl; - - @Resource - HbotControlService hbotControlService; - - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - - @Resource - IncubationPlateMgrService incubationPlateMgrService; - - @Resource - CondtionMgrService cms; - - ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); - - - @PostConstruct - void init() { - } - - /** - * 推出反应板夹 - * @throws AppException 异常 - */ - void prepareReactionPlate() throws AppException { - if (gstate.debugMode) { - logger.info("prepareReactionPlate"); - OS.forceSleep(1000); - return; - } - // Tube tube = gstate.getCurProcessingTube(); - // List projIndex = tube.projIndex; - // List incubatorPos = tube.incubatorPos; - // List bindConsumablesCh = tube.bindConsumablesCh; - // - // for (int i = 0; i < projIndex.size(); i++) { - // var tank = gstate.getIncubationPlate().getSubTank(incubatorPos.get(i)); - // reactionPlatesTransmitCtrl.pushPlate(bindConsumablesCh.get(i), incubatorPos.get(i)); - // tank.state = IncubationSubTankState.WAITING_FOR_DROP; - // } - - } - - /** - * 摇匀并取盖 - * @throws AppException - */ - void shakeAndTakeCap() throws AppException { - if (gstate.debugMode) { - logger.info("shakeAndTakeCap"); - OS.forceSleep(1000); - return; - } - - // Tube tube = gstate.getCurProcessingTube(); - // if (tube.isEmergency) { - // //如果事急诊位则什么也不做 - // return; - // } - // - // TubeHolder tubeHolder = gstate.getTubeHolder(); - // if (!tubeHolder.tubeHolderType.equals(A8kTubeHolderType.BloodTube)) { - // //如果不是全血试管则什么也不做 - // return; - // } - // - // logger.info("摇匀并取盖"); - // samplesPreProcesCtrl.takeTubeAndJudgeTubeExist(tube.isHighTube); - // samplesPreProcesCtrl.shakeTube(45, 5); - // samplesPreProcesCtrl.takeTubeCap(); - OS.forceSleep(1000); - } - - void hbotPrepareTip() throws AppException { - if (gstate.debugMode) { - logger.info("hbotPrepareTip"); - OS.forceSleep(1000); - return; - } - // Tube tube = gstate.getCurProcessingTube(); - // // hbotControlService.takeTip(); - // TipPos tippos = consumablesMgrService.takeNextTipPosAndSetUsed(); - // if (tippos == null) { - // throw ebuilder.buildAppCodeErrorException("预处理阶段,申请Tip失败"); - // } - // - // Boolean suc = hbotControlService.takeTip(tippos.group, tippos.pos); - // if (!suc) { - // logger.warn("takeTip fail"); - // tube.ecode = A8kEcode.TakeTipFail; - // tube.state = TubeState.ERROR; - // } - // - // logger.info("takeTip success"); - OS.forceSleep(1000); - } - - @Override public void doaction() throws AppException { - // - // 1.准备3份反应板夹 - // 2.取tip头 - // 3.摇匀,脱帽 - // - - Tube tube = gstate.getCurProcessingTube(); - //准备反应板夹 - var doPrepareReactionPlateFuture = executor.submit(() -> ZFnCall.callfn(this::prepareReactionPlate)); - //摇匀并取盖 - var doShakeAndTakeCapFuture = executor.submit(() -> ZFnCall.callfn(this::shakeAndTakeCap)); - //准备Hbot Tip - var doHbotPrepareTipFuture = executor.submit(() -> ZFnCall.callfn(this::hbotPrepareTip)); - - wait(doPrepareReactionPlateFuture); - wait(doShakeAndTakeCapFuture); - wait(doHbotPrepareTipFuture); - - List errors = new java.util.ArrayList<>(List.of()); - try { - errors.add(doPrepareReactionPlateFuture.get()); - errors.add(doShakeAndTakeCapFuture.get()); - errors.add(doHbotPrepareTipFuture.get()); - } catch (InterruptedException | ExecutionException ignored) { - } - errors.removeIf(Objects::isNull); - if (!errors.isEmpty()) { - throw ebuilder.buildMutiErrorAppException(errors); - } - - tubeProcessStateMgrService.setCurTubeState(TubeState.PRE_PROCESSED); - incubationPlateMgrService.waitingForDrop(tube); - logger.info("pre process success"); - } - - - @Override public Boolean checkCondition() { - return cms.isTimeToPreProcessTube(); - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.IncubationPlateModule, - A8kPublicResourceType.PlatesBoxModule, - A8kPublicResourceType.HBOT, - A8kPublicResourceType.CurTubeProcessToken - ); - } - - // - // UTILS - // - - void wait(Future future) { - while (!future.isDone()) { - OS.forceSleep(100); - } - } -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ5_PROCESS.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ5_PROCESS.java deleted file mode 100644 index aa7b41b..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ5_PROCESS.java +++ /dev/null @@ -1,96 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.OS; -import a8k.baseservice.AppExceptionBuilder; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.*; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.TubeState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.concurrent.*; - -/** - * - * 核对物料资源是否足够 - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -@Component -public class SEQ5_PROCESS extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ5_PROCESS.class); - - SEQ5_PROCESS() { - super(A8kActionStepType.SEQ5_PROCESS); - } - - @Resource - GStateService gstate; - - @Resource - AppExceptionBuilder ebuilder; - - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - - @Resource - IncubationPlateMgrService incubationPlateMgrService; - - @Resource - CondtionMgrService cms; - - - MainFlowCtrlState state; - - @PostConstruct - void init() { - state = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - // - // 1.准备3份反应板夹 - // 2.取tip头 - // 3.摇匀,脱帽 - // - tubeProcessStateMgrService.setCurTubeState(TubeState.PROCESSING); - Tube tube = gstate.getCurProcessingTube(); - OS.forceSleep(3000); - tubeProcessStateMgrService.setCurTubeState(TubeState.PROCESSED); - incubationPlateMgrService.startIncubating(tube, 60 * 2); - logger.info("pre process success"); - } - - - @Override public Boolean checkCondition() { - return cms.isTimeToProcessTube(); - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.IncubationPlateModule, - A8kPublicResourceType.HBOT, - A8kPublicResourceType.CurTubeProcessToken - ); - } - - // - // UTILS - // - - void wait(Future future) { - while (!future.isDone()) { - OS.forceSleep(100); - } - } -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ6_POST_PROCESS.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ6_POST_PROCESS.java deleted file mode 100644 index 74b8733..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ6_POST_PROCESS.java +++ /dev/null @@ -1,92 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.OS; -import a8k.baseservice.AppExceptionBuilder; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.*; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.Tube; -import a8k.service.appstate.type.state.TubeState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.concurrent.*; - -/** - * - * 核对物料资源是否足够 - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -@Component -public class SEQ6_POST_PROCESS extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ6_POST_PROCESS.class); - - SEQ6_POST_PROCESS() { - super(A8kActionStepType.SEQ6_POST_PROCESS); - } - - @Resource - GStateService gstate; - - @Resource - AppExceptionBuilder ebuilder; - - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - - @Resource - IncubationPlateMgrService incubationPlateMgrService; - - @Resource - CondtionMgrService cms; - - - ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); - - - MainFlowCtrlState state; - - @PostConstruct - void init() { - state = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - tubeProcessStateMgrService.setCurTubeState(TubeState.POST_PROCESSING); - Tube tube = gstate.getCurProcessingTube(); - OS.forceSleep(3000); - tubeProcessStateMgrService.setCurTubeState(TubeState.POST_PROCESSED); - } - - @Override public Boolean checkCondition() { - return cms.isTimeToPostProcessTube(); - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.IncubationPlateModule, - A8kPublicResourceType.PlatesBoxModule, - A8kPublicResourceType.HBOT, - A8kPublicResourceType.CurTubeProcessToken - ); - } - - // - // UTILS - // - - void wait(Future future) { - while (!future.isDone()) { - OS.forceSleep(100); - } - } -} diff --git a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ7_EJECT_TUBEHOLDER.java b/src/main/java/a8k/service/appctrl/action/mainflow/SEQ7_EJECT_TUBEHOLDER.java deleted file mode 100644 index 22ea511..0000000 --- a/src/main/java/a8k/service/appctrl/action/mainflow/SEQ7_EJECT_TUBEHOLDER.java +++ /dev/null @@ -1,60 +0,0 @@ -package a8k.service.appctrl.action.mainflow; - -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.state.TubeHolderState; -import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class SEQ7_EJECT_TUBEHOLDER extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ7_EJECT_TUBEHOLDER.class); - - SEQ7_EJECT_TUBEHOLDER() { - super(A8kActionStepType.SEQ7_EJECT_TUBEHOLDER); - } - - @Resource - GStateService gstate; - @Resource - SampleScanTransportCtrl stc; - - MainFlowCtrlState state; - - @Resource - CondtionMgrService cms; - - @PostConstruct - void init() { - state = gstate.mainFlowCtrlState; - } - - @Override public void doaction() throws AppException { - stc.ejectTubeHolder(); - stc.moveTubeRackMoveToEnterPos(); - gstate.getTubeHolder().state = TubeHolderState.IDLE; - } - - @Override public Boolean checkCondition() { - //处于工作状态,试管架已经处于空闲状态,入料光电被触发 - Boolean cond1 = cms.isCanDoAction(); - Boolean cond2 = gstate.getTubeHolder().state.equals(TubeHolderState.PROCESSING); - Boolean cond3 = cms.isNoMoreTubeToBeProcessed(); - return cond1 && cond2 && cond3; - } - - @Override public List getResourceList() { - return List.of(A8kPublicResourceType.ShakeModule); - } -} diff --git a/src/main/java/a8k/service/appctrl/action/opt/PLATE_OPT_SCAN.java b/src/main/java/a8k/service/appctrl/action/opt/PLATE_OPT_SCAN.java deleted file mode 100644 index efc5696..0000000 --- a/src/main/java/a8k/service/appctrl/action/opt/PLATE_OPT_SCAN.java +++ /dev/null @@ -1,85 +0,0 @@ -package a8k.service.appctrl.action.opt; - -import a8k.OS; -import a8k.dbservice.type.ReactionResultRecord; -import a8k.service.appctrl.CondtionMgrService; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appdata.AppReactionResultMgrService; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.IncubationPlateMgrService; -import a8k.service.appstate.OptScanModuleStateMgrService; -import a8k.service.appstate.TubeProcessStateMgrService; -import a8k.service.appstate.resource.A8kPublicResourceType; -import a8k.service.appstate.type.IncubationSubTank; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.IncubationSubTankState; -import a8k.type.ReactionResult; -import a8k.type.exception.AppException; -import a8k.type.reaction_result_type.ReactionResultStatus; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * 处理错误的试管 - */ -@Component -public class PLATE_OPT_SCAN extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(PLATE_OPT_SCAN.class); - - PLATE_OPT_SCAN() { - super(A8kActionStepType.PLATE_OPT_SCAN); - } - - @Resource - GStateService gstate; - @Resource - CondtionMgrService cms; - @Resource - IncubationPlateMgrService incubationPlateMgrService; - @Resource - OptScanModuleStateMgrService optScanModuleStateMgrService; - @Resource - TubeProcessStateMgrService tubeProcessStateMgrService; - @Resource - AppReactionResultMgrService appReactionResultMgrService; - - - MainFlowCtrlState mfcs; - - @PostConstruct - void init() { - mfcs = gstate.mainFlowCtrlState; - } - - - @Override public void doaction() throws AppException { - optScanModuleStateMgrService.startScanPlate(); - logger.info("扫描板夹"); - //记录扫描结果 - - //修改板夹状态 - optScanModuleStateMgrService.dropPlate(); - - appReactionResultMgrService.addRecord(optScanModuleStateMgrService.getCurProjProcessContext(), - new ReactionResult(ReactionResultStatus.SUCCESS, "12.8 mg/L"), - new ReactionResult(ReactionResultStatus.ERROR_RESULT_OUT_OF_RANGE, "")); - } - - @Override public Boolean checkCondition() { - Boolean cond1 = cms.isCanDoAction(); - Boolean cond2 = !optScanModuleStateMgrService.isEmpty(); - return cond1 && cond2; - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.OPTModule - ); - } -} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/CondtionMgrService.java b/src/main/java/a8k/service/appctrl/mainflowctrl/CondtionMgrService.java new file mode 100644 index 0000000..fa9b279 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/CondtionMgrService.java @@ -0,0 +1,149 @@ +package a8k.service.appctrl.mainflowctrl; + +import a8k.hardware.A8kCanBusService; +import a8k.hardware.type.a8kcanprotocol.IOId; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.IncubationPlateMgrService; +import a8k.service.appstate.OptScanModuleStateMgrService; +import a8k.service.appstate.type.Tube; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.service.appstate.type.state.TubeHolderState; +import a8k.service.appstate.type.state.TubeState; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + + +@Component +public class CondtionMgrService { + static Logger logger = LoggerFactory.getLogger(CondtionMgrService.class); + + @Resource + GStateService gstate; + + @Resource + A8kCanBusService canBus; + + @Resource + IncubationPlateMgrService incubationPlateMgrService; + + @Resource + OptScanModuleStateMgrService optScanModuleStateMgrService; + + Boolean getTubeholderEnterPosPPS() { //入料通道是否为空 + try { + return canBus.getIOState(IOId.InfeedPPS); + } catch (Exception e) { + logger.error("getTubeholderEnterPosPPS error", e); + return false; + } + } + + public Boolean isNoMoreTubeToBeProcessed() { + return !gstate.getTubeHolder().isHasTubeToBeProcessed(); + } + + public Boolean isCanDoAction() { + return gstate.mainFlowCtrlState.workState.equals(A8kWorkState.WORKING) && !gstate.mainFlowCtrlState.errorFlag && !gstate.mainFlowCtrlState.workStateChangeFlag; + } + + + public Boolean isHasSometubesToBeProcessed() { + return gstate.getTubeHolder().isHasTubeToBeProcessed() || gstate.getEmergencyTubePos().tube.state.equals(TubeState.TO_BE_PROCESSED); + } + + public Boolean isCurTubeProcessCompleted() { + return gstate.getCurProcessingTube() == null || gstate.getCurProcessingTube().state.equals(TubeState.PROCESS_COMPLETE); + } + + public Boolean isOptModuleEmpty() { + return optScanModuleStateMgrService.isEmpty(); + } + + public Boolean isTimeToEnterNewTubeHolder() { + Boolean cond0 = isCanDoAction(); + //试管架处于空闲状态 + Boolean cond1 = gstate.getTubeHolder().state.equals(TubeHolderState.IDLE); + //入料通道是否为空 + Boolean cond2 = getTubeholderEnterPosPPS(); + return cond0 && cond1 && cond2; + } + + public Boolean isTimeToSwitchNextTube() { + Boolean cond0 = isCanDoAction(); + //当前试管处理完成 + Boolean cond1 = isCurTubeProcessCompleted(); + //有待处理的试管 + Boolean cond2 = isHasSometubesToBeProcessed(); + return cond0 && cond1 && cond2; + } + + public Boolean isTimeToProcessPendingTube() { + Tube tube = gstate.getCurProcessingTube(); + if (tube == null) + return false; + + //当前正在工作 + Boolean cond1 = isCanDoAction(); + //没有试管在处理 或者 当前试管处理完成 + Boolean cond2 = tube.state.equals(TubeState.PENDING); + //急诊有待处理的试管,或者试管架正在处理 + Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); + return cond1 && cond2 && cond3; + } + + public Boolean isTimeToPreProcessTube() { + Tube tube = gstate.getCurProcessingTube(); + if (tube == null) + return false; + + //当前正在工作 + Boolean cond1 = isCanDoAction(); + //没有试管在处理 或者 当前试管处理完成 + Boolean cond2 = tube.state.equals(TubeState.RESOURCE_IS_READY); + //急诊有待处理的试管,或者试管架正在处理 + Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); + return cond1 && cond2 && cond3; + } + + public Boolean isTimeToProcessTube() { + Tube tube = gstate.getCurProcessingTube(); + if (tube == null) + return false; + + //当前正在工作 + Boolean cond1 = isCanDoAction(); + //没有试管在处理 或者 当前试管处理完成 + Boolean cond2 = tube.state.equals(TubeState.PRE_PROCESSED); + //急诊有待处理的试管,或者试管架正在处理 + Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); + return cond1 && cond2 && cond3; + } + + public Boolean isTimeToPostProcessTube() { + Tube tube = gstate.getCurProcessingTube(); + if (tube == null) + return false; + + //当前正在工作 + Boolean cond1 = isCanDoAction(); + //没有试管在处理 或者 当前试管处理完成 + Boolean cond2 = tube.state.equals(TubeState.PROCESSED); + //急诊有待处理的试管,或者试管架正在处理 + Boolean cond3 = incubationPlateMgrService.isHasEnoughIncubationIDLEPos(tube.projIndex.size()); + return cond1 && cond2 && cond3; + } + + public Boolean isHasSomeErrorPlatesToBeProcessed() { + return incubationPlateMgrService.isHasSomeErrorPlate(); + } + + public Boolean isHasSomeErrorTubeToBeProcessed() { + Tube tube = gstate.getCurProcessingTube(); + if (tube == null) + return false; + return gstate.getEmergencyTubePos().tube.state.equals(TubeState.ERROR); + } + +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/MainFlowCtrlScheduler.java b/src/main/java/a8k/service/appctrl/mainflowctrl/MainFlowCtrlScheduler.java new file mode 100644 index 0000000..27e8dd0 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/MainFlowCtrlScheduler.java @@ -0,0 +1,238 @@ +package a8k.service.appctrl.mainflowctrl; + +import a8k.OS; +import a8k.baseservice.appeventbus.AppEventBusService; +import a8k.baseservice.appeventbus.appevent.A8kEcodeContextListPromptEvent; +import a8k.baseservice.appeventbus.appevent.DoA8kStepActionEvent; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kErrorContext; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.ResourceMgrService; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Component +public class MainFlowCtrlScheduler { + static Logger logger = LoggerFactory.getLogger(MainFlowCtrlScheduler.class); + + + @FunctionalInterface + public interface A8kEcodePostProcesser { + void process(List ecodeList); + } + + @Resource + GStateService gstate; + @Resource + AppEventBusService ebus; + @Resource + ResourceMgrService resourceMgrService; + + MainFlowCtrlState state = null; + Thread workThread; + ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); + Runnable checkBeforeGuess; + A8kEcodePostProcesser ecodePostProcesser; + List stepActionList = new ArrayList<>(); + + @PostConstruct + void init() { + state = gstate.mainFlowCtrlState; + } + + /* + * Ext + */ + + public void regEcodePostProcesser(A8kEcodePostProcesser ecodePostProcesser) { + this.ecodePostProcesser = ecodePostProcesser; + } + + public void regCheckBeforeGuess(Runnable checkBeforeGuess) { + this.checkBeforeGuess = checkBeforeGuess; + } + + + public void regFn(A8kStepAction action) { + stepActionList.add(action); + } + + public void startScheduler() { + workThread = new Thread(this::threadLoopFn); + workThread.start(); + } + + public List getA8kStepActionList() { + return stepActionList; + } + + // + // 切片 + // + + void beforeDoWhat(A8kActionStepType dowhat) { + ebus.pushEvent(new DoA8kStepActionEvent(dowhat)); + } + + // + // Scheduler + // + + List guessWhatToDo() { + if (this.checkBeforeGuess != null) { + this.checkBeforeGuess.run(); + } + + try { + List dowhatList = new ArrayList<>(); + + for (A8kStepAction action : stepActionList) { + if (action.checkCondition()) { + Boolean relayResourceSuc = resourceMgrService.applyForResources(this, action.getResourceList()); + if (relayResourceSuc) { + dowhatList.add(action); + } + } + } + return dowhatList; + } catch (Exception e) { + logger.info("guessWhatToDo error:{}", e.toString()); + resourceMgrService.releaseAllResource(this); + } + return new ArrayList<>(); + } + + + A8kErrorContext callFn(A8kStepAction key) { + beforeDoWhat(key.step); + try { + logger.info("doaction:{}", key.step); + key.doaction(); + return new A8kErrorContext(key.step, null); + } catch (AppException appe) { + return new A8kErrorContext(key.step, appe.error); + } + } + + + List waitAllActionIsDone(List> futureList) { + List ecodeList = new ArrayList<>(); + while (true) { + boolean someTaskNotDone = false; + for (Future future : futureList) { + if (!future.isDone()) { + someTaskNotDone = true; + break; + } + } + if (!someTaskNotDone) { + break; + } + OS.forceSleep(30); + } + + for (Future future : futureList) { + try { + ecodeList.add(future.get()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //清空NoError + ecodeList.removeIf(ecode -> ecode.ecode == null); + return ecodeList; + } + + void doActions(List dowhatList) { + + // + List serialActionList = new ArrayList<>(); + List parallelActionList = new ArrayList<>(); + List ecodeList = new ArrayList<>(); + + for (A8kStepAction action : dowhatList) { + if (action.isAllowsParallelRunning()) { + parallelActionList.add(action); + } else { + serialActionList.add(action); + } + } + + //执行串行任务 + for (A8kStepAction action : serialActionList) { + A8kErrorContext aec = callFn(action); + ecodeList.add(aec); + } + + //执行并行任务 + List> futureList = new ArrayList<>(); + for (A8kStepAction dowhat : parallelActionList) { + var future = executor.submit(() -> callFn(dowhat)); + futureList.add(future); + } + + //等待并行任务完成 + List ecodeListParallel = waitAllActionIsDone(futureList); + resourceMgrService.releaseAllResource(this); + + //合并错误 + ecodeList.addAll(ecodeListParallel); + + if (!ecodeList.isEmpty()) { + a8kEcodePostProcesser(ecodeList); + } + } + + void a8kEcodePostProcesser(List ecodeList) { + //如果有错误,且错误列表不为空,则将错误列表添加到错误列表中 + if (!this.state.ecodeList.isEmpty()) { + ecodeList.addAll(this.state.ecodeList); + } + // + // //清除重复错误 + // List newEcodeList = new ArrayList<>(); + // for (A8kEcode ecode : ecodeList) { + // if (!newEcodeList.contains(ecode)) { + // newEcodeList.add(ecode); + // } + // } + // ecodeList = newEcodeList; + + //处理错误 + if (ecodePostProcesser != null) { + ecodePostProcesser.process(ecodeList); + } + + ebus.pushEvent(new A8kEcodeContextListPromptEvent(ecodeList)); + this.state.errorFlag = true; + this.state.ecodeList = ecodeList; + this.state.workState = A8kWorkState.PAUSE; + } + + void threadLoopFn() { + while (workThread.isAlive()) { + if (state.fatalErrorFlag) { + OS.forceSleep(800); + } else { + doActions(guessWhatToDo()); + OS.forceSleep(800); + } + } + } + +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_CLEAR_ERROR_BEFORE_WORK.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_CLEAR_ERROR_BEFORE_WORK.java new file mode 100644 index 0000000..7252930 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_CLEAR_ERROR_BEFORE_WORK.java @@ -0,0 +1,72 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.IncubationPlateMgrService; +import a8k.service.appstate.OptScanModuleStateMgrService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class DO_CLEAR_ERROR_BEFORE_WORK extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_CLEAR_ERROR_BEFORE_WORK.class); + + DO_CLEAR_ERROR_BEFORE_WORK() { + super(A8kActionStepType.DO_CLEAR_ERROR_BEFORE_WORK); + } + + @Resource + GStateService gstate; + @Resource + CondtionMgrService cms; + @Resource + IncubationPlateMgrService incubationPlateMgrService; + @Resource + OptScanModuleStateMgrService optScanModuleStateMgrService; + + MainFlowCtrlState mfcs; + + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + + @Override public void doaction() throws AppException { + + //ProcessErrorBeforeContinue + + + mfcs.errorFlag = false; + mfcs.ecodeList.clear(); + + } + + @Override public Boolean checkCondition() { + Boolean cond1 = mfcs.workStateChangeFlag; + Boolean cond2 = mfcs.errorFlag; + Boolean cond3 = mfcs.workState.equals(A8kWorkState.WORKING); + Boolean cond4 = mfcs.lastWorkState.equals(A8kWorkState.PAUSE) || mfcs.lastWorkState.equals(A8kWorkState.IDLE); + return cond1 && cond2 && cond3 && cond4; + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.IncubationPlateModule, + A8kPublicResourceType.OPTModule, + A8kPublicResourceType.PlatesBoxModule + ); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PAUSE.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PAUSE.java new file mode 100644 index 0000000..843d9c8 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PAUSE.java @@ -0,0 +1,50 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class DO_PAUSE extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_PAUSE.class); + + DO_PAUSE() { + super(A8kActionStepType.DO_PAUSE); + } + + @Resource + GStateService gstate; + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + mfcs.workStateChangeFlag = false; + } + + @Override public Boolean checkCondition() { + Boolean cond1 = mfcs.workStateChangeFlag && !mfcs.errorFlag; + Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.WORKING); + Boolean cond3 = mfcs.workState.equals(A8kWorkState.PAUSE); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of(); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_PLATE.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_PLATE.java new file mode 100644 index 0000000..8605cc3 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_PLATE.java @@ -0,0 +1,81 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.OS; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.IncubationPlateMgrService; +import a8k.service.appstate.OptScanModuleStateMgrService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.IncubationSubTank; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.IncubationSubTankState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 处理错误的孵育盘 + */ +@Component +public class DO_PROCESS_ERROR_PLATE extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_PROCESS_ERROR_PLATE.class); + + DO_PROCESS_ERROR_PLATE() { + super(A8kActionStepType.DO_PROCESS_ERROR_PLATE); + } + + @Resource + GStateService gstate; + @Resource + CondtionMgrService cms; + @Resource + IncubationPlateMgrService incubationPlateMgrService; + @Resource + OptScanModuleStateMgrService optScanModuleStateMgrService; + + MainFlowCtrlState mfcs; + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + + + @Override public void doaction() throws AppException { + //ProcessErrorBeforeContinue + + while (true) { + IncubationSubTank errorTank = incubationPlateMgrService.getErrorPlate(); + if (errorTank == null) { + break; + } + logger.info("处理错误板夹:{}", errorTank.pos); + //TODO:推出板夹到光学模组,同时丢弃板夹 + logger.info("推出板夹到光学模组"); + logger.info("丢弃板夹"); + OS.forceSleep(3000); + // + optScanModuleStateMgrService.newPlateToOptScanPos(errorTank); + optScanModuleStateMgrService.dropPlate(); + incubationPlateMgrService.setIncubationPlateState(errorTank.pos, IncubationSubTankState.EMPTY); + } + } + + @Override public Boolean checkCondition() { + Boolean cond1 = cms.isCanDoAction(); + Boolean cond2 = cms.isHasSomeErrorPlatesToBeProcessed(); + Boolean cond3 = cms.isOptModuleEmpty(); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of(); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_TUBE.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_TUBE.java new file mode 100644 index 0000000..916b967 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_PROCESS_ERROR_TUBE.java @@ -0,0 +1,83 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.OS; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.IncubationPlateMgrService; +import a8k.service.appstate.OptScanModuleStateMgrService; +import a8k.service.appstate.TubeProcessStateMgrService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.Tube; +import a8k.service.appstate.type.state.TubeState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 处理错误的试管 + */ +@Component +public class DO_PROCESS_ERROR_TUBE extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_PROCESS_ERROR_TUBE.class); + + DO_PROCESS_ERROR_TUBE() { + super(A8kActionStepType.DO_PROCESS_ERROR_TUBE); + } + + @Resource + GStateService gstate; + @Resource + CondtionMgrService cms; + @Resource + IncubationPlateMgrService incubationPlateMgrService; + @Resource + OptScanModuleStateMgrService optScanModuleStateMgrService; + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + + @Override public void doaction() throws AppException { + //ProcessErrorBeforeContinue + + Tube tube = gstate.getCurProcessingTube(); + assert tube != null; + + logger.info("处理错误试管:{}", tube.sampleid); + logger.info("复位摇匀模组"); + OS.forceSleep(4000); + //复位摇匀模组 + logger.info("复位HBOT"); + //复位HBOT + OS.forceSleep(4000); + tubeProcessStateMgrService.setCurTubeState(TubeState.PROCESS_COMPLETE); + } + + @Override public Boolean checkCondition() { + Boolean cond1 = cms.isCanDoAction(); + Boolean cond2 = cms.isHasSometubesToBeProcessed(); + return cond1 && cond2; + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.ShakeModule, + A8kPublicResourceType.HBOT + ); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_RESUME.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_RESUME.java new file mode 100644 index 0000000..259aae0 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_RESUME.java @@ -0,0 +1,50 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class DO_RESUME extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_RESUME.class); + + DO_RESUME() { + super(A8kActionStepType.DO_RESUME); + } + + @Resource + GStateService gstate; + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + mfcs.workStateChangeFlag = false; + } + + @Override public Boolean checkCondition() { + Boolean cond1 = mfcs.workStateChangeFlag; + Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.PAUSE); + Boolean cond3 = mfcs.workState.equals(A8kWorkState.WORKING); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of(); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_START.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_START.java new file mode 100644 index 0000000..fe35658 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_START.java @@ -0,0 +1,55 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class DO_START extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_START.class); + + DO_START() { + super(A8kActionStepType.DO_START); + } + + @Resource + GStateService gstate; + + @Resource + SampleScanTransportCtrl sampleScanTransportCtrl; + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + mfcs.workStateChangeFlag = false; + sampleScanTransportCtrl.ejectTubeHolder(); + } + + @Override public Boolean checkCondition() { + Boolean cond1 = mfcs.workStateChangeFlag; + Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.IDLE); + Boolean cond3 = mfcs.workState.equals(A8kWorkState.WORKING); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of(A8kPublicResourceType.ShakeModule); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_STOP.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_STOP.java new file mode 100644 index 0000000..a274cfe --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/DO_STOP.java @@ -0,0 +1,50 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.A8kWorkState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class DO_STOP extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(DO_STOP.class); + + DO_STOP() { + super(A8kActionStepType.DO_STOP); + } + + @Resource + GStateService gstate; + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + mfcs.workStateChangeFlag = false; + } + + @Override public Boolean checkCondition() { + Boolean cond1 = mfcs.workStateChangeFlag; + Boolean cond2 = mfcs.lastWorkState.equals(A8kWorkState.WORKING) || mfcs.lastWorkState.equals(A8kWorkState.PAUSE); + Boolean cond3 = mfcs.workState.equals(A8kWorkState.IDLE); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of(); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java new file mode 100644 index 0000000..87f0a6b --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java @@ -0,0 +1,81 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appdata.AppReactionResultMgrService; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.IncubationPlateMgrService; +import a8k.service.appstate.OptScanModuleStateMgrService; +import a8k.service.appstate.TubeProcessStateMgrService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.type.ReactionResult; +import a8k.type.exception.AppException; +import a8k.type.reaction_result_type.ReactionResultStatus; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 处理错误的试管 + */ +@Component +public class PLATE_OPT_SCAN extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(PLATE_OPT_SCAN.class); + + PLATE_OPT_SCAN() { + super(A8kActionStepType.PLATE_OPT_SCAN); + } + + @Resource + GStateService gstate; + @Resource + CondtionMgrService cms; + @Resource + IncubationPlateMgrService incubationPlateMgrService; + @Resource + OptScanModuleStateMgrService optScanModuleStateMgrService; + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + @Resource + AppReactionResultMgrService appReactionResultMgrService; + + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + + @Override public void doaction() throws AppException { + optScanModuleStateMgrService.startScanPlate(); + logger.info("扫描板夹"); + //记录扫描结果 + + //修改板夹状态 + optScanModuleStateMgrService.dropPlate(); + + appReactionResultMgrService.addRecord(optScanModuleStateMgrService.getCurProjProcessContext(), + new ReactionResult(ReactionResultStatus.SUCCESS, "12.8 mg/L"), + new ReactionResult(ReactionResultStatus.ERROR_RESULT_OUT_OF_RANGE, "")); + } + + @Override public Boolean checkCondition() { + Boolean cond1 = cms.isCanDoAction(); + Boolean cond2 = !optScanModuleStateMgrService.isEmpty(); + return cond1 && cond2; + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.OPTModule + ); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java new file mode 100644 index 0000000..e718e10 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java @@ -0,0 +1,80 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.OS; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.IncubationPlateMgrService; +import a8k.service.appstate.OptScanModuleStateMgrService; +import a8k.service.appstate.TubeProcessStateMgrService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.IncubationSubTank; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.state.IncubationSubTankState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 处理错误的试管 + */ +@Component +public class PROCESS_INCUBATE_COMPLETED_PLATE extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(PROCESS_INCUBATE_COMPLETED_PLATE.class); + + PROCESS_INCUBATE_COMPLETED_PLATE() { + super(A8kActionStepType.PROCESS_INCUBATE_COMPLETED_PLATE); + } + + @Resource + GStateService gstate; + @Resource + CondtionMgrService cms; + @Resource + IncubationPlateMgrService incubationPlateMgrService; + @Resource + OptScanModuleStateMgrService optScanModuleStateMgrService; + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + + + MainFlowCtrlState mfcs; + + @PostConstruct + void init() { + mfcs = gstate.mainFlowCtrlState; + } + + + @Override public void doaction() throws AppException { + IncubationSubTank tank = incubationPlateMgrService.getOneExpiredPlate(); + if (tank == null) { + return; + } + logger.info("推出板夹到光学模组,{}", tank.pos); + OS.forceSleep(3000); + + optScanModuleStateMgrService.newPlateToOptScanPos(tank); + incubationPlateMgrService.setIncubationPlateState(tank.pos, IncubationSubTankState.EMPTY); + } + + @Override public Boolean checkCondition() { + Boolean cond1 = cms.isCanDoAction(); + Boolean cond2 = incubationPlateMgrService.isHasExpiredPlate(); + Boolean cond3 = optScanModuleStateMgrService.isEmpty(); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.OPTModule, + A8kPublicResourceType.IncubationPlateModule + ); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java new file mode 100644 index 0000000..1ecd313 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java @@ -0,0 +1,254 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.baseservice.appeventbus.AppEventBusService; +import a8k.baseservice.appeventbus.appevent.AppWarningNotifyEvent; +import a8k.hardware.A8kCanBusService; +import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.TubeSettingMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.TubeProcessContextMgrService; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.TubeHolder; +import a8k.service.appstate.type.state.TubeHolderState; +import a8k.service.appstate.type.state.TubeState; +import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; +import a8k.type.exception.AppException; +import a8k.type.tube_setting.TubeHolderSetting; +import a8k.type.type.A8kTubeHolderType; +import a8k.type.type.BloodType; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * + * TubeHolderState + * IDLE --> PROCESSING + * + * TUBES STATE + * EMPTY --> TO_BE_PROCESSED + */ +@Component +public class SEQ1_ENTER_TUBEHOLDER_AND_SCAN extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ1_ENTER_TUBEHOLDER_AND_SCAN.class); + + SEQ1_ENTER_TUBEHOLDER_AND_SCAN() { + super(A8kActionStepType.SEQ1_ENTER_TUBEHOLDER_AND_SCAN); + } + + static public class TubesScanResult { + public Boolean isTubeExist = false; + public Boolean isHighTube = false; + public String tubeCode = null; + + public String toString() { + return String.format("isTubeExist:%s,isHighTube:%s,tubeCode:%s", isTubeExist, isHighTube, tubeCode); + } + } + + static public class SampleScanResult { + public TubesScanResult[] tubesScanResults; + public String tubeHolderType; + } + + + @Resource + GStateService gstate; + @Resource + CondtionMgrService cmgr; + @Resource + SampleScanTransportCtrl stc; + @Resource + AppEventBusService ebus; + @Resource + A8kCanBusService canBus; + @Resource + TubeSettingMgrService tubeSettingMgrService; + @Resource + TubeProcessContextMgrService tubeProcessContextMgrService; + + + SampleScanResult scanTubeHodler() throws AppException { + SampleScanResult result = new SampleScanResult(); + + //清空试管架 + if (!stc.tubeXChannelIsEmpty()) { + stc.ejectTubeHolder(); + } + //入料 + logger.info("开始进料"); + Boolean enterSuc = stc.enterTubeHolder(); + if (!enterSuc) { + logger.warn("进料超时,从入料口,弹出试管架"); + stc.ejectTubeHolderInEnterPos(); + throw new AppException(A8kEcode.InfeedOvertimeFail); + } + //扫描试管架类型 + String tubeType = stc.moveTubeRackToScanPosAndScan(); + if (tubeType.isEmpty()) { + logger.warn("扫描试管架类型失败,弹出试管架"); + stc.ejectTubeHolder(); + ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.ScanTubeholderTypeTimeout)); + return null; + } + logger.info("扫描试管架类型成功,{}", tubeType); + //逐个扫描试管 + TubesScanResult[] tubesScanResult = new TubesScanResult[10]; + boolean hasTube = false; + for (int i = 0; i < tubesScanResult.length; i++) { + tubesScanResult[i] = new TubesScanResult(); + Boolean isTubeExist = stc.moveAndjudgeTubeExist(i); + if (isTubeExist) { + hasTube = true; + tubesScanResult[i].isTubeExist = true; + tubesScanResult[i].isHighTube = stc.moveAndJudgeTubeAltit(i); + tubesScanResult[i].tubeCode = stc.moveTubeToScanPosAndScan(i); + } else { + tubesScanResult[i].isTubeExist = false; + } + logger.info("扫描试管{}完成,{}", i, tubesScanResult[i]); + } + //处理扫描结果 + if (!hasTube) { + logger.error("试管架中没有试管"); + ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.TubeHolderTypeIsNotSupport)); + stc.ejectTubeHolder(); + return null; + } + result.tubeHolderType = tubeType; + result.tubesScanResults = tubesScanResult; + return result; + } + + TubeHolder parseScanResult(SampleScanResult scanResult) throws AppException { + TubeHolder state = new TubeHolder(); + TubeHolderSetting setting = tubeSettingMgrService.getThelastActiveTubeHolderSettingAndLock(); + try { + //获取试管架类型 + A8kTubeHolderType tubeHolderType = A8kTubeHolderType.of(scanResult.tubeHolderType); + if (tubeHolderType == null) { + logger.error("不支持的试管架类型"); + ebus.pushEvent(new AppWarningNotifyEvent(A8kEcode.TubeHolderTypeIsNotSupport)); + stc.ejectTubeHolder(); + return null; + } + + assert setting == null || setting.tubeSettings.length == state.tubes.length; + + //逐个赋值试管配置信息 + updaetGroupId(); + for (int i = 0; i < state.tubes.length; i++) { + + if (!scanResult.tubesScanResults[i].isTubeExist) { + state.tubes[i].state = TubeState.EMPTY; + continue; + } + + state.tubes[i].state = TubeState.TO_BE_PROCESSED; + state.tubes[i].isHighTube = scanResult.tubesScanResults[i].isHighTube; + + + //首先赋值默认值 + state.tubes[i].bloodType = BloodType.WHOLE_BLOOD; + state.tubes[i].sampleBarcode = ""; + state.tubes[i].userid = ""; + state.tubes[i].projIndex = List.of();//不做任何项目 + + //然后赋值用户配置的数值 + if (setting != null) { + state.tubes[i].bloodType = setting.tubeSettings[i].bloodType; + state.tubes[i].sampleBarcode = setting.tubeSettings[i].sampleBarcode; + state.tubes[i].userid = setting.tubeSettings[i].userid; + state.tubes[i].projIndex = setting.tubeSettings[i].projIndex; + } + + if (state.tubes[i].userid.isEmpty()) { + state.tubes[i].userid = genUserId(i); + } + + //最后赋值扫描到的数值 + // + //TODO:添加请求后台的代码 + // + // state.tubeStates[i].bloodType = ; + // state.tubeStates[i].sampleBarcode = setting.tubeSettings[i].sampleBarcode; + // state.tubeStates[i].userid = setting.tubeSettings[i].userid; + // state.tubeStates[i].projIndex = setting.tubeSettings[i].projIndex; + } + //设置试管架状态 + state.state = TubeHolderState.PROCESSING; + //删除之前的试管架配置 + tubeSettingMgrService.removeTubeHolderSetting(setting); + return state; + + } catch (AppException e) { + //回滚部分状态 + tubeSettingMgrService.removeTubeHolderSetting(setting); + throw e; + } + } + + + @Override public void doaction() throws AppException { + logger.info("开始扫描试管架"); + var scanResult = scanTubeHodler(); + if (scanResult == null) { + return; + } + + logger.info("解析扫描结果"); + TubeHolder state = parseScanResult(scanResult); + if (state == null) { + return; + } + + logger.info("将样本信息写入数据库"); + tubeProcessContextMgrService.createNewTubeContexts(state.tubes); + + logger.info("更新试管架状态"); + gstate.setTubeHolder(state); + } + + @Override public Boolean checkCondition() { + return cmgr.isTimeToEnterNewTubeHolder(); + } + + @Override public List getResourceList() { + return List.of(A8kPublicResourceType.ShakeModule); + } + + // + // UTILS + // + + static Integer usrgroupidoff = 10; + static Boolean tryUpdateGroupId = false; + + String genUserId(Integer tubeoff) { + if (tryUpdateGroupId) { + usrgroupidoff++; + if (usrgroupidoff >= 100) { + usrgroupidoff = 10; + } + tryUpdateGroupId = false; + } + //构造用户ID, 年月日时分秒_试管偏移量 + int usrReadableOff = tubeoff + 1; + if (usrReadableOff >= 10) { + usrReadableOff = 0; + } + return String.format("%2d%d", usrgroupidoff, usrReadableOff); + } + + void updaetGroupId() { + tryUpdateGroupId = true; + } + + +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java new file mode 100644 index 0000000..3654d2e --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java @@ -0,0 +1,106 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.*; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.TubeHolder; +import a8k.service.appstate.type.Tube; +import a8k.service.appstate.type.state.TubeState; +import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * + * 核对物料资源是否足够 + * + * TUBE + * TO_BE_PROCESSED --> PRE_PROCESSING + */ +@Component +public class SEQ2_SWITCH_TO_THE_NEXT_TUBE extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ2_SWITCH_TO_THE_NEXT_TUBE.class); + + SEQ2_SWITCH_TO_THE_NEXT_TUBE() { + super(A8kActionStepType.SEQ2_SWITCH_TO_THE_NEXT_TUBE); + } + + @Resource + GStateService gstate; + @Resource + SampleScanTransportCtrl sstc; + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + @Resource + CondtionMgrService cms; + + + MainFlowCtrlState state; + + @PostConstruct + void init() { + state = gstate.mainFlowCtrlState; + } + + int moveToNextTube() { + TubeHolder state = gstate.getTubeHolder(); + assert state.tubes.length == 10; + int nextTubeIndex = -1; + for (int i = 0; i < 10; i++) { + Tube tube = state.tubes[i]; + if (tube.state.equals(TubeState.TO_BE_PROCESSED)) { + nextTubeIndex = i; + break; + } + } + //没有下一个试管 + return nextTubeIndex; + } + + @Override public void doaction() throws AppException { + /* + * 1. 将下一个试管移动到预处理位 + * 2. 如果当前试管是最后一个试管,则设置试管架状态为处理完成。 + * 3. 检查反应板是否有空位 + */ + //当前是否有有急诊试管需要处理 + Tube nextProcessTube = null; + boolean isEmergencyTube = false; + int nextTubeIndex = -1; + + if (gstate.getEmergencyTubePos().tube.state.equals(TubeState.TO_BE_PROCESSED)) { + nextProcessTube = gstate.getEmergencyTubePos().tube; + isEmergencyTube = true; + } else { + nextTubeIndex = moveToNextTube(); + assert nextTubeIndex != -1; + nextProcessTube = gstate.getTubeHolder().tubes[nextTubeIndex]; + } + //设置状态 + if (isEmergencyTube) { + logger.info("处理急诊试管:{}", nextProcessTube.sampleid); + } else { + logger.info("处理下一个试管:{}", nextProcessTube.sampleid); + sstc.moveTubeToPreProcessPos(nextTubeIndex); + } + + tubeProcessStateMgrService.pendingTube(nextProcessTube); + } + + @Override public Boolean checkCondition() { + return cms.isTimeToSwitchNextTube(); + } + + @Override public List getResourceList() { + return List.of(A8kPublicResourceType.ShakeModule); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ3_APPLAY_RESOURCE.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ3_APPLAY_RESOURCE.java new file mode 100644 index 0000000..cc1e803 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ3_APPLAY_RESOURCE.java @@ -0,0 +1,126 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.baseservice.AppExceptionBuilder; +import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appdata.AppProjInfoMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.*; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.Tube; +import a8k.type.Consumable; +import a8k.type.IncubatorPos; +import a8k.type.TipPos; +import a8k.type.exception.AppException; +import a8k.type.projecttype.A8kReactionFlowType; +import a8k.type.projecttype.a8kidcard.A8kIdCardInfo; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * 核对物料资源是否足够 + * + * TUBE + * TO_BE_PROCESSED --> PRE_PROCESSING + */ +@Component +public class SEQ3_APPLAY_RESOURCE extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ3_APPLAY_RESOURCE.class); + + SEQ3_APPLAY_RESOURCE() { + super(A8kActionStepType.SEQ3_APPLAY_RESOURCE); + } + + @Resource + GStateService gstate; + @Resource + ConsumablesMgrService consumablesMgrService; //耗材管理 + @Resource + AppExceptionBuilder ebuilder; //异常构造器 + @Resource + IncubationPlateMgrService incubationPlateMgrService; //孵育盘管理 + @Resource + AppProjInfoMgrService appProjInfoMgrService; //项目信息管理 + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; //试管处理状态管理 + @Resource + CondtionMgrService cms; + + + MainFlowCtrlState state; + + @PostConstruct + void init() { + state = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + Tube tube = gstate.getCurProcessingTube(); + assert tube != null; + List projs = gstate.getCurProcessingTube().projIndex; + + //检查是否有足够的耗材 + for (Integer projin : projs) { + if (!consumablesMgrService.isHasEnoughConsumables(projs)) { + throw ebuilder.buildConsumeNotEnoughError(projin); + } + } + logger.info("check consumables ok"); + + //检查tip是否足够 + int tipNum = 0; + for (Integer proj : projs) { + A8kReactionFlowType flow = appProjInfoMgrService.getA8kReactionFlowTypeByProjIndex(proj); + assert flow != null; //由于先核对的耗材,这里就一定有对应的项目 + tipNum += flow.tipUseNum; + } + if (!consumablesMgrService.isHasEnoughTips(tipNum)) { + throw ebuilder.buildAppException(A8kEcode.TipNotEnough); + } + logger.info("check tips ok"); + + assert incubationPlateMgrService.isHasEnoughIncubationIDLEPos(projs.size()); + logger.info("check incubationPlate ok"); + + //申请项目耗材 + List consumables = consumablesMgrService.takeConsumables(projs); + //申请孵育盘位置 + List incubatorPoss = incubationPlateMgrService.takeIncubationIDLEPos(projs.size()); + assert consumables != null; + assert incubatorPoss != null; + //找到项目对应的A8kIdCardInfo + List a8kIdCardInfo = new ArrayList<>(); + for (Consumable consumable : consumables) { + A8kIdCardInfo idcardInfo = appProjInfoMgrService.getA8kIdCardInfoByLotId(consumable.lotId); + assert idcardInfo != null; + a8kIdCardInfo.add(idcardInfo); + } + //申请tip头 + List> tipPos = new ArrayList<>(); + for (int i = 0; i < projs.size(); i++) { + List tips = consumablesMgrService.takeTip(a8kIdCardInfo.get(i).reactionFlowType); + assert tips != null; + tipPos.add(tips); + } + //创建项目处理上下文 + tubeProcessStateMgrService.setTubeResourceIsReady(a8kIdCardInfo, consumables, tipPos, incubatorPoss); + logger.info("apply resource ok"); + } + + @Override public Boolean checkCondition() { + return cms.isTimeToProcessPendingTube(); + } + + @Override public List getResourceList() { + return List.of(A8kPublicResourceType.CurTubeProcessToken); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java new file mode 100644 index 0000000..8911d4f --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java @@ -0,0 +1,229 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.OS; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appdata.AppProjInfoMgrService; +import a8k.baseservice.AppExceptionBuilder; +import a8k.baseservice.appeventbus.AppEventBusService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.*; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.Tube; +import a8k.service.appstate.type.state.TubeState; +import a8k.service.devicedriver.ctrl.HbotControlService; +import a8k.service.devicedriver.ctrl.ReactionPlatesTransmitCtrl; +import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; +import a8k.service.devicedriver.ctrl.SamplesPreProcesCtrl; +import a8k.type.ecode.AppError; +import a8k.type.exception.AppException; +import a8k.utils.ZFnCall; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.*; + +/** + * + * 核对物料资源是否足够 + * TUBE + * TO_BE_PROCESSED --> PRE_PROCESSING + */ +@Component +public class SEQ4_PRE_PROCESS extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ4_PRE_PROCESS.class); + + SEQ4_PRE_PROCESS() { + super(A8kActionStepType.SEQ4_PRE_PROCESS); + } + + @Resource + GStateService gstate; + + @Resource + SampleScanTransportCtrl sstc; + + + @Resource + ConsumablesMgrService consumablesMgrService; + + + @Resource + AppProjInfoMgrService appProjInfoMgrService; + + @Resource + AppEventBusService ebus; + + @Resource + AppExceptionBuilder ebuilder; + + @Resource + TubeProcessContextMgrService tubeProcessContextMgrService; + + @Resource + ReactionPlatesTransmitCtrl reactionPlatesTransmitCtrl; + + @Resource + SamplesPreProcesCtrl samplesPreProcesCtrl; + + @Resource + HbotControlService hbotControlService; + + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + + @Resource + IncubationPlateMgrService incubationPlateMgrService; + + @Resource + CondtionMgrService cms; + + ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); + + + @PostConstruct + void init() { + } + + /** + * 推出反应板夹 + * @throws AppException 异常 + */ + void prepareReactionPlate() throws AppException { + if (gstate.debugMode) { + logger.info("prepareReactionPlate"); + OS.forceSleep(1000); + return; + } + // Tube tube = gstate.getCurProcessingTube(); + // List projIndex = tube.projIndex; + // List incubatorPos = tube.incubatorPos; + // List bindConsumablesCh = tube.bindConsumablesCh; + // + // for (int i = 0; i < projIndex.size(); i++) { + // var tank = gstate.getIncubationPlate().getSubTank(incubatorPos.get(i)); + // reactionPlatesTransmitCtrl.pushPlate(bindConsumablesCh.get(i), incubatorPos.get(i)); + // tank.state = IncubationSubTankState.WAITING_FOR_DROP; + // } + + } + + /** + * 摇匀并取盖 + * @throws AppException + */ + void shakeAndTakeCap() throws AppException { + if (gstate.debugMode) { + logger.info("shakeAndTakeCap"); + OS.forceSleep(1000); + return; + } + + // Tube tube = gstate.getCurProcessingTube(); + // if (tube.isEmergency) { + // //如果事急诊位则什么也不做 + // return; + // } + // + // TubeHolder tubeHolder = gstate.getTubeHolder(); + // if (!tubeHolder.tubeHolderType.equals(A8kTubeHolderType.BloodTube)) { + // //如果不是全血试管则什么也不做 + // return; + // } + // + // logger.info("摇匀并取盖"); + // samplesPreProcesCtrl.takeTubeAndJudgeTubeExist(tube.isHighTube); + // samplesPreProcesCtrl.shakeTube(45, 5); + // samplesPreProcesCtrl.takeTubeCap(); + OS.forceSleep(1000); + } + + void hbotPrepareTip() throws AppException { + if (gstate.debugMode) { + logger.info("hbotPrepareTip"); + OS.forceSleep(1000); + return; + } + // Tube tube = gstate.getCurProcessingTube(); + // // hbotControlService.takeTip(); + // TipPos tippos = consumablesMgrService.takeNextTipPosAndSetUsed(); + // if (tippos == null) { + // throw ebuilder.buildAppCodeErrorException("预处理阶段,申请Tip失败"); + // } + // + // Boolean suc = hbotControlService.takeTip(tippos.group, tippos.pos); + // if (!suc) { + // logger.warn("takeTip fail"); + // tube.ecode = A8kEcode.TakeTipFail; + // tube.state = TubeState.ERROR; + // } + // + // logger.info("takeTip success"); + OS.forceSleep(1000); + } + + @Override public void doaction() throws AppException { + // + // 1.准备3份反应板夹 + // 2.取tip头 + // 3.摇匀,脱帽 + // + + Tube tube = gstate.getCurProcessingTube(); + //准备反应板夹 + var doPrepareReactionPlateFuture = executor.submit(() -> ZFnCall.callfn(this::prepareReactionPlate)); + //摇匀并取盖 + var doShakeAndTakeCapFuture = executor.submit(() -> ZFnCall.callfn(this::shakeAndTakeCap)); + //准备Hbot Tip + var doHbotPrepareTipFuture = executor.submit(() -> ZFnCall.callfn(this::hbotPrepareTip)); + + wait(doPrepareReactionPlateFuture); + wait(doShakeAndTakeCapFuture); + wait(doHbotPrepareTipFuture); + + List errors = new java.util.ArrayList<>(List.of()); + try { + errors.add(doPrepareReactionPlateFuture.get()); + errors.add(doShakeAndTakeCapFuture.get()); + errors.add(doHbotPrepareTipFuture.get()); + } catch (InterruptedException | ExecutionException ignored) { + } + errors.removeIf(Objects::isNull); + if (!errors.isEmpty()) { + throw ebuilder.buildMutiErrorAppException(errors); + } + + tubeProcessStateMgrService.setCurTubeState(TubeState.PRE_PROCESSED); + incubationPlateMgrService.waitingForDrop(tube); + logger.info("pre process success"); + } + + + @Override public Boolean checkCondition() { + return cms.isTimeToPreProcessTube(); + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.IncubationPlateModule, + A8kPublicResourceType.PlatesBoxModule, + A8kPublicResourceType.HBOT, + A8kPublicResourceType.CurTubeProcessToken + ); + } + + // + // UTILS + // + + void wait(Future future) { + while (!future.isDone()) { + OS.forceSleep(100); + } + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ5_PROCESS.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ5_PROCESS.java new file mode 100644 index 0000000..e511dbb --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ5_PROCESS.java @@ -0,0 +1,96 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.OS; +import a8k.baseservice.AppExceptionBuilder; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.*; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.Tube; +import a8k.service.appstate.type.state.TubeState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.concurrent.*; + +/** + * + * 核对物料资源是否足够 + * TUBE + * TO_BE_PROCESSED --> PRE_PROCESSING + */ +@Component +public class SEQ5_PROCESS extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ5_PROCESS.class); + + SEQ5_PROCESS() { + super(A8kActionStepType.SEQ5_PROCESS); + } + + @Resource + GStateService gstate; + + @Resource + AppExceptionBuilder ebuilder; + + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + + @Resource + IncubationPlateMgrService incubationPlateMgrService; + + @Resource + CondtionMgrService cms; + + + MainFlowCtrlState state; + + @PostConstruct + void init() { + state = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + // + // 1.准备3份反应板夹 + // 2.取tip头 + // 3.摇匀,脱帽 + // + tubeProcessStateMgrService.setCurTubeState(TubeState.PROCESSING); + Tube tube = gstate.getCurProcessingTube(); + OS.forceSleep(3000); + tubeProcessStateMgrService.setCurTubeState(TubeState.PROCESSED); + incubationPlateMgrService.startIncubating(tube, 60 * 2); + logger.info("pre process success"); + } + + + @Override public Boolean checkCondition() { + return cms.isTimeToProcessTube(); + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.IncubationPlateModule, + A8kPublicResourceType.HBOT, + A8kPublicResourceType.CurTubeProcessToken + ); + } + + // + // UTILS + // + + void wait(Future future) { + while (!future.isDone()) { + OS.forceSleep(100); + } + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java new file mode 100644 index 0000000..ac4d5c7 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java @@ -0,0 +1,92 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.OS; +import a8k.baseservice.AppExceptionBuilder; +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.*; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.type.Tube; +import a8k.service.appstate.type.state.TubeState; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.concurrent.*; + +/** + * + * 核对物料资源是否足够 + * TUBE + * TO_BE_PROCESSED --> PRE_PROCESSING + */ +@Component +public class SEQ6_POST_PROCESS extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ6_POST_PROCESS.class); + + SEQ6_POST_PROCESS() { + super(A8kActionStepType.SEQ6_POST_PROCESS); + } + + @Resource + GStateService gstate; + + @Resource + AppExceptionBuilder ebuilder; + + @Resource + TubeProcessStateMgrService tubeProcessStateMgrService; + + @Resource + IncubationPlateMgrService incubationPlateMgrService; + + @Resource + CondtionMgrService cms; + + + ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); + + + MainFlowCtrlState state; + + @PostConstruct + void init() { + state = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + tubeProcessStateMgrService.setCurTubeState(TubeState.POST_PROCESSING); + Tube tube = gstate.getCurProcessingTube(); + OS.forceSleep(3000); + tubeProcessStateMgrService.setCurTubeState(TubeState.POST_PROCESSED); + } + + @Override public Boolean checkCondition() { + return cms.isTimeToPostProcessTube(); + } + + @Override public List getResourceList() { + return List.of( + A8kPublicResourceType.IncubationPlateModule, + A8kPublicResourceType.PlatesBoxModule, + A8kPublicResourceType.HBOT, + A8kPublicResourceType.CurTubeProcessToken + ); + } + + // + // UTILS + // + + void wait(Future future) { + while (!future.isDone()) { + OS.forceSleep(100); + } + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ7_EJECT_TUBEHOLDER.java b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ7_EJECT_TUBEHOLDER.java new file mode 100644 index 0000000..dee50a9 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/action/SEQ7_EJECT_TUBEHOLDER.java @@ -0,0 +1,60 @@ +package a8k.service.appctrl.mainflowctrl.action; + +import a8k.service.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.appctrl.mainflowctrl.base.A8kStepAction; +import a8k.service.appstate.GStateService; +import a8k.service.appstate.type.MainFlowCtrlState; +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.service.appstate.type.state.TubeHolderState; +import a8k.service.devicedriver.ctrl.SampleScanTransportCtrl; +import a8k.type.exception.AppException; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class SEQ7_EJECT_TUBEHOLDER extends A8kStepAction { + static Logger logger = LoggerFactory.getLogger(SEQ7_EJECT_TUBEHOLDER.class); + + SEQ7_EJECT_TUBEHOLDER() { + super(A8kActionStepType.SEQ7_EJECT_TUBEHOLDER); + } + + @Resource + GStateService gstate; + @Resource + SampleScanTransportCtrl stc; + + MainFlowCtrlState state; + + @Resource + CondtionMgrService cms; + + @PostConstruct + void init() { + state = gstate.mainFlowCtrlState; + } + + @Override public void doaction() throws AppException { + stc.ejectTubeHolder(); + stc.moveTubeRackMoveToEnterPos(); + gstate.getTubeHolder().state = TubeHolderState.IDLE; + } + + @Override public Boolean checkCondition() { + //处于工作状态,试管架已经处于空闲状态,入料光电被触发 + Boolean cond1 = cms.isCanDoAction(); + Boolean cond2 = gstate.getTubeHolder().state.equals(TubeHolderState.PROCESSING); + Boolean cond3 = cms.isNoMoreTubeToBeProcessed(); + return cond1 && cond2 && cond3; + } + + @Override public List getResourceList() { + return List.of(A8kPublicResourceType.ShakeModule); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kActionStepType.java b/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kActionStepType.java new file mode 100644 index 0000000..ea5c1fd --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kActionStepType.java @@ -0,0 +1,29 @@ +package a8k.service.appctrl.mainflowctrl.base; + +public enum A8kActionStepType { + DO_START,//启动 + DO_PAUSE,//暂停 + DO_STOP, //停止 + DO_RESUME,//恢复 + + //mainflow + SEQ1_ENTER_TUBEHOLDER_AND_SCAN, //入料并扫描 + SEQ2_SWITCH_TO_THE_NEXT_TUBE,// 切换到下一个试管 + SEQ3_APPLAY_RESOURCE,//申请资源 + SEQ4_PRE_PROCESS, + SEQ5_PROCESS, + SEQ6_POST_PROCESS, + SEQ7_EJECT_TUBEHOLDER, //弹出试管架 + + //incubate + PROCESS_INCUBATE_COMPLETED_PLATE,//处理孵育完成的板 + + //OPT + PLATE_OPT_SCAN, + PLATE_OPT_DROP, + + //Error + DO_CLEAR_ERROR_BEFORE_WORK,//在启动前,清除错误 + DO_PROCESS_ERROR_TUBE, + DO_PROCESS_ERROR_PLATE, +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kErrorContext.java b/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kErrorContext.java new file mode 100644 index 0000000..82b4f25 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kErrorContext.java @@ -0,0 +1,21 @@ +package a8k.service.appctrl.mainflowctrl.base; + +import a8k.type.ecode.AppError; + +public class A8kErrorContext { + public A8kActionStepType dowhat; + public AppError ecode; + + public A8kErrorContext(A8kActionStepType dowhat, AppError ecode) { + this.dowhat = dowhat; + this.ecode = ecode; + } + + public Boolean equals(A8kErrorContext other) { + return this.dowhat.equals(other.dowhat) && this.ecode.code.equals(other.ecode.code); + } + + public String toString() { + return String.format("[%s:%s]", dowhat, ecode); + } +} diff --git a/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kStepAction.java b/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kStepAction.java new file mode 100644 index 0000000..fce44c1 --- /dev/null +++ b/src/main/java/a8k/service/appctrl/mainflowctrl/base/A8kStepAction.java @@ -0,0 +1,40 @@ +package a8k.service.appctrl.mainflowctrl.base; + + +import a8k.service.appstate.resource.A8kPublicResourceType; +import a8k.type.exception.AppException; + +import java.util.List; + +public class A8kStepAction { + + public A8kActionStepType step = null; + + public A8kStepAction(A8kActionStepType step) { + this.step = step; + } + + public Boolean checkCondition() { + return false; + } + + public Boolean getCondition() { + return checkCondition(); + } + + public List getResourceList() { + return null; + } + + public void doaction() throws AppException { + } + + public Boolean isMutiLineAction() { + return false; + } + + public Boolean isAllowsParallelRunning() { + return true; + } + +} diff --git a/src/main/java/a8k/service/appctrl/scheduler/MainFlowCtrlScheduler.java b/src/main/java/a8k/service/appctrl/scheduler/MainFlowCtrlScheduler.java deleted file mode 100644 index 510c6d4..0000000 --- a/src/main/java/a8k/service/appctrl/scheduler/MainFlowCtrlScheduler.java +++ /dev/null @@ -1,273 +0,0 @@ -package a8k.service.appctrl.scheduler; - -import a8k.OS; -import a8k.baseservice.appeventbus.AppEventBusService; -import a8k.baseservice.appeventbus.appevent.A8kEcodeContextListPromptEvent; -import a8k.baseservice.appeventbus.appevent.DoA8kStepActionEvent; -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.service.appctrl.action.base.A8kStepAction; -import a8k.service.appctrl.type.*; -import a8k.service.appstate.GStateService; -import a8k.service.appstate.ResourceMgrService; -import a8k.service.appstate.type.MainFlowCtrlState; -import a8k.service.appstate.type.state.A8kWorkState; -import a8k.type.exception.AppException; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -@Component -public class MainFlowCtrlScheduler { - static Logger logger = LoggerFactory.getLogger(MainFlowCtrlScheduler.class); - - - @FunctionalInterface - public interface A8kEcodePostProcesser { - void process(List ecodeList); - } - - @FunctionalInterface - public interface A8kEcodeClearProcesser { - boolean process(List ecodeList) throws AppException; - } - - @Resource - GStateService gstate; - - - @Resource - AppEventBusService ebus; - - @Resource - ResourceMgrService resourceMgrService; - - - MainFlowCtrlState state = null; - - Thread workThread; - ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); - - Runnable checkBeforeGuess; - A8kEcodePostProcesser ecodePostProcesser; - A8kEcodeClearProcesser ecodeClearProcesser; - - List stepActionList = new ArrayList<>(); - - @PostConstruct - void init() { - state = gstate.mainFlowCtrlState; - } - - /* - * Ext - */ - - public void regClearErrorProcesser(A8kEcodeClearProcesser ecodeClearProcesser) { - this.ecodeClearProcesser = ecodeClearProcesser; - } - - public void regEcodePostProcesser(A8kEcodePostProcesser ecodePostProcesser) { - this.ecodePostProcesser = ecodePostProcesser; - } - - public void regCheckBeforeGuess(Runnable checkBeforeGuess) { - this.checkBeforeGuess = checkBeforeGuess; - } - - - public void regFn(A8kStepAction action) { - stepActionList.add(action); - } - - public void startScheduler() { - workThread = new Thread(this::threadLoopFn); - workThread.start(); - } - - public List getA8kStepActionList() { - return stepActionList; - } - - // - // 切片 - // - - void beforeDoWhat(A8kActionStepType dowhat) { - ebus.pushEvent(new DoA8kStepActionEvent(dowhat)); - } - - // - // Scheduler - // - - List guessWhatToDo() { - if (this.checkBeforeGuess != null) { - this.checkBeforeGuess.run(); - } - - try { - List dowhatList = new ArrayList<>(); - - for (A8kStepAction action : stepActionList) { - if (action.checkCondition()) { - Boolean relayResourceSuc = resourceMgrService.applyForResources(this, action.getResourceList()); - if (relayResourceSuc) { - dowhatList.add(action); - } - } - } - return dowhatList; - } catch (Exception e) { - logger.info("guessWhatToDo error:{}", e.toString()); - resourceMgrService.releaseAllResource(this); - } - return new ArrayList<>(); - } - - - A8kErrorContext callFn(A8kStepAction key) { - beforeDoWhat(key.step); - try { - logger.info("doaction:{}", key.step); - key.doaction(); - return new A8kErrorContext(key.step, null); - } catch (AppException appe) { - return new A8kErrorContext(key.step, appe.error); - } - } - -// void clearError() { -// /* -// * 清除错误 -// */ -// clearErrorPendingFlag = false; -// try { -// beforeDoWhat(A8kActionStepType.DO_CLEAR_ERROR); -// boolean suc = ecodeClearProcesser.process(state.ecodeList); -// if (suc) { -// state.ecodeList.clear(); -// state.errorFlag = false; -// } -// } catch (AppException appe) { -// A8kErrorContext context = new A8kErrorContext(A8kActionStepType.DO_CLEAR_ERROR, appe.error); -// a8kEcodePostProcesser(List.of(context)); -// } -// } - - - List waitAllActionIsDone(List> futureList) { - List ecodeList = new ArrayList<>(); - while (true) { - boolean someTaskNotDone = false; - for (Future future : futureList) { - if (!future.isDone()) { - someTaskNotDone = true; - break; - } - } - if (!someTaskNotDone) { - break; - } - OS.forceSleep(30); - } - - for (Future future : futureList) { - try { - ecodeList.add(future.get()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //清空NoError - ecodeList.removeIf(ecode -> ecode.ecode == null); - return ecodeList; - } - - void doActions(List dowhatList) { - - // - List serialActionList = new ArrayList<>(); - List parallelActionList = new ArrayList<>(); - List ecodeList = new ArrayList<>(); - - for (A8kStepAction action : dowhatList) { - if (action.isAllowsParallelRunning()) { - parallelActionList.add(action); - } else { - serialActionList.add(action); - } - } - - //执行串行任务 - for (A8kStepAction action : serialActionList) { - A8kErrorContext aec = callFn(action); - ecodeList.add(aec); - } - - //执行并行任务 - List> futureList = new ArrayList<>(); - for (A8kStepAction dowhat : parallelActionList) { - var future = executor.submit(() -> callFn(dowhat)); - futureList.add(future); - } - - //等待并行任务完成 - List ecodeListParallel = waitAllActionIsDone(futureList); - resourceMgrService.releaseAllResource(this); - - //合并错误 - ecodeList.addAll(ecodeListParallel); - - if (!ecodeList.isEmpty()) { - a8kEcodePostProcesser(ecodeList); - } - } - - void a8kEcodePostProcesser(List ecodeList) { - //如果有错误,且错误列表不为空,则将错误列表添加到错误列表中 - if (!this.state.ecodeList.isEmpty()) { - ecodeList.addAll(this.state.ecodeList); - } - // - // //清除重复错误 - // List newEcodeList = new ArrayList<>(); - // for (A8kEcode ecode : ecodeList) { - // if (!newEcodeList.contains(ecode)) { - // newEcodeList.add(ecode); - // } - // } - // ecodeList = newEcodeList; - - //处理错误 - if (ecodePostProcesser != null) { - ecodePostProcesser.process(ecodeList); - } - - ebus.pushEvent(new A8kEcodeContextListPromptEvent(ecodeList)); - this.state.errorFlag = true; - this.state.ecodeList = ecodeList; - this.state.workState = A8kWorkState.PAUSE; - } - - void threadLoopFn() { - while (workThread.isAlive()) { - if (state.fatalErrorFlag) { - OS.forceSleep(800); - } else { - doActions(guessWhatToDo()); - OS.forceSleep(800); - } - } - } - -} diff --git a/src/main/java/a8k/service/appctrl/type/A8kErrorContext.java b/src/main/java/a8k/service/appctrl/type/A8kErrorContext.java deleted file mode 100644 index 8cfbbc1..0000000 --- a/src/main/java/a8k/service/appctrl/type/A8kErrorContext.java +++ /dev/null @@ -1,22 +0,0 @@ -package a8k.service.appctrl.type; - -import a8k.service.appctrl.action.base.A8kActionStepType; -import a8k.type.ecode.AppError; - -public class A8kErrorContext { - public A8kActionStepType dowhat; - public AppError ecode; - - public A8kErrorContext(A8kActionStepType dowhat, AppError ecode) { - this.dowhat = dowhat; - this.ecode = ecode; - } - - public Boolean equals(A8kErrorContext other) { - return this.dowhat.equals(other.dowhat) && this.ecode.code.equals(other.ecode.code); - } - - public String toString() { - return String.format("[%s:%s]", dowhat, ecode); - } -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumableState.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumableState.java deleted file mode 100644 index a21b5fb..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumableState.java +++ /dev/null @@ -1,30 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -import java.util.Date; - -public class ConsumableState { - - public Date scanDate = new Date(); - public Tips[] tips = new Tips[3]; - - public ReactionPlateGroup[] reactionPlateGroup = new ReactionPlateGroup[6]; - public LittBSGroup[] littBSGroup = new LittBSGroup[6]; - public LarBSGroup[] larBSGroup = new LarBSGroup[6]; - - public ConsumableState() { - for (int i = 0; i < tips.length; i++) { - tips[i] = new Tips(); - tips[i].tipNum = 0; - } - for (int i = 0; i < reactionPlateGroup.length; i++) { - reactionPlateGroup[i] = new ReactionPlateGroup(); - } - for (int i = 0; i < littBSGroup.length; i++) { - littBSGroup[i] = new LittBSGroup(); - } - for (int i = 0; i < larBSGroup.length; i++) { - larBSGroup[i] = new LarBSGroup(); - } - } - -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumablesScanResult.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumablesScanResult.java deleted file mode 100644 index 04cd498..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ConsumablesScanResult.java +++ /dev/null @@ -1,8 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -public class ConsumablesScanResult { - public Integer chNum; - public ScanResultState state; - public Integer projIndex; - public String lotId; -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LarBSGroup.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LarBSGroup.java deleted file mode 100644 index 93e984f..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LarBSGroup.java +++ /dev/null @@ -1,22 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -public class LarBSGroup { - public Integer projIndex; //项目ID - public String projName; //项目名称 - public String lotId = ""; //批次号 - public String color = ""; //颜色 - public Integer num = 0; - public Boolean enable = false; - - public LarBSGroup() { - } - - public LarBSGroup(Integer projIndex, String projName, String lotId, String color, Integer num) { - this.projIndex = projIndex; - this.projName = projName; - this.lotId = lotId; - this.color = color; - this.num = num; - } - -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LittBSGroup.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LittBSGroup.java deleted file mode 100644 index 62243bc..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/LittBSGroup.java +++ /dev/null @@ -1,23 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -public class LittBSGroup { - public Integer projIndex; //项目ID - public String projName; //项目名称 - public String lotId = ""; //批次号 - public String color = ""; //颜色 - public Boolean enable = false;//是否可以被修改, - public Integer num = 0; - - public LittBSGroup() { - enable = false; - } - - public LittBSGroup(Integer projIndex, String projName, String lotId, String color, Integer num) { - this.projIndex = projIndex; - this.projName = projName; - this.lotId = lotId; - this.color = color; - this.num = num; - enable = true; - } -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ReactionPlateGroup.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ReactionPlateGroup.java deleted file mode 100644 index 21f19a4..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ReactionPlateGroup.java +++ /dev/null @@ -1,22 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -public class ReactionPlateGroup { - public Integer projIndex; //项目ID - public String projName; //项目名称 - public String lotId = ""; //批次号 - public String color = ""; //颜色 - public Boolean enable = false; - - public Integer num = 0; - - public ReactionPlateGroup() { - } - - public ReactionPlateGroup(Integer projIndex, String projName, String lotId, String color, Integer num) { - this.projIndex = projIndex; - this.projName = projName; - this.lotId = lotId; - this.color = color; - this.num = num; - } -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ScanResultState.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ScanResultState.java deleted file mode 100644 index edcf27f..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/ScanResultState.java +++ /dev/null @@ -1,17 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -public enum ScanResultState { - PASS, //通过 - Empty,//空 - - LostReactionPlate, //丢弃反应板 - ConsumableExpired, //耗材过期 - - LostLittSB, //缺少小缓冲液 - LittSBLotIdIsNotMatch,//小缓冲液批号不匹配 - LostLarBS, //缺少大缓冲液 - LarBSLotIdIsNotMatch,//大缓冲液批号不匹配 - - NoMatchingProjIDCardFound,//未找到匹配的项目ID卡 - ProjInfoIsInComplete,//项目信息不全 -} diff --git a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/Tips.java b/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/Tips.java deleted file mode 100644 index fa93c04..0000000 --- a/src/main/java/a8k/service/appctrl/type/app_consumables_mgr_service/Tips.java +++ /dev/null @@ -1,5 +0,0 @@ -package a8k.service.appctrl.type.app_consumables_mgr_service; - -public class Tips { - public Integer tipNum = 0;//剩余可用数量 -} diff --git a/src/main/java/a8k/service/appstate/GStateService.java b/src/main/java/a8k/service/appstate/GStateService.java index 794e1ba..bb93b5e 100644 --- a/src/main/java/a8k/service/appstate/GStateService.java +++ b/src/main/java/a8k/service/appstate/GStateService.java @@ -1,7 +1,7 @@ package a8k.service.appstate; import a8k.constant.AppConstant; -import a8k.service.appctrl.type.app_consumables_mgr_service.ConsumableState; +import a8k.type.consumables.ConsumableState; import a8k.service.appstate.type.*; import a8k.service.appstate.type.state.A8kWorkState; import a8k.service.appstate.type.state.TubeHolderState; diff --git a/src/main/java/a8k/service/appstate/type/MainFlowCtrlState.java b/src/main/java/a8k/service/appstate/type/MainFlowCtrlState.java index 61a8126..45ebdd1 100644 --- a/src/main/java/a8k/service/appstate/type/MainFlowCtrlState.java +++ b/src/main/java/a8k/service/appstate/type/MainFlowCtrlState.java @@ -1,6 +1,6 @@ package a8k.service.appstate.type; -import a8k.service.appctrl.type.A8kErrorContext; +import a8k.service.appctrl.mainflowctrl.base.A8kErrorContext; import a8k.service.appstate.type.state.A8kWorkState; import com.fasterxml.jackson.annotation.JsonIgnore; diff --git a/src/main/java/a8k/type/consumables/ConsumableState.java b/src/main/java/a8k/type/consumables/ConsumableState.java new file mode 100644 index 0000000..78ac953 --- /dev/null +++ b/src/main/java/a8k/type/consumables/ConsumableState.java @@ -0,0 +1,30 @@ +package a8k.type.consumables; + +import java.util.Date; + +public class ConsumableState { + + public Date scanDate = new Date(); + public Tips[] tips = new Tips[3]; + + public ReactionPlateGroup[] reactionPlateGroup = new ReactionPlateGroup[6]; + public LittBSGroup[] littBSGroup = new LittBSGroup[6]; + public LarBSGroup[] larBSGroup = new LarBSGroup[6]; + + public ConsumableState() { + for (int i = 0; i < tips.length; i++) { + tips[i] = new Tips(); + tips[i].tipNum = 0; + } + for (int i = 0; i < reactionPlateGroup.length; i++) { + reactionPlateGroup[i] = new ReactionPlateGroup(); + } + for (int i = 0; i < littBSGroup.length; i++) { + littBSGroup[i] = new LittBSGroup(); + } + for (int i = 0; i < larBSGroup.length; i++) { + larBSGroup[i] = new LarBSGroup(); + } + } + +} diff --git a/src/main/java/a8k/type/consumables/LarBSGroup.java b/src/main/java/a8k/type/consumables/LarBSGroup.java new file mode 100644 index 0000000..6432068 --- /dev/null +++ b/src/main/java/a8k/type/consumables/LarBSGroup.java @@ -0,0 +1,22 @@ +package a8k.type.consumables; + +public class LarBSGroup { + public Integer projIndex; //项目ID + public String projName; //项目名称 + public String lotId = ""; //批次号 + public String color = ""; //颜色 + public Integer num = 0; + public Boolean enable = false; + + public LarBSGroup() { + } + + public LarBSGroup(Integer projIndex, String projName, String lotId, String color, Integer num) { + this.projIndex = projIndex; + this.projName = projName; + this.lotId = lotId; + this.color = color; + this.num = num; + } + +} diff --git a/src/main/java/a8k/type/consumables/LittBSGroup.java b/src/main/java/a8k/type/consumables/LittBSGroup.java new file mode 100644 index 0000000..af5c9e7 --- /dev/null +++ b/src/main/java/a8k/type/consumables/LittBSGroup.java @@ -0,0 +1,23 @@ +package a8k.type.consumables; + +public class LittBSGroup { + public Integer projIndex; //项目ID + public String projName; //项目名称 + public String lotId = ""; //批次号 + public String color = ""; //颜色 + public Boolean enable = false;//是否可以被修改, + public Integer num = 0; + + public LittBSGroup() { + enable = false; + } + + public LittBSGroup(Integer projIndex, String projName, String lotId, String color, Integer num) { + this.projIndex = projIndex; + this.projName = projName; + this.lotId = lotId; + this.color = color; + this.num = num; + enable = true; + } +} diff --git a/src/main/java/a8k/type/consumables/ReactionPlateGroup.java b/src/main/java/a8k/type/consumables/ReactionPlateGroup.java new file mode 100644 index 0000000..b9997a7 --- /dev/null +++ b/src/main/java/a8k/type/consumables/ReactionPlateGroup.java @@ -0,0 +1,22 @@ +package a8k.type.consumables; + +public class ReactionPlateGroup { + public Integer projIndex; //项目ID + public String projName; //项目名称 + public String lotId = ""; //批次号 + public String color = ""; //颜色 + public Boolean enable = false; + + public Integer num = 0; + + public ReactionPlateGroup() { + } + + public ReactionPlateGroup(Integer projIndex, String projName, String lotId, String color, Integer num) { + this.projIndex = projIndex; + this.projName = projName; + this.lotId = lotId; + this.color = color; + this.num = num; + } +} diff --git a/src/main/java/a8k/type/consumables/ScanResultState.java b/src/main/java/a8k/type/consumables/ScanResultState.java new file mode 100644 index 0000000..036a14a --- /dev/null +++ b/src/main/java/a8k/type/consumables/ScanResultState.java @@ -0,0 +1,17 @@ +package a8k.type.consumables; + +public enum ScanResultState { + PASS, //通过 + Empty,//空 + + LostReactionPlate, //丢弃反应板 + ConsumableExpired, //耗材过期 + + LostLittSB, //缺少小缓冲液 + LittSBLotIdIsNotMatch,//小缓冲液批号不匹配 + LostLarBS, //缺少大缓冲液 + LarBSLotIdIsNotMatch,//大缓冲液批号不匹配 + + NoMatchingProjIDCardFound,//未找到匹配的项目ID卡 + ProjInfoIsInComplete,//项目信息不全 +} diff --git a/src/main/java/a8k/type/consumables/Tips.java b/src/main/java/a8k/type/consumables/Tips.java new file mode 100644 index 0000000..3b8c12c --- /dev/null +++ b/src/main/java/a8k/type/consumables/Tips.java @@ -0,0 +1,5 @@ +package a8k.type.consumables; + +public class Tips { + public Integer tipNum = 0;//剩余可用数量 +}