From ff3bcad3acf9178279b8563eeb6911b28fe5e8f2 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Thu, 7 Nov 2024 11:39:42 +0800 Subject: [PATCH] update --- .../mainflowctrl/action/SEQ4_PRE_PROCESS.java | 400 ++++++++++----------- .../appctrl/mainflowctrl/action/SEQ5_PROCESS.java | 278 +++++++------- .../mainflowctrl/action/SEQ6_POST_PROCESS.java | 260 +++++++------- .../mainflowctrl/actionv2/SEQ5_PROCESS.java | 302 ++++++++++++++++ .../java/a8k/service/app/appstate/type/Tube.java | 4 +- .../a8k/type/exception/ZAppInterruptException.java | 15 + .../java/a8k/utils/ActionParallerExceutor.java | 1 - src/main/java/a8k/utils/ZFnCall.java | 11 + 8 files changed, 799 insertions(+), 472 deletions(-) create mode 100644 src/main/java/a8k/service/app/appctrl/mainflowctrl/actionv2/SEQ5_PROCESS.java create mode 100644 src/main/java/a8k/type/exception/ZAppInterruptException.java diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java index 2784588..fd63096 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java @@ -1,200 +1,200 @@ -package a8k.service.app.appctrl.mainflowctrl.action; - -import a8k.OS; -import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; - -import a8k.service.app.appstate.type.ProjProcessContext; -import a8k.service.app.appstate.type.TubeHolder; -import a8k.service.app.devicectrl.ctrlservice.*; -import a8k.service.app.devicectrl.script.DeviceCtrlScripter; -import a8k.type.IncubatorPos; -import a8k.type.type.A8kTubeHolderType; -import a8k.utils.*; -import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; -import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; -import a8k.service.app.appstate.*; -import a8k.service.app.appstate.resource.A8kPublicResourceType; -import a8k.service.app.appstate.type.Tube; -import a8k.type.ecode.AppError; -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.Objects; -import java.util.concurrent.*; - -import a8k.service.test.state.TestModeState; -import a8k.service.test.state.VirtualDevice; -import org.springframework.util.Assert; - -/** - * - * - * 处理前的准备工作 - * 1.取试管到摇匀位,并摇匀完成(全血试管) - * 2.取tip头 - * 3.孵育盘取反应板夹 - * - */ -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 - TestModeState testModeState; - @Resource - VirtualDevice virtualDevice; - - @Resource - AppExceptionBuilder ebuilder; - @Resource - ProjectProcessContextMgrService projectProcessContextMgrService; - - @Resource - PlateBoxCtrlService plateBoxCtrlService; - @Resource - TubePreProcesCtrlService tubePreProcesCtrlService; - @Resource - PipetteGunCtrlService pipetteGunCtrlService; - @Resource - DeviceCtrlScripter deviceCtrlScripter; - - @Resource - CondtionMgrService cms; - - // ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); - - ActionParallerExceutor actionParallerExceutor = new ActionParallerExceutor(); - - - @PostConstruct - void init() { - } - - /** - * 推出反应板夹到孵育盘 - * @throws AppException 异常 - */ - void prepareReactionPlate() throws AppException { - if (virtualDevice.isEnable()) { - virtualDevice.doVirtualThings("准备反应板夹", 2); - return; - } - Tube tube = gstate.getCurProcessingTube(); - List cxts = projectProcessContextMgrService.getTubeAssociatedProjContext(tube.getSampleId()); - - for (ProjProcessContext cxt : cxts) { - IncubatorPos incubatorPos = cxt.incubatorPos; - plateBoxCtrlService.pushPlateQuick(cxt.consumable.getGroup(), incubatorPos); - } - } - - /** - * 取试管,摇匀,取帽 - * @throws AppException 异常 - */ - void shakeAndTakeCap() throws AppException { - if (virtualDevice.isEnable()) { - virtualDevice.doVirtualThings("摇匀并取盖", 2); - return; - } - - Tube tube = gstate.getCurProcessingTube(); - TubeHolder tubeHolder = gstate.getTubeHolder(); - Boolean isHighTube = tube.getIsHighTube(); - - if (!tube.getIsEmergency() && tubeHolder.tubeHolderType.equals(A8kTubeHolderType.BloodTube)) { - Integer shakeTimes = ProjProcessContextUtils.getShakeTimes(tube); - logger.info("摇匀次数 :{}", shakeTimes); - logger.info("试管架类型 :{}", tubeHolder.tubeHolderType); - logger.info("是否高位试管:{}", isHighTube); - tubePreProcesCtrlService.takeTubeFromTubeholderToShakePos(isHighTube); - tubePreProcesCtrlService.shakeTube(45, shakeTimes); - tubePreProcesCtrlService.takeTubeCap(); - } else { - logger.info("不是全血试管,不需要摇匀"); - } - } - - /** - * 取一个tip头 - * @throws AppException exception - */ - void hbotPrepareTip() throws AppException { - if (virtualDevice.isEnable()) { - virtualDevice.doVirtualThings("准备Hbot Tip", 2); - return; - } - //准备第一个项目的tip头 - List cxts = projectProcessContextMgrService.getTubeAssociatedProjContext(gstate.getCurProcessingTube().getSampleId()); - Assert.isTrue(!cxts.isEmpty(), "项目上下文不能为空"); - ProjProcessContext cxt = cxts.get(0); - /* - * 此处预先做好第一个项目的准备工作 - */ - deviceCtrlScripter.doSampleProcessPrepare(cxt); - } - - - @Override public void doaction() throws AppException { - // - // 1.准备3份反应板夹 - // 2.取tip头 - // 3.摇匀,脱帽 - // - projectProcessContextMgrService.startTubePreProcessing(); - - actionParallerExceutor.submit(this::prepareReactionPlate); - actionParallerExceutor.submit(this::shakeAndTakeCap); - actionParallerExceutor.submit(this::hbotPrepareTip); - - var mutiAppException = actionParallerExceutor.waitAll(); - - //如果依然有错误,将试管状态设置为错误,同时抛出异常 - if (mutiAppException != null) { - projectProcessContextMgrService.changeTubeStateToError(gstate.getCurProcessingTube(), mutiAppException.getErrors()); - throw mutiAppException; - } - projectProcessContextMgrService.tubePreProcessingOK(); - } - - - @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); - } - } - - @Override public String logCxtState() { - var tube = gstate.getCurProcessingTube(); - if (tube == null) { - return ""; - } - return String.format("[sid: %s, proj: %s]", tube.getSampleId(), tube.getProjIndexStrList()); - } -} +//package a8k.service.app.appctrl.mainflowctrl.action; +// +//import a8k.OS; +//import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; +// +//import a8k.service.app.appstate.type.ProjProcessContext; +//import a8k.service.app.appstate.type.TubeHolder; +//import a8k.service.app.devicectrl.ctrlservice.*; +//import a8k.service.app.devicectrl.script.DeviceCtrlScripter; +//import a8k.type.IncubatorPos; +//import a8k.type.type.A8kTubeHolderType; +//import a8k.utils.*; +//import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; +//import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; +//import a8k.service.app.appstate.*; +//import a8k.service.app.appstate.resource.A8kPublicResourceType; +//import a8k.service.app.appstate.type.Tube; +//import a8k.type.ecode.AppError; +//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.Objects; +//import java.util.concurrent.*; +// +//import a8k.service.test.state.TestModeState; +//import a8k.service.test.state.VirtualDevice; +//import org.springframework.util.Assert; +// +///** +// * +// * +// * 处理前的准备工作 +// * 1.取试管到摇匀位,并摇匀完成(全血试管) +// * 2.取tip头 +// * 3.孵育盘取反应板夹 +// * +// */ +//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 +// TestModeState testModeState; +// @Resource +// VirtualDevice virtualDevice; +// +// @Resource +// AppExceptionBuilder ebuilder; +// @Resource +// ProjectProcessContextMgrService projectProcessContextMgrService; +// +// @Resource +// PlateBoxCtrlService plateBoxCtrlService; +// @Resource +// TubePreProcesCtrlService tubePreProcesCtrlService; +// @Resource +// PipetteGunCtrlService pipetteGunCtrlService; +// @Resource +// DeviceCtrlScripter deviceCtrlScripter; +// +// @Resource +// CondtionMgrService cms; +// +// // ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); +// +// ActionParallerExceutor actionParallerExceutor = new ActionParallerExceutor(); +// +// +// @PostConstruct +// void init() { +// } +// +// /** +// * 推出反应板夹到孵育盘 +// * @throws AppException 异常 +// */ +// void prepareReactionPlate() throws AppException { +// if (virtualDevice.isEnable()) { +// virtualDevice.doVirtualThings("准备反应板夹", 2); +// return; +// } +// Tube tube = gstate.getCurProcessingTube(); +// List cxts = projectProcessContextMgrService.getTubeAssociatedProjContext(tube.getSampleId()); +// +// for (ProjProcessContext cxt : cxts) { +// IncubatorPos incubatorPos = cxt.incubatorPos; +// plateBoxCtrlService.pushPlateQuick(cxt.consumable.getGroup(), incubatorPos); +// } +// } +// +// /** +// * 取试管,摇匀,取帽 +// * @throws AppException 异常 +// */ +// void shakeAndTakeCap() throws AppException { +// if (virtualDevice.isEnable()) { +// virtualDevice.doVirtualThings("摇匀并取盖", 2); +// return; +// } +// +// Tube tube = gstate.getCurProcessingTube(); +// TubeHolder tubeHolder = gstate.getTubeHolder(); +// Boolean isHighTube = tube.getIsHighTube(); +// +// if (!tube.getIsEmergency() && tubeHolder.tubeHolderType.equals(A8kTubeHolderType.BloodTube)) { +// Integer shakeTimes = ProjProcessContextUtils.getShakeTimes(tube); +// logger.info("摇匀次数 :{}", shakeTimes); +// logger.info("试管架类型 :{}", tubeHolder.tubeHolderType); +// logger.info("是否高位试管:{}", isHighTube); +// tubePreProcesCtrlService.takeTubeFromTubeholderToShakePos(isHighTube); +// tubePreProcesCtrlService.shakeTube(45, shakeTimes); +// tubePreProcesCtrlService.takeTubeCap(); +// } else { +// logger.info("不是全血试管,不需要摇匀"); +// } +// } +// +// /** +// * 取一个tip头 +// * @throws AppException exception +// */ +// void hbotPrepareTip() throws AppException { +// if (virtualDevice.isEnable()) { +// virtualDevice.doVirtualThings("准备Hbot Tip", 2); +// return; +// } +// //准备第一个项目的tip头 +// List cxts = projectProcessContextMgrService.getTubeAssociatedProjContext(gstate.getCurProcessingTube().getSampleId()); +// Assert.isTrue(!cxts.isEmpty(), "项目上下文不能为空"); +// ProjProcessContext cxt = cxts.get(0); +// /* +// * 此处预先做好第一个项目的准备工作 +// */ +// deviceCtrlScripter.doSampleProcessPrepare(cxt); +// } +// +// +// @Override public void doaction() throws AppException { +// // +// // 1.准备3份反应板夹 +// // 2.取tip头 +// // 3.摇匀,脱帽 +// // +// projectProcessContextMgrService.startTubePreProcessing(); +// +// actionParallerExceutor.submit(this::prepareReactionPlate); +// actionParallerExceutor.submit(this::shakeAndTakeCap); +// actionParallerExceutor.submit(this::hbotPrepareTip); +// +// var mutiAppException = actionParallerExceutor.waitAll(); +// +// //如果依然有错误,将试管状态设置为错误,同时抛出异常 +// if (mutiAppException != null) { +// projectProcessContextMgrService.changeTubeStateToError(gstate.getCurProcessingTube(), mutiAppException.getErrors()); +// throw mutiAppException; +// } +// projectProcessContextMgrService.tubePreProcessingOK(); +// } +// +// +// @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); +// } +// } +// +// @Override public String logCxtState() { +// var tube = gstate.getCurProcessingTube(); +// if (tube == null) { +// return ""; +// } +// return String.format("[sid: %s, proj: %s]", tube.getSampleId(), tube.getProjIndexStrList()); +// } +//} diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java index a6db2f2..266c4d2 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java @@ -1,139 +1,139 @@ -package a8k.service.app.appctrl.mainflowctrl.action; - -import a8k.service.app.devicectrl.ctrlservice.PipetteGunCtrlService; -import a8k.service.app.devicectrl.script.DeviceCtrlScripter; -import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; -import a8k.utils.AppExceptionBuilder; -import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; -import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; -import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; -import a8k.service.app.appstate.*; -import a8k.service.app.appstate.resource.A8kPublicResourceType; -import a8k.service.app.appstate.type.DeviceWorkState; -import a8k.service.app.appstate.type.ProjProcessContext; -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 a8k.service.test.state.TestModeState; -import a8k.service.test.state.VirtualDevice; - -/** - * - * 核对物料资源是否足够 - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -public class SEQ5_PROCESS extends A8kStepAction { - static Logger logger = LoggerFactory.getLogger(SEQ5_PROCESS.class); - - SEQ5_PROCESS() { - super(A8kActionStepType.SEQ5_PROCESS); - } - - @Resource - GStateService gstate; - @Resource - TestModeState testModeState; - @Resource - VirtualDevice virtualDevice; - - - @Resource - AppExceptionBuilder ebuilder; - @Resource - IncubationPlateStateMgrService incubationPlateStateMgrService; - @Resource - CondtionMgrService cms; - @Resource - ProjectProcessContextMgrService projectProcessContextMgrService; - - @Resource - PipetteGunCtrlService pipetteGunCtrlService; - @Resource - DeviceCtrlScripter deviceCtrlScripter; - - DeviceWorkState state; - - @PostConstruct - void init() { - state = gstate.deviceWorkState; - } - - - void doAction() throws AppException { - var tube = gstate.getCurProcessingTube(); - Integer projProcessOff = tube.getProjProcessOff(); - ProjProcessContext cxt = projectProcessContextMgrService.getProjProcessContext(tube.getSampleId(), tube.getProjIds().get(projProcessOff)); - A8kReactionFlowType type = cxt.projInfoContext.projInfo.reactionFlowType; - - if (virtualDevice.isEnable()) { - virtualDevice.doVirtualThings("处理样本(准备反应板,取tip,摇匀,脱帽)", 5); - return; - } - - if (projProcessOff != 0) { //第一个项目的部分动作已经在前面完成 - deviceCtrlScripter.doSampleProcessPrepare(cxt); - } - - deviceCtrlScripter.doSampleProcess(cxt); - - if (projProcessOff + 1 != tube.getProjIds().size()) { - deviceCtrlScripter.doSampleProcessPostProcess(cxt); - } - - } - - @Override - public void doaction() throws AppException { - - var tube = gstate.getCurProcessingTube(); - Integer projProcessOff = tube.getProjProcessOff(); - logger.info("处理 样本:{} 第X个项目:{}", tube.getSampleId(), projProcessOff); - ProjProcessContext cxt = projectProcessContextMgrService.getProjProcessContext(tube.getSampleId(), tube.getProjIds().get(projProcessOff)); - - if (projProcessOff == 0) { - projectProcessContextMgrService.startProcessTube(); - } - - // - // 执行待执行的动作 - // - doAction(); - - projectProcessContextMgrService.startIncubating(cxt); - if (projProcessOff + 1 < tube.getProjIds().size()) { - tube.setProjProcessOff(projProcessOff + 1); - } else { - projectProcessContextMgrService.processIngTubeOK(); - } - } - - @Override - public Boolean checkCondition() { - return cms.isTimeToProcessTube(); - } - - @Override - public List getResourceList() { - return List.of( - A8kPublicResourceType.IncubationPlateModule, - A8kPublicResourceType.HBOT, - A8kPublicResourceType.CurTubeProcessToken); - } - - - @Override - public String logCxtState() { - var tube = gstate.getCurProcessingTube(); - if (tube == null) { - return ""; - } - return String.format("[sid: %s, proj: %s]", tube.getSampleId(), tube.getProjIndexStrList()); - } -} +//package a8k.service.app.appctrl.mainflowctrl.action; +// +//import a8k.service.app.devicectrl.ctrlservice.PipetteGunCtrlService; +//import a8k.service.app.devicectrl.script.DeviceCtrlScripter; +//import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; +//import a8k.utils.AppExceptionBuilder; +//import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; +//import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; +//import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; +//import a8k.service.app.appstate.*; +//import a8k.service.app.appstate.resource.A8kPublicResourceType; +//import a8k.service.app.appstate.type.DeviceWorkState; +//import a8k.service.app.appstate.type.ProjProcessContext; +//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 a8k.service.test.state.TestModeState; +//import a8k.service.test.state.VirtualDevice; +// +///** +// * +// * 核对物料资源是否足够 +// * TUBE +// * TO_BE_PROCESSED --> PRE_PROCESSING +// */ +//public class SEQ5_PROCESS extends A8kStepAction { +// static Logger logger = LoggerFactory.getLogger(SEQ5_PROCESS.class); +// +// SEQ5_PROCESS() { +// super(A8kActionStepType.SEQ5_PROCESS); +// } +// +// @Resource +// GStateService gstate; +// @Resource +// TestModeState testModeState; +// @Resource +// VirtualDevice virtualDevice; +// +// +// @Resource +// AppExceptionBuilder ebuilder; +// @Resource +// IncubationPlateStateMgrService incubationPlateStateMgrService; +// @Resource +// CondtionMgrService cms; +// @Resource +// ProjectProcessContextMgrService projectProcessContextMgrService; +// +// @Resource +// PipetteGunCtrlService pipetteGunCtrlService; +// @Resource +// DeviceCtrlScripter deviceCtrlScripter; +// +// DeviceWorkState state; +// +// @PostConstruct +// void init() { +// state = gstate.deviceWorkState; +// } +// +// +// void doAction() throws AppException { +// var tube = gstate.getCurProcessingTube(); +//// Integer projProcessOff = tube.getProjProcessOff(); +// ProjProcessContext cxt = projectProcessContextMgrService.getProjProcessContext(tube.getSampleId(), tube.getProjIds().get(projProcessOff)); +// A8kReactionFlowType type = cxt.projInfoContext.projInfo.reactionFlowType; +// +// if (virtualDevice.isEnable()) { +// virtualDevice.doVirtualThings("处理样本(准备反应板,取tip,摇匀,脱帽)", 5); +// return; +// } +// +// if (projProcessOff != 0) { //第一个项目的部分动作已经在前面完成 +// deviceCtrlScripter.doSampleProcessPrepare(cxt); +// } +// +// deviceCtrlScripter.doSampleProcess(cxt); +// +// if (projProcessOff + 1 != tube.getProjIds().size()) { +// deviceCtrlScripter.doSampleProcessPostProcess(cxt); +// } +// +// } +// +// @Override +// public void doaction() throws AppException { +// +// var tube = gstate.getCurProcessingTube(); +// Integer projProcessOff = tube.getProjProcessOff(); +// logger.info("处理 样本:{} 第X个项目:{}", tube.getSampleId(), projProcessOff); +// ProjProcessContext cxt = projectProcessContextMgrService.getProjProcessContext(tube.getSampleId(), tube.getProjIds().get(projProcessOff)); +// +// if (projProcessOff == 0) { +// projectProcessContextMgrService.startProcessTube(); +// } +// +// // +// // 执行待执行的动作 +// // +// doAction(); +// +// projectProcessContextMgrService.startIncubating(cxt); +// if (projProcessOff + 1 < tube.getProjIds().size()) { +// tube.setProjProcessOff(projProcessOff + 1); +// } else { +// projectProcessContextMgrService.processIngTubeOK(); +// } +// } +// +// @Override +// public Boolean checkCondition() { +// return cms.isTimeToProcessTube(); +// } +// +// @Override +// public List getResourceList() { +// return List.of( +// A8kPublicResourceType.IncubationPlateModule, +// A8kPublicResourceType.HBOT, +// A8kPublicResourceType.CurTubeProcessToken); +// } +// +// +// @Override +// public String logCxtState() { +// var tube = gstate.getCurProcessingTube(); +// if (tube == null) { +// return ""; +// } +// return String.format("[sid: %s, proj: %s]", tube.getSampleId(), tube.getProjIndexStrList()); +// } +//} diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java index 1801ff8..494fbdd 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java @@ -1,130 +1,130 @@ -package a8k.service.app.appctrl.mainflowctrl.action; - -import a8k.service.app.appstate.type.ProjProcessContext; -import a8k.service.app.devicectrl.ctrlservice.PipetteGunCtrlService; -import a8k.service.app.devicectrl.ctrlservice.TubePreProcesCtrlService; -import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; -import a8k.service.app.devicectrl.script.DeviceCtrlScripter; -import a8k.utils.ActionParallerExceutor; -import a8k.utils.AppExceptionBuilder; -import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; -import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; -import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; -import a8k.service.app.appstate.*; -import a8k.service.app.appstate.resource.A8kPublicResourceType; -import a8k.service.app.appstate.type.DeviceWorkState; -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.*; - -import a8k.service.test.state.TestModeState; -import a8k.service.test.state.VirtualDevice; - -/** - * - * 核对物料资源是否足够 - * TUBE - * TO_BE_PROCESSED --> PRE_PROCESSING - */ -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 - TestModeState testModeState; - @Resource - VirtualDevice virtualDevice; - @Resource - PipetteCtrlDriver pipetteCtrlDriver; - - @Resource - AppExceptionBuilder ebuilder; - - @Resource - TubePreProcesCtrlService tubePreProcesCtrlService; - - @Resource - ProjectProcessContextMgrService projectProcessContextMgrService; - @Resource - CondtionMgrService cms; - @Resource - DeviceCtrlScripter deviceCtrlScripter; - - - ActionParallerExceutor actionParallerExceutor = new ActionParallerExceutor(); - - - DeviceWorkState state; - - @PostConstruct - void init() { - state = gstate.deviceWorkState; - } - - - void tubePostProcess() throws AppException { - var tube = gstate.getCurProcessingTube(); - Integer projProcessOff = tube.getProjProcessOff(); - ProjProcessContext cxt = projectProcessContextMgrService.getProjProcessContext(tube.getSampleId(), tube.getProjIds().get(projProcessOff)); - deviceCtrlScripter.doSampleProcessPostProcess(cxt); - } - - void doAction() throws AppException { - if (virtualDevice.isEnable()) { - virtualDevice.doVirtualThings("后处理样本", 3); - } - - actionParallerExceutor.submit(this::tubePostProcess); - actionParallerExceutor.submit(() -> tubePreProcesCtrlService.resteModule()); - - var mutiAppException = actionParallerExceutor.waitAll(); - - if (mutiAppException != null) { - projectProcessContextMgrService.changeTubeStateToError(gstate.getCurProcessingTube(), mutiAppException.getErrors()); - throw mutiAppException; - } - - } - - @Override public void doaction() throws AppException { - projectProcessContextMgrService.postProcessTube(); - doAction(); - projectProcessContextMgrService.postProcessTubeOK(); - } - - @Override public Boolean checkCondition() { - return cms.isTimeToPostProcessTube(); - } - - @Override public List getResourceList() { - return List.of( - A8kPublicResourceType.PlatesBoxModule, - A8kPublicResourceType.HBOT, - A8kPublicResourceType.IncubationPlateModule, - A8kPublicResourceType.CurTubeProcessToken - ); - } - - // - // UTILS - // - - @Override public String logCxtState() { - var tube = gstate.getCurProcessingTube(); - if (tube == null) { - return ""; - } - return String.format("[sid: %s, proj: %s]", tube.getSampleId(), tube.getProjIndexStrList()); - } -} +//package a8k.service.app.appctrl.mainflowctrl.action; +// +//import a8k.service.app.appstate.type.ProjProcessContext; +//import a8k.service.app.devicectrl.ctrlservice.PipetteGunCtrlService; +//import a8k.service.app.devicectrl.ctrlservice.TubePreProcesCtrlService; +//import a8k.service.app.devicectrl.driver.PipetteCtrlDriver; +//import a8k.service.app.devicectrl.script.DeviceCtrlScripter; +//import a8k.utils.ActionParallerExceutor; +//import a8k.utils.AppExceptionBuilder; +//import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; +//import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; +//import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; +//import a8k.service.app.appstate.*; +//import a8k.service.app.appstate.resource.A8kPublicResourceType; +//import a8k.service.app.appstate.type.DeviceWorkState; +//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.*; +// +//import a8k.service.test.state.TestModeState; +//import a8k.service.test.state.VirtualDevice; +// +///** +// * +// * 核对物料资源是否足够 +// * TUBE +// * TO_BE_PROCESSED --> PRE_PROCESSING +// */ +//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 +// TestModeState testModeState; +// @Resource +// VirtualDevice virtualDevice; +// @Resource +// PipetteCtrlDriver pipetteCtrlDriver; +// +// @Resource +// AppExceptionBuilder ebuilder; +// +// @Resource +// TubePreProcesCtrlService tubePreProcesCtrlService; +// +// @Resource +// ProjectProcessContextMgrService projectProcessContextMgrService; +// @Resource +// CondtionMgrService cms; +// @Resource +// DeviceCtrlScripter deviceCtrlScripter; +// +// +// ActionParallerExceutor actionParallerExceutor = new ActionParallerExceutor(); +// +// +// DeviceWorkState state; +// +// @PostConstruct +// void init() { +// state = gstate.deviceWorkState; +// } +// +// +// void tubePostProcess() throws AppException { +// var tube = gstate.getCurProcessingTube(); +// Integer projProcessOff = tube.getProjProcessOff(); +// ProjProcessContext cxt = projectProcessContextMgrService.getProjProcessContext(tube.getSampleId(), tube.getProjIds().get(projProcessOff)); +// deviceCtrlScripter.doSampleProcessPostProcess(cxt); +// } +// +// void doAction() throws AppException { +// if (virtualDevice.isEnable()) { +// virtualDevice.doVirtualThings("后处理样本", 3); +// } +// +// actionParallerExceutor.submit(this::tubePostProcess); +// actionParallerExceutor.submit(() -> tubePreProcesCtrlService.resteModule()); +// +// var mutiAppException = actionParallerExceutor.waitAll(); +// +// if (mutiAppException != null) { +// projectProcessContextMgrService.changeTubeStateToError(gstate.getCurProcessingTube(), mutiAppException.getErrors()); +// throw mutiAppException; +// } +// +// } +// +// @Override public void doaction() throws AppException { +// projectProcessContextMgrService.postProcessTube(); +// doAction(); +// projectProcessContextMgrService.postProcessTubeOK(); +// } +// +// @Override public Boolean checkCondition() { +// return cms.isTimeToPostProcessTube(); +// } +// +// @Override public List getResourceList() { +// return List.of( +// A8kPublicResourceType.PlatesBoxModule, +// A8kPublicResourceType.HBOT, +// A8kPublicResourceType.IncubationPlateModule, +// A8kPublicResourceType.CurTubeProcessToken +// ); +// } +// +// // +// // UTILS +// // +// +// @Override public String logCxtState() { +// var tube = gstate.getCurProcessingTube(); +// if (tube == null) { +// return ""; +// } +// return String.format("[sid: %s, proj: %s]", tube.getSampleId(), tube.getProjIndexStrList()); +// } +//} diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/actionv2/SEQ5_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/actionv2/SEQ5_PROCESS.java new file mode 100644 index 0000000..f029f6e --- /dev/null +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/actionv2/SEQ5_PROCESS.java @@ -0,0 +1,302 @@ +package a8k.service.app.appctrl.mainflowctrl.actionv2; + +import a8k.OS; +import a8k.service.app.appctrl.mainflowctrl.CondtionMgrService; +import a8k.service.app.appctrl.mainflowctrl.ResourceMgrServiceV2; +import a8k.service.app.appctrl.mainflowctrl.base.A8kActionStepType; +import a8k.service.app.appctrl.mainflowctrl.base.A8kStepActionV2; +import a8k.service.app.appctrl.mainflowctrl.base.MainFlowProcesser; +import a8k.service.app.appstate.GStateService; +import a8k.service.app.appstate.IncubationPlateStateMgrService; +import a8k.service.app.appstate.ProjectProcessContextMgrService; +import a8k.service.app.appstate.type.ProjProcessContext; +import a8k.service.app.appstate.type.Tube; +import a8k.service.app.appstate.type.TubeHolder; +import a8k.service.app.devicectrl.ctrlservice.PipetteGunCtrlService; +import a8k.service.app.devicectrl.ctrlservice.PlateBoxCtrlService; +import a8k.service.app.devicectrl.ctrlservice.TubePreProcesCtrlService; +import a8k.service.app.devicectrl.script.DeviceCtrlScripter; +import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; +import a8k.service.test.PosMeasureUtils; +import a8k.service.test.state.TestModeState; +import a8k.service.test.state.VirtualDevice; +import a8k.type.IncubatorPos; +import a8k.type.ecode.AppError; +import a8k.type.exception.AppException; +import a8k.type.exception.ZAppInterruptException; +import a8k.type.type.A8kTubeHolderType; +import a8k.utils.AppExceptionBuilder; +import a8k.utils.ProjProcessContextUtils; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.*; + +@Component +@MainFlowProcesser +@Slf4j +public class SEQ5_PROCESS extends A8kStepActionV2 { + static Logger logger = LoggerFactory.getLogger(SEQ5_PROCESS.class); + @Autowired + private PosMeasureUtils posMeasureUtils; + + SEQ5_PROCESS() { + super(A8kActionStepType.PROCESS_INCUBATE_COMPLETED_PLATE); + } + + public interface Fn { + void call() throws AppException; + } + + @Resource + GStateService gstate; + @Resource + TestModeState testModeState; + @Resource + VirtualDevice virtualDevice; + + @Resource + AppExceptionBuilder ebuilder; + @Resource + IncubationPlateStateMgrService incubationPlateStateMgrService; + @Resource + CondtionMgrService cms; + @Resource + ProjectProcessContextMgrService projectProcessContextMgrService; + + @Resource + PipetteGunCtrlService pipetteGunCtrlService; + @Resource + DeviceCtrlScripter deviceCtrlScripter; + @Resource + ResourceMgrServiceV2 resourceMgrServiceV2; + @Resource + PlateBoxCtrlService plateBoxCtrlService; + @Resource + TubePreProcesCtrlService tubePreProcesCtrlService; + // + // 取试管 取反应板夹 预处理 + // 摇匀 处理 + // 脱帽 等待样本准备OK + // 待机 取反应样本 + // 等待试管处理完成 + // + ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); + List> futures = new ArrayList<>(); + + + Boolean reactionPlateReady = false; + Boolean sampleIsReady = false; + Boolean sampleProcessFinished = false; + Boolean errorFlag = false; + + + void waittingForReactionPlateReady() throws ZAppInterruptException { + while (!reactionPlateReady) { + OS.forceSleep(100); + if (errorFlag) { + throw new ZAppInterruptException(); + } + } + } + + void waittingForSampleIsReady() throws ZAppInterruptException { + while (!sampleIsReady) { + OS.forceSleep(100); + if (errorFlag) { + throw new ZAppInterruptException(); + } + } + } + + void waittingForSampleProcessFinished() throws ZAppInterruptException { + while (!sampleProcessFinished) { + OS.forceSleep(100); + if (errorFlag) { + throw new ZAppInterruptException(); + } + } + } + + + void samplePrepare() throws AppException, ZAppInterruptException { + if (virtualDevice.isEnable()) { + virtualDevice.doVirtualThings("摇匀并取盖", 2); + sampleIsReady = true; + waittingForSampleProcessFinished(); + virtualDevice.doVirtualThings("放回试管", 2); + return; + } + + Tube tube = gstate.getCurProcessingTube(); + TubeHolder tubeHolder = gstate.getTubeHolder(); + Boolean isHighTube = tube.getIsHighTube(); + + /* + * 样本预处理 + */ + if (!tube.getIsEmergency() && tubeHolder.tubeHolderType.equals(A8kTubeHolderType.BloodTube)) { + Integer shakeTimes = ProjProcessContextUtils.getShakeTimes(tube); + logger.info("摇匀次数 :{}", shakeTimes); + logger.info("试管架类型 :{}", tubeHolder.tubeHolderType); + logger.info("是否高位试管:{}", isHighTube); + tubePreProcesCtrlService.takeTubeFromTubeholderToShakePos(isHighTube); + tubePreProcesCtrlService.shakeTube(45, shakeTimes); + tubePreProcesCtrlService.takeTubeCap(); + } else { + logger.info("不是全血试管,不需要摇匀"); + } + + sampleIsReady = true; + waittingForSampleProcessFinished(); + + //样本后处理 + tubePreProcesCtrlService.resteModule(); + } + + + void paltePrepare() throws AppException, ZAppInterruptException { + // + // VIRTUAL + // + if (virtualDevice.isEnable()) { + virtualDevice.doVirtualThings("准备反应板夹", 2); + reactionPlateReady = true; + return; + } + + // + // REAL + // + + Tube tube = gstate.getCurProcessingTube(); + List cxts = projectProcessContextMgrService.getTubeAssociatedProjContext(tube.getSampleId()); + + for (ProjProcessContext cxt : cxts) { + IncubatorPos incubatorPos = cxt.incubatorPos; + plateBoxCtrlService.pushPlateQuick(cxt.consumable.getGroup(), incubatorPos); + } + reactionPlateReady = true; + } + + + void sampleProcess() throws AppException, ZAppInterruptException { + if (virtualDevice.isEnable()) { + virtualDevice.doVirtualThings("准备Hbot Tip", 2); + waittingForSampleIsReady(); + virtualDevice.doVirtualThings("处理样本", 2); + sampleProcessFinished = true; + return; + } + //准备第一个项目的tip头 + List cxts = projectProcessContextMgrService.getTubeAssociatedProjContext(gstate.getCurProcessingTube().getSampleId()); + Assert.isTrue(!cxts.isEmpty(), "项目上下文不能为空"); + + for (ProjProcessContext cxt : cxts) { + deviceCtrlScripter.doSampleProcessPrepare(cxt); + waittingForSampleIsReady(); + deviceCtrlScripter.doSampleProcess(cxt); + deviceCtrlScripter.doSampleProcessPostProcess(cxt); + } + sampleProcessFinished = true; + } + + public Boolean isReady() { + return true; + } + + @Override public String logCxtState() { + return ""; + } + + + public void beforeDoAction() { + reactionPlateReady = false; + sampleIsReady = false; + sampleProcessFinished = false; + errorFlag = false; + } + + + List wait(List> futures) { + for (var future : futures) { + while (!future.isDone()) { + OS.forceSleep(100); + } + } + + List errors = new ArrayList<>(); + for (var future : futures) { + try { + errors.add(future.get()); + } catch (InterruptedException | ExecutionException ignored) { + } + } + errors.removeIf(Objects::isNull); + return errors; + } + + @Override public List doAction() { + var future1 = executor.submit(() -> { + try { + sampleProcess(); + } catch (AppException e) { + logger.error("error", e); + errorFlag = true; + return e.error; + } catch (ZAppInterruptException ignored) { + } + return null; + }); + var future2 = executor.submit(() -> { + try { + paltePrepare(); + } catch (AppException e) { + logger.error("error", e); + errorFlag = true; + return e.error; + } catch (ZAppInterruptException ignored) { + } + return null; + }); + var future3 = executor.submit(() -> { + try { + samplePrepare(); + } catch (AppException e) { + logger.error("error", e); + errorFlag = true; + return e.error; + } catch (ZAppInterruptException ignored) { + } + return null; + }); + + futures.add(future1); + futures.add(future2); + futures.add(future3); + + return wait(futures); + } + + /** + * 动作处理完成后的处理(串行),一般用于修改状态 + */ + @Override + public List afterDoAction(List errors) { + if (!errors.isEmpty()) { + return errors; + } + projectProcessContextMgrService.tubePreProcessingOK(); + projectProcessContextMgrService.processIngTubeOK(); + projectProcessContextMgrService.postProcessTubeOK(); + return List.of(); + } +} diff --git a/src/main/java/a8k/service/app/appstate/type/Tube.java b/src/main/java/a8k/service/app/appstate/type/Tube.java index 4046857..a7b8436 100644 --- a/src/main/java/a8k/service/app/appstate/type/Tube.java +++ b/src/main/java/a8k/service/app/appstate/type/Tube.java @@ -32,8 +32,8 @@ public class Tube { @Schema(description = "项目信息") List projInfo = new ArrayList<>(); //项目信息 - @Schema(description = "项目处理偏移") - Integer projProcessOff = 0; +// @Schema(description = "项目处理偏移") +// Integer projProcessOff = 0; // @Schema(description = "样本被处理的状态") TubeState state = TubeState.EMPTY; //样本被处理的状态 diff --git a/src/main/java/a8k/type/exception/ZAppInterruptException.java b/src/main/java/a8k/type/exception/ZAppInterruptException.java new file mode 100644 index 0000000..6631f83 --- /dev/null +++ b/src/main/java/a8k/type/exception/ZAppInterruptException.java @@ -0,0 +1,15 @@ +package a8k.type.exception; + +import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import a8k.hardware.type.a8kcanprotocol.CmdId; +import a8k.hardware.type.a8kcanprotocol.MId; +import a8k.type.ecode.AECommonError; +import a8k.type.ecode.AEHardwareError; +import a8k.type.ecode.AppError; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +public class ZAppInterruptException extends Exception { +} diff --git a/src/main/java/a8k/utils/ActionParallerExceutor.java b/src/main/java/a8k/utils/ActionParallerExceutor.java index 79edcee..f450877 100644 --- a/src/main/java/a8k/utils/ActionParallerExceutor.java +++ b/src/main/java/a8k/utils/ActionParallerExceutor.java @@ -1,7 +1,6 @@ package a8k.utils; import a8k.OS; -import a8k.type.ecode.AppError; import a8k.type.exception.AppException; import a8k.type.exception.MutiAppException; diff --git a/src/main/java/a8k/utils/ZFnCall.java b/src/main/java/a8k/utils/ZFnCall.java index e4f9f2d..5b428ab 100644 --- a/src/main/java/a8k/utils/ZFnCall.java +++ b/src/main/java/a8k/utils/ZFnCall.java @@ -13,6 +13,7 @@ public class ZFnCall { void call() throws AppException; } + public static AppException callfn(Fn fn) { try { fn.call(); @@ -21,4 +22,14 @@ public class ZFnCall { } return null; } + + + public static AppError callfn2(Fn fn) { + try { + fn.call(); + } catch (AppException e) { + return e.error; + } + return null; + } }