package com.mes.util; import com.fazecast.jSerialComm.SerialPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class Ut5310ScpiService { public static final Logger log = LoggerFactory.getLogger(Ut5310ScpiService.class); private static final Charset COMMAND_CHARSET = StandardCharsets.US_ASCII; private static final String START_COMMAND = "FUNC:START"; private static final String FETCH_COMMAND = "FETCh?"; private static String portName = "COM1"; private static int baudRate = 9600; private static int dataBits = 8; private static int stopBits = SerialPort.ONE_STOP_BIT; private static int parity = SerialPort.NO_PARITY; private static int readTimeoutMs = 1000; private static int testTimeoutMs = 60000; private static int fetchIntervalMs = 500; private static SerialPort serialPort; private static InputStream inputStream; private static OutputStream outputStream; private static volatile boolean connected = false; public static synchronized void configure(String port, int baud, int data, int stop, String parityName, int readTimeout, int testTimeout, int fetchInterval) { if (port != null && !port.trim().isEmpty()) { portName = port.trim(); } if (baud > 0) { baudRate = baud; } if (data > 0) { dataBits = data; } stopBits = toStopBits(stop); parity = toParity(parityName); if (readTimeout > 0) { readTimeoutMs = readTimeout; } if (testTimeout > 0) { testTimeoutMs = testTimeout; } if (fetchInterval > 0) { fetchIntervalMs = fetchInterval; } } public static synchronized boolean isConnected() { return connected; } public static synchronized boolean connect() { disconnect(); try { serialPort = SerialPort.getCommPort(portName); serialPort.setComPortParameters(baudRate, dataBits, stopBits, parity); serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, readTimeoutMs, readTimeoutMs); if (!serialPort.openPort()) { connected = false; log.info("UT5310 open port failed: {}", portName); return false; } inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); connected = true; log.info("UT5310 connected: {} {}bps", portName, baudRate); return true; } catch (Exception e) { connected = false; log.info("UT5310 connect failed: {}", e.getMessage()); disconnect(); return false; } } public static synchronized void disconnect() { connected = false; closeQuietly(inputStream); closeQuietly(outputStream); inputStream = null; outputStream = null; if (serialPort != null) { try { serialPort.closePort(); } catch (Exception ignored) { } serialPort = null; } } public static synchronized boolean ensureConnected() { if (connected && serialPort != null && serialPort.isOpen()) { return true; } return connect(); } public static synchronized Ut5310TestResult startAndFetchResult() throws IOException { if (!ensureConnected()) { throw new IOException("UT5310 not connected"); } drainInput(); writeCommand(START_COMMAND); log.info("UT5310 command sent: {}", START_COMMAND); long deadline = System.currentTimeMillis() + testTimeoutMs; String lastResponse = ""; while (System.currentTimeMillis() < deadline) { sleep(fetchIntervalMs); writeCommand(FETCH_COMMAND); lastResponse = readResponse(); log.info("UT5310 fetch response: {}", lastResponse); Ut5310TestResult result = parseFetchResult(lastResponse); if (result != null) { return result; } } throw new IOException("UT5310 test timeout, last response: " + lastResponse); } public static Ut5310TestResult parseFetchResult(String response) { if (response == null) { return null; } String raw = response.trim(); if (raw.isEmpty()) { return null; } String normalized = raw.toUpperCase(); if (normalized.contains("FAIL") || normalized.contains("NG")) { return new Ut5310TestResult(false, "FAIL", raw); } if (normalized.contains("PASS") || normalized.equals("OK") || normalized.startsWith("OK,")) { return new Ut5310TestResult(true, "PASS", raw); } return null; } private static void writeCommand(String command) throws IOException { outputStream.write((command + "\n").getBytes(COMMAND_CHARSET)); outputStream.flush(); } private static String readResponse() throws IOException { StringBuilder response = new StringBuilder(); byte[] buffer = new byte[256]; long deadline = System.currentTimeMillis() + readTimeoutMs; while (System.currentTimeMillis() < deadline) { int len = inputStream.read(buffer); if (len > 0) { response.append(new String(buffer, 0, len, COMMAND_CHARSET)); if (response.indexOf("\n") >= 0) { break; } } else if (response.length() > 0) { break; } } return response.toString().trim(); } private static void drainInput() { try { while (inputStream != null && inputStream.available() > 0) { inputStream.read(); } } catch (Exception ignored) { } } private static int toStopBits(int stop) { if (stop == 2) { return SerialPort.TWO_STOP_BITS; } return SerialPort.ONE_STOP_BIT; } private static int toParity(String parityName) { if (parityName == null) { return SerialPort.NO_PARITY; } String value = parityName.trim().toUpperCase(); if ("ODD".equals(value)) { return SerialPort.ODD_PARITY; } if ("EVEN".equals(value)) { return SerialPort.EVEN_PARITY; } return SerialPort.NO_PARITY; } private static void sleep(int millis) throws IOException { try { Thread.sleep(millis); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException("UT5310 test interrupted", e); } } private static void closeQuietly(Object closeable) { if (closeable == null) { return; } try { if (closeable instanceof InputStream) { ((InputStream) closeable).close(); } else if (closeable instanceof OutputStream) { ((OutputStream) closeable).close(); } } catch (Exception ignored) { } } }