Browse Source

update

tags/v0
zhaohe 7 months ago
parent
commit
7edd37e3d0
  1. 2
      appresource/static/engineer/css/app.521f1f85.css
  2. 2
      appresource/static/engineer/index.html
  3. 2
      appresource/static/engineer/js/app.15f44a8f.js
  4. 1
      appresource/static/engineer/js/app.15f44a8f.js.map
  5. 2
      appresource/static/engineer/js/app.6b28088f.js
  6. 1
      appresource/static/engineer/js/app.6b28088f.js.map
  7. 6
      appresource/static/engineer/js/chunk-vendors.a96a0e7f.js
  8. 2
      appresource/static/engineer/js/chunk-vendors.a96a0e7f.js.map
  9. 14
      src/main/java/a8k/app/a8ktype/appevent/MessageBoxUpdateEvent.java
  10. 8
      src/main/java/a8k/app/a8ktype/others/checkpoint/CheckResult.java
  11. 10
      src/main/java/a8k/app/a8ktype/others/checkpoint/Checkpoint.java
  12. 3
      src/main/java/a8k/app/a8ktype/state/OptScanModule.java
  13. 1
      src/main/java/a8k/app/a8ktype/state/enumtype/IncubationSubTankState.java
  14. 3
      src/main/java/a8k/app/a8ktype/type/ConsumablesOneChannelScanResultPacket.java
  15. 1
      src/main/java/a8k/app/a8ktype/type/ConsumablesScanReport.java
  16. 2
      src/main/java/a8k/app/a8ktype/ui/ApiRet.java
  17. 3
      src/main/java/a8k/app/controler/api/v1/app/ctrl/DeviceInit.java
  18. 11
      src/main/java/a8k/app/controler/api/v1/app/ws/AppWebSocketEndpointMgr.java
  19. 7
      src/main/java/a8k/app/factory/ZAppPromoptFactory.java
  20. 34
      src/main/java/a8k/app/hardware/basedriver/A8kCanBusService.java
  21. 8
      src/main/java/a8k/app/hardware/driver/TemperatureControlDriver.java
  22. 1
      src/main/java/a8k/app/hardware/type/a8kcanprotocol/A8kEcode.java
  23. 30
      src/main/java/a8k/app/i18n/Internationalization.java
  24. 2
      src/main/java/a8k/app/service/background/SensorDataUpdateService.java
  25. 3
      src/main/java/a8k/app/service/bases/FrontEndEventRouter.java
  26. 34
      src/main/java/a8k/app/service/lowerctrl/DeviceInitCtrlService.java
  27. 8
      src/main/java/a8k/app/service/lowerctrl/ProjIDCardCtrlAndMonitorService.java
  28. 47
      src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java
  29. 15
      src/main/java/a8k/app/service/statemgr/ConsumablesMgrService.java
  30. 28
      src/main/java/a8k/app/service/statemgr/IncubationPlateStateMgrService.java
  31. 2
      src/main/java/a8k/app/service/statemgr/OptScanModuleStateMgrService.java
  32. 11
      src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java
  33. 283
      src/main/java/a8k/extui/page/driver/LowLevelBoardVersionPreviewPage.java
  34. 58
      src/main/java/a8k/extui/page/stress_test/PipetteGunStressTest.java
  35. 5
      src/main/resources/application.yml

2
appresource/static/engineer/css/app.ae9236bd.css → appresource/static/engineer/css/app.521f1f85.css

@ -1,4 +1,4 @@
.vjs-tree-brackets{cursor:pointer}.vjs-tree-brackets:hover{color:#1890ff}.vjs-check-controller{position:absolute;left:0}.vjs-check-controller.is-checked .vjs-check-controller-inner{background-color:#1890ff;border-color:#0076e4}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-checkbox:after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-radio:after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.vjs-check-controller .vjs-check-controller-inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:2px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box;width:16px;height:16px;background-color:#fff;z-index:1;cursor:pointer;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.vjs-check-controller .vjs-check-controller-inner:after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:4px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;-webkit-transform-origin:center;transform-origin:center}.vjs-check-controller .vjs-check-controller-inner.is-radio{border-radius:100%}.vjs-check-controller .vjs-check-controller-inner.is-radio:after{border-radius:100%;height:4px;background-color:#fff;left:50%;top:50%}.vjs-check-controller .vjs-check-controller-original{opacity:0;outline:none;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.vjs-carets{position:absolute;right:0;cursor:pointer}.vjs-carets svg{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.vjs-carets:hover{color:#1890ff}.vjs-carets-close{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.vjs-tree-node{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;line-height:20px}.vjs-tree-node.has-carets{padding-left:15px}.vjs-tree-node.has-carets.has-selector,.vjs-tree-node.has-selector{padding-left:30px}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f7ff}.vjs-tree-node .vjs-indent{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative}.vjs-tree-node .vjs-indent-unit{width:1em}.vjs-tree-node .vjs-indent-unit.has-line{border-left:1px dashed #bfcbd9}.vjs-tree-node.dark.is-highlight,.vjs-tree-node.dark:hover{background-color:#2e4558}.vjs-node-index{position:absolute;right:100%;margin-right:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vjs-colon{white-space:pre}.vjs-comment{color:#bfcbd9}.vjs-value{word-break:break-word}.vjs-value-null,.vjs-value-undefined{color:#d55fde}.vjs-value-boolean,.vjs-value-number{color:#1d8ce0}.vjs-value-string{color:#13ce66}.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace;font-size:14px;text-align:left}.vjs-tree.is-virtual{overflow:auto}.vjs-tree.is-virtual .vjs-tree-node{white-space:nowrap}.wrap-text[data-v-48bc040e]{white-space:pre-wrap;word-wrap:break-word}.max-height[data-v-48bc040e]{max-height:20vh;overflow-y:auto}.group-container[data-v-48bc040e]{height:100%;display:flex;flex-direction:column}.action-param-label[data-v-69612837]{font-size:.6rem;top:-8px;position:absolute;z-index:9;left:5px;padding:0 5px;color:#7b7b7b}.action-button[data-v-69612837],.fixed-length-button[data-v-69612837]{white-space:normal;word-break:break-word}.fixed-length-button[data-v-69612837]{min-width:230px}
.vjs-tree-brackets{cursor:pointer}.vjs-tree-brackets:hover{color:#1890ff}.vjs-check-controller{position:absolute;left:0}.vjs-check-controller.is-checked .vjs-check-controller-inner{background-color:#1890ff;border-color:#0076e4}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-checkbox:after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-radio:after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.vjs-check-controller .vjs-check-controller-inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:2px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box;width:16px;height:16px;background-color:#fff;z-index:1;cursor:pointer;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.vjs-check-controller .vjs-check-controller-inner:after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:4px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;-webkit-transform-origin:center;transform-origin:center}.vjs-check-controller .vjs-check-controller-inner.is-radio{border-radius:100%}.vjs-check-controller .vjs-check-controller-inner.is-radio:after{border-radius:100%;height:4px;background-color:#fff;left:50%;top:50%}.vjs-check-controller .vjs-check-controller-original{opacity:0;outline:none;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.vjs-carets{position:absolute;right:0;cursor:pointer}.vjs-carets svg{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.vjs-carets:hover{color:#1890ff}.vjs-carets-close{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.vjs-tree-node{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;line-height:20px}.vjs-tree-node.has-carets{padding-left:15px}.vjs-tree-node.has-carets.has-selector,.vjs-tree-node.has-selector{padding-left:30px}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f7ff}.vjs-tree-node .vjs-indent{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative}.vjs-tree-node .vjs-indent-unit{width:1em}.vjs-tree-node .vjs-indent-unit.has-line{border-left:1px dashed #bfcbd9}.vjs-tree-node.dark.is-highlight,.vjs-tree-node.dark:hover{background-color:#2e4558}.vjs-node-index{position:absolute;right:100%;margin-right:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vjs-colon{white-space:pre}.vjs-comment{color:#bfcbd9}.vjs-value{word-break:break-word}.vjs-value-null,.vjs-value-undefined{color:#d55fde}.vjs-value-boolean,.vjs-value-number{color:#1d8ce0}.vjs-value-string{color:#13ce66}.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace;font-size:14px;text-align:left}.vjs-tree.is-virtual{overflow:auto}.vjs-tree.is-virtual .vjs-tree-node{white-space:nowrap}.p-style[data-v-6494155a]{white-space:pre;word-break:keep-all;max-height:20vh;overflow-y:auto}.group-container[data-v-6494155a]{height:100%;display:flex;flex-direction:column}.action-param-label[data-v-69612837]{font-size:.6rem;top:-8px;position:absolute;z-index:9;left:5px;padding:0 5px;color:#7b7b7b}.action-button[data-v-69612837],.fixed-length-button[data-v-69612837]{white-space:normal;word-break:break-word}.fixed-length-button[data-v-69612837]{min-width:230px}
/*
! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com

2
appresource/static/engineer/index.html

@ -1 +1 @@
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>a8k_webui</title><script defer="defer" src="js/chunk-vendors.5158647c.js"></script><script defer="defer" src="js/app.15f44a8f.js"></script><link href="css/app.ae9236bd.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but a8k_webui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>a8k_webui</title><script defer="defer" src="js/chunk-vendors.a96a0e7f.js"></script><script defer="defer" src="js/app.6b28088f.js"></script><link href="css/app.521f1f85.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but a8k_webui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

2
appresource/static/engineer/js/app.15f44a8f.js
File diff suppressed because it is too large
View File

1
appresource/static/engineer/js/app.15f44a8f.js.map
File diff suppressed because it is too large
View File

2
appresource/static/engineer/js/app.6b28088f.js
File diff suppressed because it is too large
View File

1
appresource/static/engineer/js/app.6b28088f.js.map
File diff suppressed because it is too large
View File

6
appresource/static/engineer/js/chunk-vendors.a96a0e7f.js
File diff suppressed because it is too large
View File

2
appresource/static/engineer/js/chunk-vendors.a96a0e7f.js.map
File diff suppressed because it is too large
View File

14
src/main/java/a8k/app/a8ktype/appevent/MessageBoxUpdateEvent.java

@ -0,0 +1,14 @@
package a8k.app.a8ktype.appevent;
import a8k.app.i18n.Internationalization;
import a8k.app.service.mainctrl.mainflowctrl.base.A8kActionStepType;
public class MessageBoxUpdateEvent extends AppEvent {
public String message;
public Integer overtimes = 0;
public MessageBoxUpdateEvent(String message) {
super(MessageBoxUpdateEvent.class.getSimpleName());
this.message = message;
}
}

8
src/main/java/a8k/app/a8ktype/others/checkpoint/CheckResult.java

@ -1,7 +1,9 @@
package a8k.app.a8ktype.others.checkpoint;
import a8k.app.a8ktype.others.CheckPointType;
public class CheckResult {
public String typechinfo;
public Enum<?> type;
public Boolean pass;
public CheckPointType type;
public String typechinfo;
public Boolean pass;
}

10
src/main/java/a8k/app/a8ktype/others/checkpoint/Checkpoint.java

@ -1,12 +1,14 @@
package a8k.app.a8ktype.others.checkpoint;
import a8k.app.a8ktype.others.CheckPointType;
public class Checkpoint {
public String typechinfo;
public Enum<?> type;
public CheckFn checkfn;
public CheckPointType type;
public String typechinfo;
public CheckFn checkfn;
public Checkpoint(String typechinfo, Enum<?> type, CheckFn checkfn) {
public Checkpoint(String typechinfo, CheckPointType type, CheckFn checkfn) {
this.typechinfo = typechinfo;
this.type = type;
this.checkfn = checkfn;

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

@ -13,8 +13,7 @@ public class OptScanModule implements Serializable {
@Schema(description = "模块状态")
public OptScanModuleState state = OptScanModuleState.EMPTY; //模块状态
@Schema(description = "是否是错误板(标识当前光学模组中的反应板存在异常)")
Boolean isErrorPlate = false;
@Schema(description = "血液类型(用于显示)")
BloodType bloodType = BloodType.WHOLE_BLOOD;
@Schema(description = "样本条码(用于显示)")

1
src/main/java/a8k/app/a8ktype/state/enumtype/IncubationSubTankState.java

@ -9,6 +9,7 @@ public enum IncubationSubTankState {
RESERVED,//预定
WAITING_FOR_DROP,//等待滴液
INCUBATING, //孵育中
INCUBATION_COMPLETE, //孵育完成
ERROR,//错误
}

3
src/main/java/a8k/app/a8ktype/type/ConsumablesOneChannelScanResultPacket.java

@ -1,6 +1,7 @@
package a8k.app.a8ktype.type;
import a8k.app.a8ktype.device.consumables.ConsumableState;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
public class ConsumablesOneChannelScanResultPacket {
@ -8,8 +9,10 @@ public class ConsumablesOneChannelScanResultPacket {
public ConsumablesScanReport scanReport;
@Schema(name = "耗材扫描原始结果")
@JsonIgnore
public ConsumableOneChRawResult scanRawResult;
@Schema(name = "耗材状态")
@JsonIgnore
public ConsumableState consumableState;
}

1
src/main/java/a8k/app/a8ktype/type/ConsumablesScanReport.java

@ -9,6 +9,7 @@ public class ConsumablesScanReport {
public Integer chNum;
@Schema(description = "扫描结果")
public ConsumablesScanReportErrorType state;
public String stateDesc;
@Schema(description = "项目ID")
public Integer projId;
@Schema(description = "批次号")

2
src/main/java/a8k/app/a8ktype/ui/ApiRet.java

@ -12,7 +12,7 @@ public class ApiRet<T> {
// 错误信息
public A8kEcode ecode = null;
public String dataType;
public Object data;
public T data;
// 接口请求时间
@Getter

3
src/main/java/a8k/app/controler/api/v1/app/ctrl/DeviceInit.java

@ -26,14 +26,11 @@ public class DeviceInit {
@Resource
DeviceInitCtrlService deviceInitCtrlService;
@Resource
BackgroudProcessCtrlService backgroudProcessCtrlService;
@Operation(description = "初始化设备")
@PostMapping("/initDevice")
public ApiRet<?> initDevice() throws AppException {
backgroudProcessCtrlService.startProcess();
deviceInitCtrlService.initDeviceAsync();
return ApiRet.success();
}

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

@ -15,6 +15,7 @@ import jakarta.websocket.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Component
@EnableScheduling
@ -118,7 +119,7 @@ public class AppWebSocketEndpointMgr {
}
@Scheduled(fixedDelay = 800)
@Scheduled(fixedDelay = 300)
public void reportDeviceState() {
reportState("DeviceWorkState", deviceWorkStateMgrService.getDeviceWorkState());
reportState("TubeHolderState", tubeStateMgrService.getTubeHolder());
@ -127,7 +128,15 @@ public class AppWebSocketEndpointMgr {
reportState("EmergencyPosState", tubeStateMgrService.getEmergencyPosRunState());
reportState("SensorState", gstate.getSensorState());
reportState("ConsumablesStateService", consumablesMgrService.getState());
}
private Integer reportConsumableStateStateVersion = 0;
@Scheduled(fixedDelay = 30)
public void reportConsumableStateState() {
if (!Objects.equals(reportConsumableStateStateVersion, consumablesMgrService.getStateVersion())) {
reportConsumableStateStateVersion = consumablesMgrService.getStateVersion();
reportState("ConsumablesStateService", consumablesMgrService.getState());
}
}
}

7
src/main/java/a8k/app/factory/ZAppPromoptFactory.java

@ -96,6 +96,13 @@ public class ZAppPromoptFactory {
}
}
public static ZAppPromopt buildNotifyPromopt(String info) {
ZAppPromopt promopt = new ZAppPromopt();
promopt.type = ZAppPromoptType.Notify;
promopt.info = info;
return promopt;
}
public static AppPromptEvents buildAppPromoptEvent(Exception e) {
return new AppPromptEvents(List.of(buildAppPromopt(e)));
}

34
src/main/java/a8k/app/hardware/basedriver/A8kCanBusService.java

@ -81,6 +81,40 @@ public class A8kCanBusService {
return A8kEcode.fromInt(packet.getContentI32(0));
}
public Integer moduleReadVersion(MId id) throws AppException {
return moduleGetReg(id, RegIndex.kreg_module_version);
}
public String moduleReadType(MId id) throws AppException {
// khbot_module = 1, // hbot模块
// ktemperature_ctrl_module = 3, // 温度控制
// kfan_ctrl_module = 5, // 风扇控制
// kcode_scaner = 6, // 扫码器
// kpipette_ctrl_module = 7, // 移液体枪控制
// ka8000_optical_module = 8, // a8000光学模组
// ktmc_step_motor = 10, // 步进电机
// kmini_servo_motor_module = 11, // 舵机
// kboard = 12, // 板子
// ka8000_idcard_reader = 13, // id卡读卡器
// ka8000_plate_code_scaner = 14, // 反应板条扫码器
var type = moduleGetReg(id, RegIndex.kreg_module_type);
return switch (type) {
case 1 -> "HBOT模块";
case 3 -> "温度控制";
case 5 -> "风扇控制";
case 6 -> "扫码器";
case 7 -> "移液体枪控制";
case 8 -> "A8000光学模组";
case 10 -> "步进电机";
case 11 -> "舵机";
case 12 -> "板子";
case 13 -> "ID卡读卡器";
case 14 -> "反应板条扫码器";
default -> "未知模块";
};
}
public Boolean getIOState(IOId ioid) throws AppException {
while (true) {

8
src/main/java/a8k/app/hardware/driver/TemperatureControlDriver.java

@ -58,14 +58,14 @@ public class TemperatureControlDriver {
}
public Double readIncubateBoxTemperature() throws AppException {
Integer readval = readReg(TemperatureControlerMid.IncubatorTCM, TemperatureControlerRegIndex.kreg_water_cooling_tmp_controler_temp0);
Double readvalDouble = readval / 10.0;
Integer readval = readReg(TemperatureControlerMid.IncubatorTCM, TemperatureControlerRegIndex.kreg_water_cooling_tmp_controler_pid_feedbackval);
Double readvalDouble = readval * 0.1;
return readvalDouble - incubatorTCMTempOffset;
}
public Double readPlateBoxTemperature() throws AppException {
Integer readval = readReg(TemperatureControlerMid.PlatesBoxTCM, TemperatureControlerRegIndex.kreg_water_cooling_tmp_controler_temp0);
Double readvalDouble = readval / 10.0;
Integer readval = readReg(TemperatureControlerMid.PlatesBoxTCM, TemperatureControlerRegIndex.kreg_water_cooling_tmp_controler_pid_feedbackval);
Double readvalDouble = readval * 0.1;
return readvalDouble - platesBoxTCMTempOffset;
}

1
src/main/java/a8k/app/hardware/type/a8kcanprotocol/A8kEcode.java

@ -48,6 +48,7 @@ public enum A8kEcode {
// 设备操作操作
//
APPE_DEVICE_IS_IN_FATAL_ERROR(150),//设备处于严重错误,请关机后重启设备进行恢复
APPE_DEVICE_INIT_CHECK_FAIL(151),//设备初始化检查失败
//

30
src/main/java/a8k/app/i18n/Internationalization.java

@ -1,5 +1,6 @@
package a8k.app.i18n;
import a8k.app.a8ktype.error.ConsumablesScanReportErrorType;
import a8k.app.hardware.type.a8kcanprotocol.A8kEcode;
import a8k.app.service.mainctrl.mainflowctrl.base.A8kActionStepType;
@ -36,6 +37,7 @@ public class Internationalization {
case APPE_TUBE_X_CHANNEL_IS_NOT_EMPTY -> "试管架通道有异物";
case APPE_PLATE_BOX_NOT_COVER -> "板夹仓未盖";
case APPE_DEVICE_NOT_INITED -> "设备未初始化";
case APPE_DEVICE_INIT_CHECK_FAIL -> "设备初始化检查失败";
case PROJ_CARD_ERROR_EXPIRYED -> "项目卡过期";
case PROJ_CARD_ERROR_WRONG_FUNCTION_NUM -> "项目卡配置的函数数量与项目配置不匹配";
@ -77,4 +79,32 @@ public class Internationalization {
};
}
public static String consumablesScanReportErrorType2String(ConsumablesScanReportErrorType errorType) {
// * PASS:通过
// * EMPTY:
// * EXPIRED:耗材过期
// * MISS_REACTION_PLATE:没有反应板夹
// * MISS_LITTSB:缺少小缓冲液
// * MISS_LARBS:缺少大缓冲液
// * MISS_IDCARD:未找到匹配的项目ID卡
// * LITTSB_LOTID_MISMATCH:小缓冲液批号不匹配
// * LARBS_LOTID_MISMATCH:大缓冲液批号不匹配
// * REACTION_PLATE_2D_CODE_FORMATE_ERROR:反应板二维码格式错误
// * CODE_ERROR_PROJINFO_IS_ERROR:代码错误项目信息异常
// * UN_SUPPORT_PROJ:不支持的项目
return switch (errorType) {
case PASS -> "通过";
case EMPTY -> "空";
case EXPIRED -> "耗材过期";
case MISS_REACTION_PLATE -> "没有反应板夹";
case MISS_LITTSB -> "缺少小缓冲液";
case MISS_LARBS -> "缺少大缓冲液";
case MISS_IDCARD -> "未找到匹配的项目ID卡";
case LITTSB_LOTID_MISMATCH -> "小缓冲液批号不匹配";
case LARBS_LOTID_MISMATCH -> "大缓冲液批号不匹配";
case REACTION_PLATE_2D_CODE_FORMATE_ERROR -> "反应板二维码格式错误";
case CODE_ERROR_PROJINFO_IS_ERROR -> "代码错误,项目信息异常";
case UN_SUPPORT_PROJ -> "不支持的项目";
};
}
}

2
src/main/java/a8k/app/service/background/SensorDataUpdateService.java

@ -90,8 +90,8 @@ public class SensorDataUpdateService {
@PostConstruct
public void init() {
updateThread = new Thread(() -> {
OS.forceSleep(3000);
while (true) {
if (!workingFlag) {

3
src/main/java/a8k/app/service/bases/FrontEndEventRouter.java

@ -18,7 +18,6 @@ public class FrontEndEventRouter {
}
@Resource
AppEventBusService eventBus;
@ -45,7 +44,7 @@ public class FrontEndEventRouter {
} else if (event instanceof AppTubeholderSettingUpdateEvent) {
return event;//前端需要更新试管架设置
} else if (event instanceof DoA8kStepActionEvent) {
return event; //前端需要更新步骤提示信息
return new MessageBoxUpdateEvent(((DoA8kStepActionEvent) event).actionStepName);
}
/*

34
src/main/java/a8k/app/service/lowerctrl/DeviceInitCtrlService.java

@ -1,7 +1,11 @@
package a8k.app.service.lowerctrl;
import a8k.app.a8ktype.ui.ZAppPromopt;
import a8k.app.a8ktype.ui.ZAppPromoptType;
import a8k.app.factory.ZAppPromoptFactory;
import a8k.app.hardware.basedriver.A8kCanBusService;
import a8k.app.hardware.extdriver.MotorEnableExDriver;
import a8k.app.hardware.type.a8kcanprotocol.A8kEcode;
import a8k.app.hardware.type.a8kcanprotocol.IOId;
import a8k.app.hardware.driver.MiniServoDriver;
import a8k.app.hardware.driver.PipetteCtrlDriver;
@ -9,6 +13,7 @@ import a8k.app.hardware.driver.StepMotorCtrlDriver;
import a8k.app.hardware.driver.type.MiniServoMId;
import a8k.app.hardware.driver.type.StepMotorMId;
import a8k.app.service.background.BackgroudProcessCtrlService;
import a8k.app.service.bases.AppEventBusService;
import a8k.teststate.VirtualDevice;
import a8k.app.a8ktype.others.CheckPointType;
@ -58,9 +63,12 @@ public class DeviceInitCtrlService {
// Service
//
@Resource
TubeFeedingCtrlService tubeFeedingCtrlService;
TubeFeedingCtrlService tubeFeedingCtrlService;
@Resource
HbotMoveExCtrlService hbotMoveExCtrlService;
HbotMoveExCtrlService hbotMoveExCtrlService;
@Resource
BackgroudProcessCtrlService backgroudProcessCtrlService;
@Resource
HbotMoveCtrlService hbotMoveCtrlService;
@ -73,6 +81,8 @@ public class DeviceInitCtrlService {
public Boolean deviceInited = false;
public Boolean isBusy = false;
public Boolean passed = false;
public ZAppPromopt promopt;
}
Thread workThread;
@ -238,28 +248,34 @@ public class DeviceInitCtrlService {
throw new RuntimeException(e);
}
}
workThread = new Thread(() -> {
log.info("设备初始化开始");
deviceInitedTaskState.isBusy = true;
deviceInitedTaskState.passed = false;
deviceInitedTaskState.deviceInited = false;
try {
boolean passed = true;
List<CheckResult> checkResults = initDevice();
for (CheckResult checkResult : checkResults) {
if (!checkResult.pass) {
passed = false;
break;
throw AppException.of(A8kEcode.APPE_DEVICE_INIT_CHECK_FAIL);
}
}
backgroudProcessCtrlService.startProcess();
deviceInitedTaskState.passed = passed;
deviceInitedTaskState.deviceInited = passed;
deviceInitedTaskState.passed = true;
deviceInitedTaskState.deviceInited = true;
deviceInitedTaskState.promopt = ZAppPromoptFactory.buildNotifyPromopt("设备初始化成功");
} catch (AppException e) {
appEventBusService.pushAppExceptionEvent(e);
deviceInitedTaskState.passed = false;
deviceInitedTaskState.deviceInited = false;
deviceInitedTaskState.promopt = ZAppPromoptFactory.buildAppPromopt(e);
}
deviceInitedTaskState.isBusy = false;
log.info("设备初始化结束");
});
workThread.start();
}

8
src/main/java/a8k/app/service/lowerctrl/ProjIDCardCtrlAndMonitorService.java

@ -1,6 +1,7 @@
package a8k.app.service.lowerctrl;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.a8ktype.appevent.*;
import a8k.app.hardware.type.regindex.RegIndex;
@ -10,6 +11,7 @@ import a8k.app.service.bases.AppEventBusService;
import a8k.app.hardware.basedriver.A8kCanBusService;
import a8k.app.hardware.type.a8kcanprotocol.*;
import a8k.app.a8kproj.A8kIdCardDataParseService;
import a8k.app.utils.ProjBuildinInfo;
import a8k.app.utils.ZWorkQueue;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
@ -30,6 +32,8 @@ public class ProjIDCardCtrlAndMonitorService {
AppEventBusService eventBus;
@Resource
A8kIdCardDataParseService idCardDataParseService;
@Resource
ProjInfoMgrService projInfoMgrService;
ZWorkQueue workQueue = new ZWorkQueue(2, 1);
@ -104,7 +108,11 @@ public class ProjIDCardCtrlAndMonitorService {
//解析ID卡信息
try {
mountedIdCardInfo = idCardDataParseService.parseAndCheck(data);
ProjBuildinInfo buildinInfo = projInfoMgrService.getProjBuildInInfo(mountedIdCardInfo.projId);
mountedIdCardInfo.color = buildinInfo.projBaseInfo.color;
eventBus.pushEvent(new AppIDCardMountEvent(mountedIdCardInfo));
} catch (AppException e) {
eventBus.pushEvent(new A8kErrorsPromptEvent(e.error));
}

47
src/main/java/a8k/app/service/mainctrl/AppConsumablesScanService.java

@ -4,6 +4,7 @@ import a8k.app.a8ktype.device.ConsumableGroup;
import a8k.app.a8ktype.device.LittleBottleConsumableType;
import a8k.app.constant.AppConstant;
import a8k.app.hardware.type.a8kcanprotocol.A8kEcode;
import a8k.app.i18n.Internationalization;
import a8k.app.service.data.ProjInfoMgrService;
import a8k.app.service.statemgr.GStateMgrService;
import a8k.app.service.statemgr.ConsumablesMgrService;
@ -59,13 +60,16 @@ public class AppConsumablesScanService {
if (ZStringUtils.isNullOrEmpty(rawResult.larBSScanResult) &&
ZStringUtils.isNullOrEmpty(rawResult.littBSScanResult) &&
ZStringUtils.isNullOrEmpty(rawResult.PBScanResult)) {
ret.state = ConsumablesScanReportErrorType.EMPTY;
ret.state = ConsumablesScanReportErrorType.EMPTY;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
if (ZStringUtils.isNullOrEmpty(rawResult.PBScanResult)) {
ret.state = ConsumablesScanReportErrorType.MISS_REACTION_PLATE;
ret.state = ConsumablesScanReportErrorType.MISS_REACTION_PLATE;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
@ -73,19 +77,25 @@ public class AppConsumablesScanService {
//解析板夹二维码
ReactionPlate2DCode rp2dcode = ReactionPlate2DCodeHelper.parse(rawResult.PBScanResult);
if (rp2dcode == null) {
ret.state = ConsumablesScanReportErrorType.REACTION_PLATE_2D_CODE_FORMATE_ERROR;
ret.state = ConsumablesScanReportErrorType.REACTION_PLATE_2D_CODE_FORMATE_ERROR;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
var projExtInfoCard = projInfoMgrService.getProjExtInfoCard(rp2dcode.lotId);
if (projExtInfoCard == null) {
logger.warn("未找到匹配的项目ID卡,LotID:{}", rp2dcode.lotId);
ret.state = ConsumablesScanReportErrorType.MISS_IDCARD;
ret.state = ConsumablesScanReportErrorType.MISS_IDCARD;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
if (projExtInfoCard.expiryDate.before(new Date())) {
logger.warn("耗材过期,LotID:{}", rp2dcode.lotId);
ret.state = ConsumablesScanReportErrorType.EXPIRED;
ret.state = ConsumablesScanReportErrorType.EXPIRED;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
@ -93,7 +103,9 @@ public class AppConsumablesScanService {
try {
projBuildinInfo = projInfoMgrService.getProjBuildInInfo(projExtInfoCard.projId);
} catch (AppException e) {
ret.state = ConsumablesScanReportErrorType.UN_SUPPORT_PROJ;
ret.state = ConsumablesScanReportErrorType.UN_SUPPORT_PROJ;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
@ -105,24 +117,32 @@ public class AppConsumablesScanService {
if (reactionType.equals(A8kReactionFlowType.SampleAndBS)) {
//校验小瓶缓冲液,小瓶缓冲液+样本
if (ZStringUtils.isNullOrEmpty(rawResult.littBSScanResult)) {
ret.state = ConsumablesScanReportErrorType.MISS_LITTSB;
ret.state = ConsumablesScanReportErrorType.MISS_LITTSB;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
if (!rawResult.littBSScanResult.equals(rp2dcode.lotId)) {
ret.state = ConsumablesScanReportErrorType.LITTSB_LOTID_MISMATCH;
ret.state = ConsumablesScanReportErrorType.LITTSB_LOTID_MISMATCH;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
} else if (reactionType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) {
// 校验大瓶缓冲液,大瓶缓冲液+小瓶缓冲液+样本
if (ZStringUtils.isNullOrEmpty(rawResult.larBSScanResult)) {
ret.state = ConsumablesScanReportErrorType.MISS_LARBS;
ret.state = ConsumablesScanReportErrorType.MISS_LARBS;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
if (!rawResult.larBSScanResult.equals(rp2dcode.lotId)) {
ret.state = ConsumablesScanReportErrorType.LARBS_LOTID_MISMATCH;
ret.state = ConsumablesScanReportErrorType.LARBS_LOTID_MISMATCH;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
return ret;
}
@ -131,9 +151,10 @@ public class AppConsumablesScanService {
throw new RuntimeException("未知的反应流程类型");
}
ret.lotId = rp2dcode.lotId;
ret.projId = projId;
ret.state = ConsumablesScanReportErrorType.PASS;
ret.lotId = rp2dcode.lotId;
ret.projId = projId;
ret.state = ConsumablesScanReportErrorType.PASS;
ret.stateDesc = Internationalization.consumablesScanReportErrorType2String(ret.state);
ret.projName = projExtInfoCard.projName;
ret.projShortName = projExtInfoCard.projShortName;
return ret;

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

@ -34,12 +34,18 @@ import java.util.List;
@Component
public class ConsumablesMgrService {
//耗材状态
private ConsumableState cState = new ConsumableState();
private ConsumableState cState = new ConsumableState();
private Integer stateVersion = 0;
synchronized public ConsumableState getState() {
return ObjectUtil.cloneByStream(cState);
}
synchronized public Integer getStateVersion() {
return stateVersion;
}
//
// PUBLIC
//
@ -47,6 +53,7 @@ public class ConsumablesMgrService {
cState.reactionPlateGroup[ch] = reactionPlateGroup;
cState.littBottleGroup[ch] = littBottleGroup;
cState.larBottleGroup[ch] = larBottleGroup;
stateVersion++;
}
/**
@ -58,6 +65,7 @@ public class ConsumablesMgrService {
var group = priGetConsumableGroupByProjIndex(projId);
if (group != null) {
Integer pos = priTakeOneConsumable(group);
return new Consumable(priGetLotId(group), group, pos);
}
return null;
@ -98,6 +106,7 @@ public class ConsumablesMgrService {
TipPos ret = new TipPos();
ret.group = TipGroup.fromInt(i);
ret.index = tipPos;
stateVersion++;
return ret;
}
}
@ -118,6 +127,7 @@ public class ConsumablesMgrService {
throw AppException.of(A8kEcode.CODEERROR, "设置Tip数量超出范围");
}
cState.tips[group.ordinal()].tipNum = num;
stateVersion++;
}
@ -171,17 +181,20 @@ public class ConsumablesMgrService {
if (cState.larBottleGroup[group.off].isUse) {
cState.larBottleGroup[group.off].num = num;
}
stateVersion++;
}
private synchronized Integer priTakeOneConsumable(ConsumableGroup group) {
Integer num = priGetConsumableRemainNum(group);
priSetConsumableGroupNum(group, num - 1);
stateVersion++;
return AppConstant.CONSUMABLE_NUM - num - 1 + 1;
}
private synchronized void priBakOneConsumable(ConsumableGroup group) {
Integer num = priGetConsumableRemainNum(group);
priSetConsumableGroupNum(group, num + 1);
stateVersion++;
}
private synchronized String priGetLotId(ConsumableGroup group) {

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

@ -59,33 +59,14 @@ public class IncubationPlateStateMgrService {
return false;
}
synchronized public Boolean isHasExpiredPlate() {
var subtanks = incubationPlate.subtanks;
for (IncubationSubTank subtank : subtanks) {
if (subtank.state.equals(IncubationSubTankState.INCUBATING)) {
var now = new Date().getTime();
var diff = now - subtank.startIncubatedTime;
if (diff > subtank.incubatedTimeSec * 1000) {
return true;
}
}
}
return false;
}
synchronized public IncubationSubTank getOneExpiredPlate() {
var subtanks = incubationPlate.subtanks;
for (IncubationSubTank subtank : subtanks) {
if (subtank.state.equals(IncubationSubTankState.INCUBATING)) {
var now = new Date().getTime();
var diff = now - subtank.startIncubatedTime;
if (diff > subtank.incubatedTimeSec * 1000) {
return subtank;
}
if (subtank.state.equals(IncubationSubTankState.INCUBATION_COMPLETE)) {
return subtank;
}
}
return null;
}
@ -175,8 +156,9 @@ public class IncubationPlateStateMgrService {
for (IncubationSubTank subtank : incubationPlate.subtanks) {
if (subtank.state.equals(IncubationSubTankState.INCUBATING)) {
subtank.remainTimeSec = (int) ((subtank.incubatedTimeSec * 1000 - (new Date().getTime() - subtank.startIncubatedTime)) / 1000);
if (subtank.remainTimeSec < 0) {
if (subtank.remainTimeSec <= 0) {
subtank.remainTimeSec = 0;
subtank.state = IncubationSubTankState.INCUBATION_COMPLETE;
}
} else {
subtank.remainTimeSec = 0;

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

@ -25,7 +25,6 @@ public class OptScanModuleStateMgrService {
synchronized public void changeOptScanModuleStateToEmpty() {
optScanModule.state = OptScanModuleState.EMPTY;
optScanModule.setIsErrorPlate(false);
optScanModule.setBloodType(null);
optScanModule.setSampleBarcode("");
optScanModule.setUserid("");
@ -37,7 +36,6 @@ public class OptScanModuleStateMgrService {
synchronized public void changeOptScanModuleStateToPlateIsReady(ProjBriefInfo projBriefInfo, SampleInfo sampleInfo) {
optScanModule.state = OptScanModuleState.PLATE_IS_READY;
optScanModule.setIsErrorPlate(false);
optScanModule.setBloodType(sampleInfo.bloodType);
optScanModule.setSampleBarcode(sampleInfo.sampleBarcode);
optScanModule.setUserid(sampleInfo.userid);

11
src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java

@ -3,6 +3,7 @@ package a8k.extui.mgr;
import a8k.extui.page.data.DeviceActionParameterSettingPage;
import a8k.extui.page.data.ProjInfoMgrPage;
import a8k.extui.page.driver.LowLevelBoardVersionPreviewPage;
import a8k.extui.page.opt_calibration.OptFormulaTestPage;
import a8k.extui.page.opt_calibration.OptFormulaTestPageV2;
import a8k.extui.page.pos_calibration.MiniServoReferencePointIniter;
@ -15,6 +16,7 @@ import a8k.extui.page.frond_end_test.FakeReactionRecordGeneratorPage;
import a8k.extui.page.frond_end_test.VirtualEventGeneratorPage;
import a8k.extui.page.opt_calibration.OptModuleParamCalibration;
import a8k.extui.page.stress_test.PipetteGunStressTest;
import a8k.extui.page.verification.P01PipetteGunVerification;
import a8k.extui.page.verification.P02A8kTemperaturaVerfication;
import a8k.extui.type.ExtUIPageCfg;
@ -38,6 +40,7 @@ public class ExtApiPageGroupCfgMgr {
driverDebug,
Verification,
Data,
StressTest,
}
@Data
@ -104,6 +107,10 @@ public class ExtApiPageGroupCfgMgr {
displayRefreshPage(PageGroupType.Data);
}
public void stressTestRefreshPage() {
displayRefreshPage(PageGroupType.StressTest);
}
@PostConstruct
void init() {
@ -160,8 +167,10 @@ public class ExtApiPageGroupCfgMgr {
//
page.addFunction("驱动调试", this::driverDebugRefreshPage);
cfgList.add(new Config(PageGroupType.driverDebug, LowLevelBoardVersionPreviewPage.class, "低级板版本预览"));
cfgList.add(new Config(PageGroupType.driverDebug, PipetteCtrlDriverPage.getPageClass(), "移液抢驱动"));
page.addFunction("数据", this::dataRefreshPage);
cfgList.add(new Config(PageGroupType.Data, DeviceActionParameterSettingPage.class, "设备动作参数设置"));
cfgList.add(new Config(PageGroupType.Data, ProjInfoMgrPage.class, "项目信息管理"));
@ -171,6 +180,8 @@ public class ExtApiPageGroupCfgMgr {
cfgList.add(new Config(PageGroupType.FrontEndDebugUtils, FakeReactionRecordGeneratorPage.class, "虚拟反应记录生成"));
cfgList.add(new Config(PageGroupType.FrontEndDebugUtils, VirtualEventGeneratorPage.class, "虚拟事件生成"));
page.addFunction("压力测试", this::stressTestRefreshPage);
cfgList.add(new Config(PageGroupType.StressTest, PipetteGunStressTest.class, "移液枪压力测试"));
displayRefreshPage(PageGroupType.Public);

283
src/main/java/a8k/extui/page/driver/LowLevelBoardVersionPreviewPage.java

@ -0,0 +1,283 @@
package a8k.extui.page.driver;
import a8k.app.a8ktype.exception.AppException;
import a8k.app.hardware.basedriver.A8kCanBusService;
import a8k.app.hardware.type.a8kcanprotocol.MId;
import a8k.extui.mgr.ExtApiPageMgr;
import a8k.extui.type.ExtApiStatu;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class LowLevelBoardVersionPreviewPage {
@Resource
ExtApiPageMgr extApiPageMgr;
@Resource
A8kCanBusService canBus;
public static class VersionInfo {
public Integer moduleId;
public String moduleName;
public Boolean online;
public String moduleType;
public Integer version;
}
Map<MId, VersionInfo> versionInfos = new HashMap<>();
// HbotBoard(10, "机械臂板模块"),//
// HbotM(11, "机械臂XY"),//
// PlatesBoxBoard(20, "板夹仓模块"),//
// PlatesBoxYM(21, "板夹仓移动电机"),//
// PlatesBoxPusherM(22, "板夹仓推杆电机"),//
// PlatesBoxScanner(23, "板夹仓扫码模组"),//
// ShakeModBoard(30, "摇匀模组板"),//
// ShakeModClampingM(31, "试管固定夹爪电机"),//
// ShakeModGripperZM(32, "摇匀升降电机"),//
// ShakeModShakeM(33, "试管摇匀电机"),//
// ShakeModGripperYSV(34, "摇匀前后移动舵机"),//
// ShakeModGripperSV(35, "摇匀试管帽夹爪舵机"),//
// ShakeModTubeScanerClampingSV(36, "试管架扫码夹紧舵机"),//
// ShakeModTubeScanerRotateSV(37, "试管架旋转舵机"),//
// PlatesBoxTCMBoard(40, "反应板夹温度控制板"),//
// PlatesBoxTCM(41, "反应板夹温度控制模块"),//
// WbTubeFanMod(42, "气溶胶风扇"),//
// IncubatorTCMBoard(50, "温度控制"),//
// IncubatorTCM(51, "温度控制"),//
// FeedingModBoard(60, "出入料模块"),//
// FeedingModInfeedM(61, "入料电机"),//
// FeedingModXM(62, "试管架平移电机"),//
// FeedingModOutfeedM(63, "出料电机"),//
// FeedingModScannerMod(64, "试管架扫码器"),//
// IncubatorRotateBoard(70, "孵育盘旋转板"),//
// IncubatorRotateCtrlM(71, "孵育盘旋转"),//
// PipetteModBoard(80, "机械臂Z轴板"),//
// PipetteMod(82, "移液枪"),//
// PipetteModCodeScanner(83, "物料扫码器"),//
// OptModBoard(90, "光学模组板"),//
// OptModScannerM(91, "板卡扫描电机"),//
// OptModPullM(92, "板卡推杆电机"),//
// OptMod(93, "扫描仪"),//
// A8kIdCardReaderBoard(100, "A8K读卡器板"),//
// A8kIdCardReader(101, "A8K读卡器"),//
@ExtApiStatu(name = "", group = "机械臂板模块", order = 1)
public VersionInfo getHbotBoard() {
return versionInfos.get(MId.HbotBoard);
}
@ExtApiStatu(name = "", group = "机械臂XY", order = 2)
public VersionInfo getHbotM() {
return versionInfos.get(MId.HbotM);
}
@ExtApiStatu(name = "", group = "板夹仓模块", order = 3)
public VersionInfo getPlatesBoxBoard() {
return versionInfos.get(MId.PlatesBoxBoard);
}
@ExtApiStatu(name = "", group = "板夹仓移动电机", order = 4)
public VersionInfo getPlatesBoxYM() {
return versionInfos.get(MId.PlatesBoxYM);
}
@ExtApiStatu(name = "", group = "板夹仓推杆电机", order = 5)
public VersionInfo getPlatesBoxPusherM() {
return versionInfos.get(MId.PlatesBoxPusherM);
}
@ExtApiStatu(name = "", group = "板夹仓扫码模组", order = 6)
public VersionInfo getPlatesBoxScanner() {
return versionInfos.get(MId.PlatesBoxScanner);
}
@ExtApiStatu(name = "", group = "摇匀模组板", order = 7)
public VersionInfo getShakeModBoard() {
return versionInfos.get(MId.ShakeModBoard);
}
@ExtApiStatu(name = "", group = "试管固定夹爪电机", order = 8)
public VersionInfo getShakeModClampingM() {
return versionInfos.get(MId.ShakeModClampingM);
}
@ExtApiStatu(name = "", group = "摇匀升降电机", order = 9)
public VersionInfo getShakeModGripperZM() {
return versionInfos.get(MId.ShakeModGripperZM);
}
@ExtApiStatu(name = "", group = "试管摇匀电机", order = 10)
public VersionInfo getShakeModShakeM() {
return versionInfos.get(MId.ShakeModShakeM);
}
@ExtApiStatu(name = "", group = "摇匀前后移动舵机", order = 11)
public VersionInfo getShakeModGripperYSV() {
return versionInfos.get(MId.ShakeModGripperYSV);
}
@ExtApiStatu(name = "", group = "摇匀试管帽夹爪舵机", order = 12)
public VersionInfo getShakeModGripperSV() {
return versionInfos.get(MId.ShakeModGripperSV);
}
@ExtApiStatu(name = "", group = "试管架扫码夹紧舵机", order = 13)
public VersionInfo getShakeModTubeScanerClampingSV() {
return versionInfos.get(MId.ShakeModTubeScanerClampingSV);
}
@ExtApiStatu(name = "", group = "试管架旋转舵机", order = 14)
public VersionInfo getShakeModTubeScanerRotateSV() {
return versionInfos.get(MId.ShakeModTubeScanerRotateSV);
}
@ExtApiStatu(name = "", group = "反应板夹温度控板", order = 15)
public VersionInfo getPlatesBoxTCMBoard() {
return versionInfos.get(MId.PlatesBoxTCMBoard);
}
@ExtApiStatu(name = "", group = "反应板夹温度控制模块", order = 16)
public VersionInfo getPlatesBoxTCM() {
return versionInfos.get(MId.PlatesBoxTCM);
}
@ExtApiStatu(name = "", group = "气溶胶风扇", order = 17)
public VersionInfo getWbTubeFanMod() {
return versionInfos.get(MId.WbTubeFanMod);
}
@ExtApiStatu(name = "", group = "孵育盘温空板", order = 18)
public VersionInfo getIncubatorTCMBoard() {
return versionInfos.get(MId.IncubatorTCMBoard);
}
@ExtApiStatu(name = "", group = "孵育盘温控模块", order = 19)
public VersionInfo getIncubatorTCM() {
return versionInfos.get(MId.IncubatorTCM);
}
@ExtApiStatu(name = "", group = "出入料模块", order = 20)
public VersionInfo getFeedingModBoard() {
return versionInfos.get(MId.FeedingModBoard);
}
@ExtApiStatu(name = "", group = "入料电机", order = 21)
public VersionInfo getFeedingModInfeedM() {
return versionInfos.get(MId.FeedingModInfeedM);
}
@ExtApiStatu(name = "", group = "试管架平移电机", order = 22)
public VersionInfo getFeedingModXM() {
return versionInfos.get(MId.FeedingModXM);
}
@ExtApiStatu(name = "", group = "出料电机", order = 23)
public VersionInfo getFeedingModOutfeedM() {
return versionInfos.get(MId.FeedingModOutfeedM);
}
@ExtApiStatu(name = "", group = "试管架扫码器", order = 24)
public VersionInfo getFeedingModScannerMod() {
return versionInfos.get(MId.FeedingModScannerMod);
}
@ExtApiStatu(name = "", group = "孵育盘旋转板", order = 25)
public VersionInfo getIncubatorRotateBoard() {
return versionInfos.get(MId.IncubatorRotateBoard);
}
@ExtApiStatu(name = "", group = "孵育盘旋转", order = 26)
public VersionInfo getIncubatorRotateCtrlM() {
return versionInfos.get(MId.IncubatorRotateCtrlM);
}
@ExtApiStatu(name = "", group = "机械臂Z轴板", order = 27)
public VersionInfo getPipetteModBoard() {
return versionInfos.get(MId.PipetteModBoard);
}
@ExtApiStatu(name = "", group = "移液枪", order = 28)
public VersionInfo getPipetteMod() {
return versionInfos.get(MId.PipetteMod);
}
@ExtApiStatu(name = "", group = "物料扫码器", order = 29)
public VersionInfo getPipetteModCodeScanner() {
return versionInfos.get(MId.PipetteModCodeScanner);
}
@ExtApiStatu(name = "", group = "光学模组板", order = 30)
public VersionInfo getOptModBoard() {
return versionInfos.get(MId.OptModBoard);
}
@ExtApiStatu(name = "", group = "板卡扫描电机", order = 31)
public VersionInfo getOptModScannerM() {
return versionInfos.get(MId.OptModScannerM);
}
@ExtApiStatu(name = "", group = "板卡推杆电机", order = 32)
public VersionInfo getOptModPullM() {
return versionInfos.get(MId.OptModPullM);
}
@ExtApiStatu(name = "", group = "扫描仪", order = 33)
public VersionInfo getOptMod() {
return versionInfos.get(MId.OptMod);
}
@ExtApiStatu(name = "", group = "A8K读卡器板", order = 34)
public VersionInfo getA8kIdCardReaderBoard() {
return versionInfos.get(MId.A8kIdCardReaderBoard);
}
@ExtApiStatu(name = "", group = "A8K读卡器", order = 35)
public VersionInfo getA8kIdCardReader() {
return versionInfos.get(MId.A8kIdCardReader);
}
public void refreshBoardState() {
var modules = MId.values();
for (var module : modules) {
if (module == MId.NotSet) {
continue;
}
try {
Integer version = canBus.moduleReadVersion(module);
String modueType = canBus.moduleReadType(module);
VersionInfo info = new VersionInfo();
info.online = true;
info.moduleType = modueType;
info.moduleId = module.index;
info.moduleName = module.chname;
info.version = version;
versionInfos.put(module, info);
} catch (AppException e) {
VersionInfo info = new VersionInfo();
info.online = false;
info.moduleId = module.index;
info.moduleName = module.chname;
versionInfos.put(module, info);
}
}
}
@PostConstruct
void init() {
var page = extApiPageMgr.newPage(this);
page.addFunction("刷新", this::refreshBoardState);
extApiPageMgr.addPage(page);
}
}

58
src/main/java/a8k/extui/page/stress_test/PipetteGunStressTest.java

@ -0,0 +1,58 @@
package a8k.extui.page.stress_test;
import a8k.app.a8ktype.exception.AppException;
import a8k.app.hardware.driver.PipetteCtrlDriver;
import a8k.extui.mgr.ExtApiPageMgr;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class PipetteGunStressTest {
@Resource
PipetteCtrlDriver pipetteCtrlDriver;
@Resource
ExtApiPageMgr extApiPageMgr;
Boolean workFlag = false;
@Scheduled(fixedRate = 10)
void pressTest() {
if (!workFlag) {
return;
}
try {
pipetteCtrlDriver.liquidOperationClearParams();
pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, 8000);
pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, 0, 123);
pipetteCtrlDriver.liquidOperationFreshParams();
log.info("pressTest");
} catch (AppException e) {
log.error("pressTest error", e);
}
}
public void startWork() {
workFlag = true;
}
public void stopWork() {
workFlag = false;
}
@PostConstruct
public void init() {
var page = extApiPageMgr.newPage(this);
page.addFunction("startWork", this::startWork);
page.addFunction("stopWork", this::stopWork);
extApiPageMgr.addPage(page);
workFlag = false;
}
}

5
src/main/resources/application.yml

@ -1,5 +1,5 @@
server:
port: 8080
port: 80
hardware.canbus.url: ws://192.168.8.10:19005
@ -22,9 +22,6 @@ spring:
serialization:
write-dates-as-timestamps: true
VirtualDevice:
enableVirtualDevice: false
springdoc:
api-docs:
path: /doc/api-docs

Loading…
Cancel
Save