Browse Source

增加移液枪性能验证接口

master
黄翔 4 months ago
parent
commit
39b80a09d9
  1. 48
      doc/检测流程.md
  2. 14
      doc/系统事件消息总线.md
  3. 35
      doc/耗材管理.md
  4. 34
      src/main/java/a8k/app/controler/api/v1/app/verification/PipetteGunPerformanceValidationController.java
  5. 151
      src/main/java/a8k/app/service/verification/PipetteGunPerformanceValidator.java

48
doc/检测流程.md

@ -220,4 +220,52 @@ sequenceDiagram
A8kCanBusConnection ->> A8kCanBusConnection: priSend
A8kCanBusConnection ->> A8kCanBusConnection: _priSend
A8kCanBusConnection ->> WebSocketClient: send
```
```mermaid
---
title: 全血样本预处理流程
---
flowchart
Begin[开始] --> S1[获取当前试管信息]
S1 --> S2[获取当前试管架配置信息]
%% 试管样本准备阶段
S2 --> S3[夹取试管到摇匀位置]
S3 --> S4[摇匀]
S4 --> S5[取试管帽]
S5 --> S6[设置样本预处理完成]
%% 反应板夹准备阶段
S6 --> S7[丢弃反应板夹为什么]
S7 --> S8[拉取反应板夹]
S8 --> S9[丢弃反应板夹为什么]
S9 --> S10[推送反应板夹]
S10 --> S11[设置反应板夹准备完毕]
%% 处理样本
S11 --> S12[刺破小缓冲液]
S12 --> S13[取样]
S13 --> S14[将孵育盘转到待滴液的位置]
S14 --> S15[滴液]
%% 孵育处理
S15 --> S16[]
```
```mermaid
---
title: 样本处理类图
---
classDiagram
%% 试管
class Tube
%% 试管架
class TubeHolder
%% 反应液类型
class A8kReactionFlowType
```

14
doc/系统事件消息总线.md

@ -65,4 +65,16 @@ classDiagram
class TubeHolderSettingMgrService
class Report
```
AppStateWebsocketEndpoint --> AppWebSocketEndpointMgr
AppEventWebsocketEndpoint --> AppWebSocketEndpointMgr
AppWebSocketEndpointMgr --> FrontEndMessageBoxAndEventMgr
AppWebSocketEndpointMgr --> DeviceWorkStateMgrService
AppWebSocketEndpointMgr --> GStateMgrService
AppWebSocketEndpointMgr --> TubeStateMgrService
AppWebSocketEndpointMgr --> IncubationPlateStateMgrService
AppWebSocketEndpointMgr --> OptScanModuleStateMgrService
AppWebSocketEndpointMgr --> ConsumablesMgrService
AppWebSocketEndpointMgr --> TubeHolderSettingMgrService
```

35
doc/耗材管理.md

@ -0,0 +1,35 @@
```mermaid
classDiagram
class A8kConsumableContainer
class TipContainer
class ReactionPlateContainer
class LittBottleContainer
class LarBottleContainer
A8kConsumableContainer "1" --> "3" TipContainer
A8kConsumableContainer "1" --> "6" ReactionPlateContainer
A8kConsumableContainer "1" --> "6" LittBottleContainer
A8kConsumableContainer "1" --> "6" LarBottleContainer
class ConsumablesMgrService
ConsumablesMgrService --> A8kConsumableContainer
class ConsumableInfo {
public String lotid;
public ConsumableGroup group; // 耗材组
public Integer pos; // 当前耗材信息属于哪个耗材组
}
```
```mermaid
---
title: 耗材状态更新机制
---
sequenceDiagram
```

34
src/main/java/a8k/app/controler/api/v1/app/verification/PipetteGunPerformanceValidationController.java

@ -0,0 +1,34 @@
package a8k.app.controler.api.v1.app.verification;
import a8k.app.service.verification.PipetteGunPerformanceValidator;
import a8k.app.type.exception.AppException;
import a8k.app.type.ui.ApiRet;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Tag(name = "移液枪性能验证", description = "")
@Slf4j
@Controller
@RequestMapping(value = "/api/v1/app/verification")
@ResponseBody
public class PipetteGunPerformanceValidationController {
@Resource
PipetteGunPerformanceValidator pipetteGunPerformanceValidator;
/**
* 移液枪10ul验证
* @return
* @throws AppException
*/
@PostMapping("/pipetteGun/10ul")
public ApiRet<Void> validate10ul() throws AppException {
pipetteGunPerformanceValidator.aspirate10ul();
return ApiRet.success();
}
}

151
src/main/java/a8k/app/service/verification/PipetteGunPerformanceValidator.java

@ -0,0 +1,151 @@
package a8k.app.service.verification;
import a8k.app.constant.AppConstant;
import a8k.app.hardware.driver.PipetteCtrlDriver;
import a8k.app.hardware.type.LldType;
import a8k.app.hardware.type.PipetteRegIndex;
import a8k.app.service.lowerctrl.HbotMoveCtrlService;
import a8k.app.service.lowerctrl.HbotMoveExCtrlService;
import a8k.app.service.lowerctrl.LiquidOperationCtrlService;
import a8k.app.service.param.exparam.HbotConsumableExParamMgr;
import a8k.app.service.param.hbotpos.HbotTipPosMgr;
import a8k.app.service.param.pipetteparam.PipetteGunExParamMgr;
import a8k.app.service.statemgr.ConsumablesMgrService;
import a8k.app.type.a8k.ConsumableGroup;
import a8k.app.type.a8k.Pos3d;
import a8k.app.type.a8k.pos.TipGroupPos;
import a8k.app.type.a8k.pos.TipPos;
import a8k.app.type.exception.AppException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 移液枪性能验证器
*/
@Slf4j
@Component
public class PipetteGunPerformanceValidator {
@Resource
HbotTipPosMgr hbotTipPosMgr;
@Resource
PipetteCtrlDriver pipetteCtrlDriver;
@Resource
HbotMoveCtrlService hbotMoveCtrlService;
@Resource
HbotMoveExCtrlService hbotMoveExCtrlService;
@Resource
HbotConsumableExParamMgr hbotConsumableExParamMgr;
@Resource
PipetteGunExParamMgr pipetteGunExParamMgr;
@Resource
ConsumablesMgrService consumablesMgrService;
/**
* 1. 移液枪获取从当前系统可用的tip位置获取一个tip头
* 2. 从耗材组1的大缓冲液中汲取10ul液体滴入到耗材组6的大缓冲液中
* 3. 移液枪移动到耗材组2大缓冲液位置
* @throws AppException
*/
public void aspirate10ul() throws AppException {
if (!takeOneTip()) {
throw AppException.ofAECodeError("获取tip失败");
}
Integer liquidPos = lld();
if (liquidPos == 0)
throw AppException.ofAECodeError("未检测到液体");
takeLiquid(10.0, liquidPos);
distributeLiquid();
resetPos();
}
private void distributeLiquid() throws AppException {
hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG6);
pipetteCtrlDriver.zMotorMoveToBlock(50);
pumpMoveTo(8000, 0.0);
pipetteCtrlDriver.zMotorMoveToBlock(0);
}
private void resetPos() throws AppException {
hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG2);
}
private Boolean takeOneTip() throws AppException {
hbotMoveCtrlService.hbotMoveTo(hbotTipPosMgr.getDropTipPos());
pipetteGunInit();
TipPos tipPos = consumablesMgrService.getFirstTipPos(TipGroupPos.TipG1);
log.info(" 取TIP {}", tipPos);
return hbotMoveExCtrlService.takeTipNoCheck(tipPos.group, tipPos.index);
}
public Integer lld() throws AppException {
Integer liquidPos = 0;
hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG1);
pipetteCtrlDriver.zMotorMoveToBlock(0);
pumpMoveTo(8000, 0.0);
pumpMoveTo(300, 100.0);
pumpMoveTo(8000, 0.0);
pumpMoveTo(300, 50.0);
Pos3d toPos = hbotConsumableExParamMgr.getLargeBufferSamplePos(ConsumableGroup.CG1);
Pos3d maxPos = hbotConsumableExParamMgr.getLargeBufferSamplePosEnd(ConsumableGroup.CG1);
pipetteCtrlDriver.zMotorMoveToBlock(toPos.z);
pipetteCtrlDriver.liquidOperationClearParams();
pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 30);
pipetteCtrlDriver.liquidOperationSetZMotorRunParams(toPos.z, maxPos.z, 60 * 80 / LiquidOperationCtrlService.helicalPitch);
pipetteCtrlDriver.liquidOperationFreshParams();
pipetteCtrlDriver.pipetteLld(LldType.kplld, 0, 30);
if (pipetteCtrlDriver.lldIsDetectLiquid()) {
liquidPos = pipetteCtrlDriver.getReg(PipetteRegIndex.kreg_pipette_zm_pos);
}
pipetteCtrlDriver.zMotorMoveToBlock(0);
pumpMoveTo(8000, 0.0);
return liquidPos;
}
public void pumpMoveTo(Integer pumpvmax, Double ul) throws AppException {
pipetteCtrlDriver.liquidOperationClearParams();
pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 1000, pumpvmax);
pipetteCtrlDriver.liquidOperationFreshParams();
pipetteCtrlDriver.pipettePumpMoveTo(ul);
}
/**
* 移液枪初始化
* @throws AppException
*/
private void pipetteGunInit() throws AppException {
pipetteCtrlDriver.pipetteInitDeviceBlock();
}
/**
* 汲取液体
* @param ul
* @throws AppException
*/
public void takeLiquid(Double ul, Integer liquidPos) throws AppException {
hbotMoveExCtrlService.moveToLargeBSSamplePosXY(ConsumableGroup.CG1);
pipetteCtrlDriver.zMotorMoveToBlock(0);
pumpMoveTo(8000, 0.0);
pumpMoveTo(8000, 150.0);
pipetteCtrlDriver.zMotorMoveToBlock(liquidPos);
pipetteCtrlDriver.liquidOperationClearParams();
pipetteCtrlDriver.liquidOperationSetGunRunParams(14, 14, 0, 900, 100);
pipetteCtrlDriver.liquidOperationSetZMotorRunParams(0, 300, 10 * 80 / LiquidOperationCtrlService.helicalPitch);
pipetteCtrlDriver.liquidOperationFreshParams();
ul = pipetteGunExParamMgr.calibrateVolume(ul);
log.info("取液体 {}", ul);
pipetteCtrlDriver.pipetteAspirate(ul);
pipetteCtrlDriver.zMotorMoveToBlock(0);
}
}
Loading…
Cancel
Save