Ut5310ScpiService.java 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package com.mes.util;
  2. import com.fazecast.jSerialComm.SerialPort;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.nio.charset.Charset;
  9. import java.nio.charset.StandardCharsets;
  10. public class Ut5310ScpiService {
  11. public static final Logger log = LoggerFactory.getLogger(Ut5310ScpiService.class);
  12. private static final Charset COMMAND_CHARSET = StandardCharsets.US_ASCII;
  13. private static final String START_COMMAND = "FUNC:START";
  14. private static final String FETCH_COMMAND = "FETCh?";
  15. private static String portName = "COM1";
  16. private static int baudRate = 9600;
  17. private static int dataBits = 8;
  18. private static int stopBits = SerialPort.ONE_STOP_BIT;
  19. private static int parity = SerialPort.NO_PARITY;
  20. private static int readTimeoutMs = 1000;
  21. private static int testTimeoutMs = 60000;
  22. private static int fetchIntervalMs = 500;
  23. private static SerialPort serialPort;
  24. private static InputStream inputStream;
  25. private static OutputStream outputStream;
  26. private static volatile boolean connected = false;
  27. public static synchronized void configure(String port, int baud, int data, int stop, String parityName,
  28. int readTimeout, int testTimeout, int fetchInterval) {
  29. if (port != null && !port.trim().isEmpty()) {
  30. portName = port.trim();
  31. }
  32. if (baud > 0) {
  33. baudRate = baud;
  34. }
  35. if (data > 0) {
  36. dataBits = data;
  37. }
  38. stopBits = toStopBits(stop);
  39. parity = toParity(parityName);
  40. if (readTimeout > 0) {
  41. readTimeoutMs = readTimeout;
  42. }
  43. if (testTimeout > 0) {
  44. testTimeoutMs = testTimeout;
  45. }
  46. if (fetchInterval > 0) {
  47. fetchIntervalMs = fetchInterval;
  48. }
  49. }
  50. public static synchronized boolean isConnected() {
  51. return connected;
  52. }
  53. public static synchronized boolean connect() {
  54. disconnect();
  55. try {
  56. serialPort = SerialPort.getCommPort(portName);
  57. serialPort.setComPortParameters(baudRate, dataBits, stopBits, parity);
  58. serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, readTimeoutMs, readTimeoutMs);
  59. if (!serialPort.openPort()) {
  60. connected = false;
  61. log.info("UT5310 open port failed: {}", portName);
  62. return false;
  63. }
  64. inputStream = serialPort.getInputStream();
  65. outputStream = serialPort.getOutputStream();
  66. connected = true;
  67. log.info("UT5310 connected: {} {}bps", portName, baudRate);
  68. return true;
  69. } catch (Exception e) {
  70. connected = false;
  71. log.info("UT5310 connect failed: {}", e.getMessage());
  72. disconnect();
  73. return false;
  74. }
  75. }
  76. public static synchronized void disconnect() {
  77. connected = false;
  78. closeQuietly(inputStream);
  79. closeQuietly(outputStream);
  80. inputStream = null;
  81. outputStream = null;
  82. if (serialPort != null) {
  83. try {
  84. serialPort.closePort();
  85. } catch (Exception ignored) {
  86. }
  87. serialPort = null;
  88. }
  89. }
  90. public static synchronized boolean ensureConnected() {
  91. if (connected && serialPort != null && serialPort.isOpen()) {
  92. return true;
  93. }
  94. return connect();
  95. }
  96. public static synchronized Ut5310TestResult startAndFetchResult() throws IOException {
  97. if (!ensureConnected()) {
  98. throw new IOException("UT5310 not connected");
  99. }
  100. drainInput();
  101. writeCommand(START_COMMAND);
  102. log.info("UT5310 command sent: {}", START_COMMAND);
  103. long deadline = System.currentTimeMillis() + testTimeoutMs;
  104. String lastResponse = "";
  105. while (System.currentTimeMillis() < deadline) {
  106. sleep(fetchIntervalMs);
  107. writeCommand(FETCH_COMMAND);
  108. lastResponse = readResponse();
  109. log.info("UT5310 fetch response: {}", lastResponse);
  110. Ut5310TestResult result = parseFetchResult(lastResponse);
  111. if (result != null) {
  112. return result;
  113. }
  114. }
  115. throw new IOException("UT5310 test timeout, last response: " + lastResponse);
  116. }
  117. public static Ut5310TestResult parseFetchResult(String response) {
  118. if (response == null) {
  119. return null;
  120. }
  121. String raw = response.trim();
  122. if (raw.isEmpty()) {
  123. return null;
  124. }
  125. String normalized = raw.toUpperCase();
  126. if (normalized.contains("FAIL") || normalized.contains("NG")) {
  127. return new Ut5310TestResult(false, "FAIL", raw);
  128. }
  129. if (normalized.contains("PASS") || normalized.equals("OK") || normalized.startsWith("OK,")) {
  130. return new Ut5310TestResult(true, "PASS", raw);
  131. }
  132. return null;
  133. }
  134. private static void writeCommand(String command) throws IOException {
  135. outputStream.write((command + "\n").getBytes(COMMAND_CHARSET));
  136. outputStream.flush();
  137. }
  138. private static String readResponse() throws IOException {
  139. StringBuilder response = new StringBuilder();
  140. byte[] buffer = new byte[256];
  141. long deadline = System.currentTimeMillis() + readTimeoutMs;
  142. while (System.currentTimeMillis() < deadline) {
  143. int len = inputStream.read(buffer);
  144. if (len > 0) {
  145. response.append(new String(buffer, 0, len, COMMAND_CHARSET));
  146. if (response.indexOf("\n") >= 0) {
  147. break;
  148. }
  149. } else if (response.length() > 0) {
  150. break;
  151. }
  152. }
  153. return response.toString().trim();
  154. }
  155. private static void drainInput() {
  156. try {
  157. while (inputStream != null && inputStream.available() > 0) {
  158. inputStream.read();
  159. }
  160. } catch (Exception ignored) {
  161. }
  162. }
  163. private static int toStopBits(int stop) {
  164. if (stop == 2) {
  165. return SerialPort.TWO_STOP_BITS;
  166. }
  167. return SerialPort.ONE_STOP_BIT;
  168. }
  169. private static int toParity(String parityName) {
  170. if (parityName == null) {
  171. return SerialPort.NO_PARITY;
  172. }
  173. String value = parityName.trim().toUpperCase();
  174. if ("ODD".equals(value)) {
  175. return SerialPort.ODD_PARITY;
  176. }
  177. if ("EVEN".equals(value)) {
  178. return SerialPort.EVEN_PARITY;
  179. }
  180. return SerialPort.NO_PARITY;
  181. }
  182. private static void sleep(int millis) throws IOException {
  183. try {
  184. Thread.sleep(millis);
  185. } catch (InterruptedException e) {
  186. Thread.currentThread().interrupt();
  187. throw new IOException("UT5310 test interrupted", e);
  188. }
  189. }
  190. private static void closeQuietly(Object closeable) {
  191. if (closeable == null) {
  192. return;
  193. }
  194. try {
  195. if (closeable instanceof InputStream) {
  196. ((InputStream) closeable).close();
  197. } else if (closeable instanceof OutputStream) {
  198. ((OutputStream) closeable).close();
  199. }
  200. } catch (Exception ignored) {
  201. }
  202. }
  203. }