6 changed files with 329 additions and 15 deletions
-
2src/main/java/a8k/app/a8ktype/state/SampleInfo.java
-
8src/main/java/a8k/app/service/mainctrl/mainflowctrl/MainFlowCtrlScheduler.java
-
29src/main/java/a8k/app/service/mainctrl/mainflowctrl/processer/MainFlowStateChangeProcesser.java
-
8src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java
-
8src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java
-
289src/main/java/a8k/extui/page/extapp/OptFullFlowVerificationPage.java
@ -0,0 +1,289 @@ |
|||
package a8k.extui.page.extapp; |
|||
|
|||
import a8k.OS; |
|||
import a8k.app.a8kproj.A8kReactionResultComputer; |
|||
import a8k.app.a8kproj.optalgo.type.OptScanResult; |
|||
import a8k.app.a8ktype.device.*; |
|||
import a8k.app.a8ktype.exception.AppException; |
|||
import a8k.app.a8ktype.param.type.A8kSamplePos; |
|||
import a8k.app.a8ktype.state.SampleInfo; |
|||
import a8k.app.a8ktype.type.ReactionResult; |
|||
import a8k.app.a8ktype.type.TubeHolderScanResult; |
|||
import a8k.app.dao.db.type.ProjExtInfoCard; |
|||
import a8k.app.dao.db.type.a8kidcard.zenum.A8kReactionFlowType; |
|||
import a8k.app.hardware.driver.PipetteCtrlDriver; |
|||
import a8k.app.service.bases.AppEventBusService; |
|||
import a8k.app.service.bases.FrontEndMessageBoxAndEventMgr; |
|||
import a8k.app.service.data.ProjIdCardInfoMgrService; |
|||
import a8k.app.service.data.ProjInfoMgrService; |
|||
import a8k.app.service.data.ReactionRecordMgrService; |
|||
import a8k.app.service.lowerctrl.*; |
|||
import a8k.app.utils.ProjBuildinInfo; |
|||
import a8k.app.utils.ProjInfo; |
|||
import a8k.app.utils.ProjInfoReader; |
|||
import a8k.app.utils.ZDateUtils; |
|||
import a8k.extui.mgr.ExtApiPageMgr; |
|||
import a8k.extui.type.ExtApiStatu; |
|||
import jakarta.annotation.PostConstruct; |
|||
import jakarta.annotation.Resource; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.util.Assert; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
@Component |
|||
public class OptFullFlowVerificationPage { |
|||
|
|||
@Resource |
|||
TubeFeedingCtrlService tubeFeedingCtrlService; |
|||
|
|||
@Resource |
|||
TubePreProcesModuleExCtrlService tubePreProcesModuleExCtrlService; |
|||
|
|||
TubeHolderScanResult tubeHolderScanResult; |
|||
|
|||
|
|||
@Resource |
|||
PlateBoxCtrlService plateBoxCtrlService; |
|||
@Resource |
|||
OptScanModuleCtrlService optScanModuleCtrlService; |
|||
@Resource |
|||
PipetteCtrlDriver pipetteCtrlDriver; |
|||
@Resource |
|||
HbotMoveExCtrlService hbotMoveExCtrlService; |
|||
@Resource |
|||
LiquidOperationCtrlService liquidOperationCtrlService; |
|||
@Resource |
|||
TurnableMoveCtrlService turnableMoveCtrlService; |
|||
|
|||
@Resource |
|||
ProjIdCardInfoMgrService projIdCardInfoMgrService; |
|||
@Resource |
|||
ProjInfoMgrService projInfoMgrService; |
|||
@Resource |
|||
AppEventBusService appEventBusService; |
|||
|
|||
@Resource |
|||
FrontEndMessageBoxAndEventMgr frontEndMessageBoxAndEventMgr; |
|||
@Autowired |
|||
private ReactionRecordMgrService reactionRecordMgrService; |
|||
|
|||
|
|||
// |
|||
//Config |
|||
// |
|||
static public class Context { |
|||
public SampleInfo sampleInfo = new SampleInfo(); |
|||
public ProjBuildinInfo projBuildinInfo; |
|||
public ProjExtInfoCard projExtInfoCard; |
|||
public A8kSamplePos samplePos = A8kSamplePos.EmergencyTubePos; |
|||
public ConsumableGroup consumableGroup = ConsumableGroup.CG1; |
|||
public Integer consumablePosOff = 0; |
|||
public IncubatorPos incubatorPos = IncubatorPos.SPACE01; |
|||
|
|||
public List<ReactionResult> results = new ArrayList<>(); |
|||
public Boolean isInit = false; |
|||
} |
|||
|
|||
static public class State { |
|||
public Integer incubateRemainTime; |
|||
} |
|||
|
|||
Context cxt = new Context(); |
|||
State state = new State(); |
|||
|
|||
|
|||
@ExtApiStatu(name = "", group = "样本信息", order = 1, minWidth = "33.3%") |
|||
public SampleInfo showSampleInfo() { |
|||
return cxt.sampleInfo; |
|||
} |
|||
|
|||
@ExtApiStatu(name = "", group = "项目信息", order = 2, minWidth = "33.3%") |
|||
public ProjBuildinInfo showProjInfo() { |
|||
return cxt.projBuildinInfo; |
|||
} |
|||
|
|||
@ExtApiStatu(name = "", group = "项目卡信息", order = 3, minWidth = "33.3%") |
|||
public ProjExtInfoCard showProjExtInfoCard() { |
|||
return cxt.projExtInfoCard; |
|||
} |
|||
|
|||
@ExtApiStatu(name = "", group = "上下文", order = 4, minWidth = "33.3%") |
|||
public Object showConsumableInfo() { |
|||
return Map.<String, Object>of( |
|||
"耗材位置", String.format("%s-%d", cxt.consumableGroup, cxt.consumablePosOff), |
|||
"孵育盘位置", cxt.incubatorPos, |
|||
"取样位置", cxt.samplePos, |
|||
"样本信息是否初始化", cxt.isInit |
|||
); |
|||
} |
|||
|
|||
@ExtApiStatu(name = "", group = "状态", order = 5, minWidth = "33.3%") |
|||
public State showState() { |
|||
return state; |
|||
} |
|||
|
|||
@ExtApiStatu(name = "", group = "结果", order = 6, minWidth = "33.3%") |
|||
public List<ReactionResult> showResults() { |
|||
return cxt.results; |
|||
} |
|||
|
|||
|
|||
Integer tippos = 0; |
|||
|
|||
void takeTip() throws AppException { |
|||
Boolean takeTip = false; |
|||
for (int i = 0; i < 10; i++) { |
|||
tippos = tippos % 120; |
|||
takeTip = hbotMoveExCtrlService.takeTipNoCheck(TipGroup.TipG1, tippos); |
|||
if (takeTip) { |
|||
break; |
|||
} |
|||
tippos++; |
|||
} |
|||
if (!takeTip) { |
|||
throw AppException.ofAECodeError("取Tip失败"); |
|||
} |
|||
} |
|||
|
|||
public void clearDevice() throws AppException { |
|||
optScanModuleCtrlService.dropPlate(); |
|||
optScanModuleCtrlService.pullPlate(IncubatorPos.SPACE01); |
|||
optScanModuleCtrlService.dropPlate(); |
|||
} |
|||
|
|||
|
|||
void prepareReactionPlate() throws AppException { |
|||
plateBoxCtrlService.pushPlateQuick(cxt.consumableGroup, cxt.incubatorPos); |
|||
} |
|||
|
|||
void procesSample() throws AppException { |
|||
liquidOperationCtrlService.setProjContext(cxt.projBuildinInfo, cxt.projExtInfoCard); |
|||
if (!hbotMoveExCtrlService.isHasTip()) |
|||
takeTip(); |
|||
if (cxt.projBuildinInfo.reactionFlowType.equals(A8kReactionFlowType.SampleAndBS)) { |
|||
//param 小瓶缓冲液位置 |
|||
var preReactionPos = new PreReactionPos(ConsumableType.SmallBottleBuffer, cxt.consumableGroup, cxt.consumablePosOff); |
|||
//param 取样量 |
|||
Integer sampleVol = ProjInfoReader.getSampleVol(cxt.projBuildinInfo, cxt.projExtInfoCard, cxt.sampleInfo.bloodType); |
|||
|
|||
|
|||
//action ->刺破 |
|||
liquidOperationCtrlService.pirceLittleBuffer(preReactionPos); |
|||
//action ->取样 |
|||
liquidOperationCtrlService.takeSample(cxt.samplePos, preReactionPos, sampleVol); |
|||
//action ->孵育盘移动到吐液位置 |
|||
turnableMoveCtrlService.trunableMoveToDropLiquidPos(cxt.incubatorPos); // |
|||
//action ->取反应液到反应板上 |
|||
liquidOperationCtrlService.takePreReactionLiquidToLiquid(preReactionPos); // |
|||
} else if (cxt.projBuildinInfo.reactionFlowType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) { |
|||
//param 探测物位置 |
|||
var preReactionPos = new PreReactionPos(ConsumableType.ProbeSubstance, cxt.consumableGroup, cxt.consumablePosOff); |
|||
//param 取样量 |
|||
Integer sampleVol = ProjInfoReader.getSampleVol(cxt.projBuildinInfo, cxt.projExtInfoCard, cxt.sampleInfo.bloodType); |
|||
|
|||
//action ->取大瓶缓冲液到探测物质 |
|||
liquidOperationCtrlService.takeLargeBottleBufferLiquidToProbeSubstance( |
|||
LargeBufferPos.of(cxt.consumableGroup), preReactionPos, cxt.projBuildinInfo.bigBufferSampleUl); |
|||
|
|||
//action ->取样品 |
|||
liquidOperationCtrlService.takeSample(cxt.samplePos, preReactionPos, sampleVol); |
|||
//action ->孵育盘移动到吐液位置 |
|||
turnableMoveCtrlService.trunableMoveToDropLiquidPos(cxt.incubatorPos); // |
|||
//action ->取反应液到反应板上 |
|||
liquidOperationCtrlService.takePreReactionLiquidToLiquid(preReactionPos); // |
|||
} |
|||
} |
|||
|
|||
void incubate() throws AppException { |
|||
//等待孵育完成 |
|||
state.incubateRemainTime = cxt.projBuildinInfo.reactionPlateIncubationTimeMin * 60; |
|||
while (state.incubateRemainTime > 0) { |
|||
state.incubateRemainTime -= 1; |
|||
OS.forceSleep(1000); |
|||
} |
|||
frontEndMessageBoxAndEventMgr.showInfo("孵育完成"); |
|||
} |
|||
|
|||
void pullAndScan() throws AppException { |
|||
optScanModuleCtrlService.pullPlate(cxt.incubatorPos); |
|||
ProjInfo projInfo = new ProjInfo(); |
|||
projInfo.buildIn = cxt.projBuildinInfo; |
|||
projInfo.ext = cxt.projExtInfoCard; |
|||
|
|||
List<OptScanResult> optScanResults = new ArrayList<>(); |
|||
for (int i = 0; i < cxt.projBuildinInfo.subProjNum; i++) { |
|||
var optScanResult = optScanModuleCtrlService.optScan(cxt.projBuildinInfo, i); |
|||
|
|||
ReactionResult result = A8kReactionResultComputer.optComputeResult(cxt.sampleInfo, projInfo, i, optScanResult.analysResult); |
|||
cxt.results.add(result); |
|||
optScanResults.add(optScanResult); |
|||
} |
|||
reactionRecordMgrService.addRecord(cxt.sampleInfo, projInfo, optScanResults, cxt.results); |
|||
|
|||
} |
|||
|
|||
|
|||
public void initSampleInfo() throws AppException { |
|||
cxt.sampleInfo.sampleId = ZDateUtils.toID(new Date()); |
|||
cxt.sampleInfo.userid = cxt.sampleInfo.sampleId; |
|||
cxt.sampleInfo.sampleBarcode = cxt.sampleInfo.sampleId; |
|||
cxt.sampleInfo.bloodType = BloodType.SERUM_OR_PLASMA; |
|||
cxt.sampleInfo.isHighTube = false; |
|||
cxt.sampleInfo.isEmergency = true; |
|||
|
|||
|
|||
cxt.projExtInfoCard = projIdCardInfoMgrService.getMountedProjInfoCard(); |
|||
Assert.notNull(cxt.projExtInfoCard, "请插入项目卡"); |
|||
cxt.projBuildinInfo = projInfoMgrService.getProjBuildInInfo(cxt.projExtInfoCard.projId); |
|||
cxt.isInit = true; |
|||
|
|||
cxt.incubatorPos = IncubatorPos.SPACE01; |
|||
cxt.consumableGroup = ConsumableGroup.CG1; |
|||
cxt.consumablePosOff = 0; |
|||
} |
|||
|
|||
public void startProcessSample(Boolean scanOnly) throws AppException { |
|||
initSampleInfo(); |
|||
clearDevice(); |
|||
frontEndMessageBoxAndEventMgr.showInfo("反应板准备"); |
|||
prepareReactionPlate(); |
|||
if (!scanOnly) { |
|||
frontEndMessageBoxAndEventMgr.showInfo("样本处理"); |
|||
procesSample(); |
|||
frontEndMessageBoxAndEventMgr.showInfo("孵育"); |
|||
incubate(); |
|||
} |
|||
frontEndMessageBoxAndEventMgr.showInfo("扫描"); |
|||
pullAndScan(); |
|||
frontEndMessageBoxAndEventMgr.showInfo("丢板"); |
|||
optScanModuleCtrlService.dropPlate(); |
|||
frontEndMessageBoxAndEventMgr.showInfo("结束"); |
|||
} |
|||
|
|||
public void sampleAndIncubateAndScan() throws AppException { |
|||
startProcessSample(false); |
|||
} |
|||
|
|||
public void scanOnly(Integer scanTimes) throws AppException { |
|||
for (int i = 0; i < scanTimes; i++) { |
|||
startProcessSample(true); |
|||
} |
|||
} |
|||
|
|||
|
|||
@Resource |
|||
ExtApiPageMgr extApiPageMgr; |
|||
|
|||
@PostConstruct |
|||
public void init() { |
|||
var page = extApiPageMgr.newPage(this); |
|||
page.addFunction("取样.孵育.扫描", this::sampleAndIncubateAndScan); |
|||
page.addFunction("只扫描", this::scanOnly); |
|||
extApiPageMgr.addPage(page); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue