diff --git a/pom.xml b/pom.xml
index 560817f..93283cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -127,7 +127,16 @@
jackson-dataformat-yaml
2.12.4
-
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.mockito
+ mockito-core
+ 3.12.4
+
diff --git a/src/main/java/a8k/OS.java b/src/main/java/a8k/OS.java
index 2e697c0..5624af6 100644
--- a/src/main/java/a8k/OS.java
+++ b/src/main/java/a8k/OS.java
@@ -93,7 +93,7 @@ public class OS {
static public String getLocalIp() {
if (isRunOnWindows()) {
- return "W:0.0.0.0";
+ return "192.168.8.10";
}
NetworkInterface networkInterface = null;
diff --git a/src/main/java/a8k/app/controler/api/v1/app/state/AppFlagStateMgrController.java b/src/main/java/a8k/app/controler/api/v1/app/state/AppFlagStateMgrController.java
index 6927d8e..7f8d674 100644
--- a/src/main/java/a8k/app/controler/api/v1/app/state/AppFlagStateMgrController.java
+++ b/src/main/java/a8k/app/controler/api/v1/app/state/AppFlagStateMgrController.java
@@ -2,6 +2,7 @@ package a8k.app.controler.api.v1.app.state;
import a8k.app.service.statemgr.AppFlagStateMgr;
import a8k.app.type.AppFlagKey;
+import a8k.app.type.DeviceWarningFlagStateGroup;
import a8k.app.type.ui.ApiRet;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -37,7 +38,7 @@ public class AppFlagStateMgrController {
@Operation(summary = "获取状态")
@PostMapping("/getFlagState")
- public ApiRet getFlagState() {
+ public ApiRet getFlagState() {
return ApiRet.success(appFlagStateMgr.getFlagState());
}
diff --git a/src/main/java/a8k/app/controler/api/v1/app/state/DeviceStateController.java b/src/main/java/a8k/app/controler/api/v1/app/state/DeviceStateController.java
index c927833..19b4cd0 100644
--- a/src/main/java/a8k/app/controler/api/v1/app/state/DeviceStateController.java
+++ b/src/main/java/a8k/app/controler/api/v1/app/state/DeviceStateController.java
@@ -47,7 +47,7 @@ public class DeviceStateController {
@Operation(summary = "获取<试管架>状态")
@PostMapping("/getTubeHolderState")
public ApiRet getTubeHolderState() {
- return ApiRet.success(tubeStateMgrService.getTubeHolder());
+ return ApiRet.success(tubeStateMgrService.getTubeHolderState());
}
@Operation(summary = "获取<孵育盘>的状态")
diff --git a/src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java b/src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java
index a7cd557..1ad6f60 100644
--- a/src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java
+++ b/src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java
@@ -11,7 +11,10 @@ import a8k.app.service.mainctrl.TubeHolderSettingMgrService;
import a8k.app.service.statemgr.*;
import a8k.app.service.background.FrontEndMessageBoxAndEventMgr;
import a8k.app.type.a8k.ConsumableGroup;
+import a8k.app.type.appevent.AppEvent;
+import a8k.app.type.appevent.AppLoginEvent;
import a8k.app.utils.ZJsonHelper;
+import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
@@ -21,6 +24,7 @@ import jakarta.websocket.*;
import java.io.IOException;
import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
@Component
@EnableScheduling
@@ -52,7 +56,7 @@ public class AppWebSocketEndpointMgr {
private final AppUserMgrService appUserMgrService;
private final AppDeviceInitCtrlService appDeviceInitCtrlService;
private final PreReactionStateMgr preReactionStateMgr;
- final private GStateMgrService gstate;
+ final private GStateMgrService gStateMgrService;
final private FrontEndMessageBoxAndEventMgr frontEndMessageBoxAndEventMgr;
final private EngineerModeStateMgrService engineerModeStateMgrService;
final private DeviceWorkStateMgrService deviceWorkStateMgrService;
@@ -61,32 +65,28 @@ public class AppWebSocketEndpointMgr {
final private OptScanModuleStateMgr optScanModuleStateMgr;
final private ConsumablesMgrService consumablesMgrService;
final private TubeHolderSettingMgrService tubeHolderSettingMgrService;
- final private AppEventBusService appEventBusService;
- final private AppFlagStateMgr appFlagStateMgrService;
+ final private AppEventBusService appEventBusService;
+ final private AppFlagStateMgr appFlagStateMgrService;
+ final private AppEventBusService eventBus;
+
List stateWebsocketSessions = new ArrayList<>();
List eventWebsocketSessions = new ArrayList<>();
- Thread workThread;
- Boolean newStateSession = false;
Map stateVersionCache = new HashMap<>();
+ final Object sessionLock = new Object();
- synchronized void setNewStateSession() {
- this.newStateSession = true;
- }
+ AtomicInteger forceUpdateCnt = new AtomicInteger(0);
- synchronized Boolean getAndClearNewStateSession() {
- Boolean ret = this.newStateSession;
- this.newStateSession = false;
- return ret;
- }
synchronized public void pushStateWebsocketSession(Session session) {
stateWebsocketSessions.add(session);
- setNewStateSession();
+ forceUpdateCnt.incrementAndGet();
}
synchronized public void removeStateWebsocketSession(Session session) {
- stateWebsocketSessions.remove(session);
+ synchronized (sessionLock) {
+ stateWebsocketSessions.remove(session);
+ }
}
synchronized public void pushEventWebsocketSession(Session session) {
@@ -140,10 +140,19 @@ public class AppWebSocketEndpointMgr {
broadcastEvent(message);
}
+
+ @PostConstruct
+ void init() {
+ eventBus.regListener((AppEvent event) -> {
+ if (event instanceof AppLoginEvent) {
+ forceUpdateCnt.incrementAndGet();
+ }
+ });
+ }
+
//
// Scheduled tasks
//
-
@Scheduled(fixedDelay = 100)
public void reportEvent() {
frontEndMessageBoxAndEventMgr.pollAllAppEvents().forEach(event -> {
@@ -152,26 +161,39 @@ public class AppWebSocketEndpointMgr {
}
- @Scheduled(fixedDelay = 200)
+ @Scheduled(fixedDelay = 900)
public void reportDeviceState() {
- //TODO : 这里可以考虑增加一个状态版本号,只有状态变化时才发送
- reportState("DeviceWorkState", deviceWorkStateMgrService.getDeviceWorkState());
- reportState("TubeHolderState", tubeStateMgrService.getTubeHolder());
+ reportState("GDeviceState", gStateMgrService.getGState());
reportState("IncubationPlateState", incubationPlateStateMgr.get());
- reportState("OptScanModuleState", optScanModuleStateMgr.getOptScanModule());
- reportState("EmergencyPosState", tubeStateMgrService.getEmergencyPosRunState());
- reportState("SensorState", gstate.getSensorState());
- reportState("ConsumablesState", consumablesMgrService.getState());
- reportState("GDeviceState", gstate.getGState());
- reportState("EngineerModeState", engineerModeStateMgrService.getState());
+ reportState("SensorState", gStateMgrService.getSensorState());
+
+ DeviceContext deviceContext = new DeviceContext();
+ deviceContext.runMode = gStateMgrService.getDeviceRunMode();
+ deviceContext.loginFlag = appUserMgrService.getLoginUsr() != null;
+ deviceContext.loginUser = appUserMgrService.getLoginUsr();
+ deviceContext.deviceInitedFlag = appDeviceInitCtrlService.getState().deviceInited;
+ deviceContext.fatalErrorFlag = deviceWorkStateMgrService.getDeviceWorkState().fatalErrorFlag;
+ reportState("DeviceContext", deviceContext);
}
- @Scheduled(fixedDelay = 30)
+ @Scheduled(fixedDelay = 100)
public void quickReportStateSchedule() {
quickReportStateSchedule(false);
}
public void quickReportStateSchedule(boolean force) {
+
+ reportState("EngineerModeState", engineerModeStateMgrService.getVersion(), force,
+ engineerModeStateMgrService::getState);
+ reportState("TubeHolderState", tubeStateMgrService.getVersion(), force, tubeStateMgrService::getTubeHolderState);
+ reportState("EmergencyPosState", tubeStateMgrService.getVersion(), force, tubeStateMgrService::getEmergencyPosRunState);
+
+ reportState("OptScanModuleState", optScanModuleStateMgr.getStateVersion(), force,
+ optScanModuleStateMgr::getOptScanModule);
+
+ reportState("DeviceWorkState", deviceWorkStateMgrService.getVersion(), force,
+ deviceWorkStateMgrService::getDeviceWorkState);
+
reportState("TubeHolderSetting", tubeHolderSettingMgrService.getTubeHolderSettingVersion(), force,
tubeHolderSettingMgrService::getTubeHolderSettings);
reportState("AppFlagStateList", appFlagStateMgrService.getStateVersion(), force,
@@ -195,24 +217,21 @@ public class AppWebSocketEndpointMgr {
}
- @Scheduled(fixedDelay = 1000)
- public void reportSessionState() {
- DeviceContext deviceContext = new DeviceContext();
- deviceContext.runMode = gstate.getDeviceRunMode();
- deviceContext.loginFlag = appUserMgrService.getLoginUsr() != null;
- deviceContext.loginUser = appUserMgrService.getLoginUsr();
- deviceContext.deviceInitedFlag = appDeviceInitCtrlService.getState().deviceInited;
- deviceContext.fatalErrorFlag = deviceWorkStateMgrService.getDeviceWorkState().fatalErrorFlag;
- reportState("DeviceContext", deviceContext);
- }
+ Boolean isForceUpdateNow() {
+ if (forceUpdateCnt.get() != 0) {
+ forceUpdateCnt.getAndDecrement();
+ return true;
+ }
+ return false;
+ }
+
@Scheduled(fixedDelay = 30)
public void onNewStateSession() {
- if (getAndClearNewStateSession()) {
+ if (isForceUpdateNow()) {
log.info("onNewStateSession: new state session detected, broadcasting current state");
reportDeviceState();
- reportSessionState();
quickReportStateSchedule(true);
}
}
diff --git a/src/main/java/a8k/app/factory/BiLisDoubleTrackFrameFactory.java b/src/main/java/a8k/app/factory/BiLisDoubleTrackFrameFactory.java
index a89621e..1c4f93a 100644
--- a/src/main/java/a8k/app/factory/BiLisDoubleTrackFrameFactory.java
+++ b/src/main/java/a8k/app/factory/BiLisDoubleTrackFrameFactory.java
@@ -3,6 +3,7 @@ package a8k.app.factory;
import a8k.app.constant.AppConstant;
import a8k.app.dao.type.db.ReactionRecord;
import a8k.app.type.lisprotocol.BiLisDoubleTrackFrame;
+import a8k.app.type.lisprotocol.BiLisDoubleTrackFrameBuildContext;
import a8k.app.type.lisprotocol.BiLisFrameParseErrorCode;
import a8k.app.type.lisprotocol.BiLisFrameParseException;
import a8k.app.utils.ByteArrayUtils;
@@ -14,11 +15,13 @@ import java.lang.reflect.Field;
@Slf4j
public class BiLisDoubleTrackFrameFactory {
-
//
- static public BiLisDoubleTrackFrame.RFrame createRFrame(ReactionRecord reactionRecord, Integer subProjIndex) {
+ static public BiLisDoubleTrackFrameBuildContext createRFrame(ReactionRecord reactionRecord, Integer subProjIndex) {
//R|A10|123456789|^PCT/CRP^CRP^#|46|mg/L|0.5-200||L_1^_03|F||||20141201144906||0|
+ BiLisDoubleTrackFrameBuildContext buildContext = new BiLisDoubleTrackFrameBuildContext();
+
+ BiLisDoubleTrackFrame frame = new BiLisDoubleTrackFrame();
BiLisDoubleTrackFrame.RFrame rFrame = new BiLisDoubleTrackFrame.RFrame();
Double rawResultVal = reactionRecord.results.get(subProjIndex).result;
@@ -66,17 +69,32 @@ public class BiLisDoubleTrackFrameFactory {
rFrame.pid = reactionRecord.sampleUserid;
rFrame.sampleType = sampleType;//样本类型
- return rFrame;
+ frame.frameType = BiLisDoubleTrackFrame.STX;
+ frame.frameContent = rFrame;
+ buildContext.frame = frame;
+
+ serialize(buildContext, frame);
+ return buildContext;
}
- static public byte[] createRFrameBytes(BiLisDoubleTrackFrame.RFrame rFrame) {
- BiLisDoubleTrackFrame frame = new BiLisDoubleTrackFrame();
+ static public BiLisDoubleTrackFrameBuildContext createQFrameBytes(String deviceName, String barcode) {
+ BiLisDoubleTrackFrameBuildContext context = new BiLisDoubleTrackFrameBuildContext();
+
+ BiLisDoubleTrackFrame frame = new BiLisDoubleTrackFrame();
+ BiLisDoubleTrackFrame.QFrame qFrame = new BiLisDoubleTrackFrame.QFrame();
frame.frameType = BiLisDoubleTrackFrame.STX;
- frame.frameContent = rFrame;
- return serialize(frame);
+ qFrame.type = "Q"; // 请求类型
+ qFrame.deviceName = deviceName;
+ qFrame.barcode = String.format("^%s", barcode); // 条形码,以^开头
+ frame.frameContent = qFrame;
+
+ context.frame = frame;
+ serialize(context, frame);
+ return context;
}
+
static public BiLisDoubleTrackFrame createOFrame(byte[] rxData) throws BiLisFrameParseException {
/*
* Frame Structure:
@@ -89,7 +107,7 @@ public class BiLisDoubleTrackFrameFactory {
throw new BiLisFrameParseException(BiLisFrameParseErrorCode.FrameLengthTooShort, "rx packet length is too short: " + rxData.length);
}
byte stx = rxData[0];
- byte fn = rxData[1];
+ char fn = (char) rxData[1];
byte etx = rxData[rxData.length - 5];
byte c1 = rxData[rxData.length - 4];
byte c2 = rxData[rxData.length - 3];
@@ -158,39 +176,29 @@ public class BiLisDoubleTrackFrameFactory {
}
- static public byte[] createQFrameBytes(String deviceName, String barcode) {
- BiLisDoubleTrackFrame frame = new BiLisDoubleTrackFrame();
- BiLisDoubleTrackFrame.QFrame qFrame = new BiLisDoubleTrackFrame.QFrame();
- frame.frameType = BiLisDoubleTrackFrame.STX;
- qFrame.type = "Q"; // 请求类型
- qFrame.deviceName = deviceName;
- qFrame.barcode = String.format("^%s", barcode); // 条形码,以^开头
- frame.frameContent = qFrame;
- return serialize(frame);
- }
-
- static public byte[] serialize(BiLisDoubleTrackFrame frame) {
+ static public void serialize(BiLisDoubleTrackFrameBuildContext buildContext, BiLisDoubleTrackFrame frame) {
/*
* Frame Structure:
* STX,FN,Content,ETX,C1,C2,CR,LF
*/
if (frame.frameType != BiLisDoubleTrackFrame.STX) {
log.warn("Frame type is not STX, cannot serialize: {}", frame.frameType);
- return new byte[0];
+ buildContext.buildSuccess = false;
}
if ((frame.frameContent instanceof BiLisDoubleTrackFrame.QFrame
|| frame.frameContent instanceof BiLisDoubleTrackFrame.RFrame
)) {
- String frameContent = serializeFrameContent(frame.frameContent);
- return ByteArrayUtils.toByteArray(createBiLisDoubleTrackFrame(frameContent));
+ String content = serializeFrameContent(frame.frameContent);
+ buildContext.frameContentStr = content;
+ createBiLisDoubleTrackFrame(buildContext, content);
} else {
log.warn("Unsupported frame content type: {}", frame.frameContent.getClass().getSimpleName());
- return new byte[0];
+ buildContext.buildSuccess = false;
}
}
- private static ByteBuf createBiLisDoubleTrackFrame(String content) {
+ private static void createBiLisDoubleTrackFrame(BiLisDoubleTrackFrameBuildContext context, String content) {
char[] checksum = computeChecksum(content);
ByteBuf byteBuf = io.netty.buffer.Unpooled.buffer(BiLisDoubleTrackFrame.PACKET_MAX_LENGTH);
byteBuf.writeByte(BiLisDoubleTrackFrame.STX);
@@ -201,10 +209,12 @@ public class BiLisDoubleTrackFrameFactory {
byteBuf.writeByte(checksum[1]);
byteBuf.writeByte(BiLisDoubleTrackFrame.CR);
byteBuf.writeByte(BiLisDoubleTrackFrame.LF);
- return byteBuf;
+
+ context.frameBytes = ByteArrayUtils.toByteArray(byteBuf);
+ context.checksum = checksum;
}
- private static String serializeFrameContent(Object obj) {
+ public static String serializeFrameContent(Object obj) {
StringBuilder sb = new StringBuilder();
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
@@ -229,7 +239,7 @@ public class BiLisDoubleTrackFrameFactory {
return removeTrailingPipes(sb.toString());
}
- private static String removeTrailingPipes(String str) {
+ public static String removeTrailingPipes(String str) {
// 去除末尾的换行符和回车符
str = str.trim();
// 从字符串末尾开始检查连续的|字符
@@ -246,21 +256,23 @@ public class BiLisDoubleTrackFrameFactory {
return str + "\r";
}
- private static char[] computeChecksum(String content) {
+ public static char[] computeChecksum(String content) {
int checksum = 0;
- checksum += BiLisDoubleTrackFrame.FN;
- checksum += BiLisDoubleTrackFrame.ETX;
+
if (content != null) {
for (char c : content.toCharArray()) {
checksum += c;
}
}
+ checksum += BiLisDoubleTrackFrame.ETX;
+ checksum += BiLisDoubleTrackFrame.FN;
+
checksum = checksum % 256; // 取模运算,确保checksum在0-255范围内
//C1高4位,C2低4位
return intToHexChars(checksum);
}
- private static char[] intToHexChars(int value) {
+ public static char[] intToHexChars(int value) {
// 将整数转换为两个十六进制字符 ret (0-9,a-f)
char[] hexChars = new char[2];
hexChars[0] = Character.forDigit((value >> 4) & 0x0F, 16); // 高4位
@@ -274,7 +286,7 @@ public class BiLisDoubleTrackFrameFactory {
return hexChars;
}
- static private String strArraySafeGet(String[] list, int index) {
+ static public String strArraySafeGet(String[] list, int index) {
if (list == null || index < 0 || index >= list.length) {
return "";
}
diff --git a/src/main/java/a8k/app/interceptor/RefreshAccessInterceptor.java b/src/main/java/a8k/app/interceptor/RefreshAccessInterceptor.java
index 9843872..0ff77b9 100644
--- a/src/main/java/a8k/app/interceptor/RefreshAccessInterceptor.java
+++ b/src/main/java/a8k/app/interceptor/RefreshAccessInterceptor.java
@@ -21,7 +21,6 @@ public class RefreshAccessInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
- userMgr.recordAccess();
return true;
}
}
diff --git a/src/main/java/a8k/app/service/DeviceVirtualStateMgrService.java b/src/main/java/a8k/app/service/DeviceVirtualStateMgrService.java
new file mode 100644
index 0000000..92cdf86
--- /dev/null
+++ b/src/main/java/a8k/app/service/DeviceVirtualStateMgrService.java
@@ -0,0 +1,258 @@
+package a8k.app.service;
+
+
+import a8k.app.channel.iflytophald.type.protocol.A8kEcode;
+import a8k.app.constant.AppConstant;
+import a8k.app.factory.FakeA8kConsumableContainerFactory;
+import a8k.app.factory.FakeAppErrorFactory;
+import a8k.app.factory.ZAppPromptFactory;
+import a8k.app.service.utils.ProjInfoUtils;
+import a8k.app.type.AppFlagKey;
+import a8k.app.type.DeviceWarningFlagStateGroup;
+import a8k.app.type.PreReactionGrid;
+import a8k.app.type.PreReactionGridGroup;
+import a8k.app.type.a8k.BloodType;
+import a8k.app.type.a8k.ConsumableGroup;
+import a8k.app.type.a8k.LittleBottleConsumableType;
+import a8k.app.type.a8k.proj.ProjBriefInfo;
+import a8k.app.type.a8k.state.*;
+import a8k.app.type.a8k.state.enumtype.IncubationSubTankState;
+import a8k.app.type.a8k.state.enumtype.TubeHolderState;
+import a8k.app.type.a8k.state.enumtype.TubeState;
+import a8k.app.type.error.AppError;
+import a8k.app.utils.ZList;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class DeviceVirtualStateMgrService {
+
+
+ /**
+ * 获取虚拟孵育盘状态
+ * @return 虚拟孵育盘状态
+ */
+ synchronized public IncubationPlate getVirtualIncubationPlateState() {
+ IncubationPlate incubationPlate = new IncubationPlate();
+ int i = 0;
+ for (IncubationSubTank subtank : incubationPlate.subtanks) {
+ i++;
+ switch (i) {
+ case 1 -> subtank.state = IncubationSubTankState.RESERVED;
+ case 2 -> subtank.state = IncubationSubTankState.WAITING_FOR_DROP;
+ case 3 -> subtank.state = IncubationSubTankState.INCUBATING;
+ case 4 -> subtank.state = IncubationSubTankState.ERROR;
+ case 5 -> subtank.state = IncubationSubTankState.INCUBATION_COMPLETE;
+ default -> subtank.state = IncubationSubTankState.EMPTY;
+ }
+
+ subtank.sampleInfo = new SampleInfo(
+ "250109_001E01", 0, false, false, BloodType.WHOLE_BLOOD, "B3A7KK8DKF", "250109_001E"
+ );
+
+
+ subtank.sampleInfo.bloodType = BloodType.WHOLE_BLOOD;
+ subtank.sampleInfo.sampleBarcode = "112334455667";
+ subtank.sampleInfo.userid = "250109_001E";
+ subtank.projInfo = new ProjBriefInfo();
+ subtank.projInfo.projId = 1;
+ subtank.projInfo.projName = "hsCRP";
+ subtank.projInfo.projShortName = "CA";
+ subtank.projInfo.color = "#DC143C";
+ subtank.sampleInfo.sampleId = "250109_001E01";
+ subtank.projId = 1;
+ subtank.lotId = "CA123456";
+ subtank.isEmergency = i == 2;
+ if (subtank.state.equals(IncubationSubTankState.ERROR)) {
+ subtank.error = new AppError(A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED, "");
+ subtank.errorInfo = ZAppPromptFactory.buildAppPrompt(subtank.error);
+ }
+ subtank.startIncubatedTime = new Date().getTime();
+ subtank.incubatedTimeSec = 3 * 60;
+ subtank.remainTimeSec = 3 * 60;
+ }
+ return incubationPlate;
+ }
+
+
+ static void addProjInfoToTube(Tube tube, Integer projId) {
+ ProjBriefInfo projBriefInfo = FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(projId);
+ tube.getProjInfo().add(projBriefInfo);
+ tube.getProjIds().add(projBriefInfo.projId);
+ }
+
+ 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));
+
+ switch (pos) {
+ case 1 -> tube.setState(TubeState.EMPTY);
+ case 2 -> {
+ tube.setState(TubeState.ERROR);
+ tube.setError(FakeAppErrorFactory.buildAEConsumeNotEnoughError());
+ tube.setErrorInfo(ZAppPromptFactory.buildAppPrompt(tube.getError()));
+
+ addProjInfoToTube(tube, 1);
+ addProjInfoToTube(tube, 2);
+
+ }
+ case 3, 4, 5, 6 -> {
+ tube.setState(TubeState.PROCESS_COMPLETE);
+ addProjInfoToTube(tube, 1);
+ addProjInfoToTube(tube, 2);
+ addProjInfoToTube(tube, 3);
+ }
+ case 7 -> {
+ tube.setState(TubeState.PROCESSING);
+ addProjInfoToTube(tube, 1);
+ addProjInfoToTube(tube, 2);
+ addProjInfoToTube(tube, 3);
+ }
+ case 8, 9, 10 -> {
+ tube.setState(TubeState.TO_BE_PROCESSED);
+ addProjInfoToTube(tube, 1);
+ addProjInfoToTube(tube, 2);
+ }
+ }
+ tube.setIsHighTube(pos % 2 == 0); //假设偶数位置为高位管
+
+ return tube;
+ }
+
+ public TubeHolder getVirtualTubeHolderState() {
+ TubeHolder tubeHolder = new TubeHolder();
+ tubeHolder.setTubes(new Tube[]{
+ createFakeTube(1),
+ createFakeTube(2),
+ createFakeTube(3),
+ createFakeTube(4),
+ createFakeTube(5),
+ createFakeTube(6),
+ createFakeTube(7),
+ createFakeTube(8),
+ createFakeTube(9),
+ createFakeTube(10)
+ });
+ tubeHolder.setState(TubeHolderState.PROCESSING);
+ return tubeHolder;
+ }
+
+ public EmergencyTubePos getVirtualEmergencyTube() {
+ var tubePosState = new EmergencyTubePos();
+ tubePosState.tube = createFakeTube(0);
+ tubePosState.tube.setPos(0);
+ tubePosState.tube.setIsEmergency(true);
+ return tubePosState;
+ }
+
+
+ public PreReactionGridGroup getFakePreReactionGridGroup(ConsumableGroup group) {
+ PreReactionGridGroup gridGroup = new PreReactionGridGroup(group);
+ gridGroup.group = group;
+ if (group.off % 2 == 0) {
+ gridGroup.installed = true;
+ gridGroup.hasSomeGridInReacting = true;
+ gridGroup.hasSomeGridReactedCompleted = true;
+ } else {
+ gridGroup.installed = false;
+ gridGroup.hasSomeGridInReacting = false;
+ gridGroup.hasSomeGridReactedCompleted = false;
+ }
+ gridGroup.consumableType = LittleBottleConsumableType.BufferSolution;
+ var projBuildInInfo = FakeA8kConsumableContainerFactory.buildFakeProjBuildInInfo(group.off);
+ gridGroup.projBriefInfo = ProjInfoUtils.buildProjBrefInfo(projBuildInInfo);
+ gridGroup.version = 10;
+ for (int i = 0; i < AppConstant.CONSUMABLE_NUM; i++) {
+
+ gridGroup.grids.get(i).projId = projBuildInInfo.projId;
+ gridGroup.grids.get(i).projBuildinInfo = projBuildInInfo;
+ gridGroup.grids.get(i).projExtInfoCard = null;
+
+ switch (i / 5) {
+ case 0 -> {
+ gridGroup.grids.get(i).state = PreReactionGrid.State.UNINSTALL;
+ }
+ case 1 -> {
+ gridGroup.grids.get(i).state = PreReactionGrid.State.USED;
+ }
+
+ case 2 -> {
+ gridGroup.grids.get(i).state = PreReactionGrid.State.REACTION_COMPLETED;
+ gridGroup.grids.get(i).sampleInfo.userid = "UID123";
+ }
+ case 3 -> {
+ gridGroup.grids.get(i).state = PreReactionGrid.State.REACTING;
+ gridGroup.grids.get(i).sampleInfo.userid = "UID123";
+ gridGroup.grids.get(i).reactionRemainingTime = 3 * 60L;
+ }
+ case 4 -> {
+ gridGroup.grids.get(i).state = PreReactionGrid.State.TO_BE_USED;
+ }
+ }
+ }
+ return gridGroup;
+ }
+
+ public SensorState getVirtualSensorState() {
+ SensorState sensorState = new SensorState();
+ sensorState.setPboxTemperature(24);
+ sensorState.setIncubateBoxTemperature(25);
+ sensorState.setWasteBinFullFlag(false);
+ return sensorState;
+ }
+
+ //
+ // VIRTUAL_OPERATION
+ //
+ public DeviceWarningFlagStateGroup getDeviceFlagStateVirtualStateInitVal(DeviceWarningFlagStateGroup deviceWarningFlagState) {
+
+ DeviceWarningFlagStateGroup virtualWarningState = ObjectUtil.clone(deviceWarningFlagState); //初始化时复制一份状态版本号
+ virtualWarningState.version = 10000;
+
+ //设置VirtualState初始值
+ var consumeNotEnoughState = virtualWarningState.find(AppFlagKey.ConsumeNotEnoughState);
+ consumeNotEnoughState.state = true; //
+ consumeNotEnoughState.errorDetailInfo = FakeAppErrorFactory.buildAEConsumeNotEnoughError();
+ consumeNotEnoughState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(consumeNotEnoughState.errorDetailInfo);
+
+ var tipNotEnoughState = virtualWarningState.find(AppFlagKey.TipNotEnoughState);
+ tipNotEnoughState.state = true; //
+ tipNotEnoughState.errorDetailInfo = FakeAppErrorFactory.buildError(A8kEcode.APPE_TIP_NOT_ENOUGH);
+ tipNotEnoughState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(tipNotEnoughState.errorDetailInfo);
+
+ var infeedExceptionState = virtualWarningState.find(AppFlagKey.InfeedExceptionState);
+ infeedExceptionState.state = true; //
+ infeedExceptionState.errorDetailInfo = FakeAppErrorFactory.buildAEHardwareError();
+ infeedExceptionState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(infeedExceptionState.errorDetailInfo);
+
+ var outfeedAreaFullState = virtualWarningState.find(AppFlagKey.OutfeedAreaFullState);
+ outfeedAreaFullState.state = true; //
+ outfeedAreaFullState.errorDetailInfo = FakeAppErrorFactory.buildError(A8kEcode.APPE_OUTFEED_AREA_IS_FULL);
+ outfeedAreaFullState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(outfeedAreaFullState.errorDetailInfo);
+
+ var wasteBinFullState = virtualWarningState.find(AppFlagKey.WasteBinFull);
+ wasteBinFullState.state = true; //
+ wasteBinFullState.errorDetailInfo = FakeAppErrorFactory.buildError(A8kEcode.APPE_WAST_BIN_IS_FULL);
+ wasteBinFullState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(wasteBinFullState.errorDetailInfo);
+
+ if (AppFlagKey.InfeedPPSFlag.enabled)
+ virtualWarningState.find(AppFlagKey.InfeedPPSFlag).state = true; //入料区光电
+ if (AppFlagKey.OutfeedPPSFlag.enabled)
+ virtualWarningState.find(AppFlagKey.OutfeedPPSFlag).state = false; //入料区光电
+ if (AppFlagKey.TubeholderChannelPPSFlag.enabled)
+ virtualWarningState.find(AppFlagKey.TubeholderChannelPPSFlag).state = true; //入料区光电
+ if (AppFlagKey.PlateBoxLidPPSState.enabled)
+ virtualWarningState.find(AppFlagKey.PlateBoxLidPPSState).state = false; //入料区光电
+ return virtualWarningState;
+
+ }
+}
diff --git a/src/main/java/a8k/app/service/data/AppUserMgrService.java b/src/main/java/a8k/app/service/data/AppUserMgrService.java
index 49d08be..480b2fb 100644
--- a/src/main/java/a8k/app/service/data/AppUserMgrService.java
+++ b/src/main/java/a8k/app/service/data/AppUserMgrService.java
@@ -5,9 +5,12 @@ import a8k.app.dao.DeviceSettingDao;
import a8k.app.dao.type.db.AppUser;
import a8k.app.dao.type.db.DeviceSetting;
import a8k.app.channel.iflytophald.type.protocol.A8kEcode;
+import a8k.app.service.background.AppEventBusService;
+import a8k.app.type.appevent.AppLoginEvent;
import a8k.app.type.exception.AppException;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
@@ -19,33 +22,19 @@ import java.util.List;
@Component
@EnableScheduling //Enable scheduled tasks
+@RequiredArgsConstructor
public class AppUserMgrService {
static Logger logger = org.slf4j.LoggerFactory.getLogger(AppUserMgrService.class);
/**
* current user
*/
- @Resource
- AppUsrDao appUsrDao;
- @Resource
- DeviceSettingDao deviceSettingDao;
+ private final AppUsrDao appUsrDao;
+ private final DeviceSettingDao deviceSettingDao;
+ private final AppEventBusService appEventBusService;
AppUser loginUsr = null;
- /**
- * timestamp of last access
- */
- private volatile Instant lastAccess;
-
- /**
- * auto logout time out duration
- */
- private volatile Duration autoLogoutTimeout;
-
- /**
- * flag to enable auto logout
- */
- private volatile boolean autoLogout;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// EXT FUNC
@@ -58,9 +47,7 @@ public class AppUserMgrService {
public void init() {
DeviceSetting deviceSetting = deviceSettingDao.get();
int minutes = deviceSetting.getAutoLogoutTimeout();
- this.autoLogoutTimeout = Duration.ofMinutes(minutes);
- boolean autoLogout = deviceSetting.getAutoLogout();
- this.autoLogout = autoLogout;
+ boolean autoLogout = deviceSetting.getAutoLogout();
logger.debug("initialized autoLogout={}, timeout={} minutes", autoLogout, minutes);
}
@@ -74,6 +61,7 @@ public class AppUserMgrService {
throw new AppException(A8kEcode.USR_PASSWORD_ERROR);
}
loginUsr = usr;
+ appEventBusService.pushEvent(new AppLoginEvent(usr));
return (usr);
}
@@ -87,22 +75,6 @@ public class AppUserMgrService {
/**
* refresh lastAccess on each intercepted request
*/
- public synchronized void recordAccess() {
- if (loginUsr != null) {
- this.lastAccess = Instant.now();
- }
- }
-
- public synchronized void updateAutoLogout(boolean autoLogout) {
- this.autoLogout = autoLogout;
- logger.debug("updated cache autoLogout:{}", autoLogout);
- }
-
- public synchronized void updateAutoLogoutTimeout(int autoLogoutTimeout) {
- this.autoLogoutTimeout = Duration.ofMinutes(autoLogoutTimeout);
- logger.debug("updated cache autoLogoutTimeout {} minutes", autoLogoutTimeout);
- }
-
synchronized public AppUser getLoginUsr() {
return (loginUsr);
@@ -119,7 +91,6 @@ public class AppUserMgrService {
return (appUsrDao.getAllUsr());
}
-
public AppUser addUser(String account, String password, AppUser.UsrRole type) throws AppException {
var user = appUsrDao.getUsrByAccount(account);
if (user != null) {
@@ -130,7 +101,6 @@ public class AppUserMgrService {
return appUsrDao.getUsrByAccount(account);
}
-
public Void delUser(Integer id) {
appUsrDao.deleteUserById(id);
return null;
diff --git a/src/main/java/a8k/app/service/engineer/state/EngineerModeStateMgrService.java b/src/main/java/a8k/app/service/engineer/state/EngineerModeStateMgrService.java
index 7101070..28d1158 100644
--- a/src/main/java/a8k/app/service/engineer/state/EngineerModeStateMgrService.java
+++ b/src/main/java/a8k/app/service/engineer/state/EngineerModeStateMgrService.java
@@ -13,12 +13,19 @@ import org.springframework.stereotype.Component;
public class EngineerModeStateMgrService {
EngineerModeState state = new EngineerModeState();
+ Integer version = 0;
+
synchronized public EngineerModeState getState() {
return state;
}
+ synchronized public Integer getVersion() {
+ return version;
+ }
+
synchronized public void setEngineerWorkState(EngineerWorkState engineerWorkState) {
state.engineerWorkState = engineerWorkState;
+ version++;
}
diff --git a/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java b/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java
index d39c754..1aaec9b 100644
--- a/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java
+++ b/src/main/java/a8k/app/service/mainctrl/AppDeviceInitCtrlService.java
@@ -31,6 +31,7 @@ import java.util.List;
@RequiredArgsConstructor
public class AppDeviceInitCtrlService {
private final AppEventBusService appEventBusService;
+ private final GStateMgrService gStateMgrService;
public static class Checkpoint {
public enum Type {
@@ -238,6 +239,9 @@ public class AppDeviceInitCtrlService {
if (virtualDevice.isEnable()) {
virtualDevice.doVirtualThings("初始化设备");
gstate.setDeviceInited(true);
+
+
+
return results;
}
diff --git a/src/main/java/a8k/app/service/module/SamplePreProcessModule.java b/src/main/java/a8k/app/service/module/SamplePreProcessModule.java
index 8820190..5a6289d 100644
--- a/src/main/java/a8k/app/service/module/SamplePreProcessModule.java
+++ b/src/main/java/a8k/app/service/module/SamplePreProcessModule.java
@@ -245,7 +245,7 @@ public class SamplePreProcessModule {
actionTaskPool.pushTask(TaskLine.SamplePrepare, () -> {
Tube tube = tubeStateMgrService.getCurProcessingTube();
- TubeHolder tubeHolder = tubeStateMgrService.getTubeHolder();
+ TubeHolder tubeHolder = tubeStateMgrService.getTubeHolderState();
Boolean isHighTube = tube.getIsHighTube();
/*
* 样本预处理,包括脱帽,盖帽,摇匀
@@ -281,7 +281,7 @@ public class SamplePreProcessModule {
//
// 取样本到小缓冲瓶或者探测物质中进行反应
//
- TubeHolder tubeHolder = tubeStateMgrService.getTubeHolder();
+ TubeHolder tubeHolder = tubeStateMgrService.getTubeHolderState();
Tube tube = tubeStateMgrService.getCurProcessingTube();
A8kSamplePos samplePos = ProjectParamUtils.getSamplePos(tubeHolder, tube);
List cxts = tube.getPreProcessContexts();
diff --git a/src/main/java/a8k/app/service/setting/AppSettingsMgrService.java b/src/main/java/a8k/app/service/setting/AppSettingsMgrService.java
index 54dfba7..82cd9b9 100644
--- a/src/main/java/a8k/app/service/setting/AppSettingsMgrService.java
+++ b/src/main/java/a8k/app/service/setting/AppSettingsMgrService.java
@@ -72,14 +72,12 @@ public class AppSettingsMgrService {
DeviceSetting setting = deviceSettingDao.get();
setting.autoLogoutTimeout = val;
deviceSettingDao.update(setting);
- appUserMgrService.updateAutoLogoutTimeout(val);
}
public void setAutoLogout(Boolean val) {
DeviceSetting setting = deviceSettingDao.get();
setting.autoLogout = val;
deviceSettingDao.update(setting);
- appUserMgrService.updateAutoLogout(val);
}
diff --git a/src/main/java/a8k/app/service/statemgr/AppFlagStateMgr.java b/src/main/java/a8k/app/service/statemgr/AppFlagStateMgr.java
index 8144d67..d1abd87 100644
--- a/src/main/java/a8k/app/service/statemgr/AppFlagStateMgr.java
+++ b/src/main/java/a8k/app/service/statemgr/AppFlagStateMgr.java
@@ -1,13 +1,13 @@
package a8k.app.service.statemgr;
-import a8k.app.factory.FakeAppErrorFactory;
import a8k.app.factory.ZAppPromptFactory;
-import a8k.app.channel.iflytophald.type.protocol.A8kEcode;
import a8k.app.i18n.Internationalization;
+import a8k.app.service.DeviceVirtualStateMgrService;
import a8k.app.type.AppFlagKey;
import a8k.app.type.AppFlagType;
import a8k.app.type.DeviceRunMode;
+import a8k.app.type.DeviceWarningFlagStateGroup;
import a8k.app.type.error.AppError;
import a8k.app.type.ui.ZAppPromopt;
import a8k.app.utils.ZJsonHelper;
@@ -17,8 +17,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
@Component
@@ -26,6 +24,8 @@ import java.util.Objects;
@RequiredArgsConstructor
public class AppFlagStateMgr {
+ private final DeviceVirtualStateMgrService deviceVirtualStateMgrService;
+
static public class AppFlagState implements java.io.Serializable {
public boolean state;
public AppFlagType flagType;
@@ -47,40 +47,6 @@ public class AppFlagStateMgr {
}
}
- static public class DeviceWarningFlagStateGroup implements java.io.Serializable {
- public List states = new ArrayList<>();
- public Integer version = 0; //状态版本号
-
- // 别删,被前端使用
- public Boolean isHasWarningTriggerFlag() {
- for (AppFlagState state : states) {
- if (state.flagType.equals(AppFlagType.WarningFlag) && state.state) {
- return true; //如果有任意一个状态为true,则返回true
- }
- }
- return false; //如果没有任意一个状态为true,则返回false
- }
-
- public Boolean isHasErrorTriggerFlag() {
- for (AppFlagState state : states) {
- if (state.flagType.equals(AppFlagType.ErrorFlag) && state.state) {
- return true; //如果有任意一个状态为true,则返回true
- }
- }
- return false; //如果没有任意一个状态为true,则返回false
- }
-
- public AppFlagState find(AppFlagKey appFlagKey) {
- for (AppFlagState state : states) {
- if (state.keyName.equals(appFlagKey)) {
- return state;
- }
- }
- log.error("find: Unknown DeviceWarningFlagState: {}", appFlagKey.name());
- return null; //如果没有找到,返回null
- }
- }
-
private final GStateMgrService gstate;
@@ -97,13 +63,12 @@ public class AppFlagStateMgr {
deviceWarningFlagState.states.add(new AppFlagState(flagKey, flagKey.flagType));
}
lastCpyDeviceWarningFlagState = ObjectUtil.clone(deviceWarningFlagState); //初始化时复制一份状态
- initVirtualState();
-
+ virtualWarningState = deviceVirtualStateMgrService.getDeviceFlagStateVirtualStateInitVal(deviceWarningFlagState);
}
synchronized public DeviceWarningFlagStateGroup getFlagState() {
if (gstate.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
- log.info("virtualWarningState: {}", ZJsonHelper.objectToJson(virtualWarningState));
+// log.info("virtualWarningState: {}", ZJsonHelper.objectToJson(virtualWarningState));
return virtualWarningState;
}
//
@@ -228,51 +193,8 @@ public class AppFlagStateMgr {
return true;
}
- //
- // VIRTUAL_OPERATION
- //
- private void initVirtualState() {
- virtualWarningState = ObjectUtil.clone(deviceWarningFlagState); //初始化时复制一份状态版本号
- virtualWarningState.version = 10000;
-
- //设置VirtualState初始值
- var consumeNotEnoughState = virtualWarningState.find(AppFlagKey.ConsumeNotEnoughState);
- consumeNotEnoughState.state = true; //
- consumeNotEnoughState.errorDetailInfo = FakeAppErrorFactory.buildAEConsumeNotEnoughError();
- consumeNotEnoughState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(consumeNotEnoughState.errorDetailInfo);
-
- var tipNotEnoughState = virtualWarningState.find(AppFlagKey.TipNotEnoughState);
- tipNotEnoughState.state = true; //
- tipNotEnoughState.errorDetailInfo = FakeAppErrorFactory.buildError(A8kEcode.APPE_TIP_NOT_ENOUGH);
- tipNotEnoughState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(tipNotEnoughState.errorDetailInfo);
-
- var infeedExceptionState = virtualWarningState.find(AppFlagKey.InfeedExceptionState);
- infeedExceptionState.state = true; //
- infeedExceptionState.errorDetailInfo = FakeAppErrorFactory.buildAEHardwareError();
- infeedExceptionState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(infeedExceptionState.errorDetailInfo);
-
- var outfeedAreaFullState = virtualWarningState.find(AppFlagKey.OutfeedAreaFullState);
- outfeedAreaFullState.state = true; //
- outfeedAreaFullState.errorDetailInfo = FakeAppErrorFactory.buildError(A8kEcode.APPE_OUTFEED_AREA_IS_FULL);
- outfeedAreaFullState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(outfeedAreaFullState.errorDetailInfo);
-
- var wasteBinFullState = virtualWarningState.find(AppFlagKey.WasteBinFull);
- wasteBinFullState.state = true; //
- wasteBinFullState.errorDetailInfo = FakeAppErrorFactory.buildError(A8kEcode.APPE_WAST_BIN_IS_FULL);
- wasteBinFullState.errorPromptInfo = ZAppPromptFactory.buildAppPrompt(wasteBinFullState.errorDetailInfo);
-
- if (AppFlagKey.InfeedPPSFlag.enabled)
- virtualWarningState.find(AppFlagKey.InfeedPPSFlag).state = true; //入料区光电
- if (AppFlagKey.OutfeedPPSFlag.enabled)
- virtualWarningState.find(AppFlagKey.OutfeedPPSFlag).state = false; //入料区光电
- if (AppFlagKey.TubeholderChannelPPSFlag.enabled)
- virtualWarningState.find(AppFlagKey.TubeholderChannelPPSFlag).state = true; //入料区光电
- if (AppFlagKey.PlateBoxLidPPSState.enabled)
- virtualWarningState.find(AppFlagKey.PlateBoxLidPPSState).state = true; //入料区光电
-
- }
synchronized public void resetVirtualState() {
- initVirtualState();
+ virtualWarningState = deviceVirtualStateMgrService.getDeviceFlagStateVirtualStateInitVal(deviceWarningFlagState);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java b/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java
index 2ad78f9..5c854e7 100644
--- a/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java
+++ b/src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java
@@ -68,25 +68,10 @@ public class ConsumablesMgrService {
@PostConstruct
void init() {
- // for (var ch : ConsumableGroup.values()) {
- // ReactionPlateContainer reactionPlateContainer = appStatePersistenceDao.getReactionPlateContainer(ch);
- // if (reactionPlateContainer == null)
- // continue;
- //
- // if (!reactionPlateContainer.isInstall)
- // continue;
- //
- // try {
- // installConsumable(ch.off, reactionPlateContainer.projId, reactionPlateContainer.lotId);
- // } catch (AppException ignored) {
- // }
- // }
-
}
//耗材状态
- // private final A8kConsumableContainer cState = new A8kConsumableContainer();
private Integer stateVersion = 0;
@@ -185,6 +170,10 @@ public class ConsumablesMgrService {
ReactionPlateContainerInfo reactionPlateContainerInfo,
LittBottleConsumablesInfo littBottleConsumablesInfo,
LargeBottleConsumablesInfo largeBottleConsumablesInfo) {
+
+ reactionPlateContainerStateMgr.uninstall(ConsumableGroup.of(ch));
+ littBottleContainerStateMgr.uninstall(ConsumableGroup.of(ch));
+ larBottleContainerStateMgr.uninstall(ConsumableGroup.of(ch));
if (reactionPlateContainerInfo != null) {
reactionPlateContainerStateMgr.install(Objects.requireNonNull(ConsumableGroup.of(ch)), reactionPlateContainerInfo);
}
@@ -221,44 +210,53 @@ public class ConsumablesMgrService {
LittBottleConsumablesInfo littBottleConsumablesInfo = null;
LargeBottleConsumablesInfo largeBottleConsumablesInfo = null;
- if (reactionType.equals(A8kReactionFlowType.SampleAndBS)) {
- reactionPlateContainer = new ReactionPlateContainerInfo(
- projId,
- projExtInfoCard.projName,
- projCfg.projShortName,
- lotid,
- projExtInfoCard.color);
-
- littBottleConsumablesInfo = new LittBottleConsumablesInfo(
- LittleBottleConsumableType.BufferSolution,
- projId,
- projExtInfoCard.projName,
- projCfg.projShortName,
- lotid,
- projExtInfoCard.color);
-
- } else if (reactionType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) {
- reactionPlateContainer = new ReactionPlateContainerInfo(
- projId,
- projExtInfoCard.projName,
- projCfg.projShortName,
- lotid,
- projExtInfoCard.color);
- littBottleConsumablesInfo = new LittBottleConsumablesInfo(
- LittleBottleConsumableType.ProbeSubstance,
- projId,
- projExtInfoCard.projName,
- projCfg.projShortName,
- lotid,
- projExtInfoCard.color);
- largeBottleConsumablesInfo = new LargeBottleConsumablesInfo(
- projId,
- projExtInfoCard.projName,
- projCfg.projShortName,
- lotid,
- projExtInfoCard.color);
- } else {
- throw new RuntimeException("未知的反应流程类型");
+ switch (reactionType) {
+ case SampleAndBS -> {
+ reactionPlateContainer = new ReactionPlateContainerInfo(
+ projId,
+ projExtInfoCard.projName,
+ projCfg.projShortName,
+ lotid,
+ projExtInfoCard.color);
+
+ littBottleConsumablesInfo = new LittBottleConsumablesInfo(
+ LittleBottleConsumableType.BufferSolution,
+ projId,
+ projExtInfoCard.projName,
+ projCfg.projShortName,
+ lotid,
+ projExtInfoCard.color);
+
+ }
+ case SampleAndBSAndProbeSubstance -> {
+ reactionPlateContainer = new ReactionPlateContainerInfo(
+ projId,
+ projExtInfoCard.projName,
+ projCfg.projShortName,
+ lotid,
+ projExtInfoCard.color);
+ littBottleConsumablesInfo = new LittBottleConsumablesInfo(
+ LittleBottleConsumableType.ProbeSubstance,
+ projId,
+ projExtInfoCard.projName,
+ projCfg.projShortName,
+ lotid,
+ projExtInfoCard.color);
+ largeBottleConsumablesInfo = new LargeBottleConsumablesInfo(
+ projId,
+ projExtInfoCard.projName,
+ projCfg.projShortName,
+ lotid,
+ projExtInfoCard.color);
+ }
+ case SampleOnly -> {
+ reactionPlateContainer = new ReactionPlateContainerInfo(
+ projId,
+ projExtInfoCard.projName,
+ projCfg.projShortName,
+ lotid,
+ projExtInfoCard.color);
+ }
}
//更新耗材
diff --git a/src/main/java/a8k/app/service/statemgr/DeviceWorkStateMgrService.java b/src/main/java/a8k/app/service/statemgr/DeviceWorkStateMgrService.java
index 3e270b1..f0f03c0 100644
--- a/src/main/java/a8k/app/service/statemgr/DeviceWorkStateMgrService.java
+++ b/src/main/java/a8k/app/service/statemgr/DeviceWorkStateMgrService.java
@@ -18,6 +18,7 @@ import java.util.List;
public class DeviceWorkStateMgrService {
final private GStateMgrService gstate;
DeviceWorkState deviceWorkState = new DeviceWorkState();
+ Integer version = 0;
synchronized public DeviceWorkState getDeviceWorkState() {
@@ -29,6 +30,9 @@ public class DeviceWorkStateMgrService {
return deviceWorkState;
}
+ synchronized public Integer getVersion() {
+ return version;
+ }
//
// WORK STATE GETTER AND SETTER
@@ -36,14 +40,19 @@ public class DeviceWorkStateMgrService {
synchronized public void setStopActionPending(Boolean stopActionPending) {
deviceWorkState.stopActionPending = stopActionPending;
+ version++;
}
synchronized public void setPauseActionPending(Boolean pauseActionPending) {
deviceWorkState.pauseActionPending = pauseActionPending;
+ version++;
+
}
synchronized public void setResumeActionPending(Boolean resumeActionPending) {
deviceWorkState.resumeActionPending = resumeActionPending;
+ version++;
+
}
synchronized public void setStartActionPending(A8kWorkTaskType workTaskType, Boolean startActionPending) {
@@ -52,17 +61,43 @@ public class DeviceWorkStateMgrService {
deviceWorkState.stopActionPending = false;
deviceWorkState.pauseActionPending = false;
deviceWorkState.resumeActionPending = false;
+ version++;
+
}
synchronized public void clearPending() {
deviceWorkState.clearPending();
+ version++;
+
}
synchronized public void updateWorkState(A8kWorkState workState) {
deviceWorkState.lastWorkState = deviceWorkState.workState;
deviceWorkState.workState = workState;
+ version++;
+
+ }
+
+ synchronized public void setFatalErrorFlag(AppError appError) {
+ gstate.setFatalError(appError);
+ deviceWorkState.fatalErrorFlag = true;
+ version++;
+
+ }
+
+ synchronized public void clearFatalErrorFlag() {
+ gstate.clearFatalError();
+ deviceWorkState.fatalErrorFlag = false;
+ version++;
+
+ }
+
+ synchronized public void setMayHaveNewTubeHolder(Boolean val) {
+ deviceWorkState.mayHaveNewTubeHolder = val;
+ version++;
+
}
@@ -109,15 +144,6 @@ public class DeviceWorkStateMgrService {
// ERROR FLAG FUNCTIONS
//
- synchronized public void setFatalErrorFlag(AppError appError) {
- gstate.setFatalError(appError);
- deviceWorkState.fatalErrorFlag = true;
- }
-
- synchronized public void clearFatalErrorFlag() {
- gstate.clearFatalError();
- deviceWorkState.fatalErrorFlag = false;
- }
//
// SOME FLAGS
@@ -126,8 +152,5 @@ public class DeviceWorkStateMgrService {
return deviceWorkState.mayHaveNewTubeHolder;
}
- synchronized public void setMayHaveNewTubeHolder(Boolean val) {
- deviceWorkState.mayHaveNewTubeHolder = val;
- }
}
diff --git a/src/main/java/a8k/app/service/statemgr/GStateMgrService.java b/src/main/java/a8k/app/service/statemgr/GStateMgrService.java
index 245fef1..07aade1 100644
--- a/src/main/java/a8k/app/service/statemgr/GStateMgrService.java
+++ b/src/main/java/a8k/app/service/statemgr/GStateMgrService.java
@@ -1,6 +1,7 @@
package a8k.app.service.statemgr;
import a8k.app.i18n.Internationalization;
+import a8k.app.service.DeviceVirtualStateMgrService;
import a8k.app.type.BoardVersions;
import a8k.app.type.DeviceRunMode;
import a8k.app.type.GState;
@@ -20,6 +21,7 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class GStateMgrService {
private final GState gState;
+ private final DeviceVirtualStateMgrService deviceVirtualStateMgrService;
public synchronized Boolean isDeviceInited() {
@@ -35,16 +37,9 @@ public class GStateMgrService {
}
- Integer i = 0;
-
public synchronized SensorState getSensorState() {
if (isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
- SensorState sensorState = new SensorState();
- sensorState.setPboxTemperature(-i % 40);
- sensorState.setIncubateBoxTemperature(i % 40);
- sensorState.setWasteBinFullFlag((i / 100) % 2 == 0);
- i++;
- return sensorState;
+ return deviceVirtualStateMgrService.getVirtualSensorState();
}
return this.gState.sensorState;
}
diff --git a/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgr.java b/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgr.java
index a295826..e002992 100644
--- a/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgr.java
+++ b/src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgr.java
@@ -2,6 +2,7 @@ package a8k.app.service.statemgr;
import a8k.app.factory.ZAppPromptFactory;
import a8k.app.channel.iflytophald.type.protocol.A8kEcode;
+import a8k.app.service.DeviceVirtualStateMgrService;
import a8k.app.type.DeviceRunMode;
import a8k.app.type.a8k.BloodType;
import a8k.app.type.a8k.pos.ConsumableInfo;
@@ -18,6 +19,7 @@ import a8k.app.service.utils.ProjInfoUtils;
import a8k.app.utils.ZTimeUtils;
import cn.hutool.core.util.ObjectUtil;
import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -28,6 +30,7 @@ import java.util.List;
@Component
@Slf4j
+@RequiredArgsConstructor
public class IncubationPlateStateMgr {
@FunctionalInterface
@@ -35,61 +38,19 @@ public class IncubationPlateStateMgr {
void syncState(IncubatorPos pos);
}
- @Resource
- GStateMgrService gStateMgrService;
+ private final GStateMgrService gStateMgrService;
+ private final DeviceVirtualStateMgrService deviceVirtualStateMgrService;
//孵育盘状态
private final IncubationPlate incubationPlate = new IncubationPlate();
synchronized public IncubationPlate get() {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
- return getVirtualState();
+ return deviceVirtualStateMgrService.getVirtualIncubationPlateState();
}
return ObjectUtil.cloneByStream(incubationPlate);
}
- synchronized public IncubationPlate getVirtualState() {
- IncubationPlate incubationPlate = new IncubationPlate();
- int i = 0;
- for (IncubationSubTank subtank : incubationPlate.subtanks) {
- i++;
- switch (i % 6) {
- case 0 -> subtank.state = IncubationSubTankState.EMPTY;
- case 1 -> subtank.state = IncubationSubTankState.RESERVED;
- case 2 -> subtank.state = IncubationSubTankState.INCUBATING;
- case 3 -> subtank.state = IncubationSubTankState.INCUBATION_COMPLETE;
- case 4 -> subtank.state = IncubationSubTankState.ERROR;
- case 5 -> subtank.state = IncubationSubTankState.WAITING_FOR_DROP;
- }
-
- subtank.sampleInfo = new SampleInfo(
- "250109_001E01", 0, false, false, BloodType.WHOLE_BLOOD, "112334455667", "250109_001E"
- );
-
-
- subtank.sampleInfo.bloodType = BloodType.WHOLE_BLOOD;
- subtank.sampleInfo.sampleBarcode = "112334455667";
- subtank.sampleInfo.userid = "250109_001E";
- subtank.projInfo = new ProjBriefInfo();
- subtank.projInfo.projId = 1;
- subtank.projInfo.projName = "hsCRP";
- subtank.projInfo.projShortName = "CA";
- subtank.projInfo.color = "#DC143C";
- subtank.sampleInfo.sampleId = "250109_001E01";
- subtank.projId = 1;
- subtank.lotId = "CA123456";
- subtank.isEmergency = i % 2 == 0;
- if (subtank.state.equals(IncubationSubTankState.ERROR)) {
- subtank.error = new AppError(A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED, "");
- subtank.errorInfo = ZAppPromptFactory.buildAppPrompt(subtank.error);
- }
- 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];
}
diff --git a/src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgr.java b/src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgr.java
index fc51e62..e38c93f 100644
--- a/src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgr.java
+++ b/src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgr.java
@@ -22,6 +22,9 @@ public class OptScanModuleStateMgr {
@Resource
GStateMgrService gStateMgrService;
+
+ Integer version = 0;
+
//光学模组状态
private final OptScanModuleState optScanModule = new OptScanModuleState();
@@ -39,6 +42,7 @@ public class OptScanModuleStateMgr {
synchronized public void setCleared(Boolean cleared) {
optScanModule.setCleared(cleared);
+ version++;
}
synchronized public IncubationRecordInfo getIncubationRecordInfo() {
@@ -60,12 +64,20 @@ public class OptScanModuleStateMgr {
return ObjectUtil.cloneByStream(optScanModule);
}
+ synchronized public Integer getStateVersion() {
+ if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
+ return 1;
+ }
+ return version;
+ }
+
synchronized public void changeOptScanModuleStateToEmpty() {
optScanModule.state = OptScanModuleStateEnum.EMPTY;
optScanModule.sampleInfo = SampleInfo.createEmpty();
optScanModule.setProjInfo(null);
optScanModule.setProjId(null);
log.info("光学模块: 状态->空闲");
+ version++;
}
synchronized public void changeOptScanModuleStateToPlateIsReady(String cxtid, SampleInfo sampleInfo, IncubationRecordInfo incubationRecordInfo, ProjBuildInInfo projBuildinInfo,
@@ -80,12 +92,14 @@ public class OptScanModuleStateMgr {
optScanModule.setCxtId(cxtid);
optScanModule.setIncubationRecordInfo(incubationRecordInfo);
log.info("光学模块:状态->反应板准备就绪 {}", sampleInfo);
+ version++;
}
synchronized public void changeOptScanModuleStateToScanning() {
log.info("光学模块: 状态->开始扫描");
optScanModule.state = OptScanModuleStateEnum.SCANNING;
+ version++;
}
diff --git a/src/main/java/a8k/app/service/statemgr/PreReactionStateMgr.java b/src/main/java/a8k/app/service/statemgr/PreReactionStateMgr.java
index 468b5fa..aa2670e 100644
--- a/src/main/java/a8k/app/service/statemgr/PreReactionStateMgr.java
+++ b/src/main/java/a8k/app/service/statemgr/PreReactionStateMgr.java
@@ -2,6 +2,7 @@ package a8k.app.service.statemgr;
import a8k.app.constant.AppConstant;
import a8k.app.factory.FakeA8kConsumableContainerFactory;
+import a8k.app.service.DeviceVirtualStateMgrService;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.service.utils.ProjInfoUtils;
import a8k.app.type.DeviceRunMode;
@@ -32,6 +33,7 @@ public class PreReactionStateMgr {
private final ProjInfoMgrService projInfoMgrService;
private final GStateMgrService gStateMgrService;
+ private final DeviceVirtualStateMgrService deviceVirtualStateMgrService;
PreReactionPosState preReactionPosState = new PreReactionPosState();
@@ -39,57 +41,11 @@ public class PreReactionStateMgr {
return ObjectUtil.cloneByStream(preReactionPosState);
}
- private PreReactionGridGroup buildFakePreReactionGridGroup(ConsumableGroup group) {
- PreReactionGridGroup gridGroup = new PreReactionGridGroup(group);
- gridGroup.group = group;
- if (group.off % 2 == 0) {
- gridGroup.installed = true;
- gridGroup.hasSomeGridInReacting = true;
- gridGroup.hasSomeGridReactedCompleted = true;
- } else {
- gridGroup.installed = false;
- gridGroup.hasSomeGridInReacting = false;
- gridGroup.hasSomeGridReactedCompleted = false;
- }
- gridGroup.consumableType = LittleBottleConsumableType.BufferSolution;
- var projBuildInInfo = FakeA8kConsumableContainerFactory.buildFakeProjBuildInInfo(group.off);
- gridGroup.projBriefInfo = ProjInfoUtils.buildProjBrefInfo(projBuildInInfo);
- gridGroup.version = 10;
- for (int i = 0; i < AppConstant.CONSUMABLE_NUM; i++) {
-
- gridGroup.grids.get(i).projId = projBuildInInfo.projId;
- gridGroup.grids.get(i).projBuildinInfo = projBuildInInfo;
- gridGroup.grids.get(i).projExtInfoCard = null;
-
- switch (i / 5) {
- case 0 -> {
- gridGroup.grids.get(i).state = PreReactionGrid.State.UNINSTALL;
- }
- case 1 -> {
- gridGroup.grids.get(i).state = PreReactionGrid.State.USED;
- }
-
- case 2 -> {
- gridGroup.grids.get(i).state = PreReactionGrid.State.REACTION_COMPLETED;
- gridGroup.grids.get(i).sampleInfo.userid = "FAKE-UID-123";
- }
- case 3 -> {
- gridGroup.grids.get(i).state = PreReactionGrid.State.REACTING;
- gridGroup.grids.get(i).sampleInfo.userid = "FAKE-UID-121";
- gridGroup.grids.get(i).reactionRemainingTime = i * 60L;
- }
- case 4 -> {
- gridGroup.grids.get(i).state = PreReactionGrid.State.TO_BE_USED;
- }
- }
- }
- return gridGroup;
- }
public synchronized PreReactionGridGroup getPreReactionGridGroupState(ConsumableGroup group) {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
- return buildFakePreReactionGridGroup(group);
+ return deviceVirtualStateMgrService.getFakePreReactionGridGroup(group);
}
PreReactionGridGroup gridGroup = getPreReactionGridGroup(group);
return ObjectUtil.cloneByStream(gridGroup);
@@ -106,7 +62,7 @@ public class PreReactionStateMgr {
public synchronized Integer getPreReactionGridGroupVersion(ConsumableGroup group) {
if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
- return buildFakePreReactionGridGroup(group).version;
+ return deviceVirtualStateMgrService.getFakePreReactionGridGroup(group).version;
}
PreReactionGridGroup gridGroup = getPreReactionGridGroup(group);
diff --git a/src/main/java/a8k/app/service/statemgr/TubeStateMgr.java b/src/main/java/a8k/app/service/statemgr/TubeStateMgr.java
index 726ace6..dd9b5a0 100644
--- a/src/main/java/a8k/app/service/statemgr/TubeStateMgr.java
+++ b/src/main/java/a8k/app/service/statemgr/TubeStateMgr.java
@@ -1,9 +1,8 @@
package a8k.app.service.statemgr;
import a8k.app.dao.type.db.DeviceStatistic;
-import a8k.app.factory.FakeA8kConsumableContainerFactory;
-import a8k.app.factory.FakeAppErrorFactory;
import a8k.app.factory.ZAppPromptFactory;
+import a8k.app.service.DeviceVirtualStateMgrService;
import a8k.app.service.analyzer.ConsumableStateAnalyzerService;
import a8k.app.type.DeviceRunMode;
import a8k.app.type.a8k.pos.ConsumableInfo;
@@ -26,7 +25,6 @@ import a8k.app.dao.type.combination.ProjBuildInInfo;
import a8k.app.service.utils.ProjInfoUtils;
import a8k.app.service.utils.ZAppChecker;
import a8k.app.utils.ZJsonHelper;
-import a8k.app.utils.ZList;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -48,6 +46,7 @@ public class TubeStateMgr {
private final ProjInfoMgrService projInfoMgrService;
private final ConsumablesMgrService consumablesMgrService;
private final ConsumableStateAnalyzerService consumableStateAnalyzerService;
+ private final DeviceVirtualStateMgrService deviceVirtualStateMgrService;
private final SampleRecordDBDao sampleRecordDBDao;
@@ -58,58 +57,34 @@ public class TubeStateMgr {
private final TubeHolder tubeHolder = new TubeHolder(); //当前正在被处理的试管架状态
private final EmergencyTubePos emergencyTubePos = new EmergencyTubePos(); //急诊为状态
private Tube curProcessingTube;
+ private Integer version = 0;
- private String priGenerateSampleId(Integer tubePos, Boolean isEmergency) {
- String sampleid = "";
- Integer cnt = 0;
- Date date = new Date();
- SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
- if (isEmergency) {
- cnt = deviceStatisticDao.get(DeviceStatistic.StatisticType.EmergencyTubeCnt, date);
- sampleid = String.format("%s_%sE", sdf.format(date), cnt);
- deviceStatisticDao.setCnt(DeviceStatistic.StatisticType.EmergencyTubeCnt, date, cnt + 1);
- } else {
- cnt = deviceStatisticDao.get(DeviceStatistic.StatisticType.TubeHolderCnt, date);
- sampleid = String.format("%s_%d%02d", sdf.format(date), cnt, tubePos + 1);
- deviceStatisticDao.setCnt(DeviceStatistic.StatisticType.TubeHolderCnt, date, cnt + 1);
+ synchronized public EmergencyTubePos getEmergencyPosRunState() {
+ if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
+ return deviceVirtualStateMgrService.getVirtualEmergencyTube();
}
- return sampleid;
+ return ObjectUtil.cloneByStream(emergencyTubePos);
}
- private void assignSampleRecord(Tube tube, SampleRecord sampleRecord) {
- sampleRecord.bloodType = tube.getBloodType();
- sampleRecord.isEmergency = tube.getIsEmergency();
- sampleRecord.sampleBarcode = tube.getSampleBarcode();
- if (tube.getUserid() == null || tube.getUserid().isEmpty()) {
- sampleRecord.userid = sampleRecord.sampleid;
- } else {
- sampleRecord.userid = tube.getUserid();
+ public synchronized TubeHolder getTubeHolderState() {
+ if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
+ return deviceVirtualStateMgrService.getVirtualTubeHolderState();
}
- sampleRecord.projIds = tube.getProjIds();
+ return ObjectUtil.cloneByStream(tubeHolder);
}
-
- private void updateSampleInfo(Tube tube) {
- SampleRecord sampleRecord = sampleRecordDBDao.findBySampleId(tube.getSampleId());
- if (sampleRecord == null) {
- return;
- }
- assignSampleRecord(tube, sampleRecord);
- sampleRecordDBDao.update(sampleRecord);
+ public synchronized Integer getVersion() {
+ return version;
}
- private void deleteSampleInfo(String sampleId) {
- sampleRecordDBDao.deleteBySampleId(sampleId);
-
- }
/**
* 向样本数据库中插入一个新的样本信息,并返回唯一的样本ID
* @param tube 试管
* @return 样本ID
*/
- public String newSample(Tube tube) {
+ private String newSample(Tube tube) {
SampleRecord sampleRecord = new SampleRecord();
sampleRecord.sampleid = priGenerateSampleId(tube.getPos(), tube.getIsEmergency());
sampleRecord.createDate = new Date();
@@ -131,18 +106,6 @@ public class TubeStateMgr {
return new ProjectPreProcessContext(sampleInfo, consumableInfo, projId, projBuildinInfo, projExtInfoCard, off);
}
- public synchronized void initTubeByTubeInfo(Tube tube, TubeInfo tubeInfo) {
- if (!tubeInfo.isHasTube) {
- tube.reset();
- return;
- }
-
- if (tubeInfo.projIds.isEmpty()) {
- tube.reset();
- return;
- }
- }
-
//
//试管状态管理
@@ -209,7 +172,7 @@ public class TubeStateMgr {
tubeHolder.reset();
throw e;
}
-
+ version++;
}
@@ -288,6 +251,8 @@ public class TubeStateMgr {
}
throw e;
}
+ version++;
+
}
synchronized public void setTubeCxtIncubationPos(ProjectPreProcessContext cxt, IncubatorPos pos) {
@@ -296,6 +261,9 @@ public class TubeStateMgr {
return;
}
+ version++;
+
+
if (emergencyTubePos.tube != null) {
for (ProjectPreProcessContext context : emergencyTubePos.tube.getPreProcessContexts()) {
if (context.getCxtId().equals(cxt.getCxtId())) {
@@ -341,83 +309,6 @@ public class TubeStateMgr {
return ObjectUtil.cloneByStream(tubeHolder.getTubes()[pos]);
}
- 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));
-
- var toBeUsedPBI = ZList.of(
- FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(0),
- FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(1),
- FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(2),
- FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(3),
- FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(4),
- FakeA8kConsumableContainerFactory.buildFakeProjBriefInfo(5)
- );
-
- for (int i = 0; i < pos; i++) {
- if (i >= 6)
- break;
- if (i < toBeUsedPBI.size()) {
- tube.getProjInfo().add(toBeUsedPBI.get(i));
- tube.getProjIds().add(toBeUsedPBI.get(i).projId);
- }
- }
-
- switch (pos) {
- case 0 -> tube.setState(TubeState.TO_BE_PROCESSED);
- case 1 -> tube.setState(TubeState.PENDING);
- case 2 -> tube.setState(TubeState.RESOURCE_IS_READY);
- case 3 -> tube.setState(TubeState.PROCESSING);
- case 4, 5, 7, 8 -> tube.setState(TubeState.PROCESS_COMPLETE);
- case 6 -> {
- tube.setState(TubeState.ERROR);
- tube.setError(FakeAppErrorFactory.buildAEConsumeNotEnoughError());
- tube.setErrorInfo(ZAppPromptFactory.buildAppPrompt(tube.getError()));
- }
- case 9 -> tube.setState(TubeState.EMPTY);
- }
- tube.setIsHighTube(pos % 2 == 0); //假设偶数位置为高位管
-
-
- return tube;
- }
-
-
- synchronized public EmergencyTubePos getEmergencyPosRunState() {
- if (gStateMgrService.isInMode(DeviceRunMode.VirtualStateGenerateMode)) {
- var tubePosState = new EmergencyTubePos();
- tubePosState.tube = createFakeTube(3);
- tubePosState.tube.setPos(0);
- tubePosState.tube.setIsEmergency(true);
- 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);
- }
//
// STATE CHANGE HELPER
@@ -431,17 +322,23 @@ public class TubeStateMgr {
log.info("挂起一个待处理试管 SampleId:{} \n{}", curProcessingTube.getSampleId(), ZJsonHelper.objectToJson(curProcessingTube));
curProcessingTube.setState(TubeState.PENDING);
+ version++;
+
}
synchronized public void changeTubeStateToResourceIsReady() {
log.info("试管 状态->资源准备就绪 SampleId:{}", curProcessingTube.getSampleId());
curProcessingTube.setState(TubeState.RESOURCE_IS_READY);
+ version++;
+
}
synchronized public void changeTubeStateToProcessing() {
log.info("试管 状态->处理中 SampleId:{}", curProcessingTube.getSampleId());
curProcessingTube.setState(TubeState.PROCESSING);
+ version++;
+
}
@@ -451,17 +348,23 @@ public class TubeStateMgr {
curProcessingTube.setError(error);
curProcessingTube.setErrorInfo(ZAppPromptFactory.buildAppPrompt(error));
curProcessingTube = null;
+ version++;
+
}
synchronized public void changeTubeStateToProcessComplete() {
log.info("试管 状态->处理完成 SampleId:{}", curProcessingTube.getSampleId());
curProcessingTube.setState(TubeState.PROCESS_COMPLETE);
curProcessingTube = null;
+ version++;
+
}
synchronized public void changeTubeHolderStateToIDLE() {
log.info("试管架 状态->空闲");
tubeHolder.reset();
+ version++;
+
}
synchronized public void resetAll() {
@@ -469,6 +372,8 @@ public class TubeStateMgr {
curProcessingTube = null;
tubeHolder.reset();
emergencyTubePos.tube.setState(TubeState.EMPTY);
+ version++;
+
}
@@ -486,6 +391,7 @@ public class TubeStateMgr {
}
}
//没有下一个试管
+ version++;
return nextTubeIndex;
}
@@ -529,4 +435,48 @@ public class TubeStateMgr {
}
+ private String priGenerateSampleId(Integer tubePos, Boolean isEmergency) {
+ String sampleid = "";
+ Integer cnt = 0;
+ Date date = new Date();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
+ if (isEmergency) {
+ cnt = deviceStatisticDao.get(DeviceStatistic.StatisticType.EmergencyTubeCnt, date);
+ sampleid = String.format("%s_%sE", sdf.format(date), cnt);
+ deviceStatisticDao.setCnt(DeviceStatistic.StatisticType.EmergencyTubeCnt, date, cnt + 1);
+ } else {
+ cnt = deviceStatisticDao.get(DeviceStatistic.StatisticType.TubeHolderCnt, date);
+ sampleid = String.format("%s_%d%02d", sdf.format(date), cnt, tubePos);
+ deviceStatisticDao.setCnt(DeviceStatistic.StatisticType.TubeHolderCnt, date, cnt + 1);
+ }
+ return sampleid;
+ }
+
+ private void assignSampleRecord(Tube tube, SampleRecord sampleRecord) {
+ sampleRecord.bloodType = tube.getBloodType();
+ sampleRecord.isEmergency = tube.getIsEmergency();
+ sampleRecord.sampleBarcode = tube.getSampleBarcode();
+ if (tube.getUserid() == null || tube.getUserid().isEmpty()) {
+ sampleRecord.userid = sampleRecord.sampleid;
+ } else {
+ sampleRecord.userid = tube.getUserid();
+ }
+ sampleRecord.projIds = tube.getProjIds();
+ }
+
+
+ private void updateSampleInfo(Tube tube) {
+ SampleRecord sampleRecord = sampleRecordDBDao.findBySampleId(tube.getSampleId());
+ if (sampleRecord == null) {
+ return;
+ }
+ assignSampleRecord(tube, sampleRecord);
+ sampleRecordDBDao.update(sampleRecord);
+ }
+
+ private void deleteSampleInfo(String sampleId) {
+ sampleRecordDBDao.deleteBySampleId(sampleId);
+
+ }
+
}
diff --git a/src/main/java/a8k/app/type/DeviceWarningFlagStateGroup.java b/src/main/java/a8k/app/type/DeviceWarningFlagStateGroup.java
new file mode 100644
index 0000000..6a46388
--- /dev/null
+++ b/src/main/java/a8k/app/type/DeviceWarningFlagStateGroup.java
@@ -0,0 +1,40 @@
+package a8k.app.type;
+
+import a8k.app.service.statemgr.AppFlagStateMgr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DeviceWarningFlagStateGroup implements java.io.Serializable {
+ public List states = new ArrayList<>();
+ public Integer version = 0; //状态版本号
+
+ // 别删,被前端使用
+ public Boolean isHasWarningTriggerFlag() {
+ for (AppFlagStateMgr.AppFlagState state : states) {
+ if (state.flagType.equals(AppFlagType.WarningFlag) && state.state) {
+ return true; //如果有任意一个状态为true,则返回true
+ }
+ }
+ return false; //如果没有任意一个状态为true,则返回false
+ }
+
+ public Boolean isHasErrorTriggerFlag() {
+ for (AppFlagStateMgr.AppFlagState state : states) {
+ if (state.flagType.equals(AppFlagType.ErrorFlag) && state.state) {
+ return true; //如果有任意一个状态为true,则返回true
+ }
+ }
+ return false; //如果没有任意一个状态为true,则返回false
+ }
+
+ public AppFlagStateMgr.AppFlagState find(AppFlagKey appFlagKey) {
+ for (AppFlagStateMgr.AppFlagState state : states) {
+ if (state.keyName.equals(appFlagKey)) {
+ return state;
+ }
+ }
+// AppFlagStateMgr.log.error("find: Unknown DeviceWarningFlagState: {}", appFlagKey.name());
+ return null; //如果没有找到,返回null
+ }
+}
diff --git a/src/main/java/a8k/app/type/GState.java b/src/main/java/a8k/app/type/GState.java
index c575a3b..ecc7010 100644
--- a/src/main/java/a8k/app/type/GState.java
+++ b/src/main/java/a8k/app/type/GState.java
@@ -24,9 +24,9 @@ public class GState {
public String mcuVersion = "";
public BoardVersions mcuVersionDetail = new BoardVersions(); //MCU版本详细信息
//设备SN
- public String sn = "TEST001";//
+ public String sn = "TEST001";// 巴迪泰 叫做 工厂序列号(FactorySerial)
//
- public String assetId = "TEST001";// 资产ID
+ public String assetId = "TEST001";// 巴迪泰 叫做 出厂序列号(DeviceSerial)
//
public Boolean fatalError = false;
//
diff --git a/src/main/java/a8k/app/type/a8k/state/Tube.java b/src/main/java/a8k/app/type/a8k/state/Tube.java
index 88292a8..8227db0 100644
--- a/src/main/java/a8k/app/type/a8k/state/Tube.java
+++ b/src/main/java/a8k/app/type/a8k/state/Tube.java
@@ -20,7 +20,7 @@ public class Tube implements Serializable {
@Schema(description = "样本ID,系统生成-唯一标识一个样本")
String sampleId; //样本ID-系统生成-唯一标识一个样本
@Schema(description = "样本在样本架上的位置")
- Integer pos = -1; //样本在样本架上的位置
+ Integer pos = -1; //样本在样本架上的位置 1->10
@Schema(description = "是否高位管")
Boolean isHighTube = false;
diff --git a/src/main/java/a8k/app/type/a8k/state/TubeHolder.java b/src/main/java/a8k/app/type/a8k/state/TubeHolder.java
index db445b0..494f608 100644
--- a/src/main/java/a8k/app/type/a8k/state/TubeHolder.java
+++ b/src/main/java/a8k/app/type/a8k/state/TubeHolder.java
@@ -18,13 +18,11 @@ public class TubeHolder implements Serializable {
public TubeHolder() {
for (int i = 0; i < tubes.length; i++) {
- tubes[i] = new Tube(i);
+ tubes[i] = new Tube(i + 1);
}
}
-
-
public void reset() {
this.state = TubeHolderState.IDLE;
for (Tube tube : tubes) {
diff --git a/src/main/java/a8k/app/type/appevent/AppLoginEvent.java b/src/main/java/a8k/app/type/appevent/AppLoginEvent.java
new file mode 100644
index 0000000..83c5720
--- /dev/null
+++ b/src/main/java/a8k/app/type/appevent/AppLoginEvent.java
@@ -0,0 +1,12 @@
+package a8k.app.type.appevent;
+
+import a8k.app.dao.type.db.AppUser;
+
+public class AppLoginEvent extends AppEvent {
+ public AppUser user;
+
+ public AppLoginEvent(AppUser user) {
+ super(AppLoginEvent.class.getSimpleName());
+ this.user = user;
+ }
+}
diff --git a/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrame.java b/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrame.java
index 804c5d6..9ad346f 100644
--- a/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrame.java
+++ b/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrame.java
@@ -8,7 +8,7 @@ public class BiLisDoubleTrackFrame {
public static final Integer PACKET_MAX_LENGTH = 1024; // 最大包长度
public static final byte STX = 0x02; // Start of Text
- public static final byte FN = 0x01; // Start of Text
+ public static final char FN = '1'; // Start of Text
public static final byte ETB = 0x17; // End of Text Block
public static final byte CR = 0x0D; // Carriage Return
public static final byte LF = 0x0A; // Line Feed
diff --git a/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrameBuildContext.java b/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrameBuildContext.java
new file mode 100644
index 0000000..c173c72
--- /dev/null
+++ b/src/main/java/a8k/app/type/lisprotocol/BiLisDoubleTrackFrameBuildContext.java
@@ -0,0 +1,10 @@
+package a8k.app.type.lisprotocol;
+
+public class BiLisDoubleTrackFrameBuildContext {
+ public BiLisDoubleTrackFrame frame;
+ public byte[] frameBytes;
+ public String frameContentStr;
+ public char[] checksum;
+ public Boolean buildSuccess = true;
+
+}
diff --git a/src/main/java/a8k/extui/page/debug/P12TueStateDebugPage.java b/src/main/java/a8k/extui/page/debug/P12TueStateDebugPage.java
index 9801353..818505f 100644
--- a/src/main/java/a8k/extui/page/debug/P12TueStateDebugPage.java
+++ b/src/main/java/a8k/extui/page/debug/P12TueStateDebugPage.java
@@ -18,57 +18,57 @@ public class P12TueStateDebugPage {
@ExtApiStatu(name = "", group = "试管架状态", minWidth = "100%", order = 1)
public TubeHolder getTubeHolder() {
- return tubeStateMgrService.getTubeHolder();
+ return tubeStateMgrService.getTubeHolderState();
}
@ExtApiStatu(name = "", group = "试管1", order = 2)
public Tube getTube0State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[0];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[0];
}
@ExtApiStatu(name = "", group = "试管2", order = 3)
public Tube getTube1State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[1];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[1];
}
@ExtApiStatu(name = "", group = "试管3", order = 4)
public Tube getTube2State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[2];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[2];
}
@ExtApiStatu(name = "", group = "试管4", order = 5)
public Tube getTube3State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[3];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[3];
}
@ExtApiStatu(name = "", group = "试管5", order = 6)
public Tube getTube4State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[4];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[4];
}
@ExtApiStatu(name = "", group = "试管6", order = 7)
public Tube getTube5State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[5];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[5];
}
@ExtApiStatu(name = "", group = "试管7", order = 8)
public Tube getTube6State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[6];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[6];
}
@ExtApiStatu(name = "", group = "试管8", order = 9)
public Tube getTube7State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[7];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[7];
}
@ExtApiStatu(name = "", group = "试管9", order = 10)
public Tube getTube8State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[8];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[8];
}
@ExtApiStatu(name = "", group = "试管10", order = 11)
public Tube getTube9State() {
- return tubeStateMgrService.getTubeHolder().getTubes()[9];
+ return tubeStateMgrService.getTubeHolderState().getTubes()[9];
}
diff --git a/src/test/java/a8k/app/factory/BiLisDoubleTrackFrameFactoryTest.java b/src/test/java/a8k/app/factory/BiLisDoubleTrackFrameFactoryTest.java
new file mode 100644
index 0000000..066b71e
--- /dev/null
+++ b/src/test/java/a8k/app/factory/BiLisDoubleTrackFrameFactoryTest.java
@@ -0,0 +1,88 @@
+package a8k.app.factory;
+
+import a8k.app.constant.AppConstant;
+import a8k.app.type.lisprotocol.BiLisDoubleTrackFrameBuildContext;
+import a8k.app.utils.ByteArrayUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@Slf4j
+class BiLisDoubleTrackFrameFactoryTest {
+
+ @Test
+ void createRFrame() {
+
+ }
+
+ @Test
+ void createRFrameBytes() {
+ }
+
+ @Test
+ void createOFrame() {
+ }
+
+ @Test
+ void createQFrameBytes() {
+ BiLisDoubleTrackFrameBuildContext cxt = BiLisDoubleTrackFrameFactory.createQFrameBytes("A8000", "123456789");
+ log.info("frameBytes {}", ByteArrayUtils.toByteString(cxt.frameBytes));
+ log.info("frameContent {}",cxt.frameContentStr);
+ log.info("checksum {} {}", cxt.checksum[0], cxt.checksum[1]);
+
+
+ assertNotNull(cxt);
+ assertTrue(cxt.buildSuccess);
+ assertEquals("Q|A8000|^123456789|\r", cxt.frameContentStr);
+ }
+
+ @Test
+ void serialize() {
+ }
+
+ @Test
+ void createBiLisDoubleTrackFrame() {
+ }
+
+ @Test
+ void serializeFrameContent() {
+ }
+
+ @Test
+ void removeTrailingPipes() {
+ String str = "O|A5000p|1111||^NT-proBNP^^|||20220401112632\r";
+ String result = BiLisDoubleTrackFrameFactory.removeTrailingPipes(str);
+ assertEquals("O|A5000p|1111||^NT-proBNP^^|||20220401112632\r", result);
+
+ str = "O|A5000p|1111||^NT-proBNP^^|||20220401112632||||\r";
+ result = BiLisDoubleTrackFrameFactory.removeTrailingPipes(str);
+ assertEquals("O|A5000p|1111||^NT-proBNP^^|||20220401112632|\r", result);
+ }
+
+ @Test
+ void computeChecksum() {
+ char[] checksum = BiLisDoubleTrackFrameFactory.computeChecksum("O|A5000p|1111||^NT-proBNP^^|||20220401112632\r");
+ assertEquals(2, checksum.length);
+ assertEquals('0', checksum[0]);
+ assertEquals('2', checksum[1]);
+ }
+
+ @Test
+ void intToHexChars() {
+ char[] chars;
+ chars = BiLisDoubleTrackFrameFactory.intToHexChars(0x23);
+ assertEquals(2, chars.length);
+ assertEquals('2', chars[0]);
+ assertEquals('3', chars[1]);
+
+ chars = BiLisDoubleTrackFrameFactory.intToHexChars(0x0A);
+ assertEquals(2, chars.length);
+ assertEquals('0', chars[0]);
+ assertEquals('a', chars[1]);
+ }
+
+ @Test
+ void strArraySafeGet() {
+ }
+}
\ No newline at end of file
diff --git a/代码说明/20240718.txt b/代码说明/20240718.txt
deleted file mode 100644
index 1ad5db5..0000000
--- a/代码说明/20240718.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-
-```
- 1.添加下面几种数据类型,每种类型都对应一种json,json的格式已经在对应的类中给出
- Pos3d("Pos3d"),//
- Pos2d("Pos2d"),//
- Bool("Bool"),//
- Int("Int"),//
- String("String"),//
- LargeBottleBufferPosInfo("LargeBottleBufferPosInfo"),//
- Plates2dCodeScanPosInfo("Plates2dCodeScanPosInfo"),//
- SmallBottleBufferPosInfo("SmallBottleBufferPosInfo"),//
- TipPickUpPosInfo("TipPickUpPosInfo"),//
- TubeSamplePos("TubeSamplePos"),//
- Float("Float");
- 2.Hbot控制涉及到参数的访问和更改写在,HbotControlParamsService
- 3.反应板夹搬运(板夹出仓,转盘转动...,勾取反应板)相关参数的访问和更改写在 ReactionPlatesTransmitCtrlParamService
- 4.样本预处理(脱毛盖帽摇匀)涉及到参数的访问和更改写在 SamplesPreProcessModuleCtrlParamsService
-
- 5.所有硬件控制涉及到的参数都写在HardwareServiceSetting数据库中,数据库中的条目索引,由key+ServiceName作为索引标识。
-
- 6.之前写的进出料控制,也改成类似的风格。(这个我没有改)
- 7.删除掉试管类型数据库,试管类型信息存储在A8kTubeType枚举中。试管架间距,参数也放在MotorTubeRackMoveCtrlServiceParameterDao中,(我没有删,你改完之后再删)
-
-```
-
-```
- 1. 添加AppWarningNotifyEvent,前端接收到该事件,弹窗显示dispalyInfo即可
- 2. 添加AppStepNotifyEvent,前端收到该事件,在页面的信息栏显示dispalyInfo即可。
- ```
-
- ```
- regIndex 换成枚举类型
- A8kCanBusService添加,read_reg,get_reg 方法
- ```
\ No newline at end of file