Browse Source

添加虚拟状态生成模式

tags/v0
zhaohe 7 months ago
parent
commit
db5e7441a9
  1. 1
      src/main/java/a8k/app/a8ktype/DeviceRunMode.java
  2. 2
      src/main/java/a8k/app/a8ktype/device/consumables/LarBottleGroup.java
  3. 4
      src/main/java/a8k/app/a8ktype/device/consumables/LittBottleGroup.java
  4. 3
      src/main/java/a8k/app/a8ktype/device/consumables/Tips.java
  5. 3
      src/main/java/a8k/app/a8ktype/state/IncubationPlate.java
  6. 8
      src/main/java/a8k/app/a8ktype/state/IncubationSubTank.java
  7. 2
      src/main/java/a8k/app/a8ktype/state/OptScanModule.java
  8. 2
      src/main/java/a8k/app/a8ktype/state/Tube.java
  9. 4
      src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java
  10. 63
      src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java
  11. 33
      src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java
  12. 19
      src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgrService.java
  13. 50
      src/main/java/a8k/app/service/statemgr/TubeStateMgrService.java
  14. 9
      src/main/java/a8k/extui/page/debug/P21AppDebugModeConfigPage.java
  15. 73
      src/main/java/a8k/extui/page/frond_end_test/FakeStateGeneratorPage.java

1
src/main/java/a8k/app/a8ktype/DeviceRunMode.java

@ -4,4 +4,5 @@ public enum DeviceRunMode {
RealMode, //真实模式
VirtualMode,//虚拟模式
RunOnlyMode,//空转模式
VirtualStateGenerateMode,//虚拟状态模式
}

2
src/main/java/a8k/app/a8ktype/device/consumables/LarBottleGroup.java

