diff --git a/src/main/java/com/dreamworks/boditech/controller/TmpController.java b/src/main/java/com/dreamworks/boditech/controller/TmpController.java index 628674e..24ad1ec 100644 --- a/src/main/java/com/dreamworks/boditech/controller/TmpController.java +++ b/src/main/java/com/dreamworks/boditech/controller/TmpController.java @@ -7,6 +7,7 @@ import com.dreamworks.boditech.driver.actuator.ActuatorModule; import com.dreamworks.boditech.driver.consumable.CsmPipetteTip; import com.dreamworks.boditech.driver.consumable.CsmPipetteTipBox; import com.dreamworks.boditech.driver.consumable.CsmPipetteTipManager; +import com.dreamworks.boditech.driver.entity.LisTestInfo; import com.dreamworks.boditech.driver.entity.ParamPipetteTipUpdate; import com.dreamworks.boditech.service.AccountService; import com.dreamworks.boditech.service.DeviceService; @@ -28,6 +29,14 @@ public class TmpController extends BaseController { private DeviceService deviceService; @ResponseBody + @PostMapping("/api/tmp/lis-request-test-info") + public ApiResponse lisRequestTestInfo( @RequestBody Map params ) { + String barCode = (String)params.get("barCode"); + LisTestInfo info = this.deviceService.device.lis.requestTestInfo(barCode); + return this.success(info); + } + + @ResponseBody @PostMapping("/api/tmp/move-to-liquid-level") public ApiResponse moveToLiquidLevel(@RequestBody Map params ) { String name = (String)params.get("name"); diff --git a/src/main/java/com/dreamworks/boditech/driver/Device.java b/src/main/java/com/dreamworks/boditech/driver/Device.java index a439caf..b72fe11 100644 --- a/src/main/java/com/dreamworks/boditech/driver/Device.java +++ b/src/main/java/com/dreamworks/boditech/driver/Device.java @@ -3,12 +3,9 @@ import com.dreamworks.boditech.driver.actuator.*; import com.dreamworks.boditech.driver.connection.ClientRequest; import com.dreamworks.boditech.driver.connection.ComSerialPort; import com.dreamworks.boditech.driver.connection.ComWebsocket; -import com.dreamworks.boditech.driver.connection.ComLisClient; import com.dreamworks.boditech.driver.consumable.*; -import com.dreamworks.boditech.driver.entity.DeviceLogEntry; import com.dreamworks.boditech.mapper.DeviceLogMapper; import com.dreamworks.boditech.service.*; -import com.dreamworks.boditech.utils.MyByteBuffer; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import org.slf4j.Logger; @@ -18,8 +15,6 @@ import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Map; @Component @@ -45,7 +40,7 @@ public class Device { @Resource public TestService testService; @Resource - public ComLisClient lis; + public DeviceLisService lis; @Resource public WebsocketServerService websocketServerService; @Resource diff --git a/src/main/java/com/dreamworks/boditech/driver/DeviceLisService.java b/src/main/java/com/dreamworks/boditech/driver/DeviceLisService.java new file mode 100644 index 0000000..02802e4 --- /dev/null +++ b/src/main/java/com/dreamworks/boditech/driver/DeviceLisService.java @@ -0,0 +1,84 @@ +package com.dreamworks.boditech.driver; +import com.dreamworks.boditech.driver.connection.ClientRequest; +import com.dreamworks.boditech.driver.connection.ComLisConnection; +import com.dreamworks.boditech.driver.connection.ComLisSerialPort; +import com.dreamworks.boditech.driver.entity.LisTestInfo; +import com.dreamworks.boditech.service.RuntimeOptionService; +import com.dreamworks.boditech.service.RuntimeVariableService; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +@Component +public class DeviceLisService { + @Resource + private RuntimeOptionService options; + + // connection + private ComLisConnection connection; + + @PostConstruct + public void init() { + String conType = this.options.getString("app.lis.connectionType"); + if ("SerialPort".equals(conType)) { + ComLisSerialPort con = new ComLisSerialPort(); + con.path = this.options.getString("app.lis.serialport.path"); + con.baudrate = this.options.getInteger("app.lis.serialport.baudrate"); + con.connect(); + this.connection = con; + } else { + throw new RuntimeException("not support connection type"); + } + } + + // request test info + public LisTestInfo requestTestInfo( String barCode ) { + List bodyItems = new ArrayList<>(); + bodyItems.add("Q"); + bodyItems.add("A8000"); + bodyItems.add("^" + barCode + "\r"); + String body = String.join("|", bodyItems); + byte[] bodyBytes = body.getBytes(); + int bodySum = 0; + for ( byte b : bodyBytes ) { + bodySum += b; + } + bodySum = bodySum % 256; + + ByteBuffer parameter = ByteBuffer.allocate(body.length() + 7); + parameter.order(ByteOrder.BIG_ENDIAN); + parameter.put((byte)0x02); // + parameter.put((byte)0x01); // FN + parameter.put(bodyBytes); // + parameter.put((byte)0x03); // + parameter.putShort((short)bodySum); // validate + parameter.put((byte)0x0D); // + parameter.put((byte)0x0A); // + ByteBuffer response = this.connection.call(parameter); + + short validate = response.getShort(response.limit() - 3); + // @TODO : check validate + // @TODO : 这里分割的还不对 ~~~ 后面再写 ~~~ + byte[] responseBytes = new byte[response.limit() - 7]; + response.get(responseBytes,2, responseBytes.length - 4); + String responseBody = new String(responseBytes); + String[] responseItems = responseBody.split("\\|"); + LisTestInfo testInfo = new LisTestInfo(); + testInfo.deviceName = responseItems[1]; + testInfo.sampleId = responseItems[2]; + testInfo.sampleType = responseItems[5]; + testInfo.sampleTime = responseItems[7].trim(); + testInfo.projectNames = new ArrayList<>(); + String[] projectNames = responseItems[4].split("\\\\"); + for ( String projectName : projectNames ) { + projectName = projectName.replace("^", ""); + testInfo.projectNames.add(projectName); + } + return testInfo; + } +} diff --git a/src/main/java/com/dreamworks/boditech/driver/connection/ComLisClient.java b/src/main/java/com/dreamworks/boditech/driver/connection/ComLisClient.java deleted file mode 100644 index 3f4eac9..0000000 --- a/src/main/java/com/dreamworks/boditech/driver/connection/ComLisClient.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dreamworks.boditech.driver.connection; -import com.dreamworks.boditech.driver.entity.LisTestInfo; -import org.springframework.stereotype.Component; -import java.util.ArrayList; -@Component -public class ComLisClient { - // request test info - public LisTestInfo requestTestInfo( String barCode ) { - if ( barCode.isEmpty() ) { - return null; - } - - LisTestInfo testInfo = new LisTestInfo(); - testInfo.sampleType = "WB"; - testInfo.projectNames = new ArrayList<>(); - testInfo.projectNames.add("hsCRP"); - return testInfo; - } -} diff --git a/src/main/java/com/dreamworks/boditech/driver/connection/ComLisConnection.java b/src/main/java/com/dreamworks/boditech/driver/connection/ComLisConnection.java new file mode 100644 index 0000000..de9e4e3 --- /dev/null +++ b/src/main/java/com/dreamworks/boditech/driver/connection/ComLisConnection.java @@ -0,0 +1,7 @@ +package com.dreamworks.boditech.driver.connection; +import java.nio.ByteBuffer; +public interface ComLisConnection { + void connect(); + ByteBuffer call(ByteBuffer request); + void write(ByteBuffer data); +} diff --git a/src/main/java/com/dreamworks/boditech/driver/connection/ComLisSerialPort.java b/src/main/java/com/dreamworks/boditech/driver/connection/ComLisSerialPort.java new file mode 100644 index 0000000..b10636d --- /dev/null +++ b/src/main/java/com/dreamworks/boditech/driver/connection/ComLisSerialPort.java @@ -0,0 +1,114 @@ +package com.dreamworks.boditech.driver.connection; +import com.dreamworks.boditech.utils.AppError; +import com.dreamworks.boditech.utils.AppRuntimeException; +import com.fazecast.jSerialComm.SerialPort; +import com.fazecast.jSerialComm.SerialPortEvent; +import com.fazecast.jSerialComm.SerialPortMessageListener; +import java.nio.ByteBuffer; +import java.util.Timer; +import java.util.TimerTask; +public class ComLisSerialPort implements ComLisConnection { + // serial port path + public String path; + // serial port baud rate + public Integer baudrate; + // serial port connection + private SerialPort port; + // request lock + private final Object requestLock = new Object(); + // request + private ClientRequest request; + + @Override + public void connect() { + this.port = SerialPort.getCommPort(this.path); + this.port.openPort(); + if ( !this.port.isOpen() ) { + throw new AppRuntimeException(AppError.DEVICE_LIS_SERIAL_PORT_OPEN_FAILED); + } + this.port.setBaudRate(this.baudrate); + + this.port.addDataListener(new SerialPortMessageListener() { + @Override + public byte[] getMessageDelimiter() { + return new byte[] { (byte)0x0D, (byte)0x0A }; + } + + @Override + public boolean delimiterIndicatesEndOfMessage() { + return true; + } + + @Override + public int getListeningEvents() { + return SerialPort.LISTENING_EVENT_DATA_RECEIVED; + } + + @Override + public void serialEvent(SerialPortEvent serialPortEvent) { + ComLisSerialPort.this.handleOnData(serialPortEvent); + } + }); + } + + // handle on data + public void handleOnData(SerialPortEvent event) { + byte[] buffer = event.getReceivedData(); + ByteBuffer data = ByteBuffer.wrap(buffer, 0, buffer.length); + if ( null != this.request ) { + this.request.isResponseReceived = true; + this.request.response = data; + synchronized (this.requestLock) { + this.requestLock.notify(); + } + } { + throw new RuntimeException("Received data from lis server but no request"); + } + } + + @Override + public ByteBuffer call(ByteBuffer buffer) { + this.request = new ClientRequest(); + this.request.parameter = buffer; + + // timeout check +// TimerTask timerTask = new TimerTask() { +// @Override +// public void run() { +// synchronized (ComLisSerialPort.this.requestLock) { +// if ( ComLisSerialPort.this.request.isResponseReceived ) { +// return ; +// } +// ComLisSerialPort.this.request.response = null; +// ComLisSerialPort.this.request.errorCode = ClientRequest.ERROR_CODE_TIMEOUT; +// ComLisSerialPort.this.requestLock.notify(); +// } +// } +// }; +// Timer timer = new Timer(); +// timer.schedule(timerTask, 5000); + + synchronized (this.requestLock) { + this.write(request.parameter); + try { + this.requestLock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + if ( 0 != request.errorCode ) { + throw new RuntimeException("device error : " + request.errorCode); + } + + ByteBuffer response = request.response; + this.request = null; + return response; + } + + @Override + public void write(ByteBuffer data) { + byte[] bytes = data.array(); + this.port.writeBytes(bytes, bytes.length); + } +} diff --git a/src/main/java/com/dreamworks/boditech/driver/entity/LisTestInfo.java b/src/main/java/com/dreamworks/boditech/driver/entity/LisTestInfo.java index 5e2b128..62c35d3 100644 --- a/src/main/java/com/dreamworks/boditech/driver/entity/LisTestInfo.java +++ b/src/main/java/com/dreamworks/boditech/driver/entity/LisTestInfo.java @@ -1,6 +1,14 @@ package com.dreamworks.boditech.driver.entity; import java.util.List; public class LisTestInfo { + // device name + public String deviceName; + // sample id + public String sampleId; + // sample name public List projectNames; + // sample type public String sampleType; + // sample time + public String sampleTime; } diff --git a/src/main/java/com/dreamworks/boditech/service/RuntimeOptionService.java b/src/main/java/com/dreamworks/boditech/service/RuntimeOptionService.java index dc057fa..a0ba83c 100644 --- a/src/main/java/com/dreamworks/boditech/service/RuntimeOptionService.java +++ b/src/main/java/com/dreamworks/boditech/service/RuntimeOptionService.java @@ -15,4 +15,13 @@ public class RuntimeOptionService { } return Integer.parseInt(value); } + + // get string value + public String getString(String name) { + String value = this.optionMapper.findByName(name); + if ( value == null ) { + throw new RuntimeException("option not found: " + name); + } + return value; + } } diff --git a/src/main/java/com/dreamworks/boditech/utils/AppError.java b/src/main/java/com/dreamworks/boditech/utils/AppError.java index 71733dd..aa6d887 100644 --- a/src/main/java/com/dreamworks/boditech/utils/AppError.java +++ b/src/main/java/com/dreamworks/boditech/utils/AppError.java @@ -30,4 +30,5 @@ public enum AppError { DEVICE_EXECUTING_REQUIRED, DEVICE_START_RESET_EXECUTING, DEVICE_LIQUID_LEVEL_DETECT_FAILED, + DEVICE_LIS_SERIAL_PORT_OPEN_FAILED, }