Browse Source

update

tags/v0
zhaohe 10 months ago
parent
commit
ab290afac4
  1. 17
      src/main/java/a8k/baseservice/AppExceptionBuilder.java
  2. 1
      src/main/java/a8k/hardware/type/a8kcanprotocol/A8kEcode.java
  3. 70
      src/main/java/a8k/service/appdevicectrl/AppConsumablesMgrService.java
  4. 6
      src/main/java/a8k/service/appdevicectrl/AppEmergencySamplePosStateMgrService.java
  5. 2
      src/main/java/a8k/service/appdevicectrl/action/DO_PAUSE.java
  6. 2
      src/main/java/a8k/service/appdevicectrl/action/DO_START.java
  7. 2
      src/main/java/a8k/service/appdevicectrl/action/DO_STOP.java
  8. 5
      src/main/java/a8k/service/appdevicectrl/action/base/A8kActionStepType.java
  9. 2
      src/main/java/a8k/service/appdevicectrl/action/base/A8kStepAction.java
  10. 2
      src/main/java/a8k/service/appdevicectrl/action/mainflow/DO_EJECT_TUBEHOLDER.java
  11. 10
      src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java
  12. 2
      src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java
  13. 221
      src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ3_PRE_PROCESS.java
  14. 2
      src/main/java/a8k/service/appdevicectrl/scheduler/MainFlowCtrlScheduler.java
  15. 4
      src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/LarBSGroup.java
  16. 8
      src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/LittBSGroup.java
  17. 6
      src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/ReactionPlateGroup.java
  18. 30
      src/main/java/a8k/service/appstate/TubeProcessContextMgrService.java
  19. 3
      src/main/java/a8k/service/appstate/resource/A8kPublicResourceType.java
  20. 31
      src/main/java/a8k/service/appstate/type/IncubationPlate.java
  21. 10
      src/main/java/a8k/service/appstate/type/Tube.java
  22. 14
      src/main/java/a8k/service/appstate/type/TubeProcessContext.java
  23. 425
      src/main/java/a8k/service/devicedriver/ctrl/HbotControlService.java
  24. 18
      src/main/java/a8k/service/devicedriver/ctrl/SamplesPreProcesCtrl.java
  25. 6
      src/main/java/a8k/type/ConsumableGroup.java
  26. 12
      src/main/java/a8k/type/ecode/AppCodeError.java
  27. 22
      src/main/java/a8k/utils/ZFnCall.java

17
src/main/java/a8k/baseservice/AppExceptionBuilder.java

@ -1,14 +1,19 @@
package a8k.baseservice;
import a8k.type.ecode.AppCodeError;
import a8k.type.ecode.AppError;
import a8k.type.ecode.ConsumeNotEnoughError;
import a8k.type.exception.AppException;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.springframework.stereotype.Component;
import a8k.service.appdata.AppProjInfoMgrService;
import java.util.List;
@Component
public class AppExceptionBuilder {
static Logger logger = org.slf4j.LoggerFactory.getLogger(AppExceptionBuilder.class);
@Resource
AppProjInfoMgrService projConfigMgrService;
@ -19,4 +24,14 @@ public class AppExceptionBuilder {
return new AppException(new ConsumeNotEnoughError(projName, projIndex));
}
public AppException buildMutiErrorAppException(List<AppError> errors) {
if (errors.size() > 1) {
logger.error("buildMutiErrorAppException errors size > 1,drop all errors except the first one");
}
return new AppException(errors.get(0));
}
public AppException buildAppCodeErrorException(String extraMsg) {
return new AppException(new AppCodeError(extraMsg));
}
}

1
src/main/java/a8k/hardware/type/a8kcanprotocol/A8kEcode.java