@ -18,7 +18,7 @@ public class LarBottleGroup implements Serializable {
public String color = ""; //颜色
@Schema(description = "是否启用")
public Boolean isUse = false;
public Boolean isUse;
@Schema(description = "数量")
public Integer num = 0;
@Schema(description = "预留数量")

4
src/main/java/a8k/app/a8ktype/device/consumables/LittBottleGroup.java

@ -24,7 +24,10 @@ public class LittBottleGroup implements Serializable {
@Schema(description = "预留数量")
public Integer reserveNum = 0;
public Boolean isUsed = false;
public LittBottleGroup() {
isUsed = false;
}
public LittBottleGroup(LittleBottleConsumableType type, Integer projId, String projName, String projShortName, String lotId, String color, Integer num) {
@ -35,5 +38,6 @@ public class LittBottleGroup implements Serializable {
this.lotId = lotId;
this.color = color;
this.num = num;
this.isUsed = false;
}
}

3
src/main/java/a8k/app/a8ktype/device/consumables/Tips.java

@ -6,5 +6,6 @@ import java.io.Serializable;
public class Tips implements Serializable {
@Schema(description = "tip剩余可用数量")
public Integer tipNum = 0;//剩余可用数量
public Integer tipNum = 0;//剩余可用数量
public Integer totalNum = 120;//总数量
}

3
src/main/java/a8k/app/a8ktype/state/IncubationPlate.java

@ -5,7 +5,8 @@ import a8k.app.a8ktype.device.IncubatorPos;
import java.io.Serializable;
public class IncubationPlate implements Serializable {
public IncubationSubTank[] subtanks = new IncubationSubTank[20];
public IncubationSubTank[] subtanks = new IncubationSubTank[20];
public IncubatorPos space01Pos = IncubatorPos.SPACE01;
public IncubationPlate() {
for (int i = 0; i < 20; i++) {

8
src/main/java/a8k/app/a8ktype/state/IncubationSubTank.java

@ -38,6 +38,9 @@ public class IncubationSubTank implements Serializable {
@Schema(description = "项目ID")
public Integer projId = 0;
@Schema(description = "是否是急诊样本")
public Boolean isEmergency = false;
//
//孵育时间
@Schema(description = "开始孵育时间(ms时间戳)")
@ -45,13 +48,14 @@ public class IncubationSubTank implements Serializable {
@Schema(description = "目标孵育时间(s)")
public Integer incubatedTimeSec = 0; //目标孵育时间
@Schema(description = "剩余孵育时间(s)")
public Integer remainTimeSec = 0; //剩余孵育时间
public Integer remainTimeSec = 0; //剩余孵育时间
@Setter
@Schema(description = "错误信息,用来标识当前孵育盘的错误信息,例如推出的反应板夹有问题")
public List<AppError> errors = new ArrayList<>(); //错误信息
public IncubationSubTank(IncubatorPos pos) {
this.pos = pos;
}
@ -61,7 +65,7 @@ public class IncubationSubTank implements Serializable {
state = IncubationSubTankState.EMPTY;
bloodType = null;
sampleBarcode = "";
userid = "";
// userid = "";
projInfo = null;
sampleId = "";
projId = null;

2
src/main/java/a8k/app/a8ktype/state/OptScanModule.java

@ -26,5 +26,7 @@ public class OptScanModule implements Serializable {
String sampleId = "";
@Schema(description = "项目ID")
Integer projId = 0;
@Schema(description = "是否是急诊样本")
Boolean isEmergency = false;
}

2
src/main/java/a8k/app/a8ktype/state/Tube.java

@ -44,7 +44,7 @@ public class Tube implements Serializable {
List<AppError> errors = new ArrayList<>(); //错误信息
Tube(Integer pos) {
public Tube(Integer pos) {
this.pos = pos;
}

4
src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java

@ -139,7 +139,7 @@ public class AppWebSocketEndpointMgr {
reportState("OptScanModuleState", optScanModuleStateMgrService.getOptScanModule());
reportState("EmergencyPosState", tubeStateMgrService.getEmergencyPosRunState());
reportState("SensorState", gstate.getSensorState());
reportState("ConsumablesStateService", consumablesMgrService.getState());
reportState("ConsumablesState", consumablesMgrService.getState());
}
private Integer reportConsumableStateStateVersion = 0;
@ -156,7 +156,7 @@ public class AppWebSocketEndpointMgr {
if (forceReport || !Objects.equals(reportConsumableStateStateVersion, consumablesMgrService.getStateVersion())) {
reportConsumableStateStateVersion = consumablesMgrService.getStateVersion();
reportState("ConsumablesStateService", consumablesMgrService.getState());
reportState("ConsumablesState", consumablesMgrService.getState());
}
if (forceReport || !reportFrontEndMessageBoxStateVersion.equals(frontEndMessageBoxAndEventMgr.getMessageBoxState().stateVersion)) {

63
src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java

@ -1,5 +1,6 @@
package a8k.app.service.statemgr;
import a8k.app.a8ktype.DeviceRunMode;
import a8k.app.a8ktype.device.Consumable;
import a8k.app.a8ktype.device.TipPos;
import a8k.app.a8ktype.exception.AppException;
@ -11,7 +12,9 @@ import a8k.app.a8ktype.device.consumables.ReactionPlateGroup;
import a8k.app.a8ktype.device.ConsumableGroup;
import a8k.app.a8ktype.device.TipGroup;
import a8k.app.hardware.type.a8kcanprotocol.A8kEcode;
import a8k.app.service.data.UtilsProjectColorAllocer;
import cn.hutool.core.util.ObjectUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
/**
@ -29,12 +32,71 @@ import org.springframework.stereotype.Component;
*/
@Component
public class ConsumablesMgrService {
@Resource
GStateMgrService gStateMgrService;
//耗材状态
private final ConsumableState cState = new ConsumableState();
private Boolean consumableIsNotEnoughFlag = false;
private Integer stateVersion = 0;
static void initConsumableState(ConsumableState state, int i) {
state.reactionPlateGroup[i].num = 23;
state.reactionPlateGroup[i].color = UtilsProjectColorAllocer.getProjColor(1);
state.reactionPlateGroup[i].projName = "hsCRP";
state.reactionPlateGroup[i].projShortName = "CA";
state.reactionPlateGroup[i].lotId = "CA123456";
state.reactionPlateGroup[i].reserveNum = 0;
state.reactionPlateGroup[i].projId = 1;
state.littBottleGroup[i].num = 23;
state.littBottleGroup[i].color = UtilsProjectColorAllocer.getProjColor(1);
state.littBottleGroup[i].projName = "hsCRP";
state.littBottleGroup[i].projShortName = "CA";
state.littBottleGroup[i].lotId = "CA123456";
state.littBottleGroup[i].reserveNum = 0;
state.littBottleGroup[i].isUsed = true;
state.littBottleGroup[i].projId = 1;
state.larBottleGroup[i].num = 23;
state.larBottleGroup[i].color = UtilsProjectColorAllocer.getProjColor(1);
state.larBottleGroup[i].projName = "hsCRP";
state.larBottleGroup[i].projShortName = "CA";
state.larBottleGroup[i].lotId = "CA123456";
state.larBottleGroup[i].reserveNum = 0;
state.larBottleGroup[i].isUse = true;
state.larBottleGroup[i].projId = 1;
if (i == 4) {
state.littBottleGroup[i].isUsed = true;
state.larBottleGroup[i].isUse = false;
}
if (i == 5) {
state.littBottleGroup[i].isUsed = false;
state.larBottleGroup[i].isUse = false;
}
}
synchronized public ConsumableState getState() {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
ConsumableState state = new ConsumableState();
state.tips[0].tipNum = 100;
state.tips[1].tipNum = 101;
state.tips[2].tipNum = 102;
for (int i = 0; i < 6; i++) {
initConsumableState(state, i);
}
return state;
}
return ObjectUtil.cloneByStream(cState);
}
@ -154,6 +216,7 @@ public class ConsumablesMgrService {
synchronized public void setConsumableIsNotEnoughFlag(Boolean flag) {
consumableIsNotEnoughFlag = flag;
}
synchronized public Boolean getConsumableIsNotEnoughFlag() {
return consumableIsNotEnoughFlag;
}

33
src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java

@ -1,5 +1,7 @@
package a8k.app.service.statemgr;
import a8k.app.a8ktype.DeviceRunMode;
import a8k.app.a8ktype.device.BloodType;
import a8k.app.a8ktype.state.IncubationPlate;
import a8k.app.a8ktype.state.IncubationSubTank;
import a8k.app.a8ktype.state.SampleInfo;
@ -9,6 +11,7 @@ import a8k.app.a8ktype.type.ProjBriefInfo;
import a8k.app.a8ktype.error.AppError;
import a8k.app.utils.ZTimeUtils;
import cn.hutool.core.util.ObjectUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@ -20,14 +23,41 @@ import java.util.List;
@Slf4j
public class IncubationPlateStateMgrService {
@Resource
GStateMgrService gStateMgrService;
//孵育盘状态
private final IncubationPlate incubationPlate = new IncubationPlate();
synchronized public IncubationPlate get() {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
return getVirtualState();
}
return ObjectUtil.cloneByStream(incubationPlate);
}
synchronized public IncubationPlate getVirtualState() {
IncubationPlate incubationPlate = new IncubationPlate();
for (IncubationSubTank subtank : incubationPlate.subtanks) {
subtank.state = IncubationSubTankState.ERROR;
subtank.bloodType = BloodType.WHOLE_BLOOD;
subtank.sampleBarcode = "112334455667";
subtank.userid = "250109_001E";
subtank.projInfo = new ProjBriefInfo();
subtank.projInfo.projId = 1;
subtank.projInfo.projName = "hsCRP";
subtank.projInfo.projShortName = "CA";
subtank.projInfo.color = "#DC143C";
subtank.sampleId = "250109_001E01";
subtank.projId = 1;
subtank.isEmergency = true;
subtank.startIncubatedTime = new Date().getTime();
subtank.incubatedTimeSec = 3 * 60;
subtank.remainTimeSec = 3 * 60;
}
return incubationPlate;
}
synchronized public IncubationSubTank getSubTank(IncubatorPos pos) {
return incubationPlate.subtanks[pos.off];
}
@ -85,7 +115,7 @@ public class IncubationPlateStateMgrService {
}
synchronized public void resetIncubatorPos(IncubatorPos pos) {
if(pos == null){
if (pos == null) {
return;
}
var subtanks = incubationPlate.subtanks;
@ -127,6 +157,7 @@ public class IncubationPlateStateMgrService {
subtanks[pos.off].bloodType = sampleInfo.bloodType;
subtanks[pos.off].sampleBarcode = sampleInfo.sampleBarcode;
subtanks[pos.off].userid = sampleInfo.userid;
subtanks[pos.off].isEmergency = sampleInfo.isEmergency;
subtanks[pos.off].projInfo = projBriefInfo;
}

19
src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgrService.java

@ -1,10 +1,14 @@
package a8k.app.service.statemgr;
import a8k.app.a8ktype.DeviceRunMode;
import a8k.app.a8ktype.device.BloodType;
import a8k.app.a8ktype.state.OptScanModule;
import a8k.app.a8ktype.state.SampleInfo;
import a8k.app.a8ktype.state.enumtype.OptScanModuleState;
import a8k.app.a8ktype.type.ProjBriefInfo;
import a8k.app.service.data.UtilsProjectColorAllocer;
import cn.hutool.core.util.ObjectUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -12,6 +16,8 @@ import org.springframework.stereotype.Component;
@Slf4j
public class OptScanModuleStateMgrService {
@Resource
GStateMgrService gStateMgrService;
//光学模组状态
private final OptScanModule optScanModule = new OptScanModule();
@ -20,6 +26,17 @@ public class OptScanModuleStateMgrService {
}
synchronized public OptScanModule getOptScanModule() {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
OptScanModule virstate = new OptScanModule();
virstate.state = OptScanModuleState.PLATE_IS_READY;
virstate.setBloodType(BloodType.WHOLE_BLOOD);
virstate.setSampleBarcode("1234567890");
virstate.setUserid("2250103_003");
virstate.setProjInfo(new ProjBriefInfo(1, "hsCRP", "CA", UtilsProjectColorAllocer.getProjColor(1)));
virstate.setProjId(1);
virstate.setIsEmergency(true);
return virstate;
}
return ObjectUtil.cloneByStream(optScanModule);
}
@ -41,8 +58,8 @@ public class OptScanModuleStateMgrService {
optScanModule.setUserid(sampleInfo.userid);
optScanModule.setProjInfo(projBriefInfo);
optScanModule.setSampleId(sampleInfo.sampleId);
optScanModule.setIsEmergency(sampleInfo.isEmergency);
optScanModule.setProjId(projBriefInfo.projId);
log.info("光学模块:状态->反应板准备就绪 {}", sampleInfo);

50
src/main/java/a8k/app/service/statemgr/TubeStateMgrService.java

@ -1,9 +1,11 @@
package a8k.app.service.statemgr;
import a8k.app.a8ktype.DeviceRunMode;
import a8k.app.a8ktype.device.Consumable;
import a8k.app.a8ktype.error.AEConsumeNotEnoughError;
import a8k.app.a8ktype.others.ConsumableStatInfo;
import a8k.app.a8ktype.state.ProjectTaskContext;
import a8k.app.a8ktype.type.ProjBriefInfo;
import a8k.app.dao.db.DeviceStatisticDao;
import a8k.app.dao.db.SampleRecordDBDao;
import a8k.app.dao.db.type.ProjExtInfoCard;
@ -20,6 +22,7 @@ import a8k.app.dao.db.type.StatisticType;
import a8k.app.a8ktype.error.AppError;
import a8k.app.a8ktype.exception.AppException;
import a8k.app.a8ktype.device.BloodType;
import a8k.app.service.data.UtilsProjectColorAllocer;
import a8k.app.utils.ProjBuildinInfo;
import a8k.app.utils.ProjInfoUtils;
import a8k.app.utils.ZAppChecker;
@ -38,6 +41,9 @@ import java.util.List;
@Component
@Slf4j
public class TubeStateMgrService {
@Resource
GStateMgrService gStateMgrService;
@Resource
ProjInfoMgrService projInfoMgrService;
@Resource
@ -233,11 +239,55 @@ public class TubeStateMgrService {
return ObjectUtil.cloneByStream(emergencyTubePos.tube);
}
static Tube createFakeTube(Integer pos) {
Tube tube = new Tube(pos);
tube.setSampleId("250109_001E0" + pos);
tube.setBloodType(BloodType.WHOLE_BLOOD);
tube.setSampleBarcode("112334455667");
tube.setUserid(String.format("250109_%dE", pos));
tube.setProjInfo(List.of(
new ProjBriefInfo(1, "hsCRP", "CA", UtilsProjectColorAllocer.getProjColor(1)),
new ProjBriefInfo(2, "PCT", "PC", UtilsProjectColorAllocer.getProjColor(2)),
new ProjBriefInfo(3, "TSH", "TS", UtilsProjectColorAllocer.getProjColor(3)),
new ProjBriefInfo(4, "TRL", "PL", UtilsProjectColorAllocer.getProjColor(4)),
new ProjBriefInfo(10, "Progesterone", "T3", UtilsProjectColorAllocer.getProjColor(10)),
new ProjBriefInfo(20, "Tn-I/CK-MB/Myoglobin", "T4", UtilsProjectColorAllocer.getProjColor(20))
));
tube.setProjIds(List.of(1, 2, 3, 4, 10, 20));
tube.setState(TubeState.TO_BE_PROCESSED);
return tube;
}
synchronized public EmergencyTubePos getEmergencyPosRunState() {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
var tubePosState = new EmergencyTubePos();
tubePosState.tube = createFakeTube(0);
return tubePosState;
}
return ObjectUtil.cloneByStream(emergencyTubePos);
}
public synchronized TubeHolder getTubeHolder() {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
TubeHolder tubeHolder = new TubeHolder();
tubeHolder.setTubes(new Tube[]{
createFakeTube(0),
createFakeTube(1),
createFakeTube(2),
createFakeTube(3),
createFakeTube(4),
createFakeTube(5),
createFakeTube(6),
createFakeTube(7),
createFakeTube(8),
createFakeTube(9)
});
tubeHolder.setState(TubeHolderState.PROCESSING);
return tubeHolder;
}
return ObjectUtil.cloneByStream(tubeHolder);
}

9
src/main/java/a8k/extui/page/debug/P21AppDebugModeConfigPage.java

@ -22,8 +22,10 @@ public class P21AppDebugModeConfigPage {
return "虚拟模式";
} else if (gstate.getDeviceRunMode() == DeviceRunMode.RunOnlyMode) {
return "设备空转模式";
} else if (gstate.getDeviceRunMode() == DeviceRunMode.VirtualStateGenerateMode) {
return "虚拟状态生成模式";
}
return "";
return gstate.getDeviceRunMode().name();
}
//
@ -39,6 +41,10 @@ public class P21AppDebugModeConfigPage {
gstate.setDeviceRunMode(DeviceRunMode.RunOnlyMode);
}
public void setInVirtualStateMode() {
gstate.setDeviceRunMode(DeviceRunMode.VirtualStateGenerateMode);
}
@Resource
ExtApiPageMgr extApiPageMgr;
@ -48,6 +54,7 @@ public class P21AppDebugModeConfigPage {
page.addFunction("设置为真实模式", this::setInRealMode);
page.addFunction("设置为虚拟模式", this::setInVirtualMode);
page.addFunction("设置为设备空转模式", this::setInRunOnlyMode);
page.addFunction("设置为虚拟状态生成模式", this::setInVirtualStateMode);
extApiPageMgr.addPage(page);
}
}

73
src/main/java/a8k/extui/page/frond_end_test/FakeStateGeneratorPage.java

@ -0,0 +1,73 @@
package a8k.extui.page.frond_end_test;
import a8k.SpringBootBeanUtil;
import a8k.app.a8ktype.device.BloodType;
import a8k.app.a8ktype.opttype.ReactionResultStatus;
import a8k.app.a8ktype.type.ReactionResult;
import a8k.app.dao.db.ReactionRecordDao;
import a8k.app.dao.db.type.ReactionResultRecord;
import a8k.app.dao.db.type.a8kidcard.zenum.A8kResultUnit;
import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.utils.ZDateUtils;
import a8k.extui.mgr.ExtApiPageMgr;
import a8k.extui.type.ExtApiStatu;
import a8k.extui.type.ExtUIPageCfg;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
@Component
public class FakeStateGeneratorPage {
@Resource
GStateMgrService gstate;
@Resource
ExtApiPageMgr extApiPageMgr;
@PostConstruct
void init() {
ExtUIPageCfg page = new ExtUIPageCfg(this);
page.addFunction("添加1条反应结果记录", this::addVirtualReactionRecord);
page.addFunction("添加100条反应结果记录", this::add100VirtualReactionRecord);
extApiPageMgr.addPage(page);
}
public void add100VirtualReactionRecord() {
for (int i = 0; i < 100; i++) {
addVirtualReactionRecord(String.format("SAMPLE%03d", i));
}
}
@ExtApiStatu(name = "", group = "使用说明")
public String usage() {
return "生成虚拟状态生成,用于测试,如果设备运行起来了,请勿调用此接口会造成设备状态混乱";
}
public void addVirtualReactionRecord(String sampleId) {
ReactionRecordDao service = SpringBootBeanUtil.getBean(ReactionRecordDao.class);
ReactionResultRecord record = new ReactionResultRecord();
record.sampleBloodType = BloodType.WHOLE_BLOOD;
record.sampleBarcode = "XXXXXXXXXXXXXXX";
record.sampleUserid = "ABCDEFG";
record.projName = "Tn-I/CK-MB/Myoglobin";
record.projShortName = "TC";
record.lotId = "CAHAC46U";
record.projId = 1;
record.sampleId = sampleId;
record.setExpiryDate(ZDateUtils.nextDay());
record.operator = "admin"; // 操作员
record.appVersion = gstate.getAppVersion();// 上层应用版本
record.mcuVersion = gstate.getMcuVersion(); // MCU软件版本
record.sn = gstate.getSn(); // 仪器序列号 =;
record.subProjResult1 = new ReactionResult("Tn-I", "Tn-I", 11.11, 22.22, 33.33, A8kResultUnit.iuPml,
A8kResultUnit.iuPml, A8kResultUnit.coi);
record.subProjResult2 = new ReactionResult("CK-MB", "CK-MB", ReactionResultStatus.ERROR_LOST_PEAK_C, "C峰丢失");
record.subProjResult3 = new ReactionResult("Myoglobin", "MG", 11.11, 22.22, 33.33, A8kResultUnit.iuPml,
A8kResultUnit.iuPml, A8kResultUnit.coi);
service.add(record);
}
}
Loading…
Cancel
Save