Browse Source

update

tags/v0
zhaohe 9 months ago
parent
commit
ff3bcad3ac
  1. 400
      src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ4_PRE_PROCESS.java
  2. 278
      src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java
  3. 260
      src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ6_POST_PROCESS.java
  4. 302
      src/main/java/a8k/service/app/appctrl/mainflowctrl/actionv2/SEQ5_PROCESS.java
  5. 4
      src/main/java/a8k/service/app/appstate/type/Tube.java
  6. 15
      src/main/java/a8k/type/exception/ZAppInterruptException.java
  7. 1
      src/main/java/a8k/utils/ActionParallerExceutor.java
  8. 11
      src/main/java/a8k/utils/ZFnCall.java

400
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<ProjProcessContext> 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<ProjProcessContext> 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<A8kPublicResourceType> 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<ProjProcessContext> 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<ProjProcessContext> 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<A8kPublicResourceType> 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());
// }
//}

278
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<A8kPublicResourceType> 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<A8kPublicResourceType> 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());
// }
//}

260
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<A8kPublicResourceType> 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<A8kPublicResourceType> 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());
// }
//}

302
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<Future<AppError>> 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<ProjProcessContext> 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<ProjProcessContext> 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<AppError> wait(List<Future<AppError>> futures) {
for (var future : futures) {
while (!future.isDone()) {
OS.forceSleep(100);
}
}
List<AppError> 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<AppError> 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<AppError> afterDoAction(List<AppError> errors) {
if (!errors.isEmpty()) {
return errors;
}
projectProcessContextMgrService.tubePreProcessingOK();
projectProcessContextMgrService.processIngTubeOK();
projectProcessContextMgrService.postProcessTubeOK();
return List.of();
}
}

4
src/main/java/a8k/service/app/appstate/type/Tube.java

@ -32,8 +32,8 @@ public class Tube {
@Schema(description = "项目信息")
List<ProjBriefInfo> projInfo = new ArrayList<>(); //项目信息
@Schema(description = "项目处理偏移")
Integer projProcessOff = 0;
// @Schema(description = "项目处理偏移")
// Integer projProcessOff = 0;
//
@Schema(description = "样本被处理的状态")
TubeState state = TubeState.EMPTY; //样本被处理的状态

15
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 {
}

1
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;

11
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;
}
}
Loading…
Cancel
Save