@ -58,6 +58,7 @@ public enum A8kEcode {
TubeHolderTypeIsNotSupport(140),//试管架类型不支持
EmergencySampleIsProcessing(141),//急诊样本正在处理中
ConsumeNotEnough(142),//耗材不足
TakeTubeFail(143),//取试管失败
/**
* 特殊服务错误码

70
src/main/java/a8k/service/appdevicectrl/AppConsumablesMgrService.java

@ -8,6 +8,7 @@ import a8k.service.appdata.AppProjInfoMgrService;
import a8k.service.appdevicectrl.type.app_consumables_mgr_service.*;
import a8k.service.appstate.AppA8kGStateService;
import a8k.service.devicedriver.ctrl.ConsumablesScanCtrl;
import a8k.type.ConsumableGroup;
import a8k.type.exception.AppException;
import a8k.type.projecttype.A8kReactionFlowType;
import a8k.type.projecttype.a8kidcard.A8kIdCardInfo;
@ -114,42 +115,13 @@ public class AppConsumablesMgrService {
assert a8kIdCardInfo != null;
assert reactionType != null;
cState.reactionPlateGroup[ch] = new ReactionPlateGroup(//
result.projIndex, //
a8kIdCardInfo.projName, //
result.lotId, //
a8kIdCardInfo.color, //
EachConsumableNum);
cState.reactionPlateGroup[ch].editable = true;
cState.reactionPlateGroup[ch] = new ReactionPlateGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum);
if (reactionType.equals(A8kReactionFlowType.ReactionWithLittBS)) {
cState.littBSGroup[ch] = new LittBSGroup(//
result.projIndex, //
a8kIdCardInfo.projName, //
result.lotId, //
a8kIdCardInfo.color, //
EachConsumableNum);
cState.littBSGroup[ch].editable = true;
cState.larBSGroup[ch] = new LarBSGroup();
cState.larBSGroup[ch].editable = false;
cState.littBSGroup[ch] = new LittBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum);
cState.larBSGroup[ch] = new LarBSGroup();
} else if (reactionType.equals(A8kReactionFlowType.ReactionWithLarBsAndDetection)) {
cState.littBSGroup[ch] = new LittBSGroup(//
result.projIndex, //
a8kIdCardInfo.projName, //
result.lotId, //
a8kIdCardInfo.color, //
EachConsumableNum);
cState.littBSGroup[ch].editable = true;
cState.larBSGroup[ch] = new LarBSGroup(//
result.projIndex, //
a8kIdCardInfo.projName, //
result.lotId, //
a8kIdCardInfo.color, //
EachConsumableNum);
cState.larBSGroup[ch].editable = true;
cState.littBSGroup[ch] = new LittBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum);
cState.larBSGroup[ch] = new LarBSGroup(result.projIndex, a8kIdCardInfo.projName, result.lotId, a8kIdCardInfo.color, EachConsumableNum);
} else {
throw new RuntimeException("未知的反应流程类型");
}
@ -233,9 +205,9 @@ public class AppConsumablesMgrService {
var cState = gstate.getConsumableState();
assert cState != null;
cState.reactionPlateGroup[ch].num = num;
if (cState.littBSGroup[ch].editable)
if (cState.littBSGroup[ch].enable)
cState.littBSGroup[ch].num = num;
if (cState.larBSGroup[ch].editable)
if (cState.larBSGroup[ch].enable)
cState.larBSGroup[ch].num = num;
}
@ -257,7 +229,6 @@ public class AppConsumablesMgrService {
}
synchronized public Boolean isHasEnoughConsumables(List<Integer> projIndex) {
//
//只检查反应板的数量即可
for (Integer index : projIndex) {
Integer total = getConsumableNum(index);
@ -273,4 +244,29 @@ public class AppConsumablesMgrService {
return total >= 1;
}
synchronized public ConsumableGroup getChannelNumByProjIndex(Integer projIndex) {
var cState = gstate.getConsumableState();
for (int i = 0; i < cState.reactionPlateGroup.length; i++) {
if (cState.reactionPlateGroup[i].projIndex.equals(projIndex)) {
if (cState.reactionPlateGroup[i].num > 0) {
return ConsumableGroup.fromInt(i);
}
}
}
return null;
}
synchronized public Integer allocConsumable(ConsumableGroup ch) {
if (ch == null) {
return null;
}
var cState = gstate.getConsumableState();
int chNum = ch.off;
if (cState.reactionPlateGroup[chNum].num < 0) {
return null;
}
Integer posIndex = 25 - cState.reactionPlateGroup[chNum].num;
setReactionConsumableNum(chNum, cState.reactionPlateGroup[chNum].num - 1);
return posIndex;
}
}

6
src/main/java/a8k/service/appdevicectrl/AppEmergencySamplePosStateMgrService.java

@ -7,7 +7,7 @@ import a8k.controler.extapi.utils.ExtApiTab;
import a8k.hardware.type.a8kcanprotocol.A8kEcode;
import a8k.service.appdata.AppSampleRecordMgrService;
import a8k.service.appstate.AppA8kGStateService;
import a8k.service.appstate.AppSampleProcessContextMgrService;
import a8k.service.appstate.TubeProcessContextMgrService;
import a8k.service.appstate.type.EmergencyTubePos;
import a8k.service.appstate.type.Tube;
import a8k.service.appstate.type.state.TubeState;
@ -27,7 +27,7 @@ public class AppEmergencySamplePosStateMgrService {
AppSampleRecordMgrService sampleRecordMgrService;
@Resource
AppSampleProcessContextMgrService appSampleProcessContextMgrService;
TubeProcessContextMgrService tubeProcessContextMgrService;
/**
* 提交紧急样本设置
@ -54,7 +54,7 @@ public class AppEmergencySamplePosStateMgrService {
}
tube.state = TubeState.TO_BE_PROCESSED;
sampleRecordMgrService.addEmergencySampleRecord(tube);
appSampleProcessContextMgrService.createNewTubeContext(tube);
tubeProcessContextMgrService.createNewTubeContext(tube);
} else {
throw new AppException(A8kEcode.EmergencySampleIsProcessing);
}

2
src/main/java/a8k/service/appdevicectrl/action/DO_PAUSE.java

@ -40,7 +40,7 @@ public class DO_PAUSE extends A8kStepAction {
return cond1 & cond2;
}
@Override public List<A8kPublicResourceType> getDeplyResourceList() {
@Override public List<A8kPublicResourceType> getResourceList() {
return List.of();
}
}

2
src/main/java/a8k/service/appdevicectrl/action/DO_START.java

@ -51,7 +51,7 @@ public class DO_START extends A8kStepAction {
return cond1 & cond2;
}
@Override public List<A8kPublicResourceType> getDeplyResourceList() {
@Override public List<A8kPublicResourceType> getResourceList() {
return List.of(A8kPublicResourceType.SampleTransferXMotor);
}
}

2
src/main/java/a8k/service/appdevicectrl/action/DO_STOP.java

@ -39,7 +39,7 @@ public class DO_STOP extends A8kStepAction {
return cond1 & cond2;
}
@Override public List<A8kPublicResourceType> getDeplyResourceList() {
@Override public List<A8kPublicResourceType> getResourceList() {
return List.of();
}
}

5
src/main/java/a8k/service/appdevicectrl/action/base/A8kActionStepType.java

@ -6,6 +6,11 @@ public enum A8kActionStepType {
DO_STOP, //停止
SEQ1_ENTER_TUBEHOLDER_AND_SCAN, //入料并扫描
SEQ2_SWITCH_TO_THE_NEXT_TUBE,// 切换到下一个试管
SEQ3_PRE_PROCESS,
// SEQ4_PROCESS,
// SEQ5_POS_PROCESS_TUBE,
DO_EJECT_TUBEHOLDER, //弹出试管架

2
src/main/java/a8k/service/appdevicectrl/action/base/A8kStepAction.java

@ -22,7 +22,7 @@ public class A8kStepAction {
return checkCondition();
}
public List<A8kPublicResourceType> getDeplyResourceList() {
public List<A8kPublicResourceType> getResourceList() {
return null;
}

2
src/main/java/a8k/service/appdevicectrl/action/mainflow/DO_EJECT_TUBEHOLDER.java

@ -52,7 +52,7 @@ public class DO_EJECT_TUBEHOLDER extends A8kStepAction {
return cond1 & cond2 & cond3;
}
@Override public List<A8kPublicResourceType> getDeplyResourceList() {
@Override public List<A8kPublicResourceType> getResourceList() {
return List.of(A8kPublicResourceType.SampleTransferXMotor);
}
}

10
src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ1_ENTER_TUBEHOLDER_AND_SCAN.java

@ -10,7 +10,7 @@ import a8k.service.appdevicectrl.AppTubeSettingMgrService;
import a8k.service.appdevicectrl.action.base.A8kActionStepType;
import a8k.service.appdevicectrl.action.base.A8kStepAction;
import a8k.service.appstate.AppA8kGStateService;
import a8k.service.appstate.AppSampleProcessContextMgrService;
import a8k.service.appstate.TubeProcessContextMgrService;
import a8k.service.appstate.MainFlowCtrlState;
import a8k.service.appstate.resource.A8kPublicResourceType;
import a8k.service.appstate.type.TubeHolder;
@ -72,9 +72,9 @@ public class SEQ1_ENTER_TUBEHOLDER_AND_SCAN extends A8kStepAction {
@Resource
AppTubeSettingMgrService appTubeSettingMgrService;
@Resource
AppSampleRecordMgrService appSampleRecordMgrService; //样本管理服务
AppSampleRecordMgrService appSampleRecordMgrService; //样本管理服务
@Resource
AppSampleProcessContextMgrService appSampleProcessContextMgrService;
TubeProcessContextMgrService tubeProcessContextMgrService;
MainFlowCtrlState mfcs;
@ -221,7 +221,7 @@ public class SEQ1_ENTER_TUBEHOLDER_AND_SCAN extends A8kStepAction {
logger.info("将样本信息写入数据库");
appSampleRecordMgrService.addSampleRecord(state.tubes);
appSampleProcessContextMgrService.createNewTubeContexts(state.tubes);
tubeProcessContextMgrService.createNewTubeContexts(state.tubes);
logger.info("更新试管架状态");
@ -238,7 +238,7 @@ public class SEQ1_ENTER_TUBEHOLDER_AND_SCAN extends A8kStepAction {
return cond1 && cond2 && cond3;
}
@Override public List<A8kPublicResourceType> getDeplyResourceList() {
@Override public List<A8kPublicResourceType> getResourceList() {
return List.of(A8kPublicResourceType.SampleTransferXMotor);
}

2
src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ2_SWITCH_TO_THE_NEXT_TUBE.java

@ -137,7 +137,7 @@ public class SEQ2_SWITCH_TO_THE_NEXT_TUBE extends A8kStepAction {
return cond1 && cond2 && cond3;
}
@Override public List<A8kPublicResourceType> getDeplyResourceList() {
@Override public List<A8kPublicResourceType> getResourceList() {
return List.of(A8kPublicResourceType.SampleTransferXMotor);
}
}

221
src/main/java/a8k/service/appdevicectrl/action/mainflow/SEQ3_PRE_PROCESS.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);
}
}
}

2
src/main/java/a8k/service/appdevicectrl/scheduler/MainFlowCtrlScheduler.java

@ -117,7 +117,7 @@ public class MainFlowCtrlScheduler {
for (A8kStepAction action : stepActionList) {
if (action.checkCondition()) {
Boolean relayResourceSuc = appResourceMgrService.applyForResources(this, action.getDeplyResourceList());
Boolean relayResourceSuc = appResourceMgrService.applyForResources(this, action.getResourceList());
if (relayResourceSuc) {
dowhatList.add(action);
}

4
src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/LarBSGroup.java

@ -5,8 +5,8 @@ public class LarBSGroup {
public String projName; //项目名称
public String lotId = ""; //批次号
public String color = ""; //颜色
public Integer num = 0;
public Boolean editable = false;
public Integer num = 0;
public Boolean enable = false;
public LarBSGroup() {
}

8
src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/LittBSGroup.java

@ -4,11 +4,12 @@ public class LittBSGroup {
public Integer projIndex; //项目ID
public String projName; //项目名称
public String lotId = ""; //批次号
public String color = ""; //颜色
public Boolean editable = false;//是否可以被修改
public Integer num = 0;
public String color = ""; //颜色
public Boolean enable = false;//是否可以被修改
public Integer num = 0;
public LittBSGroup() {
enable = false;
}
public LittBSGroup(Integer projIndex, String projName, String lotId, String color, Integer num) {
@ -17,5 +18,6 @@ public class LittBSGroup {
this.lotId = lotId;
this.color = color;
this.num = num;
enable = true;
}
}

6
src/main/java/a8k/service/appdevicectrl/type/app_consumables_mgr_service/ReactionPlateGroup.java

@ -3,9 +3,9 @@ package a8k.service.appdevicectrl.type.app_consumables_mgr_service;
public class ReactionPlateGroup {
public Integer projIndex; //项目ID
public String projName; //项目名称
public String lotId = ""; //批次号
public String color = ""; //颜色
public Boolean editable = false;
public String lotId = ""; //批次号
public String color = ""; //颜色
public Boolean enable = false;
public Integer num = 0;

30
src/main/java/a8k/service/appstate/AppSampleProcessContextMgrService.java → src/main/java/a8k/service/appstate/TubeProcessContextMgrService.java

@ -8,22 +8,30 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class AppSampleProcessContextMgrService {
public class TubeProcessContextMgrService {
List<TubeProcessContext> contexts = new ArrayList<>();
void assignTubeProcessContext(TubeProcessContext cxt, Tube tube) {
cxt.sampleid = tube.sampleid;
cxt.isHighTube = tube.isHighTube;
cxt.isEmergency = tube.isEmergency;
cxt.bloodType = tube.bloodType;
cxt.sampleBarcode = tube.sampleBarcode;
cxt.userid = tube.userid;
cxt.projIndex = tube.projIndex;
cxt.bindConsumablesCh = tube.bindConsumablesCh;
cxt.consumablePos = tube.consumablePos;
cxt.incubatorPos = tube.incubatorPos;
}
synchronized public void createNewTubeContext(Tube tube) {
assert tube != null;
assert !tube.sampleid.isEmpty();
TubeProcessContext context = new TubeProcessContext();
context.sampleid = tube.sampleid;
context.isHighTube = tube.isHighTube;
context.isEmergency = tube.isEmergency;
context.bloodType = tube.bloodType;
context.sampleBarcode = tube.sampleBarcode;
context.userid = tube.userid;
context.projIndex = tube.projIndex;
assignTubeProcessContext(context, tube);
contexts.add(context);
}
@ -42,5 +50,11 @@ public class AppSampleProcessContextMgrService {
return null;
}
synchronized public void updateTubeContext(Tube tube) {
TubeProcessContext context = getTubeContext(tube.sampleid);
if (context != null) {
assignTubeProcessContext(context, tube);
}
}
}

3
src/main/java/a8k/service/appstate/resource/A8kPublicResourceType.java

@ -2,4 +2,7 @@ package a8k.service.appstate.resource;
public enum A8kPublicResourceType {
SampleTransferXMotor,//样本平移电机
IncubationPlateMotor,//孵育盘电机
PlatesBoxMotor,//板夹仓电机
HBOT,//HBOT
}

31
src/main/java/a8k/service/appstate/type/IncubationPlate.java

@ -3,6 +3,8 @@ package a8k.service.appstate.type;
import a8k.service.appstate.type.state.IncubationSubTankState;
import a8k.type.IncubatorPos;
import java.util.List;
public class IncubationPlate {
public IncubationSubTank[] subtanks = new IncubationSubTank[20];
public IncubatorPos incubationPos = IncubatorPos.SPACE01;
@ -13,7 +15,7 @@ public class IncubationPlate {
}
}
public IncubatorPos getEmptyPos() {
synchronized public IncubatorPos getEmptyPos() {
for (IncubationSubTank subtank : subtanks) {
if (subtank.state.equals(IncubationSubTankState.EMPTY)) {
return subtank.pos;
@ -22,7 +24,23 @@ public class IncubationPlate {
return null;
}
public Integer getEmptyPosNum() {
synchronized public List<IncubatorPos> getEmptyPosList(Integer num) {
List<IncubatorPos> ret = new java.util.ArrayList<>();
for (IncubationSubTank subtank : subtanks) {
if (subtank.state.equals(IncubationSubTankState.EMPTY)) {
ret.add(subtank.pos);
if (ret.size() >= num) {
break;
}
}
}
if (ret.size() < num) {
return null;
}
return ret;
}
synchronized public Integer getEmptyPosNum() {
Integer num = 0;
for (IncubationSubTank subtank : subtanks) {
if (subtank.state.equals(IncubationSubTankState.EMPTY)) {
@ -32,5 +50,14 @@ public class IncubationPlate {
return num;
}
synchronized public IncubationSubTank getSubTank(IncubatorPos pos) {
for (IncubationSubTank subtank : subtanks) {
if (subtank.pos.equals(pos)) {
return subtank;
}
}
return null;
}
}

10
src/main/java/a8k/service/appstate/type/Tube.java

@ -1,6 +1,8 @@
package a8k.service.appstate.type;
import a8k.service.appstate.type.state.TubeState;
import a8k.type.ConsumableGroup;
import a8k.type.IncubatorPos;
import a8k.type.type.BloodType;
import java.util.ArrayList;
@ -18,9 +20,9 @@ public class Tube {
public List<Integer> projIndex = new ArrayList<>(); //项目代码
//
public TubeState state = TubeState.EMPTY; //样本被处理的状态
public TubeState state = TubeState.EMPTY; //样本被处理的状态
public List<ConsumableGroup> bindConsumablesCh = new ArrayList<>(); //耗材绑定的通道号
public List<Integer> consumablePos = new ArrayList<>(); //使用的耗材的位置
public List<IncubatorPos> incubatorPos = new ArrayList<>(); //孵育位置
}

14
src/main/java/a8k/service/appstate/type/TubeProcessContext.java

@ -1,5 +1,7 @@
package a8k.service.appstate.type;
import a8k.type.ConsumableGroup;
import a8k.type.IncubatorPos;
import a8k.type.type.BloodType;
import java.util.ArrayList;
@ -11,11 +13,13 @@ public class TubeProcessContext {
public Boolean isHighTube = false;
public Boolean isEmergency = false;
public BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型
public String sampleBarcode = ""; //用于请求用户信息的条码ID
public String userid = ""; //用户输入的样本ID不做逻辑只做展示
public List<Integer> projIndex = new ArrayList<>(); //项目代码
public BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型
public String sampleBarcode = ""; //用于请求用户信息的条码ID
public String userid = ""; //用户输入的样本ID不做逻辑只做展示
public List<Integer> projIndex = new ArrayList<>(); //项目代码
public List<ConsumableGroup> bindConsumablesCh = new ArrayList<>(); //耗材绑定的通道号
public List<Integer> consumablePos = new ArrayList<>(); //耗材索引
public List<IncubatorPos> incubatorPos = new ArrayList<>(); //孵育位置
}

425
src/main/java/a8k/service/devicedriver/ctrl/HbotControlService.java

@ -3,6 +3,9 @@ package a8k.service.devicedriver.ctrl;
import a8k.controler.extapi.pagecontrol.ExtApiTabConfig;
import a8k.hardware.A8kPipetteCtrlModule;
import a8k.hardware.type.regindex.PipetteRegIndex;
import a8k.service.devicedriver.param.PosParam;
import a8k.service.devicedriver.param.TimeParam;
import a8k.type.ConsumableGroup;
import a8k.type.exception.AppException;
import a8k.type.cfg.*;
import a8k.controler.extapi.utils.*;
@ -30,6 +33,12 @@ public class HbotControlService {
@Resource
A8kPipetteCtrlModule pipetteCtrlModule;
@Resource
PosParam pp;
@Resource
TimeParam timep;
Integer ao = 20000;
@ -90,7 +99,6 @@ public class HbotControlService {
}
}
//
// public Integer getGripperZeroYPos() {
// 之所以这样写是因为是为了放置两个类之间的循环依赖
@ -101,268 +109,177 @@ public class HbotControlService {
// return 0;
// }
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 基础控制
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// private void checkPublicArea() throws AppException {
// if (canBus.miniServoReadPos(MId.ShakeModGripperYSV) > getGripperZeroYPos() + 20) {
// logger.error("ShakeModGripperYSV Pos:{} > {}", canBus.miniServoReadPos(MId.ShakeModGripperYSV),
// getGripperZeroYPos() + 20);
// throw new AppException(A8kEcode.ShakeModGripperYSVInXYPublicArea);
// }
// }
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 基础控制
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// /**
// * Hboot 移动
// *
// * @param targetPos 目标位置
// * @throws AppException e
// * @throws InterruptedException e
// */
// public void hbotCheckAndMoveTo(Pos3d targetPos) throws AppException {
// logger.info("hbotCheckAndMoveTo:{}", targetPos);
// if (!canBus.getIOState(IOId.PlateBoxCoverClosurePPS)) {
// throw new AppException(A8kEcode.PlateBoxNotCover);
// }
//
//
// boolean zEnable = true;
// boolean hbotEnable = canBus.moduleGetReg(MId.HbotM, RegIndex.kreg_xyrobot_is_enable) == 1;
//
// if (pipetteCtrlModule.getReg(PipetteRegIndex.kreg_pipette_zm_is_enable) == 0) {
// pipetteCtrlModule.zMotorEnable(1);
// pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
// zEnable = false;
// }
//
// if (!pipetteCtrlModule.zAixsZeroPointIsTrigger()) {
// pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
// }
//
// if (!pipetteCtrlModule.zAixsZeroPointIsTrigger()) {
// throw new AppException(A8kEcode.ZMNotAtZPosWhenHbotTryMove);
// }
// Pos2d nowHbotPos = canBus.hbotReadPos(MId.HbotM);
// HbotLimitArea sampleArea = pp.getSampleCollectionArea();
//
// // 检查采样区域是否有障碍
// // if (sampleArea.checkIsInArea(nowHbotPos) || sampleArea.checkIsInArea(targetPos.getXYPos())) {
// // checkPublicArea();
// // }
//
// // HBot移动
// canBus.hbotEnable(MId.HbotM, 1);
// canBus.hbotMoveToBlock(MId.HbotM, targetPos.x - 20, targetPos.y - 20, timep.getActionOvertime());
// canBus.hbotMoveToBlock(MId.HbotM, targetPos.x, targetPos.y, timep.getActionOvertime());
// canBus.hbotMoveToBlock(MId.HbotM, targetPos.x, targetPos.y, timep.getActionOvertime());
//
// // Z轴移动
// if (targetPos.z != 0) {
// pipetteCtrlModule.zMotorEnable(1);
// pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
// pipetteCtrlModule.zMotorMoveToBlock(targetPos.z);
// }
// pipetteCtrlModule.zMotorEnable(zEnable ? 1 : 0);
// canBus.hbotEnable(MId.HbotM, hbotEnable ? 1 : 0);
// }
//
// public void zMoveTo(Integer z) throws AppException {
// if (z == 0) {
// pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
// } else {
// pipetteCtrlModule.zMotorMoveToBlock(z);
// }
// }
//
// private void hbotCheckAndMoveTo(Pos2d targetPos) throws AppException {
// hbotCheckAndMoveTo(new Pos3d(targetPos.x, targetPos.y, 0));
// }
//
// private void modGroupMoveToZero() throws AppException {
// if (!canBus.getIOState(IOId.PlateBoxCoverClosurePPS)) {
// throw new AppException(A8kEcode.PlateBoxNotCover);
// }
//
// pipetteCtrlModule.zMotorEnable(1);
// canBus.hbotEnable(MId.HbotM, 1);
//
// canBus.hbotMoveToZeroBlock(MId.HbotM, timep.getHbotRuntoZeroActionOvertime());
//
// // 丢弃tip
// Pos3d dropPos = pp.getTipDropPos();
// hbotCheckAndMoveTo(dropPos);
// // TODO: canBus.pipetteCtrlInitDeviceBlock(MId.PipetteMod, timep.getActionOvertime());
//
// // 快速归零
// modGroupMoveToZeroQuick();
// }
//
// private void modGroupMoveToZeroQuick() throws AppException {
// hbotCheckAndMoveTo(new Pos2d(0, 0));
// }
public void zMoveTo(Integer z) throws AppException {
if (z == 0) {
pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
} else {
pipetteCtrlModule.zMotorMoveToBlock(z);
}
}
// // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// // 单步测试
// // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// @ExtApiFn(name = "丢Tip", group = "单步测试")
// public void dropTip() throws AppException {
// Pos3d pos = pp.getTipDropPos();
// hbotMoveTo(pos.x, pos.y);
// zMoveTo(pos.z);
// pipetteCtrlModule.putTipBlock();
// zMoveTo(0);
// }
//
// @ExtApiFn(name = "取Tip", group = "单步测试")
// public AppRet<Boolean> takeTip(Integer groupId, Integer index) throws AppException {
// logger.info("takeTip groupId:{} index:{}", groupId, index);
// if (groupId > 2 || groupId < 0) {
// throw new AppException(A8kEcode.ParamOutOfRange);
// }
//
// if (index > TipPickUpPosInfo.cgetTipNum() || index < 0) {
// throw new AppException(A8kEcode.ParamOutOfRange);
// }
//
// TipPickUpPosInfo tipPos = pp.getTipPickUpPosInfo();
// Pos2d pos = tipPos.getTipPos(groupId, index);
// hbotMoveTo(pos.x, pos.y);
//
// //TODO: 补偿group大于1时z轴需要补偿0.2mm
// Integer zCompensate = 0;
// if (groupId > 1) {
// zCompensate = 2;
// }
//
// pipetteCtrlModule.zMotorMoveToBlock(tipPos.getPickUpZPos(groupId) + zCompensate);
// pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
//
// Boolean isGetTip = canBus.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1;
// if (!isGetTip) {
// logger.error("takeTip fail");
// }
// return AppRet.success(isGetTip);
// }
//
// @ExtApiFn(name = "HBot移动到", group = "单步测试")
// public void hbotMoveTo(Integer x, Integer y) throws AppException {
// hbotCheckAndMoveTo(new Pos2d(x, y));
// }
//
// @ExtApiFn(name = "HBot移动到小瓶缓冲液X孔", group = "单步测试")
// public void hbotMoveToSmallBottleGroup(ConsumableGroup group, Integer Xhole)
// throws AppException {
// BottleGroupsPosInfo posInfo = pp.getBottleBufferPosInfo();
// if (Xhole < 0 || Xhole > BottlesPosInfo.cgetMAX()) {
// throw new AppException(A8kEcode.ParamOutOfRange);
// }
// Pos2d pos = posInfo.cgetSmallBottleBufferPos(group.off, Xhole);
// hbotCheckAndMoveTo(pos);
// }
//
// @ExtApiFn(name = "HBot移动到探测物质X孔", group = "单步测试")
// public void hbotMoveToDetectMaterialPos(ConsumableGroup group, Integer Xhole)
// throws AppException {
// BottleGroupsPosInfo posInfo = pp.getBottleBufferPosInfo();
// if (Xhole < 0 || Xhole > BottlesPosInfo.cgetMAX()) {
// throw new AppException(A8kEcode.ParamOutOfRange);
// }
// Pos2d pos = posInfo.cgetDetectMaterialPos(group.off, Xhole);
// hbotCheckAndMoveTo(pos);
// }
//
// @ExtApiFn(name = "HBot移动到大瓶缓冲液X孔", group = "单步测试")
// public void hbotMoveToLargeBottleGroup(ConsumableGroup ch) throws AppException {
// LargeBottleBufferPos posInfo = pp.getLargeBottleBufferPosInfo();
// Pos2d pos = posInfo.cgetBottlePos(ch.off);
// hbotCheckAndMoveTo(pos);
// }
//
// @ExtApiFn(name = "HBot移动到急诊位", group = "单步测试")
// public void hbotMoveToEmergencyPos() throws AppException {
// hbotCheckAndMoveTo(pp.getEmergencyPos());
// }
private void hbotCheckAndMoveTo(Pos2d targetPos) throws AppException {
hbotMoveTo(new Pos3d(targetPos.x, targetPos.y, 0));
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 坐标获取工具
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// @ExtApiFn(name = "Hbot使能", group = "坐标获取工具")
// public void hBotEnable() throws AppException {
// canBus.hbotEnable(MId.HbotM, 1);
// }
//
// @ExtApiFn(name = "Hbot失能", group = "坐标获取工具")
// public void hBotDisable() throws AppException {
// canBus.hbotEnable(MId.HbotM, 0);
// }
//
// @ExtApiFn(name = "Z轴使能", group = "坐标获取工具")
// public void zAxisEnable() throws AppException {
// pipetteCtrlModule.zMotorEnable(1);
// }
//
// @ExtApiFn(name = "Z轴失能", group = "坐标获取工具")
// public void zAxisDisable() throws AppException {
// pipetteCtrlModule.zMotorEnable(0);
// }
private void modGroupMoveToZero() throws AppException {
if (!canBus.getIOState(IOId.PlateBoxCoverClosurePPS)) {
throw new AppException(A8kEcode.PlateBoxNotCover);
}
pipetteCtrlModule.zMotorEnable(1);
canBus.hbotEnable(MId.HbotM, 1);
canBus.hbotMoveToZeroBlock(MId.HbotM, timep.getHbotRuntoZeroActionOvertime());
// 丢弃tip
Pos3d dropPos = pp.getTipDropPos();
hbotMoveTo(dropPos);
// TODO: canBus.pipetteCtrlInitDeviceBlock(MId.PipetteMod, timep.getActionOvertime());
// 快速归零
modGroupMoveToZeroQuick();
}
private void modGroupMoveToZeroQuick() throws AppException {
hbotCheckAndMoveTo(new Pos2d(0, 0));
}
// @ExtApiFn(name = "归零读取Z轴坐标", group = "坐标获取工具")
// public AppRet<Integer> readZAxisPosByMoveToZero() throws HardwareException {
// return AppRet.success(canBus.stepMotorReadPosByMoveToZeroBlock(MId.PipetteModZM, timep.getActionOvertime()));
// }
//
// @ExtApiFn(name = "打开扫码器", group = "坐标获取工具")
// public void openCodeScaner(Boolean power) throws AppException {
// if (power) {
// canBus.codeScanerStartScan(MId.PipetteModCodeScanner);
// } else {
// canBus.codeScanerStopScan(MId.PipetteModCodeScanner);
// }
// }
//
// Pos2d hbotRefPos = new Pos2d(0, 0);
//
// @ExtApiFn(name = "设置HBOT参考坐标", group = "坐标获取工具")
// public void setHbotRefPos(Integer x, Integer y) throws AppException {
// hbotRefPos.x = x;
// hbotRefPos.y = y;
// }
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// hbot移动到并扫码
// 单步测试
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// private AppRet<String> hBotMoveToAndScan(Pos2d pos) throws AppException {
// hbotCheckAndMoveTo(pos);
// canBus.codeScanerStartScan(MId.PipetteModCodeScanner);
// String result = canBus.codeScanerWaittingForResult(MId.PipetteModCodeScanner, timep.getScancodeOvertime());
// return AppRet.success(result);
// }
//
// // 扫描板夹仓二维码
// @ExtApiFn(name = "扫描板夹仓二维码", group = "扫码")
// public AppRet<String> scanPlatesCode(ConsumableGroup ch) throws AppException {
// var posInfo = pp.getPlates2dCodeScanPosInfo();
// return hBotMoveToAndScan(posInfo.cgetScanPos(ch.off));
// }
//
// // 扫描缓冲液二维码
// @ExtApiFn(name = "扫描缓冲液区二维码", group = "扫码")
// public AppRet<String> scanBottleBuffersCode(ConsumableGroup group) throws AppException {
// BottleGroupsPosInfo posInfo = pp.getBottleBufferPosInfo();
// return hBotMoveToAndScan(posInfo.cgetScanPos(group.ordinal()));
// }
//
// // 扫描大缓冲液二维码
// @ExtApiFn(name = "扫描大缓冲液二维码", group = "扫码")
// public AppRet<String> scanBigBottleBufferCode(ConsumableGroup group)
// throws AppException {
// LargeBottleBufferPos posInfo = pp.getLargeBottleBufferPosInfo();
// return hBotMoveToAndScan(posInfo.cgetScanPos(group.off));
// }
@ExtApiFn(name = "丢Tip", group = "单步测试")
public void dropTip() throws AppException {
Pos3d pos = pp.getTipDropPos();
hbotMoveTo(pos.x, pos.y);
zMoveTo(pos.z);
pipetteCtrlModule.putTipBlock();
zMoveTo(0);
}
@ExtApiFn(name = "取Tip", group = "单步测试")
public Boolean takeTip(Integer groupId, Integer index) throws AppException {
logger.info("takeTip groupId:{} index:{}", groupId, index);
if (groupId > 2 || groupId < 0) {
throw new AppException(A8kEcode.ParamOutOfRange);
}
if (index > TipPickUpPosInfo.cgetTipNum() || index < 0) {
throw new AppException(A8kEcode.ParamOutOfRange);
}
TipPickUpPosInfo tipPos = pp.getTipPickUpPosInfo();
Pos2d pos = tipPos.getTipPos(groupId, index);
hbotMoveTo(pos.x, pos.y);
//TODO: 补偿group大于1时z轴需要补偿0.2mm
Integer zCompensate = 0;
if (groupId > 1) {
zCompensate = 2;
}
pipetteCtrlModule.zMotorMoveToBlock(tipPos.getPickUpZPos(groupId) + zCompensate);
pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock();
Boolean isGetTip = canBus.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1;
if (!isGetTip) {
logger.error("takeTip fail");
}
return isGetTip;
}
@ExtApiFn(name = "HBot移动到", group = "单步测试")
public void hbotMoveTo(Integer x, Integer y) throws AppException {
hbotCheckAndMoveTo(new Pos2d(x, y));
}
@ExtApiFn(name = "HBot移动到小瓶缓冲液X孔", group = "单步测试")
public void hbotMoveToSmallBottleGroup(ConsumableGroup group, Integer Xhole)
throws AppException {
BottleGroupsPosInfo posInfo = pp.getBottleBufferPosInfo();
if (Xhole < 0 || Xhole > BottlesPosInfo.cgetMAX()) {
throw new AppException(A8kEcode.ParamOutOfRange);
}
Pos2d pos = posInfo.cgetSmallBottleBufferPos(group.off, Xhole);
hbotCheckAndMoveTo(pos);
}
@ExtApiFn(name = "HBot移动到探测物质X孔", group = "单步测试")
public void hbotMoveToDetectMaterialPos(ConsumableGroup group, Integer Xhole)
throws AppException {
BottleGroupsPosInfo posInfo = pp.getBottleBufferPosInfo();
if (Xhole < 0 || Xhole > BottlesPosInfo.cgetMAX()) {
throw new AppException(A8kEcode.ParamOutOfRange);
}
Pos2d pos = posInfo.cgetDetectMaterialPos(group.off, Xhole);
hbotCheckAndMoveTo(pos);
}
@ExtApiFn(name = "HBot移动到大瓶缓冲液X孔", group = "单步测试")
public void hbotMoveToLargeBottleGroup(ConsumableGroup ch) throws AppException {
LargeBottleBufferPos posInfo = pp.getLargeBottleBufferPosInfo();
Pos2d pos = posInfo.cgetBottlePos(ch.off);
hbotCheckAndMoveTo(pos);
}
@ExtApiFn(name = "HBot移动到急诊位", group = "单步测试")
public void hbotMoveToEmergencyPos() throws AppException {
hbotMoveTo(pp.getEmergencyPos());
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 坐标获取工具
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@ExtApiFn(name = "Hbot使能", group = "坐标获取工具")
public void hBotEnable() throws AppException {
canBus.hbotEnable(MId.HbotM, 1);
}
@ExtApiFn(name = "Hbot失能", group = "坐标获取工具")
public void hBotDisable() throws AppException {
canBus.hbotEnable(MId.HbotM, 0);
}
@ExtApiFn(name = "Z轴使能", group = "坐标获取工具")
public void zAxisEnable() throws AppException {
pipetteCtrlModule.zMotorEnable(1);
}
@ExtApiFn(name = "Z轴失能", group = "坐标获取工具")
public void zAxisDisable() throws AppException {
pipetteCtrlModule.zMotorEnable(0);
}
@ExtApiFn(name = "归零读取Z轴坐标", group = "坐标获取工具")
public Integer readZAxisPosByMoveToZero() throws AppException {
pipetteCtrlModule.zMotorMeasureDistance();
return pipetteCtrlModule.zMotorReadMeasureDistanceResult();
}
@ExtApiFn(name = "打开扫码器", group = "坐标获取工具")
public void openCodeScaner(Boolean power) throws AppException {
if (power) {
canBus.codeScanerStartScan(MId.PipetteModCodeScanner);
} else {
canBus.codeScanerStopScan(MId.PipetteModCodeScanner);
}
}
Pos2d hbotRefPos = new Pos2d(0, 0);
@ExtApiFn(name = "设置HBOT参考坐标", group = "坐标获取工具")
public void setHbotRefPos(Integer x, Integer y) throws AppException {
hbotRefPos.x = x;
hbotRefPos.y = y;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// hbot取样品

18
src/main/java/a8k/service/devicedriver/ctrl/SamplesPreProcesCtrl.java

@ -153,15 +153,15 @@ public class SamplesPreProcesCtrl {
canBus.miniServoMoveToBlock(MId.ShakeModGripperYSV, pp.getGripperTakeTubeYPos(), timep.getActionOvertime());
//打开夹爪
canBus.miniServoMoveToBlock(MId.ShakeModGripperSV, pp.getGripperOpenPos(), timep.getActionOvertime());
// //Z轴下移动到试管帽有无检测位
// canBus.stepMotorEasyMoveToBlock(MId.ShakeModGripperZM, gripperJudgeCapZPos, timep.getActionOvertime());
//闭合夹爪检测试管帽是否存在
// canBus.miniServoRotateWithTorque(MId.ShakeModGripperSV, -400);
// Thread.sleep(timep.getTubeCapJudgeDelayTime());
// if (ZEQ.IntEq(canBus.miniServoReadPos(MId.ShakeModGripperSV), pp.getGripperClosePos(), 30)) {
// logger.info("试管帽不存在");
// tubeCapExist = false;
// }
// //Z轴下移动到试管帽有无检测位
// canBus.stepMotorEasyMoveToBlock(MId.ShakeModGripperZM, gripperJudgeCapZPos, timep.getActionOvertime());
// 闭合夹爪检测试管帽是否存在
// canBus.miniServoRotateWithTorque(MId.ShakeModGripperSV, -400);
// Thread.sleep(timep.getTubeCapJudgeDelayTime());
// if (ZEQ.IntEq(canBus.miniServoReadPos(MId.ShakeModGripperSV), pp.getGripperClosePos(), 30)) {
// logger.info("试管帽不存在");
// tubeCapExist = false;
// }
if (dp.getDebugMode() || tubeCapExist) {
//打开夹爪
canBus.miniServoMoveToBlock(MId.ShakeModGripperSV, pp.getGripperOpenPos(), timep.getActionOvertime());

6
src/main/java/a8k/type/ConsumableGroup.java

@ -9,4 +9,10 @@ public enum ConsumableGroup {
this.off = this.ordinal();
}
public static ConsumableGroup fromInt(int i) {
if (i < 0 || i >= ConsumableGroup.values().length) {
return null;
}
return ConsumableGroup.values()[i];
}
}

12
src/main/java/a8k/type/ecode/AppCodeError.java

@ -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;
}
}

22
src/main/java/a8k/utils/ZFnCall.java

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