20 changed files with 412 additions and 297 deletions
-
4src/main/java/a8k/baseservice/appeventbus/AppEventBusService.java
-
4src/main/java/a8k/baseservice/appeventbus/appevent/A8kErrorPromptEvent.java
-
15src/main/java/a8k/baseservice/appeventbus/appevent/AppWarningNotifyEvent.java
-
3src/main/java/a8k/controler/extapi/pagecontrol/ExtApiTabConfig.java
-
23src/main/java/a8k/hardware/type/a8kcanprotocol/A8kEcode.java
-
63src/main/java/a8k/service/appctrl/AppContrlService.java
-
26src/main/java/a8k/service/appctrl/AppCtrlExceptionProcesser.java
-
193src/main/java/a8k/service/appctrl/AppCtrlSamplePreProcess.java
-
251src/main/java/a8k/service/appctrl/AppCtrlSampleScanService.java
-
4src/main/java/a8k/service/appctrl/ReactionPlateProcesser.java
-
11src/main/java/a8k/service/appctrl/type/AppCtrlServiceWorkState.java
-
17src/main/java/a8k/service/appstate/A8kState.java
-
1src/main/java/a8k/service/appstate/AppA8kStateService.java
-
59src/main/java/a8k/service/appstate/AppResourceMgrService.java
-
5src/main/java/a8k/service/appstate/resource/A8kPublicResourceType.java
-
5src/main/java/a8k/service/appstate/type/TubeHolderState.java
-
6src/main/java/a8k/service/appstate/type/state/A8kSamplePreProcessState.java
-
7src/main/java/a8k/service/appstate/type/state/A8kWorkState.java
-
11src/main/java/a8k/service/devicectrl/ctrl/SampleScanTransportCtrl.java
-
1src/main/java/a8k/type/exception/AppException.java
@ -1,15 +1,20 @@ |
|||
package a8k.baseservice.appeventbus.appevent; |
|||
|
|||
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|||
|
|||
public class AppWarningNotifyEvent extends AppEvent { |
|||
String displayInfo; |
|||
public Integer errorCode; |
|||
public String errorCodeStr; |
|||
|
|||
AppWarningNotifyEvent(String displayInfo) { |
|||
public AppWarningNotifyEvent(Integer errorCode) { |
|||
super(AppWarningNotifyEvent.class.getSimpleName()); |
|||
this.displayInfo = displayInfo; |
|||
|
|||
this.errorCode = errorCode; |
|||
this.errorCodeStr = A8kEcode.toDisPlayString(errorCode); |
|||
} |
|||
|
|||
public String getDisplayInfo() { |
|||
return displayInfo; |
|||
public AppWarningNotifyEvent(A8kEcode ecode) { |
|||
this(ecode.index); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,63 @@ |
|||
package a8k.service.appctrl; |
|||
|
|||
import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; |
|||
import a8k.controler.extapi.utils.ExtApiFn; |
|||
import a8k.controler.extapi.utils.ExtApiTab; |
|||
import a8k.service.appctrl.type.AppCtrlServiceWorkState; |
|||
import a8k.service.appstate.A8kState; |
|||
import a8k.service.appstate.AppA8kStateService; |
|||
import a8k.service.appstate.type.state.A8kWorkState; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import com.fasterxml.jackson.databind.node.ObjectNode; |
|||
import jakarta.annotation.Resource; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
@ExtApiTab(cfg = ExtApiTabConfig.AppContrlService) |
|||
public class AppContrlService { |
|||
|
|||
@Resource |
|||
AppA8kStateService a8kStateService; |
|||
|
|||
@Resource |
|||
AppCtrlSampleScanService sampleScanService; |
|||
|
|||
|
|||
@ExtApiFn(name = "开始工作") |
|||
public void startWork() { |
|||
A8kState gstate = a8kStateService.getDeviceState(); |
|||
gstate.workState = A8kWorkState.WORKING; |
|||
sampleScanService.setClearErrorPendingFlag(); |
|||
} |
|||
|
|||
@ExtApiFn(name = "停止工作") |
|||
public void stopWork() { |
|||
A8kState gstate = a8kStateService.getDeviceState(); |
|||
gstate.workState = A8kWorkState.IDLE; |
|||
} |
|||
|
|||
@ExtApiFn(name = "暂停工作") |
|||
public void pauseWork() { |
|||
A8kState gstate = a8kStateService.getDeviceState(); |
|||
gstate.workState = A8kWorkState.PAUSE; |
|||
} |
|||
|
|||
@ExtApiFn(name = "继续工作") |
|||
public void continueWork() { |
|||
A8kState gstate = a8kStateService.getDeviceState(); |
|||
gstate.workState = A8kWorkState.WORKING; |
|||
sampleScanService.setClearErrorPendingFlag(); |
|||
} |
|||
|
|||
|
|||
@ExtApiFn(name = "获取设备工作状态") |
|||
public ObjectNode getDeviceWorkState() { |
|||
ObjectMapper mapper = new ObjectMapper(); |
|||
ObjectNode json = new ObjectNode(mapper.getNodeFactory()); |
|||
json.put("sampleScanService", mapper.valueToTree(sampleScanService.getWorkState())); |
|||
json.put("globalWorkState", mapper.valueToTree(a8kStateService.getDeviceState().workState)); |
|||
return json; |
|||
} |
|||
|
|||
|
|||
} |
@ -1,26 +0,0 @@ |
|||
package a8k.service.appctrl; |
|||
|
|||
import a8k.baseservice.appeventbus.AppEventBusService; |
|||
import a8k.baseservice.appeventbus.appevent.A8kErrorPromptEvent; |
|||
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|||
import a8k.type.exception.AppException; |
|||
import a8k.utils.state_machine.AppStateMachine; |
|||
import jakarta.annotation.Resource; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
public class AppCtrlExceptionProcesser { |
|||
|
|||
|
|||
@Resource |
|||
AppEventBusService ebus; |
|||
|
|||
public void processException(AppStateMachine<?> sm, AppException e) { |
|||
if (e.getErrorCode().equals(A8kEcode.InfeedOvertimeFail.index)) { |
|||
sm.selfPause(); |
|||
} else { |
|||
sm.selfStop(); |
|||
} |
|||
ebus.pushEvent(new A8kErrorPromptEvent(e.getErrorCode())); |
|||
} |
|||
} |
@ -1,193 +0,0 @@ |
|||
package a8k.service.appctrl; |
|||
|
|||
import a8k.baseservice.appeventbus.AppEventBusService; |
|||
import a8k.baseservice.appeventbus.appevent.A8kErrorPromptEvent; |
|||
import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; |
|||
import a8k.controler.extapi.utils.ExtApiFn; |
|||
import a8k.controler.extapi.utils.ExtApiTab; |
|||
import a8k.hardware.A8kCanBusService; |
|||
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|||
import a8k.hardware.type.a8kcanprotocol.IOId; |
|||
import a8k.service.appstate.AppA8kStateService; |
|||
import a8k.service.devicectrl.ctrl.SampleScanTransportCtrl; |
|||
import a8k.service.devicectrl.ctrl.SamplesPreProcesCtrl; |
|||
import a8k.type.exception.AppException; |
|||
import a8k.utils.state_machine.AppStateMachine; |
|||
import a8k.utils.state_machine.type.event.*; |
|||
import a8k.utils.state_machine.type.event.base.AppStateMachineEvent; |
|||
import jakarta.annotation.PostConstruct; |
|||
import jakarta.annotation.Resource; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@ExtApiTab(cfg = ExtApiTabConfig.AppCtrlSamplePreProcess) |
|||
@Component |
|||
public class AppCtrlSamplePreProcess { |
|||
static Logger logger = LoggerFactory.getLogger(AppCtrlSamplePreProcess.class); |
|||
|
|||
public enum Step { |
|||
IDLE, //空闲 |
|||
WaitNewTubeHolder, //等待试管架 |
|||
EnterTubeHolder, //进料 |
|||
ScanTubeHolderType,//扫描试管架类型 |
|||
ScanTube,//扫描试管 |
|||
PreProcessTube,//预处理样本 |
|||
DisChargeTubeHolder,//出料 |
|||
} |
|||
|
|||
static class TubesScanResult { |
|||
Boolean isTubeExist = false; |
|||
Boolean isHighTube = false; |
|||
String tubeCode = null; |
|||
|
|||
public String toString() { |
|||
return String.format("isTubeExist:%s,isHighTube:%s,tubeCode:%s", isTubeExist, isHighTube, tubeCode); |
|||
} |
|||
} |
|||
|
|||
; |
|||
|
|||
|
|||
@Resource |
|||
AppA8kStateService sms; |
|||
|
|||
@Resource |
|||
SamplesPreProcesCtrl sppc; |
|||
|
|||
@Resource |
|||
SampleScanTransportCtrl stc; |
|||
|
|||
@Resource |
|||
A8kCanBusService canBus; |
|||
|
|||
|
|||
@Resource |
|||
AppCtrlExceptionProcesser acep; |
|||
|
|||
@Resource |
|||
AppEventBusService ebus; |
|||
|
|||
|
|||
AppStateMachine<Step> sm = new AppStateMachine<>(AppCtrlSamplePreProcess.class.getSimpleName()); |
|||
TubesScanResult[] tubesScanResult = new TubesScanResult[10]; |
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
sm.regIdleStateProcesser(Step.IDLE, this::processIDLE); |
|||
sm.regStateProcesser(Step.WaitNewTubeHolder, this::processWaitNewTubeHolder); |
|||
sm.regStateProcesser(Step.EnterTubeHolder, this::processEnterTubeHolder); |
|||
sm.regStateProcesser(Step.ScanTubeHolderType, this::processScanTubeHolderType); |
|||
sm.regStateProcesser(Step.ScanTube, this::processScanTube); |
|||
sm.regStateProcesser(Step.PreProcessTube, this::processPreProcessTube); |
|||
sm.regStateProcesser(Step.DisChargeTubeHolder, this::processDisChargeTubeHolder); |
|||
sm.startSchedule(); |
|||
} |
|||
|
|||
@ExtApiFn(name = "开始工作") |
|||
public void startWork() throws AppException { |
|||
if (sm.getCurrentState() != Step.IDLE) { |
|||
throw new AppException(A8kEcode.A8kIsNotInIdleState.index); |
|||
} |
|||
assert sm.getCurrentState() == Step.IDLE; |
|||
sm.changeState(Step.WaitNewTubeHolder); |
|||
} |
|||
|
|||
public void pauseWork() { |
|||
sm.usrPause(); |
|||
} |
|||
|
|||
public void continueWork() { |
|||
sm.usrContinueDo(); |
|||
} |
|||
|
|||
public void stopWork() { |
|||
sm.usrStop(); |
|||
} |
|||
|
|||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|||
* PRIV 私有方法 |
|||
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ |
|||
void processIDLE(AppStateMachineEvent event) { |
|||
// doNothing |
|||
} |
|||
|
|||
//等待新的试管架 |
|||
void processWaitNewTubeHolder(AppStateMachineEvent event) { |
|||
if (event instanceof PeriodicSchedulingEvent) { |
|||
try { |
|||
if (canBus.getIOState(IOId.InfeedPPS)) { |
|||
sm.changeState(Step.EnterTubeHolder); |
|||
} |
|||
} catch (AppException ignored) { |
|||
} |
|||
} |
|||
} |
|||
|
|||
//进料 |
|||
void processEnterTubeHolder(AppStateMachineEvent event) throws AppException { |
|||
if (event instanceof StateEnterEvent) { |
|||
Boolean enterSuc = stc.enterTubeHolder(); |
|||
if (enterSuc) { |
|||
sm.changeState(Step.ScanTubeHolderType); |
|||
} else { |
|||
stc.ejectTubeHolderInEnterPos(); |
|||
sm.selfPause(); |
|||
ebus.pushEvent(new A8kErrorPromptEvent(A8kEcode.InfeedOvertimeFail)); |
|||
} |
|||
} else if (event instanceof UsrContinueEvent) { |
|||
sm.changeState(Step.WaitNewTubeHolder); |
|||
} |
|||
} |
|||
|
|||
//扫描试管架类型 |
|||
void processScanTubeHolderType(AppStateMachineEvent event) throws AppException { |
|||
if (event instanceof StateEnterEvent) { |
|||
String result = stc.moveTubeRackToScanPosAndScan(); |
|||
if (result.isEmpty()) { |
|||
logger.warn("扫描试管架类型失败"); |
|||
stc.ejectTubeHolder(); |
|||
ebus.pushEvent(new A8kErrorPromptEvent(A8kEcode.ScanTubeholderTypeTimeout)); |
|||
} |
|||
logger.info("扫描试管架类型成功,{}", result); |
|||
} else if (event instanceof UsrContinueEvent) { |
|||
sm.changeState(Step.WaitNewTubeHolder); |
|||
} |
|||
} |
|||
|
|||
//扫描试管编码,高低试管,试管有无 |
|||
void processScanTube(AppStateMachineEvent event) throws AppException { |
|||
if (event instanceof StateEnterEvent) { |
|||
for (int i = 0; i < tubesScanResult.length; i++) { |
|||
Boolean isTubeExist = stc.moveAndjudgeTubeExist(i); |
|||
if (isTubeExist) { |
|||
tubesScanResult[i].isTubeExist = true; |
|||
tubesScanResult[i].isHighTube = stc.moveAndJudgeTubeAltit(i); |
|||
tubesScanResult[i].tubeCode = stc.moveTubeToScanPosAndScan(i); |
|||
} |
|||
logger.info("扫描试管{}完成,{}", i, tubesScanResult[i]); |
|||
} |
|||
|
|||
Boolean suc = stc.ejectTubeHolder(); |
|||
if (!suc) { |
|||
logger.warn("弹出试管架失败"); |
|||
ebus.pushEvent(new A8kErrorPromptEvent(A8kEcode.EjectTubeholderTimeout)); |
|||
sm.selfPause(); |
|||
} else { |
|||
stc.moveTubeRackMoveToEnterPos(); |
|||
sm.changeState(Step.PreProcessTube); |
|||
} |
|||
} |
|||
|
|||
else if (event instanceof UsrContinueEvent) { |
|||
sm.changeState(Step.WaitNewTubeHolder); |
|||
} |
|||
|
|||
} |
|||
|
|||
void processPreProcessTube(AppStateMachineEvent event) {} |
|||
|
|||
void processDisChargeTubeHolder(AppStateMachineEvent event) {} |
|||
|
|||
|
|||
} |
@ -0,0 +1,11 @@ |
|||
package a8k.service.appctrl.type; |
|||
|
|||
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|||
import a8k.service.appstate.type.state.A8kWorkState; |
|||
|
|||
public class AppCtrlServiceWorkState { |
|||
public A8kWorkState workState = A8kWorkState.IDLE; |
|||
public Boolean errorFlag; |
|||
public Boolean fatalErrorFlag; |
|||
public A8kEcode errorCode; |
|||
} |
@ -0,0 +1,59 @@ |
|||
package a8k.service.appstate; |
|||
|
|||
|
|||
import a8k.service.appstate.resource.A8kPublicResourceType; |
|||
import jakarta.annotation.PostConstruct; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.List; |
|||
import java.util.Vector; |
|||
|
|||
@Component |
|||
public class AppResourceMgrService { |
|||
|
|||
static public class Resource { |
|||
public A8kPublicResourceType type; |
|||
public Boolean state = false; |
|||
public Object ownerNow = null; |
|||
|
|||
public Resource(A8kPublicResourceType type) { |
|||
this.type = type; |
|||
} |
|||
} |
|||
|
|||
List<Resource> resources = new Vector<>(); |
|||
|
|||
@PostConstruct |
|||
public void init() { |
|||
for (A8kPublicResourceType type : A8kPublicResourceType.values()) { |
|||
resources.add(new Resource(type)); |
|||
} |
|||
} |
|||
|
|||
public Boolean applyForResource(Object applyer, A8kPublicResourceType type) { |
|||
for (Resource r : resources) { |
|||
if (r.type == type) { |
|||
if (r.state) { |
|||
return false; |
|||
} |
|||
r.state = true; |
|||
r.ownerNow = applyer; |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public void releaseResource(Object applyer, A8kPublicResourceType type) { |
|||
for (Resource r : resources) { |
|||
if (r.type == type) { |
|||
if (r.ownerNow == applyer) { |
|||
r.state = false; |
|||
r.ownerNow = null; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,5 @@ |
|||
package a8k.service.appstate.resource; |
|||
|
|||
public enum A8kPublicResourceType { |
|||
SampleTransferXMotor,//样本平移电机 |
|||
} |
@ -0,0 +1,6 @@ |
|||
package a8k.service.appstate.type.state; |
|||
|
|||
public enum A8kSamplePreProcessState { |
|||
PROCESSING, |
|||
IDLE, |
|||
} |
@ -0,0 +1,7 @@ |
|||
package a8k.service.appstate.type.state; |
|||
|
|||
public enum A8kWorkState { |
|||
IDLE, |
|||
PAUSE, |
|||
WORKING, |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue