16 changed files with 442 additions and 112 deletions
-
2src/main/java/a8k/app/constant/AppConstant.java
-
8src/main/java/a8k/app/controler/api/v1/app/data/ReactionResultControler.java
-
7src/main/java/a8k/app/hardware/channel/A8kCanBusConnection.java
-
10src/main/java/a8k/app/hardware/channel/A8kCanBusService.java
-
83src/main/java/a8k/app/hardware/channel/LisUartChannelConnection.java
-
164src/main/java/a8k/app/hardware/channel/PrinterUartChannel.java
-
34src/main/java/a8k/app/service/appsetup/A8kSubModuleRegInitService.java
-
15src/main/java/a8k/app/service/data/ReactionRecordMgrService.java
-
151src/main/java/a8k/app/service/peripheral/PrinterService.java
-
4src/main/java/a8k/app/service/statemgr/GStateMgrService.java
-
1src/main/java/a8k/app/service/utils/ReactionPlate2DCodeHelper.java
-
1src/main/java/a8k/app/utils/ZStringUtils.java
-
3src/main/java/a8k/extui/mgr/ExtApiPageGroupCfgMgr.java
-
58src/main/java/a8k/extui/page/driver/PrinterDebugPage.java
-
6src/main/java/a8k/extui/page/extsetting/db/ReactionRecordMgrDebugPage.java
-
3src/main/resources/application.yml
@ -1,83 +0,0 @@ |
|||
package a8k.app.hardware.channel; |
|||
|
|||
import a8k.app.config.IflytophaldConnectionConfig; |
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.Value; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.java_websocket.client.WebSocketClient; |
|||
import org.java_websocket.enums.ReadyState; |
|||
import org.java_websocket.handshake.ServerHandshake; |
|||
import org.springframework.scheduling.annotation.Scheduled; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.net.URI; |
|||
|
|||
// |
|||
//@Slf4j |
|||
//@Component |
|||
//@RequiredArgsConstructor |
|||
//public class LisUartChannelConnection { |
|||
// WebSocketClient conn; |
|||
// IflytophaldConnectionConfig iflytophaldConnectionConfig; |
|||
// |
|||
// @PostConstruct |
|||
// void init() { |
|||
// conn = new WebSocketClient(URI.create(iflytophaldConnectionConfig.getDatachUrl("lis"))) { |
|||
// @Override |
|||
// public void onOpen(ServerHandshake serverHandshake) { |
|||
// LisUartChannelConnection.this.onOpen(serverHandshake); |
|||
// } |
|||
// |
|||
// @Override |
|||
// public void onMessage(String s) { |
|||
// LisUartChannelConnection.this.onMessage(s); |
|||
// } |
|||
// |
|||
// @Override |
|||
// public void onClose(int i, String s, boolean b) { |
|||
// LisUartChannelConnection.this.onClose(i, s, b); |
|||
// } |
|||
// |
|||
// @Override |
|||
// public void onError(Exception e) { |
|||
// LisUartChannelConnection.this.onError(e); |
|||
// } |
|||
// }; |
|||
// } |
|||
// |
|||
// |
|||
// public void onOpen(ServerHandshake serverHandshake) { |
|||
// log.info("a8k canbus connect sucess"); |
|||
// } |
|||
// |
|||
// public void onMessage(String s) { |
|||
// } |
|||
// |
|||
// public void onClose(int i, String s, boolean b) { |
|||
// log.warn("a8k canbus lost connection..."); |
|||
// } |
|||
// |
|||
// public void onError(Exception e) { |
|||
// log.info("a8k can-websocket-channel on error"); |
|||
// } |
|||
// |
|||
// // |
|||
// // PRIVATE |
|||
// // |
|||
// @Scheduled(fixedRate = 1000) |
|||
// private void autoConnect() { |
|||
// if (!conn.isOpen()) { |
|||
// if (conn.getReadyState().equals(ReadyState.NOT_YET_CONNECTED)) { |
|||
// try { |
|||
// conn.connect(); |
|||
// } catch (IllegalStateException ignored) { |
|||
// } |
|||
// } else if (conn.getReadyState().equals(ReadyState.CLOSED)) { |
|||
// conn.reconnect(); |
|||
// } |
|||
// } |
|||
// } |
|||
//} |
|||
|
|||
// |
@ -0,0 +1,164 @@ |
|||
package a8k.app.hardware.channel; |
|||
|
|||
import a8k.OS; |
|||
import a8k.app.config.IflytophaldConnectionConfig; |
|||
import a8k.app.utils.ByteArray; |
|||
import a8k.app.utils.ZStringUtils; |
|||
import cn.hutool.core.util.ByteUtil; |
|||
import cn.hutool.core.util.CharsetUtil; |
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.java_websocket.client.WebSocketClient; |
|||
import org.java_websocket.enums.ReadyState; |
|||
import org.java_websocket.handshake.ServerHandshake; |
|||
import org.springframework.scheduling.annotation.Scheduled; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.io.UnsupportedEncodingException; |
|||
import java.net.URI; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.LinkedList; |
|||
import java.util.List; |
|||
import java.util.Queue; |
|||
|
|||
|
|||
@Slf4j |
|||
@Component |
|||
@RequiredArgsConstructor |
|||
public class PrinterUartChannel { |
|||
WebSocketClient conn; |
|||
|
|||
private final IflytophaldConnectionConfig config; |
|||
private Queue<byte[]> sendQueue = new LinkedList<>(); |
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
String url = config.getDatachUrl("printer"); |
|||
log.info("PrinterUartChannel url: {}", url); |
|||
conn = new WebSocketClient(URI.create(url)) { |
|||
@Override |
|||
public void onOpen(ServerHandshake serverHandshake) { |
|||
PrinterUartChannel.this.onOpen(serverHandshake); |
|||
} |
|||
|
|||
@Override |
|||
public void onMessage(String s) { |
|||
PrinterUartChannel.this.onMessage(s); |
|||
} |
|||
|
|||
@Override |
|||
public void onClose(int i, String s, boolean b) { |
|||
PrinterUartChannel.this.onClose(i, s, b); |
|||
} |
|||
|
|||
@Override |
|||
public void onError(Exception e) { |
|||
PrinterUartChannel.this.onError(e); |
|||
} |
|||
}; |
|||
conn.connect(); |
|||
} |
|||
|
|||
/** |
|||
* 打印字符串 |
|||
* @param fmt 格式化字符串 |
|||
* @param args 参数 |
|||
* 1. 打印%时候,需要使用%%,否则会报错 |
|||
* |
|||
*/ |
|||
public void printf(String fmt, Object... args) { |
|||
if (conn.isOpen()) { |
|||
String s = String.format(fmt, args); |
|||
try { |
|||
byte[] toSend = s.getBytes("GBK"); |
|||
pushToSend(toSend); |
|||
} catch (UnsupportedEncodingException e) { |
|||
log.error("charset error", e); |
|||
} |
|||
} else { |
|||
log.warn("PrinterUartChannel is not open"); |
|||
} |
|||
} |
|||
|
|||
public void printfEnd() { |
|||
if (conn.isOpen()) { |
|||
printf("\r\n"); |
|||
printf("\r\n"); |
|||
printf("\r\n"); |
|||
} |
|||
} |
|||
|
|||
|
|||
// |
|||
// PRIVATE |
|||
// |
|||
|
|||
|
|||
private void onOpen(ServerHandshake serverHandshake) { |
|||
log.info("a8k canbus connect sucess"); |
|||
} |
|||
|
|||
private void onMessage(String s) { |
|||
} |
|||
|
|||
private void onClose(int i, String s, boolean b) { |
|||
log.warn("a8k canbus lost connection..."); |
|||
} |
|||
|
|||
private void onError(Exception e) { |
|||
log.info("a8k can-websocket-channel on error"); |
|||
} |
|||
|
|||
|
|||
synchronized private void pushToSend(byte[] toSend) { |
|||
sendQueue.add(toSend); |
|||
} |
|||
|
|||
synchronized private byte[] popToSend() { |
|||
if (!sendQueue.isEmpty()) { |
|||
return sendQueue.poll(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
// conn.send(toSend); |
|||
// if (toSend.length > 10) { |
|||
// OS.forceSleep(150); |
|||
// } |
|||
@Scheduled(fixedRate = 400) |
|||
private void autoSend() { |
|||
while (true) { |
|||
var tosend = popToSend(); |
|||
if (tosend != null) { |
|||
if (conn.isOpen()) { |
|||
conn.send(tosend); |
|||
} |
|||
if (tosend.length > 2) { |
|||
break; |
|||
} |
|||
} else { |
|||
break; |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
@Scheduled(fixedRate = 1000) |
|||
private void autoConnect() { |
|||
if (!conn.isOpen()) { |
|||
if (conn.getReadyState().equals(ReadyState.NOT_YET_CONNECTED)) { |
|||
try { |
|||
conn.connect(); |
|||
} catch (IllegalStateException ignored) { |
|||
} |
|||
} else if (conn.getReadyState().equals(ReadyState.CLOSED)) { |
|||
conn.reconnect(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
@ -0,0 +1,151 @@ |
|||
package a8k.app.service.peripheral; |
|||
|
|||
import a8k.app.dao.type.db.ProjExtInfoCard; |
|||
import a8k.app.dao.type.db.ReactionReport; |
|||
import a8k.app.hardware.channel.PrinterUartChannel; |
|||
import a8k.app.optalgo.type.ReactionResultStatus; |
|||
import a8k.app.service.data.ProjInfoMgrService; |
|||
import a8k.app.service.statemgr.GStateMgrService; |
|||
import a8k.app.type.a8k.BloodType; |
|||
import a8k.app.type.a8k.opt.A8kOptType; |
|||
import a8k.app.type.a8k.opt.OptScanResult; |
|||
import a8k.app.type.a8k.proj.A8kResultUnit; |
|||
import a8k.app.type.a8k.proj.ProjInfo; |
|||
import a8k.app.type.a8k.state.SampleInfo; |
|||
import a8k.app.type.exception.AppException; |
|||
import a8k.extui.factory.FakeOptScanResultFactory; |
|||
import a8k.extui.factory.ProjExtInfoCardFactory; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.text.SimpleDateFormat; |
|||
import java.util.ArrayList; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class PrinterService { |
|||
private final PrinterUartChannel printer; |
|||
private final ProjInfoMgrService projInfoMgrService; |
|||
private final GStateMgrService gStateMgrService; |
|||
|
|||
String bloodTypeToString(BloodType bloodType) { |
|||
return switch (bloodType) { |
|||
case WHOLE_BLOOD -> "全血"; |
|||
case SERUM_OR_PLASMA -> "血清/血浆"; |
|||
}; |
|||
} |
|||
|
|||
public void printDemoReactionReport() { |
|||
|
|||
ProjExtInfoCard.A8kResultUintFn resultBuilder0 = // |
|||
new ProjExtInfoCard.A8kResultUintFn(A8kResultUnit.coi, A8kResultUnit.iuPml, A8kResultUnit.uPl, 2.0, 2.0, 3.0, 3.0); |
|||
ProjExtInfoCard.A8kResultUintFn resultBuilder1 =// |
|||
new ProjExtInfoCard.A8kResultUintFn(A8kResultUnit.coi, A8kResultUnit.iuPml, A8kResultUnit.uPl, 2.0, 2.0, 3.0, 3.0); |
|||
ProjExtInfoCard.A8kResultUintFn resultBuilder2 =// |
|||
new ProjExtInfoCard.A8kResultUintFn(A8kResultUnit.coi, A8kResultUnit.iuPml, A8kResultUnit.uPl, 2.0, 2.0, 3.0, 3.0); |
|||
List<ReactionReport.ReactionResult> reactionResults = new ArrayList<>(); |
|||
reactionResults.add(new ReactionReport.ReactionResult("Tn-I", "Tn-I", 1.0, resultBuilder0.toResultUnitConverters())); |
|||
reactionResults.add(new ReactionReport.ReactionResult("CK-MB", "CK-MB", 2.0, resultBuilder1.toResultUnitConverters())); |
|||
reactionResults.add(new ReactionReport.ReactionResult("Myoglobin", "MG", 3.0, resultBuilder2.toResultUnitConverters())); |
|||
|
|||
|
|||
ReactionReport record = new ReactionReport(); |
|||
record.sampleBloodType = BloodType.WHOLE_BLOOD; |
|||
record.sampleBarcode = "ASDF123456789"; |
|||
record.sampleUserid = "U1023"; |
|||
record.sampleId = "1122334456"; |
|||
record.projName = "HSCrp"; |
|||
record.lotId = "CA2312345"; |
|||
record.projId = 1; |
|||
record.setExpiryDate(new Date()); |
|||
record.operator = "张三"; |
|||
record.projShortName = "CA"; |
|||
record.appVersion = gStateMgrService.getAppVersion(); |
|||
record.mcuVersion = gStateMgrService.getMcuVersion(); |
|||
record.sn = gStateMgrService.getSn(); |
|||
record.subProjNum = reactionResults.size(); |
|||
record.projInfoIdCardVersion = 1; |
|||
record.projInfo = null; |
|||
record.results = reactionResults; |
|||
record.detailOptData = null; |
|||
|
|||
print(record); |
|||
|
|||
} |
|||
|
|||
public void print(ReactionReport report) { |
|||
/* |
|||
* 日期: 2023-10-01 12:00:00 |
|||
* 操作人: 张三 |
|||
* 软件版本: 1.0.0 |
|||
* MCU版本: 1.0.0 |
|||
* 仪器序列号: 123456789 |
|||
* |
|||
* UID:sampleUserid |
|||
* 条码ID: sampleBarcode |
|||
* |
|||
* 样本类型:全血/血清/血浆 |
|||
* 项目名称: |
|||
* 批次号: |
|||
* |
|||
* <子项目名称> |
|||
* 结果: |
|||
* 结果(单位1): |
|||
* 结果(单位2): |
|||
* |
|||
* <子项目名称> |
|||
* 结果: |
|||
* 结果(单位1): |
|||
* 结果(单位2): |
|||
* |
|||
*/ |
|||
// 定义日期格式 |
|||
if(report == null) { |
|||
return; |
|||
} |
|||
|
|||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
|||
printer.printf("*****************************\r\n"); |
|||
printer.printf(" 日期: %s\r\n", dateFormat.format(report.creatDate)); |
|||
printer.printf(" 操作人: %s\r\n", report.operator); |
|||
printer.printf(" 软件版本: %s\r\n", report.appVersion); |
|||
printer.printf(" MCU版本: %s\r\n", report.mcuVersion); |
|||
printer.printf(" 仪器序列号: %s\r\n", report.sn); |
|||
printer.printf(" \r\n"); |
|||
printer.printf(" \r\n"); |
|||
printer.printf(" UID: %s\r\n", report.sampleUserid); |
|||
printer.printf(" BARCODE: %s\r\n", report.sampleBarcode); |
|||
printer.printf(" \r\n"); |
|||
printer.printf(" 样本类型: %s\r\n", bloodTypeToString(report.sampleBloodType)); |
|||
printer.printf(" 项目名称: %s\r\n", report.projName); |
|||
printer.printf(" 批次号: %s\r\n", report.lotId); |
|||
printer.printf(" \r\n"); |
|||
printer.printf(" \r\n"); |
|||
for (var result : report.results) { |
|||
if (result == null) |
|||
continue; |
|||
printer.printf(" 子项目名称: %s\r\n", result.subProjName); |
|||
if (result.status.equals(ReactionResultStatus.SUCCESS)) { |
|||
printer.printf(" 结果: %s\r\n", result.result); |
|||
for (int j = 0; j < result.resultConverters.size(); j++) { |
|||
var converter = result.resultConverters.get(j); |
|||
if (converter == null) |
|||
continue; |
|||
printer.printf(" 结果(单位%d): %s\r\n", j + 1, converter.convert(result.result)); |
|||
} |
|||
printer.printf(" \r\n"); |
|||
} else { |
|||
printer.printf(" ERROR\r\n"); |
|||
printer.printf(" %s\r\n", result.errorInfo); |
|||
printer.printf(" \r\n"); |
|||
} |
|||
} |
|||
printer.printf("*****************************\r\n"); |
|||
printer.printfEnd(); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,58 @@ |
|||
package a8k.extui.page.driver; |
|||
|
|||
import a8k.OS; |
|||
import a8k.app.hardware.channel.PrinterUartChannel; |
|||
import a8k.app.hardware.driver.PipetteCtrlDriver; |
|||
import a8k.app.service.peripheral.PrinterService; |
|||
import a8k.extui.mgr.ExtApiPageMgr; |
|||
import a8k.extui.type.ExtUIPageCfg; |
|||
import jakarta.annotation.PostConstruct; |
|||
import jakarta.annotation.Resource; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class PrinterDebugPage { |
|||
|
|||
private final PrinterUartChannel printerUartChannel; |
|||
private final ExtApiPageMgr extApiPageMgr; |
|||
private final PrinterService printerService; |
|||
|
|||
|
|||
public void printf(String str) { |
|||
printerUartChannel.printf(str + "\r\n"); |
|||
} |
|||
|
|||
public void printerTest() { |
|||
printerUartChannel.printf("ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"); |
|||
OS.forceSleep(100); |
|||
printerUartChannel.printf("abcdefghijklmnopqrstuvwxyz\r\n"); |
|||
OS.forceSleep(100); |
|||
printerUartChannel.printf("0123456789\r\n"); |
|||
OS.forceSleep(100); |
|||
printerUartChannel.printf("!@#$%%*()^_+\r\n"); |
|||
OS.forceSleep(100); |
|||
printerUartChannel.printf("~`!@#$%%^&*()_+|\\{}[]:\";'<>?,./\r\n"); |
|||
OS.forceSleep(100); |
|||
printerUartChannel.printf("中文测试\r\n"); |
|||
OS.forceSleep(100); |
|||
printerUartChannel.printfEnd(); |
|||
|
|||
} |
|||
|
|||
public void printDemoReactionReport() { |
|||
printerService.printDemoReactionReport(); |
|||
} |
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
ExtUIPageCfg page = new ExtUIPageCfg(this); |
|||
page.addFunction("printf", this::printf); |
|||
page.addFunction("printerTest", this::printerTest); |
|||
page.addFunction("打印报告(示例)", this::printDemoReactionReport); |
|||
extApiPageMgr.addPage(page); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue