|
@ -3,6 +3,8 @@ package a8k.service.app; |
|
|
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|
|
import a8k.hardware.type.a8kcanprotocol.A8kEcode; |
|
|
import a8k.service.app.app_consumables_mgr_service.ConsumablesScanRawResult; |
|
|
import a8k.service.app.app_consumables_mgr_service.ConsumablesScanRawResult; |
|
|
import a8k.baseservice.ActionReactorService; |
|
|
import a8k.baseservice.ActionReactorService; |
|
|
|
|
|
import a8k.service.app.app_consumables_mgr_service.ConsumablesScanResult; |
|
|
|
|
|
import a8k.service.app.app_consumables_mgr_service.ScanResultState; |
|
|
import a8k.service.devicectrl.ctrl.HbotControlService; |
|
|
import a8k.service.devicectrl.ctrl.HbotControlService; |
|
|
import a8k.service.hardwareparam.Hbot2DCodeScanPosMgrService; |
|
|
import a8k.service.hardwareparam.Hbot2DCodeScanPosMgrService; |
|
|
import a8k.type.appret.AppRet; |
|
|
import a8k.type.appret.AppRet; |
|
@ -13,10 +15,21 @@ import a8k.service.app.app_consumables_mgr_service.ConsumableState; |
|
|
import a8k.service.app.appstate.AppStateMgrService; |
|
|
import a8k.service.app.appstate.AppStateMgrService; |
|
|
import a8k.type.cfg.Pos2d; |
|
|
import a8k.type.cfg.Pos2d; |
|
|
import a8k.type.exception.AppException; |
|
|
import a8k.type.exception.AppException; |
|
|
|
|
|
import a8k.type.projecttype.A8kReactionFlowType; |
|
|
|
|
|
import a8k.type.projecttype.a8kidcard.A8kIdCardInfo; |
|
|
|
|
|
import a8k.utils.ReactionPlate2DCode; |
|
|
|
|
|
import a8k.utils.ReactionPlate2DCodeParser; |
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper; |
|
|
|
|
|
import com.google.gson.JsonArray; |
|
|
|
|
|
import com.google.gson.JsonObject; |
|
|
import jakarta.annotation.Resource; |
|
|
import jakarta.annotation.Resource; |
|
|
import org.slf4j.Logger; |
|
|
import org.slf4j.Logger; |
|
|
import org.springframework.stereotype.Component; |
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.Date; |
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ExtApiTab(cfg = ExtApiTabConfig.AppConsumablesMgrService) |
|
|
@ExtApiTab(cfg = ExtApiTabConfig.AppConsumablesMgrService) |
|
|
@Component |
|
|
@Component |
|
@ -42,6 +55,9 @@ public class AppConsumablesMgrService { |
|
|
Hbot2DCodeScanPosMgrService hbotScanPos; |
|
|
Hbot2DCodeScanPosMgrService hbotScanPos; |
|
|
|
|
|
|
|
|
@Resource |
|
|
@Resource |
|
|
|
|
|
AppProjInfoMgrService appProjMgr; |
|
|
|
|
|
|
|
|
|
|
|
@Resource |
|
|
HbotControlService hbot; |
|
|
HbotControlService hbot; |
|
|
|
|
|
|
|
|
ConsumableState consumableState = new ConsumableState(); |
|
|
ConsumableState consumableState = new ConsumableState(); |
|
@ -56,25 +72,26 @@ public class AppConsumablesMgrService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String scanPB(int ch) throws AppException, InterruptedException { |
|
|
|
|
|
|
|
|
private String scanPB(int ch) throws AppException, InterruptedException { |
|
|
Pos2d pos = hbotScanPos.getPBScanPos(ch); |
|
|
Pos2d pos = hbotScanPos.getPBScanPos(ch); |
|
|
hbotMoveTo(pos); |
|
|
hbotMoveTo(pos); |
|
|
return scan2dCode(100); |
|
|
return scan2dCode(100); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public String scanLittBS(int ch) throws AppException, InterruptedException { |
|
|
|
|
|
|
|
|
private String scanLittBS(int ch) throws AppException, InterruptedException { |
|
|
Pos2d pos = hbotScanPos.getLittBS(ch); |
|
|
Pos2d pos = hbotScanPos.getLittBS(ch); |
|
|
hbotMoveTo(pos); |
|
|
hbotMoveTo(pos); |
|
|
return scan2dCode(100); |
|
|
return scan2dCode(100); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public String scanLarBS(int ch) throws AppException, InterruptedException { |
|
|
|
|
|
|
|
|
private String scanLarBS(int ch) throws AppException, InterruptedException { |
|
|
Pos2d pos = hbotScanPos.getLarBS(ch); |
|
|
Pos2d pos = hbotScanPos.getLarBS(ch); |
|
|
hbotMoveTo(pos); |
|
|
hbotMoveTo(pos); |
|
|
return scan2dCode(100); |
|
|
return scan2dCode(100); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ExtApiFn(name = "执行-扫描耗材-动作", order = ORDER.doScanConsumablesAction) |
|
|
@ExtApiFn(name = "执行-扫描耗材-动作", order = ORDER.doScanConsumablesAction) |
|
|
public ConsumablesScanRawResult doScanConsumablesAction() throws AppException, InterruptedException { |
|
|
public ConsumablesScanRawResult doScanConsumablesAction() throws AppException, InterruptedException { |
|
|
if (!stateMgrService.isDeviceInited()) { |
|
|
if (!stateMgrService.isDeviceInited()) { |
|
@ -94,64 +111,123 @@ public class AppConsumablesMgrService { |
|
|
ar.dosome("扫描耗材-大瓶缓冲液", () -> result.larBSScanResult[finalI] = scanLarBS(finalI)); |
|
|
ar.dosome("扫描耗材-大瓶缓冲液", () -> result.larBSScanResult[finalI] = scanLarBS(finalI)); |
|
|
} |
|
|
} |
|
|
hbotMoveTo(new Pos2d(0, 0)); |
|
|
hbotMoveTo(new Pos2d(0, 0)); |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* 清空 result 中的所有\r |
|
|
|
|
|
*/ |
|
|
|
|
|
for (int i = 0; i < 6; i++) { |
|
|
|
|
|
if (result.PBScanResult[i] != null) { |
|
|
|
|
|
result.PBScanResult[i] = result.PBScanResult[i].replaceAll("\r", ""); |
|
|
|
|
|
} |
|
|
|
|
|
if (result.littBSScanResult[i] != null) { |
|
|
|
|
|
result.littBSScanResult[i] = result.littBSScanResult[i].replaceAll("\r", ""); |
|
|
|
|
|
} |
|
|
|
|
|
if (result.larBSScanResult[i] != null) { |
|
|
|
|
|
result.larBSScanResult[i] = result.larBSScanResult[i].replaceAll("\r", ""); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//扫描耗材 |
|
|
|
|
|
@ExtApiFn(name = "扫描耗材", order = ORDER.scanningConsumables) |
|
|
|
|
|
public AppRet<ConsumableState> scanningConsumables() throws AppException, InterruptedException { |
|
|
|
|
|
if (!stateMgrService.isDeviceInited()) { |
|
|
|
|
|
return AppRet.fail(A8kEcode.DeviceNotInited.index); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ExtApiFn(name = "获取耗材状态", order = ORDER.getConsumables) |
|
|
|
|
|
public AppRet<ConsumableState> getConsumables() { |
|
|
|
|
|
return AppRet.success(consumableState); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ConsumableState var = new ConsumableState(); |
|
|
|
|
|
for (int i = 0; i < var.tipGroup.length; i++) { |
|
|
|
|
|
var.tipGroup[i].tipNum = 96; |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 解析扫描结果,返回耗材扫描结果 |
|
|
|
|
|
* |
|
|
|
|
|
* @param ch 通道号(0...5) |
|
|
|
|
|
* @param rawResult 原始扫描结果 |
|
|
|
|
|
* @return 耗材扫描结果 |
|
|
|
|
|
*/ |
|
|
|
|
|
ConsumablesScanResult parseScanResult(Integer ch, ConsumablesScanRawResult rawResult) throws AppException { |
|
|
|
|
|
ConsumablesScanResult ret = new ConsumablesScanResult(); |
|
|
|
|
|
ret.chNum = ch; |
|
|
|
|
|
|
|
|
|
|
|
if (rawResult.larBSScanResult[ch] == null && rawResult.littBSScanResult[ch] == null && rawResult.PBScanResult[ch] == null) { |
|
|
|
|
|
ret.state = ScanResultState.Empty; |
|
|
|
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ConsumablesScanRawResult scanResult = doScanConsumablesAction(); |
|
|
|
|
|
|
|
|
if (rawResult.PBScanResult[ch] == null) { |
|
|
|
|
|
ret.state = ScanResultState.LostReactionPlate; |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// |
|
|
|
|
|
// |
|
|
|
|
|
// |
|
|
|
|
|
|
|
|
//解析板夹二维码 |
|
|
|
|
|
ReactionPlate2DCode rp2dcode = ReactionPlate2DCodeParser.parse(rawResult.PBScanResult[ch]); |
|
|
|
|
|
|
|
|
String[] tLotVal = new String[6]; |
|
|
|
|
|
String[] tProjId = new String[6]; |
|
|
|
|
|
//解析lotVal |
|
|
|
|
|
|
|
|
//检查耗材是否过期 |
|
|
|
|
|
if (rp2dcode.expDate.before(new Date())) { |
|
|
|
|
|
ret.state = ScanResultState.ConsumableExpired; |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++) { |
|
|
|
|
|
// var.reactantItems[i] = new ReactantItem(); |
|
|
|
|
|
// var.reactantItems[i].projId = "PROJECT_" + i; |
|
|
|
|
|
// var.reactantItems[i].lotVal = "LOT_" + i; |
|
|
|
|
|
// var.reactantItems[i].color = projectColorAllocer.getProjectColor(var.reactantItems[i].projId); |
|
|
|
|
|
// var.reactantItems[i].hasDetectionMaterial = i % 2 == 0; |
|
|
|
|
|
// var.reactantItems[i].hasSmallBufferBottle = i % 2 == 1; |
|
|
|
|
|
// var.reactantItems[i].hasLargeBufferBottle = i % 2 == 0; |
|
|
|
|
|
|
|
|
//检查项目ID卡是否存在 |
|
|
|
|
|
A8kIdCardInfo a8kIdCardInfo = appProjMgr.getA8kIdCardInfoByLotId(rp2dcode.lotId); |
|
|
|
|
|
if (a8kIdCardInfo == null) { |
|
|
|
|
|
ret.state = ScanResultState.NoMatchingProjIDCardFound; |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//通过项目ID卡获取项目需要的耗材 |
|
|
|
|
|
A8kReactionFlowType reactionType = appProjMgr.getA8kReactionFlowTypeByProjIndex(rp2dcode.projIndex); |
|
|
|
|
|
if (reactionType == null) { |
|
|
|
|
|
ret.state = ScanResultState.ProjInfoIsInComplete; |
|
|
|
|
|
return ret; |
|
|
} |
|
|
} |
|
|
// var.tip[0] = new TipGroupInfo(); |
|
|
|
|
|
// var.tip[1] = new TipGroupInfo(); |
|
|
|
|
|
// var.tip[2] = new TipGroupInfo(); |
|
|
|
|
|
// stateMgrService.setConsumable(var); |
|
|
|
|
|
this.consumableState = var; |
|
|
|
|
|
return AppRet.success(var); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (reactionType.equals(A8kReactionFlowType.ReactionWithLittBS)) { |
|
|
|
|
|
//校验小瓶缓冲液,小瓶缓冲液+样本 |
|
|
|
|
|
if (rawResult.littBSScanResult[ch] == null) { |
|
|
|
|
|
ret.state = ScanResultState.LostLittSB; |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
} else if (reactionType.equals(A8kReactionFlowType.ReactionWithLarBsAndDetection)) { |
|
|
|
|
|
// 校验大瓶缓冲液,大瓶缓冲液+小瓶缓冲液+样本 |
|
|
|
|
|
if (rawResult.larBSScanResult[ch] == null) { |
|
|
|
|
|
ret.state = ScanResultState.LostLarBS; |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
throw new RuntimeException("未知的反应流程类型"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private String hBotMoveToAndScan(Pos2d pos) throws AppException, InterruptedException { |
|
|
|
|
|
// hbotCheckAndMoveTo(pos); |
|
|
|
|
|
// canBus.codeScanerStartScan(MId.PipetteModCodeScanner); |
|
|
|
|
|
// String result = canBus.codeScanerWaittingForResult(MId.PipetteModCodeScanner, timep.getScancodeOvertime()); |
|
|
|
|
|
// return AppRet.success(result); |
|
|
|
|
|
return ""; |
|
|
|
|
|
|
|
|
ret.lotId = rp2dcode.lotId; |
|
|
|
|
|
ret.projIndex = rp2dcode.projIndex; |
|
|
|
|
|
ret.expireDate = rp2dcode.expDate; |
|
|
|
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//扫描耗材 |
|
|
|
|
|
@ExtApiFn(name = "扫描耗材", order = ORDER.scanningConsumables) |
|
|
|
|
|
public AppRet<Map<String,Object>> scanningConsumables() throws AppException, InterruptedException { |
|
|
|
|
|
if (!stateMgrService.isDeviceInited()) { |
|
|
|
|
|
return AppRet.fail(A8kEcode.DeviceNotInited.index); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ExtApiFn(name = "获取耗材状态", order = ORDER.getConsumables) |
|
|
|
|
|
public AppRet<ConsumableState> getConsumables() { |
|
|
|
|
|
return AppRet.success(consumableState); |
|
|
|
|
|
|
|
|
List<ConsumablesScanResult> scanResult = new java.util.ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
//执行扫描耗材动作 |
|
|
|
|
|
var scanRawResult = doScanConsumablesAction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//解析扫描结果 |
|
|
|
|
|
for (int i = 0; i < 6; i++) { |
|
|
|
|
|
var result = parseScanResult(i, scanRawResult); |
|
|
|
|
|
scanResult.add(result); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Map<String,Object> ret = new java.util.HashMap<>(); |
|
|
|
|
|
ret.put("scanResult", scanResult); |
|
|
|
|
|
ret.put("scanRawResult",scanRawResult); |
|
|
|
|
|
|
|
|
|
|
|
return AppRet.success(ret); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |