28 changed files with 628 additions and 381 deletions
-
17src/main/java/a8k/baseservice/AppExceptionBuilder.java
-
1src/main/java/a8k/hardware/type/a8kcanprotocol/A8kEcode.java
-
70src/main/java/a8k/service/appdevicectrl/AppConsumablesMgrService.java
-
6src/main/java/a8k/service/appdevicectrl/AppEmergencySamplePosStateMgrService.java
-
2src/main/java/a8k/service/appdevicectrl/action/DO_PAUSE.java
-
2src/main/java/a8k/service/appdevicectrl/action/DO_START.java
-
2src/main/java/a8k/service/appdevicectrl/action/DO_STOP.java
-
5src/main/java/a8k/service/appdevicectrl/action/base/A8kActionStepType.java
-
2src/main/java/a8k/service/appdevicectrl/action/base/A8kStepAction.java
-
2src/main/java/a8k/service/appdevicectrl/action/mainflow/DO_EJECT_TUBEHOLDER.java
-
10src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java
-
2src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java
-
221src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ3_PRE_PROCESS.java
-
2src/main/java/a8k/service/appdevicectrl/scheduler/MainFlowCtrlScheduler.java
-
4src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/LarBSGroup.java
-
8src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/LittBSGroup.java
-
6src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/ReactionPlateGroup.java
-
30src/main/java/a8k/service/appstate/TubeProcessContextMgrService.java
-
3src/main/java/a8k/service/appstate/resource/A8kPublicResourceType.java
-
31src/main/java/a8k/service/appstate/type/IncubationPlate.java
-
10src/main/java/a8k/service/appstate/type/Tube.java
-
14src/main/java/a8k/service/appstate/type/TubeProcessContext.java
-
425src/main/java/a8k/service/devicedriver/ctrl/HbotControlService.java
-
18src/main/java/a8k/service/devicedriver/ctrl/SamplesPreProcesCtrl.java
-
6src/main/java/a8k/type/ConsumableGroup.java
-
12src/main/java/a8k/type/ecode/AppCodeError.java
-
22src/main/java/a8k/utils/ZFnCall.java
@ -0,0 +1,221 @@ |
|||
package a8k.service.appdevicectrl.action.mainflow; |
|||
|
|||
import a8k.OS; |
|||
import a8k.baseservice.AppExceptionBuilder; |
|||
import a8k.baseservice.appeventbus.AppEventBusService; |
|||
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|||
import a8k.service.appdevicectrl.AppConsumablesMgrService; |
|||
import a8k.service.appdevicectrl.action.base.A8kActionStepType; |
|||
import a8k.service.appdevicectrl.action.base.A8kStepAction; |
|||
import a8k.service.appstate.AppA8kGStateService; |
|||
import a8k.service.appstate.TubeProcessContextMgrService; |
|||
import a8k.service.appstate.resource.A8kPublicResourceType; |
|||
import a8k.service.appstate.type.Tube; |
|||
import a8k.service.appstate.type.TubeHolder; |
|||
import a8k.service.appstate.type.state.IncubationSubTankState; |
|||
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.ConsumableGroup; |
|||
import a8k.type.IncubatorPos; |
|||
import a8k.type.ecode.AppError; |
|||
import a8k.type.exception.AppException; |
|||
import a8k.type.type.A8kTubeHolderType; |
|||
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.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
import java.util.concurrent.*; |
|||
|
|||
/** |
|||
* |
|||
* 核对物料资源是否足够 |
|||
* TUBE |
|||
* TO_BE_PROCESSED --> PRE_PROCESSING |
|||
*/ |
|||
@Component |
|||
public class SEQ3_PRE_PROCESS extends A8kStepAction { |
|||
static Logger logger = LoggerFactory.getLogger(SEQ3_PRE_PROCESS.class); |
|||
|
|||
SEQ3_PRE_PROCESS() { |
|||
super(A8kActionStepType.SEQ2_SWITCH_TO_THE_NEXT_TUBE); |
|||
} |
|||
|
|||
@Resource |
|||
AppA8kGStateService gstate; |
|||
|
|||
@Resource |
|||
SampleScanTransportCtrl sstc; |
|||
|
|||
@Resource |
|||
AppConsumablesMgrService consumablesMgrService; |
|||
|
|||
@Resource |
|||
AppEventBusService ebus; |
|||
|
|||
@Resource |
|||
AppExceptionBuilder ebuilder; |
|||
|
|||
@Resource |
|||
TubeProcessContextMgrService tubeProcessContextMgrService; |
|||
|
|||
@Resource |
|||
ReactionPlatesTransmitCtrl reactionPlatesTransmitCtrl; |
|||
|
|||
@Resource |
|||
SamplesPreProcesCtrl samplesPreProcesCtrl; |
|||
|
|||
@Resource |
|||
HbotControlService hbotControlService; |
|||
|
|||
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10)); |
|||
|
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 推出反应板夹 |
|||
* @throws AppException 异常 |
|||
*/ |
|||
void prepareReactionPlate() throws AppException { |
|||
Tube tube = gstate.getCurProcessingTube(); |
|||
List<Integer> projIndex = tube.projIndex; |
|||
List<IncubatorPos> incubatorPos = tube.incubatorPos; |
|||
List<ConsumableGroup> 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 { |
|||
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(); |
|||
} |
|||
|
|||
void hbotPrepareTip() throws AppException { |
|||
|
|||
|
|||
|
|||
Tube tube = gstate.getCurProcessingTube(); |
|||
} |
|||
|
|||
@Override public void doaction() throws AppException { |
|||
|
|||
Tube tube = gstate.getCurProcessingTube(); |
|||
//构建样本和耗材绑定关系 |
|||
List<ConsumableGroup> bindConsumableCH = new ArrayList<>(); |
|||
List<Integer> consumablePosIndexList = new ArrayList<>(); |
|||
List<IncubatorPos> incubatorPosList = new ArrayList<>(); |
|||
for (Integer projIndex : tube.projIndex) { |
|||
ConsumableGroup chNum = consumablesMgrService.getChannelNumByProjIndex(projIndex); |
|||
Integer consumablePosIndex = consumablesMgrService.allocConsumable(chNum); |
|||
|
|||
|
|||
if (chNum == null) { |
|||
logger.error("apply consumable failed, projIndex:{}", projIndex); |
|||
throw ebuilder.buildAppCodeErrorException("预处理阶段,申请耗材失败"); |
|||
} |
|||
if (consumablePosIndex == null) { |
|||
logger.error("alloc consumable failed, projIndex:{}", projIndex); |
|||
throw ebuilder.buildAppCodeErrorException("预处理阶段,申请耗材失败x"); |
|||
} |
|||
bindConsumableCH.add(chNum); |
|||
consumablePosIndexList.add(consumablePosIndex); |
|||
incubatorPosList = gstate.getIncubationPlate().getEmptyPosList(tube.projIndex.size()); |
|||
} |
|||
tube.bindConsumablesCh = bindConsumableCH; |
|||
tube.consumablePos = consumablePosIndexList; |
|||
tube.incubatorPos = incubatorPosList; |
|||
|
|||
tubeProcessContextMgrService.updateTubeContext(tube);//更新样本上下文 |
|||
|
|||
|
|||
//检测反应板是否有空位 |
|||
if (gstate.getIncubationPlate().getEmptyPosNum() < tube.projIndex.size()) { |
|||
throw ebuilder.buildAppCodeErrorException("预处理阶段,反应板空位不足"); |
|||
} |
|||
|
|||
//准备反应板夹 |
|||
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<AppError> 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); |
|||
} |
|||
// |
|||
|
|||
} |
|||
|
|||
@Override public Boolean checkCondition() { |
|||
//当前正在工作 |
|||
Boolean cond1 = gstate.isWorking(); |
|||
//有需要进行预处理的样本 |
|||
Boolean cond2 = gstate.getCurProcessingTube() != null && gstate.getCurProcessingTube().state.equals(TubeState.PRE_PROCESSING); |
|||
return cond1 && cond2; |
|||
} |
|||
|
|||
@Override public List<A8kPublicResourceType> getResourceList() { |
|||
return List.of( |
|||
A8kPublicResourceType.IncubationPlateMotor, |
|||
A8kPublicResourceType.PlatesBoxMotor, |
|||
A8kPublicResourceType.HBOT |
|||
); |
|||
} |
|||
|
|||
// |
|||
// UTILS |
|||
// |
|||
|
|||
void wait(Future<?> future) { |
|||
while (!future.isDone()) { |
|||
OS.forceSleep(100); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
package a8k.type.ecode; |
|||
|
|||
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|||
|
|||
public class AppCodeError extends AppError { |
|||
public String exmsg; |
|||
|
|||
public AppCodeError(String exmsg) { |
|||
super(A8kEcode.CodeError); |
|||
this.exmsg = exmsg; |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
package a8k.utils; |
|||
|
|||
|
|||
import a8k.type.ecode.AppError; |
|||
import a8k.type.exception.AppException; |
|||
|
|||
public class ZFnCall { |
|||
|
|||
@FunctionalInterface |
|||
public interface Fn { |
|||
void call() throws AppException; |
|||
} |
|||
|
|||
public static AppError callfn(Fn fn) { |
|||
try { |
|||
fn.call(); |
|||
} catch (AppException e) { |
|||
return e.error; |
|||
} |
|||
return null; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue