28 changed files with 763 additions and 285 deletions
-
241doc/代码框架.md
-
3src/main/java/a8k/controler/extapi/pagecontrol/ExtApiTabConfig.java
-
7src/main/java/a8k/optalgo/OptAlgo.java
-
9src/main/java/a8k/optalgo/type/OptAlgoError.java
-
14src/main/java/a8k/optalgo/type/OptAlgoResult.java
-
11src/main/java/a8k/optalgo/type/PeakInfo.java
-
31src/main/java/a8k/service/app/AppA8kDeviceStateMgrService.java
-
3src/main/java/a8k/service/app/AppConsumablesMgrService.java
-
3src/main/java/a8k/service/app/AppDeviceInitializationModule.java
-
4src/main/java/a8k/service/app/AppSampleFormulaMgrService.java
-
105src/main/java/a8k/service/appctrl/AppCoreCtrlService.java
-
89src/main/java/a8k/service/appctrl/AppRunTask.java
-
28src/main/java/a8k/service/appstate/A8kState.java
-
6src/main/java/a8k/service/appstate/type/EmergencyPosRunState.java
-
5src/main/java/a8k/service/appstate/type/IncubationPlateStatus.java
-
7src/main/java/a8k/service/appstate/type/ReactingPlateState.java
-
4src/main/java/a8k/service/appstate/type/SampleState.java
-
16src/main/java/a8k/service/appstate/type/TubeHolderState.java
-
26src/main/java/a8k/service/bak_appbase/A8kDeviceState.java
-
6src/main/java/a8k/service/bak_appbase/progress/TubeHolderProgress.java
-
20src/main/java/a8k/service/bak_appbase/runstate/TubeHolderRunState.java
-
4src/main/java/a8k/type/exception/ActionBreakException.java
-
4src/main/java/a8k/type/exception/AppPauseException.java
@ -0,0 +1,241 @@ |
|||
/* |
|||
* |
|||
* while(!isWaitingForStop()){ |
|||
* if(当前样本处理完成){ |
|||
* if(入料口有样本){ |
|||
* 扫描样本 && 判断耗材是否充足 |
|||
* 如果耗材不足, |
|||
* 提示用户(抛出提示事件), |
|||
* 暂停设备(退出线程(抛出pause异常)) |
|||
* 如果扫描样本有误 |
|||
* 提示用户 |
|||
* 暂停设备 |
|||
* } |
|||
* } |
|||
* else{ |
|||
* 处理样本 |
|||
* } |
|||
* } |
|||
* |
|||
* try{ |
|||
* |
|||
* }catch(PauseException e){ |
|||
* //pauseSelf |
|||
* //抛出事件 |
|||
* } |
|||
* |
|||
* if(event){ |
|||
* pauseSampleProcessThread(); |
|||
* } |
|||
* |
|||
*/ |
|||
|
|||
|
|||
经验: |
|||
动作与赋值分开 |
|||
当一组动作完全执行完之后,再赋值给状态,这样就可以使得动作在执行过程中任意时间点都可以被打断。 |
|||
|
|||
|
|||
while(true){ |
|||
TubeCfg cfg = getTubeCfg(i); |
|||
moveTubeHolderProcessPos |
|||
if(tubeType == xxx) |
|||
takeTube |
|||
shakeTube(times,degree) |
|||
takeHap |
|||
move |
|||
else if(){ |
|||
... |
|||
|
|||
} |
|||
pausePoint; |
|||
} |
|||
|
|||
问题: |
|||
有两种暂停状态: |
|||
一种是复位势暂停。 |
|||
一种是保持现状势暂停。(前提是循环中) |
|||
|
|||
pause/stop |
|||
|
|||
|
|||
动作划分为状态机 |
|||
scan{ |
|||
. |
|||
. |
|||
. |
|||
. |
|||
} |
|||
|
|||
|
|||
状态机->enter |
|||
状态机->enter |
|||
|
|||
|
|||
{ |
|||
IDLE |
|||
{ |
|||
if(state.eq(wokring)){ |
|||
state.changeTo(scanPrepare) |
|||
} |
|||
|
|||
} |
|||
|
|||
SCANPREPARE |
|||
{ |
|||
enterState |
|||
exitState |
|||
|
|||
if(ioTrigger){ |
|||
moveTubeHolderTo |
|||
waitForIoTrigger |
|||
changeStateTo(scanTubeHolderType) |
|||
if(error){ |
|||
changeStateToError |
|||
} |
|||
} |
|||
} |
|||
SCANHODLER |
|||
{ |
|||
move |
|||
scan |
|||
|
|||
|
|||
|
|||
} |
|||
SCAN |
|||
|
|||
PAUSE |
|||
{ |
|||
|
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
``` |
|||
用户PAUSE --> 暂停,恢复,全局状态的变更。 |
|||
遇到错误 --> 通知,记录,清空工作位。无需恢复。 |
|||
状态机 --> |
|||
修改全局状态。 |
|||
记录。 |
|||
执行动作。 |
|||
|
|||
|
|||
|
|||
前端接口: |
|||
pause; |
|||
continue; |
|||
|
|||
|
|||
全局都有哪些状态? |
|||
1. 类似于配置, |
|||
初始化 |
|||
运行过程中修改(前端提交) |
|||
|
|||
2. 运行过程控制,记录当前设备运行到哪一步,以便执行下一步。 |
|||
|
|||
|
|||
步骤与暂停之间的关系。 |
|||
步骤与恢复? |
|||
|
|||
|
|||
步骤与停止之间的关系。 |
|||
|
|||
步骤 |
|||
步骤 |
|||
步骤 |
|||
步骤 |
|||
步骤 |
|||
暂停 |
|||
步骤 |
|||
|
|||
---------------------------------------------- |
|||
每一步都有几种处理方法 |
|||
1. firstEnter |
|||
checkCondition是否满足 |
|||
2. finalExit |
|||
3. loop |
|||
4. pause |
|||
5. continue |
|||
|
|||
waitting_for_take_sample |
|||
|
|||
pause |
|||
stepPause; |
|||
stepContinue; |
|||
|
|||
stop |
|||
|
|||
|
|||
协作? |
|||
全局状态 |
|||
|
|||
|
|||
|
|||
{ |
|||
|
|||
take_tip |
|||
take_xxx |
|||
put_xxx |
|||
waitting_for |
|||
onPause{ |
|||
.... |
|||
} |
|||
onStop{ |
|||
... |
|||
} |
|||
|
|||
pauseCondtion{ |
|||
... |
|||
} |
|||
} |
|||
|
|||
{ |
|||
pause... |
|||
} |
|||
|
|||
pause_point |
|||
|
|||
``` |
|||
|
|||
|
|||
``` |
|||
服务的提供者, |
|||
服务的使用者, |
|||
|
|||
相互配合呢? |
|||
|
|||
triggerHasTakeSample |
|||
doNext |
|||
|
|||
|
|||
---处理--- |
|||
| | |
|||
| --搬运--(等待) |
|||
| | |
|||
扫描与预处理(等待) 抛出事件。 |
|||
|
|||
|
|||
机械臂 |
|||
takeSampleEnd |
|||
|
|||
---------------------------- |
|||
暂停: |
|||
waitingForPause,不需要弹出,只有单次循环结束 |
|||
停止: |
|||
break? |
|||
异常: |
|||
exception? |
|||
|
|||
|
|||
第一假如需要允许暂停,则需要将步骤进行拆分,暂停点作为一步。 |
|||
|
|||
|
|||
机械动作的暂停,涉及到,暂停和暂停恢复,不能简单的在代码中添加一个pause就可以的。 |
|||
|
|||
|
|||
|
|||
|
|||
``` |
@ -0,0 +1,7 @@ |
|||
package a8k.optalgo; |
|||
|
|||
public class OptAlgo { |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,9 @@ |
|||
package a8k.optalgo.type; |
|||
|
|||
public enum OptAlgoError { |
|||
Success, |
|||
LostPeak, |
|||
LostPeakStart, |
|||
LostPeakEnd, |
|||
} |
|||
|
@ -0,0 +1,14 @@ |
|||
package a8k.optalgo.type; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class OptAlgoResult { |
|||
// vector<float> ogigin_val; // 1200 |
|||
// vector<float> supper_val; // 原始数据,线性填充,1200*5=6000 |
|||
// vector<float> supper_median_val; // supper_val 窗口平滑滤波,6000 |
|||
// vector<float> supper_smooth_sub_val; // supper_smooth_val 均值压缩,6000/6=1000 |
|||
public Float[] ogiginVal; |
|||
public Float[] supperVal; |
|||
public Float[] supperMedianVal; |
|||
public Float[] supperSmoothSubVal; |
|||
} |
@ -0,0 +1,11 @@ |
|||
package a8k.optalgo.type; |
|||
|
|||
public class PeakInfo { |
|||
public Boolean findPeak; |
|||
public Float peakFullArea; |
|||
public Float peakBaseLineArea; |
|||
public Float area; |
|||
public Integer peakPos; |
|||
public Integer peakStartPos; |
|||
public Integer peakEndPos; |
|||
} |
@ -0,0 +1,105 @@ |
|||
package a8k.service.appctrl; |
|||
|
|||
import a8k.controler.extapi.pagecontrol.ExtApiTabConfig; |
|||
import a8k.controler.extapi.utils.ExtApiTab; |
|||
import a8k.service.app.AppA8kDeviceStateMgrService; |
|||
import a8k.service.bak_appbase.progress.TubeHolderProgress; |
|||
import jakarta.annotation.PostConstruct; |
|||
import jakarta.annotation.Resource; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@ExtApiTab(cfg = ExtApiTabConfig.AppCoreCtrlService) |
|||
@Component |
|||
public class AppCoreCtrlService { |
|||
|
|||
@Resource |
|||
AppA8kDeviceStateMgrService sms; |
|||
|
|||
AppRunTask sampleScanAndPreProcessThread; |
|||
AppRunTask sampleProcessThread; |
|||
AppRunTask incubationPlateCtrlThread; |
|||
AppRunTask plateClampResultScanThread; |
|||
|
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
sampleScanAndPreProcessThread = new AppRunTask(); |
|||
sampleProcessThread = new AppRunTask(); |
|||
incubationPlateCtrlThread = new AppRunTask(); |
|||
plateClampResultScanThread = new AppRunTask(); |
|||
|
|||
sampleScanAndPreProcessThread.init(this::sampleScanAndPreProcessThreadWorkFn); |
|||
|
|||
} |
|||
|
|||
public void startWork() { |
|||
//启动所有线程 |
|||
// setGState,notify |
|||
} |
|||
|
|||
public void pauseWork() { |
|||
//暂停掉 入料和样本处理线程 |
|||
// setGstate,notify |
|||
// waitForStop |
|||
// waitForStop |
|||
// |
|||
} |
|||
|
|||
public void continueWork() { |
|||
//继续入料和样本处理线程 |
|||
//setGState |
|||
//notify |
|||
} |
|||
|
|||
public void stopWork() { |
|||
//停止所有线程 |
|||
//setGState |
|||
//notify |
|||
//waitForStop |
|||
} |
|||
|
|||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|||
* PRIV 私有方法 |
|||
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ |
|||
|
|||
private void doSampleScanAndPreProcessThreadWorkFn() { |
|||
AppRunTask appRunTask = sampleScanAndPreProcessThread; |
|||
while (!appRunTask.isWaitingForStop()) { |
|||
//试管架处理状态-空闲 |
|||
if (sms.getTubeHolderProgress().equals(TubeHolderProgress.Idle)) { |
|||
} else if (sms.getTubeHolderProgress().equals(TubeHolderProgress.Processing)) { |
|||
} else if (sms.getTubeHolderProgress().equals(TubeHolderProgress.Scaning)) { |
|||
} |
|||
} |
|||
/* |
|||
* |
|||
* motorRun |
|||
* waitForTrigger |
|||
* scanTubeHolderType |
|||
* pausePoint() |
|||
* for(int i < 6){ |
|||
* scanTubeAndAssignTubeCfg; |
|||
* pausePoint(){throw PauseException;} |
|||
* } |
|||
* assignTubeCfg(); |
|||
* |
|||
* 用户暂停 |
|||
* 程序出错主动暂停 |
|||
* |
|||
* // pause |
|||
* |
|||
*/ |
|||
|
|||
|
|||
} |
|||
|
|||
private void sampleScanAndPreProcessThreadWorkFn() { |
|||
try { |
|||
doSampleScanAndPreProcessThreadWorkFn(); |
|||
} catch (Exception ignored) { |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,89 @@ |
|||
package a8k.service.appctrl; |
|||
|
|||
|
|||
public class AppRunTask { |
|||
|
|||
Thread workThread; |
|||
Runnable task; |
|||
|
|||
Boolean ctrlState = false; |
|||
Boolean runState = false; |
|||
|
|||
public AppRunTask() { |
|||
|
|||
} |
|||
|
|||
public void init(Runnable task) { |
|||
this.task = task; |
|||
this.workThread = new Thread(this::work); |
|||
this.workThread.start(); |
|||
} |
|||
|
|||
|
|||
private void work() { |
|||
while (true) { |
|||
if (ctrlState) { |
|||
runState = true; |
|||
if (task != null) |
|||
task.run(); |
|||
runState = false; |
|||
} else { |
|||
sleep(500); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Boolean isWaitingForStop() { |
|||
return !ctrlState; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 启动线程 |
|||
*/ |
|||
public void start() { |
|||
ctrlState = true; |
|||
this.task.notify(); |
|||
} |
|||
|
|||
/** |
|||
* 停止线程 |
|||
*/ |
|||
public void stop() { |
|||
ctrlState = false; |
|||
} |
|||
|
|||
/** |
|||
* 等待线程停止 |
|||
*/ |
|||
public void waitForStop() { |
|||
while (runState) { |
|||
sleep(10); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 睡眠 |
|||
* @param mills 毫秒 |
|||
*/ |
|||
public void sleep(Integer mills) { |
|||
try { |
|||
Thread.sleep(mills); |
|||
} catch (InterruptedException ignored) { |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 强制睡眠,不会被打断 |
|||
* @param mills 毫秒 |
|||
*/ |
|||
public void forceSleep(Integer mills) { |
|||
int end = mills + (int) System.currentTimeMillis(); |
|||
while (System.currentTimeMillis() < end) { |
|||
sleep(50); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,28 @@ |
|||
package a8k.service.appstate; |
|||
|
|||
import a8k.service.appstate.type.*; |
|||
import a8k.service.bak_appbase.progress.TubeHolderProgress; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class A8kState { |
|||
public TubeHolderProgress tubeHolderProgress = TubeHolderProgress.Idle; |
|||
|
|||
|
|||
//当前正在被处理的试管架状态 |
|||
public TubeHolderState tubeHolderState = new TubeHolderState(); |
|||
//急诊为状态 |
|||
public EmergencyPosRunState emergencyPosRunState = new EmergencyPosRunState(); |
|||
//孵育盘状态 |
|||
public IncubationPlateStatus incubationPlateStatus = new IncubationPlateStatus(); |
|||
//温度 |
|||
public Integer temperature = 25; |
|||
//设备是否初始化过 |
|||
public Boolean deviceInited = false; |
|||
|
|||
//所有样本的状态(包含本次开机已经处理过的样本的状态) |
|||
public List<SampleState> sampleStates; |
|||
//所有反应盘的状态(包含本次开机已经处理过的反应盘的状态) |
|||
public List<ReactingPlateState> reactingPlateStates; |
|||
|
|||
} |
@ -0,0 +1,5 @@ |
|||
package a8k.service.appstate.type; |
|||
|
|||
public class IncubationPlateStatus { |
|||
public ReactingPlateState[] plateStates = new ReactingPlateState[20]; |
|||
} |
@ -1,9 +1,9 @@ |
|||
package a8k.service.bak_appbase.runstate; |
|||
package a8k.service.appstate.type; |
|||
|
|||
import a8k.type.sampleinfo.SampleInfo; |
|||
import a8k.service.bak_appbase.progress.TubeProcessProgress; |
|||
|
|||
public class TubeRunState { |
|||
public class SampleState { |
|||
public TubeProcessProgress tubeProcessProgress = TubeProcessProgress.EMPTY; //样本运行状态 |
|||
public SampleInfo bindSample = new SampleInfo(); //绑定的样本运行状态 |
|||
} |
@ -0,0 +1,16 @@ |
|||
package a8k.service.appstate.type; |
|||
|
|||
import a8k.type.type.A8kTubeType; |
|||
import a8k.type.type.BloodType; |
|||
import a8k.service.bak_appbase.progress.TubeHolderProgress; |
|||
|
|||
public class TubeHolderState { |
|||
public A8kTubeType tubeHolderType = A8kTubeType.BloodTube; //管子类型 |
|||
public BloodType bloodType = BloodType.WHOLE_BLOOD; //血型 |
|||
|
|||
//样本状态 |
|||
public SampleState[] sampleStates = new SampleState[10]; |
|||
|
|||
public TubeHolderProgress tubeHolderProgress = TubeHolderProgress.Idle; //管子状态 |
|||
public Integer processingTubeIndex = -1; //当前正在被处理的试管索引 |
|||
} |
@ -1,26 +0,0 @@ |
|||
package a8k.service.bak_appbase; |
|||
|
|||
import a8k.service.app.app_consumables_mgr_service.ConsumableState; |
|||
import a8k.service.bak_appbase.runstate.ReactingPlateRunState; |
|||
import a8k.service.bak_appbase.runstate.EmergencyPosRunState; |
|||
import a8k.service.bak_appbase.runstate.TubeHolderRunState; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class A8kDeviceState { |
|||
//耗材状态 |
|||
public ConsumableState consumable = new ConsumableState(); |
|||
//急诊为状态 |
|||
public EmergencyPosRunState emergencyPosRunState = new EmergencyPosRunState(); |
|||
//正在孵育的任务状态 |
|||
public List<ReactingPlateRunState> incubatingPlateStates = null; |
|||
//当前正在被处理的试管架状态 |
|||
public TubeHolderRunState tubeHolderRunState = new TubeHolderRunState(); |
|||
//温度 |
|||
public Integer temperature = 25; |
|||
|
|||
|
|||
public Boolean deviceInited = false; //设备是否初始化过 |
|||
public Boolean devicePoweredOffNormally = false; //设备是否正常关机 |
|||
|
|||
} |
@ -1,7 +1,7 @@ |
|||
package a8k.service.bak_appbase.progress; |
|||
|
|||
public enum TubeHolderProgress { |
|||
TubeHolderStateIdle, //空闲 |
|||
TubeHolderStateProcessing, //处理中 |
|||
TubeHolderStateProcessed, //处理完成 |
|||
Idle, //空闲 |
|||
Processing, //处理中 |
|||
Scaning, //处理中 |
|||
} |
@ -1,20 +0,0 @@ |
|||
package a8k.service.bak_appbase.runstate; |
|||
|
|||
import a8k.type.type.A8kTubeType; |
|||
import a8k.type.type.BloodType; |
|||
import a8k.service.bak_appbase.progress.TubeHolderProgress; |
|||
|
|||
public class TubeHolderRunState { |
|||
public BloodType bloodType = BloodType.WHOLE_BLOOD; //血型 |
|||
public A8kTubeType tubeHolderType = A8kTubeType.BloodTube; //管子类型 |
|||
public TubeHolderProgress tubeHolderProgress = TubeHolderProgress.TubeHolderStateIdle; //管子状态 |
|||
public TubeRunState[] tubeRunStates = new TubeRunState[10]; //管子 |
|||
public Integer processingTubeIndex = -1; //当前正在被处理的试管索引 |
|||
|
|||
public TubeHolderRunState() { |
|||
for (int i = 0; i < tubeRunStates.length; i++) { |
|||
tubeRunStates[i] = new TubeRunState(); |
|||
} |
|||
processingTubeIndex = 1; |
|||
} |
|||
} |
@ -1,4 +0,0 @@ |
|||
package a8k.type.exception; |
|||
|
|||
public class ActionBreakException extends Exception { |
|||
} |
@ -0,0 +1,4 @@ |
|||
package a8k.type.exception; |
|||
|
|||
public class AppPauseException extends Exception { |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue