|
|
@ -1,19 +1,20 @@ |
|
|
|
package a8k.app.service.lowerctrl; |
|
|
|
package a8k.app.service.mainctrl; |
|
|
|
|
|
|
|
import a8k.app.hardware.driver.*; |
|
|
|
import a8k.app.hardware.type.*; |
|
|
|
import a8k.app.service.lowerctrl.HbotMoveCtrlService; |
|
|
|
import a8k.app.service.lowerctrl.HbotMoveExCtrlService; |
|
|
|
import a8k.app.service.lowerctrl.TubeFeedingCtrlService; |
|
|
|
import a8k.app.service.lowerctrl.TubePreProcesModuleCtrlService; |
|
|
|
import a8k.app.type.ui.ZAppPromopt; |
|
|
|
import a8k.app.type.ui.ZAppPromoptFormsItem; |
|
|
|
import a8k.app.type.ui.MessageLevel; |
|
|
|
import a8k.app.factory.ZAppPromoptFactory; |
|
|
|
import a8k.app.hardware.channel.A8kCanBusService; |
|
|
|
|
|
|
|
import a8k.app.service.background.AppEventBusService; |
|
|
|
import a8k.app.teststate.VirtualDevice; |
|
|
|
import a8k.app.service.statemgr.GStateMgrService; |
|
|
|
import a8k.app.type.exception.AppException; |
|
|
|
import jakarta.annotation.PostConstruct; |
|
|
|
import lombok.Getter; |
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.springframework.stereotype.Component; |
|
|
@ -24,20 +25,15 @@ import java.util.List; |
|
|
|
@Component |
|
|
|
@Slf4j |
|
|
|
@RequiredArgsConstructor |
|
|
|
public class DeviceMoveToZeroCtrlService { |
|
|
|
|
|
|
|
|
|
|
|
private final PipetteCtrlDriverV2 pipetteCtrlDriverV2; |
|
|
|
|
|
|
|
public class AppDeviceInitCtrlService { |
|
|
|
public static class Checkpoint { |
|
|
|
public enum Type { |
|
|
|
CHECK_TUBE_XCHANNEL_IS_EMPTY,//入料通道是否为空 |
|
|
|
CHECK_TUBE_X_CHANNEL_IS_EMPTY,//入料通道是否为空 |
|
|
|
CHECK_PLATE_BOX_IS_COVER,//板夹仓盖子是否盖着 |
|
|
|
CHECK_PLATE_STUCK_DETECTOR_SENSOR1_IS_TRIGGER,//板夹仓卡板检测 |
|
|
|
CHECK_PLATE_STUCK_DETECTOR_SENSOR2_IS_TRIGGER,//板夹仓卡板检测 |
|
|
|
|
|
|
|
CHECK_PULLERM_IS_IN_ZEROPOS,//检查拉杆电机是否在零点位置 |
|
|
|
CHECK_PUSHERM_IN_IN_ZEROPOS,//检查推杆电机是否在零点位置 |
|
|
|
CHECK_PULLER_MOTOR_IS_IN_ZERO_POS,//检查拉杆电机是否在零点位置 |
|
|
|
CHECK_PUSHER_MOTOR_IN_IN_ZERO_POS,//检查推杆电机是否在零点位置 |
|
|
|
CHECK_RECYCLE_BIN_IS_OVERFLOW,//检查垃圾箱是否满 |
|
|
|
} |
|
|
|
|
|
|
@ -65,99 +61,170 @@ public class DeviceMoveToZeroCtrlService { |
|
|
|
} |
|
|
|
|
|
|
|
public static class State { |
|
|
|
public Boolean deviceInited = false; |
|
|
|
public Boolean isBusy = false; |
|
|
|
public Boolean passed = false; |
|
|
|
public ZAppPromopt promopt; |
|
|
|
public Boolean deviceInited = false; //设备是否已经被初始化 |
|
|
|
public Boolean isBusy = false; //是否正在初始化 |
|
|
|
public Boolean passed = false; //设备自检是否通过 |
|
|
|
public ZAppPromopt promopt; //设备初始化报告 |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private final GStateMgrService gstate; |
|
|
|
|
|
|
|
private final VirtualDevice virtualDevice; |
|
|
|
private final AppEventBusService appEventBusService; |
|
|
|
|
|
|
|
private final GStateMgrService gstate; |
|
|
|
private final VirtualDevice virtualDevice; |
|
|
|
// |
|
|
|
// Driver |
|
|
|
// |
|
|
|
|
|
|
|
private final A8kCanBusService canBus; |
|
|
|
private final InputDetectDriver inputDetectDriver; |
|
|
|
private final MiniServoDriver miniServoDriver; |
|
|
|
private final StepMotorCtrlDriver stepMotorCtrlDriver; |
|
|
|
private final PipetteCtrlDriverV2 pipetteCtrlDriver; |
|
|
|
|
|
|
|
|
|
|
|
// |
|
|
|
// ExDriver |
|
|
|
// |
|
|
|
|
|
|
|
private final ModuleEnableCtrlDriver moduleEnableCtrlDriver; |
|
|
|
private final InputDetectDriver inputDetectDriver; |
|
|
|
private final MiniServoDriver miniServoDriver; |
|
|
|
private final StepMotorCtrlDriver stepMotorCtrlDriver; |
|
|
|
private final PipetteCtrlDriverV2 pipetteCtrlDriverV2; |
|
|
|
private final ModuleEnableCtrlDriver moduleEnableCtrlDriver; |
|
|
|
// |
|
|
|
// Service |
|
|
|
// |
|
|
|
|
|
|
|
private final TubeFeedingCtrlService tubeFeedingCtrlService; |
|
|
|
private final TubePreProcesModuleCtrlService tubePreProcesModuleCtrlService; |
|
|
|
private final HbotMoveExCtrlService hbotMoveExCtrlService; |
|
|
|
private final HbotMoveCtrlService hbotMoveCtrlService; |
|
|
|
|
|
|
|
|
|
|
|
private final HbotMoveCtrlService hbotMoveCtrlService; |
|
|
|
|
|
|
|
List<Checkpoint> checkPoints = new ArrayList<>(); |
|
|
|
|
|
|
|
private final List<Checkpoint> checkPoints = new ArrayList<>(); |
|
|
|
private final State state = new State(); |
|
|
|
private Thread workThread; |
|
|
|
public List<CheckResult> checkResults; |
|
|
|
|
|
|
|
Thread workThread; |
|
|
|
@Getter |
|
|
|
State state = new State(); |
|
|
|
public List<CheckResult> checkResults; |
|
|
|
|
|
|
|
|
|
|
|
@PostConstruct |
|
|
|
void init() { |
|
|
|
// checkPoints.add(new Checkpoint("检查入料通道是否为空",// |
|
|
|
// CheckPointType.CHECK_TUBE_XCHANNEL_IS_EMPTY, () -> !inputDetectDriver.getIOState(InputIOId.THChInterPPS) && !inputDetectDriver.getIOState(InputIOId.THChOuterPPS))); |
|
|
|
checkPoints.add(new Checkpoint("检查板夹仓盖子是否盖上",// |
|
|
|
Checkpoint.Type.CHECK_PLATE_BOX_IS_COVER, () -> inputDetectDriver.getIOState(InputIOId.PlateBoxCoverClosurePPS))); |
|
|
|
checkPoints.add(new Checkpoint("检测孵育盘入口是否卡板",// |
|
|
|
Checkpoint.Type.CHECK_PLATE_STUCK_DETECTOR_SENSOR1_IS_TRIGGER, () -> !inputDetectDriver.getIOState(InputIOId.IncubationPlateInletStuckPPS))); |
|
|
|
checkPoints.add(new Checkpoint("检测孵育盘出口是否卡板",// |
|
|
|
Checkpoint.Type.CHECK_PLATE_STUCK_DETECTOR_SENSOR2_IS_TRIGGER, () -> !inputDetectDriver.getIOState(InputIOId.IncubationPlateOutletStuckPPS))); |
|
|
|
// checkPoints.add(new Checkpoint("检查拉杆电机是否在零点位置",// |
|
|
|
// CheckPointType.CHECK_PULLERM_IS_IN_ZEROPOS, () -> inputDetectDriver.getIOState(InputIOId.PullerMZeroPPS))); |
|
|
|
// checkPoints.add(new Checkpoint("检查推杆电机是否在零点位置",// |
|
|
|
// CheckPointType.CHECK_PUSHERM_IN_IN_ZEROPOS, () -> inputDetectDriver.getIOState(InputIOId.PusherMZeroPPS))); |
|
|
|
|
|
|
|
synchronized public State getState() { |
|
|
|
return state; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 使能所有电机 |
|
|
|
* @throws AppException e |
|
|
|
*/ |
|
|
|
public void enableAllMotor() throws AppException { |
|
|
|
moduleEnableCtrlDriver.enableAllMotor(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 失能所有电机 |
|
|
|
* @throws AppException e |
|
|
|
*/ |
|
|
|
public void disableAllMotor() throws AppException { |
|
|
|
moduleEnableCtrlDriver.forceDisableAllMotor(); |
|
|
|
} |
|
|
|
|
|
|
|
// disableAllMiniServo |
|
|
|
//enableAllMiniServo |
|
|
|
|
|
|
|
/** |
|
|
|
* 失能所有舵机 |
|
|
|
* @throws AppException e |
|
|
|
*/ |
|
|
|
public void disableAllMiniServo() throws AppException { |
|
|
|
for (MiniServoMId miniServoMId : MiniServoMId.values()) { |
|
|
|
miniServoDriver.miniServoEnable(miniServoMId, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 使能所有舵机 |
|
|
|
* @throws AppException e |
|
|
|
*/ |
|
|
|
public void enableAllMiniServo() throws AppException { |
|
|
|
for (MiniServoMId miniServoMId : MiniServoMId.values()) { |
|
|
|
miniServoDriver.miniServoEnable(miniServoMId, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void moveAllMotorToZero() throws AppException { |
|
|
|
|
|
|
|
/** |
|
|
|
* 设备初始化(同步操作) |
|
|
|
* @return 设备自检结果 |
|
|
|
* @throws AppException e |
|
|
|
*/ |
|
|
|
synchronized public List<CheckResult> initDevice() throws AppException { |
|
|
|
try { |
|
|
|
return doDeviceMoveToZero(); |
|
|
|
} catch (AppException e) { |
|
|
|
throw e; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 设备初始化(异步操作) |
|
|
|
* @throws AppException e |
|
|
|
*/ |
|
|
|
synchronized public void initDeviceAsync() throws AppException { |
|
|
|
if (workThread != null && workThread.isAlive()) { |
|
|
|
throw AppException.ofAECodeError("设备正在初始化中"); |
|
|
|
} |
|
|
|
if (!gstate.getBoardParamInited()) { |
|
|
|
throw AppException.of(A8kEcode.DEVICE_STARTUP_IN_PROGRESS); |
|
|
|
} |
|
|
|
if (workThread != null) { |
|
|
|
try { |
|
|
|
workThread.join(); |
|
|
|
} catch (InterruptedException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} |
|
|
|
} |
|
|
|
workThread = new Thread(() -> { |
|
|
|
log.info("设备初始化开始"); |
|
|
|
state.isBusy = true; |
|
|
|
state.passed = false; |
|
|
|
state.deviceInited = false; |
|
|
|
try { |
|
|
|
checkResults = initDevice(); |
|
|
|
for (CheckResult checkResult : checkResults) { |
|
|
|
if (!checkResult.pass) { |
|
|
|
throw AppException.of(A8kEcode.APPE_DEVICE_INIT_CHECK_FAIL); |
|
|
|
} |
|
|
|
} |
|
|
|
state.passed = true; |
|
|
|
state.deviceInited = true; |
|
|
|
state.promopt = ZAppPromoptFactory.buildNotifyPromopt("设备初始化成功"); |
|
|
|
|
|
|
|
} catch (AppException e) { |
|
|
|
state.passed = false; |
|
|
|
state.deviceInited = false; |
|
|
|
if (e.getError().code.equals(A8kEcode.APPE_DEVICE_INIT_CHECK_FAIL)) { |
|
|
|
state.promopt = buildAppPromopt(checkResults); |
|
|
|
} else { |
|
|
|
state.promopt = ZAppPromoptFactory.buildAppPromopt(e); |
|
|
|
} |
|
|
|
} |
|
|
|
state.isBusy = false; |
|
|
|
log.info("设备初始化结束"); |
|
|
|
}); |
|
|
|
workThread.start(); |
|
|
|
} |
|
|
|
|
|
|
|
//****************************************************************************************** |
|
|
|
// PRIVATE |
|
|
|
//****************************************************************************************** |
|
|
|
|
|
|
|
|
|
|
|
@PostConstruct |
|
|
|
private void init() { |
|
|
|
// checkPoints.add(new Checkpoint("检查入料通道是否为空",// |
|
|
|
// CheckPointType.CHECK_TUBE_XCHANNEL_IS_EMPTY, () -> !inputDetectDriver.getIOState(InputIOId.THChInterPPS) && !inputDetectDriver.getIOState(InputIOId.THChOuterPPS))); |
|
|
|
checkPoints.add(new Checkpoint("检查板夹仓盖子是否盖上",// |
|
|
|
Checkpoint.Type.CHECK_PLATE_BOX_IS_COVER, () -> inputDetectDriver.getIOState(InputIOId.PlateBoxCoverClosurePPS))); |
|
|
|
checkPoints.add(new Checkpoint("检测孵育盘入口是否卡板",// |
|
|
|
Checkpoint.Type.CHECK_PLATE_STUCK_DETECTOR_SENSOR1_IS_TRIGGER, () -> !inputDetectDriver.getIOState(InputIOId.IncubationPlateInletStuckPPS))); |
|
|
|
checkPoints.add(new Checkpoint("检测孵育盘出口是否卡板",// |
|
|
|
Checkpoint.Type.CHECK_PLATE_STUCK_DETECTOR_SENSOR2_IS_TRIGGER, () -> !inputDetectDriver.getIOState(InputIOId.IncubationPlateOutletStuckPPS))); |
|
|
|
// checkPoints.add(new Checkpoint("检查拉杆电机是否在零点位置",// |
|
|
|
// CheckPointType.CHECK_PULLERM_IS_IN_ZEROPOS, () -> inputDetectDriver.getIOState(InputIOId.PullerMZeroPPS))); |
|
|
|
// checkPoints.add(new Checkpoint("检查推杆电机是否在零点位置",// |
|
|
|
// CheckPointType.CHECK_PUSHERM_IN_IN_ZEROPOS, () -> inputDetectDriver.getIOState(InputIOId.PusherMZeroPPS))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void moveAllMotorToZero() throws AppException { |
|
|
|
moduleEnableCtrlDriver.enableAllMotor(); |
|
|
|
try { |
|
|
|
log.info("HbotZ轴回零"); |
|
|
|
pipetteCtrlDriver.zMotorMoveZeroBlock(); |
|
|
|
pipetteCtrlDriverV2.zMotorMoveZeroBlock(); |
|
|
|
log.info("HBot回零"); |
|
|
|
hbotMoveCtrlService.moveToZero(); |
|
|
|
//进出料初始化 |
|
|
@ -206,16 +273,8 @@ public class DeviceMoveToZeroCtrlService { |
|
|
|
}//HBot初始化 |
|
|
|
} |
|
|
|
|
|
|
|
Boolean firstInit = true; |
|
|
|
|
|
|
|
void doSomeThingWhenError() throws AppException { |
|
|
|
stepMotorCtrlDriver.stepMotorEnable(StepMotorMId.ShakeModClampingM, 1); |
|
|
|
stepMotorCtrlDriver.stepMotorEasyMoveByBlock(StepMotorMId.ShakeModClampingM, 5); |
|
|
|
moduleEnableCtrlDriver.forceDisableAllMotor(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<CheckResult> doDeviceMoveToZero() throws AppException { |
|
|
|
private List<CheckResult> doDeviceMoveToZero() throws AppException { |
|
|
|
|
|
|
|
List<CheckResult> results = checkBeforeInitDevice(); |
|
|
|
if (virtualDevice.isEnable()) { |
|
|
@ -234,11 +293,6 @@ public class DeviceMoveToZeroCtrlService { |
|
|
|
|
|
|
|
moveAllMotorToZero(); |
|
|
|
|
|
|
|
|
|
|
|
//弹出无效物料 |
|
|
|
if (firstInit) { |
|
|
|
firstInit = false; |
|
|
|
} |
|
|
|
//弹出试管架 |
|
|
|
tubeFeedingCtrlService.ejectTubeHolder(); |
|
|
|
tubeFeedingCtrlService.moveTubeRackMoveToEnterPos(); |
|
|
@ -256,78 +310,6 @@ public class DeviceMoveToZeroCtrlService { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
synchronized public List<CheckResult> initDevice() throws AppException { |
|
|
|
try { |
|
|
|
return doDeviceMoveToZero(); |
|
|
|
} catch (AppException e) { |
|
|
|
//释放试管夹爪 |
|
|
|
// doSomeThingWhenError(); |
|
|
|
throw e; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
synchronized public void initDeviceWithException() throws AppException { |
|
|
|
List<CheckResult> results = initDevice(); |
|
|
|
for (CheckResult result : results) { |
|
|
|
if (!result.pass) { |
|
|
|
throw AppException.ofAECodeError("设备初始化失败: check " + result.info + " fail"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
synchronized public State getState() { |
|
|
|
return state; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
synchronized public void initDeviceAsync() throws AppException { |
|
|
|
if (workThread != null && workThread.isAlive()) { |
|
|
|
throw AppException.ofAECodeError("设备正在初始化中"); |
|
|
|
} |
|
|
|
if (!gstate.getBoardParamInited()) { |
|
|
|
throw AppException.of(A8kEcode.DEVICE_STARTUP_IN_PROGRESS); |
|
|
|
} |
|
|
|
if (workThread != null) { |
|
|
|
try { |
|
|
|
workThread.join(); |
|
|
|
} catch (InterruptedException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} |
|
|
|
} |
|
|
|
workThread = new Thread(() -> { |
|
|
|
log.info("设备初始化开始"); |
|
|
|
state.isBusy = true; |
|
|
|
state.passed = false; |
|
|
|
state.deviceInited = false; |
|
|
|
try { |
|
|
|
checkResults = initDevice(); |
|
|
|
for (CheckResult checkResult : checkResults) { |
|
|
|
if (!checkResult.pass) { |
|
|
|
throw AppException.of(A8kEcode.APPE_DEVICE_INIT_CHECK_FAIL); |
|
|
|
} |
|
|
|
} |
|
|
|
state.passed = true; |
|
|
|
state.deviceInited = true; |
|
|
|
state.promopt = ZAppPromoptFactory.buildNotifyPromopt("设备初始化成功"); |
|
|
|
|
|
|
|
} catch (AppException e) { |
|
|
|
state.passed = false; |
|
|
|
state.deviceInited = false; |
|
|
|
if (e.getError().code.equals(A8kEcode.APPE_DEVICE_INIT_CHECK_FAIL)) { |
|
|
|
state.promopt = buildAppPromopt(checkResults); |
|
|
|
} else { |
|
|
|
state.promopt = ZAppPromoptFactory.buildAppPromopt(e); |
|
|
|
} |
|
|
|
} |
|
|
|
state.isBusy = false; |
|
|
|
log.info("设备初始化结束"); |
|
|
|
}); |
|
|
|
workThread.start(); |
|
|
|
} |
|
|
|
|
|
|
|
private static ZAppPromopt buildAppPromopt(List<CheckResult> checkResults) { |
|
|
|
|
|
|
|
List<ZAppPromoptFormsItem> detailInfos = new ArrayList<>(); |