RelayDriver.java 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package com.mes.device;
  2. import com.fazecast.jSerialComm.SerialPort;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import java.math.BigInteger;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. /**
  9. * 继电器驱动(Modbus RTU串口通信)
  10. * 用于控制继电器开关
  11. */
  12. public class RelayDriver implements IDeviceDriver {
  13. private static final Logger log = LoggerFactory.getLogger(RelayDriver.class);
  14. private SerialPort serialPort;
  15. private String portName = "COM2";
  16. private int baudrate = 38400;
  17. private String openCommand = "010600000000"; // 开继电器命令
  18. private String closeCommand = "010600000001"; // 关继电器命令
  19. private volatile boolean connected = false;
  20. public RelayDriver() {
  21. }
  22. public RelayDriver(String portName, int baudrate) {
  23. this.portName = portName;
  24. this.baudrate = baudrate;
  25. }
  26. @Override
  27. public void connect(Map<String, Object> config) {
  28. if (config != null) {
  29. if (config.containsKey("port")) {
  30. this.portName = config.get("port").toString();
  31. }
  32. if (config.containsKey("baudrate")) {
  33. this.baudrate = ((Number) config.get("baudrate")).intValue();
  34. }
  35. if (config.containsKey("open_command")) {
  36. this.openCommand = config.get("open_command").toString();
  37. }
  38. if (config.containsKey("close_command")) {
  39. this.closeCommand = config.get("close_command").toString();
  40. }
  41. }
  42. try {
  43. serialPort = SerialPort.getCommPort(portName);
  44. serialPort.setComPortParameters(baudrate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
  45. serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 1000, 0);
  46. if (serialPort.openPort()) {
  47. connected = true;
  48. log.info("继电器串口{}打开成功", portName);
  49. } else {
  50. connected = false;
  51. log.error("继电器串口{}打开失败", portName);
  52. }
  53. } catch (Exception e) {
  54. log.error("继电器连接失败: {}", e.getMessage());
  55. connected = false;
  56. }
  57. }
  58. @Override
  59. public void disconnect() {
  60. if (serialPort != null && serialPort.isOpen()) {
  61. serialPort.closePort();
  62. log.info("继电器串口已关闭");
  63. }
  64. connected = false;
  65. }
  66. @Override
  67. public boolean isConnected() {
  68. return connected && serialPort != null && serialPort.isOpen();
  69. }
  70. /**
  71. * 开继电器
  72. */
  73. public void open() {
  74. sendCommand(openCommand);
  75. log.info("继电器已开启");
  76. }
  77. /**
  78. * 关继电器
  79. */
  80. public void close() {
  81. sendCommand(closeCommand);
  82. log.info("继电器已关闭");
  83. }
  84. /**
  85. * 发送命令
  86. */
  87. private void sendCommand(String command) {
  88. if (!isConnected()) {
  89. reconnect();
  90. }
  91. if (!isConnected()) {
  92. log.error("继电器未连接,无法发送命令");
  93. return;
  94. }
  95. try {
  96. String crc = getCRC16ModbusStr(command);
  97. byte[] writeBuffer = hexStringToByteArray(command + crc);
  98. serialPort.writeBytes(writeBuffer, writeBuffer.length);
  99. // 读取响应
  100. byte[] readBuffer = new byte[512];
  101. int numRead = serialPort.readBytes(readBuffer, readBuffer.length);
  102. log.debug("继电器响应: {} bytes", numRead);
  103. } catch (Exception e) {
  104. log.error("发送继电器命令失败: {}", e.getMessage());
  105. }
  106. }
  107. /**
  108. * 重新连接
  109. */
  110. private void reconnect() {
  111. disconnect();
  112. Map<String, Object> config = new HashMap<>();
  113. config.put("port", portName);
  114. config.put("baudrate", baudrate);
  115. connect(config);
  116. }
  117. /**
  118. * CRC16 Modbus校验
  119. */
  120. private String getCRC16ModbusStr(String data) {
  121. data = data.replace(" ", "");
  122. int len = data.length();
  123. if (len % 2 != 0) {
  124. return "0000";
  125. }
  126. int num = len / 2;
  127. byte[] para = new byte[num];
  128. for (int i = 0; i < num; i++) {
  129. int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
  130. para[i] = (byte) value;
  131. }
  132. return getCRC(para);
  133. }
  134. private String getCRC(byte[] bytes) {
  135. int CRC = 0x0000ffff;
  136. int POLYNOMIAL = 0x0000a001;
  137. for (byte b : bytes) {
  138. CRC ^= ((int) b & 0x000000ff);
  139. for (int j = 0; j < 8; j++) {
  140. if ((CRC & 0x00000001) != 0) {
  141. CRC >>= 1;
  142. CRC ^= POLYNOMIAL;
  143. } else {
  144. CRC >>= 1;
  145. }
  146. }
  147. }
  148. String result = Integer.toHexString(CRC).toUpperCase();
  149. if (result.length() != 4) {
  150. StringBuilder sb = new StringBuilder("0000");
  151. result = sb.replace(4 - result.length(), 4, result).toString();
  152. }
  153. return result.substring(2, 4) + result.substring(0, 2);
  154. }
  155. private byte[] hexStringToByteArray(String hexString) {
  156. hexString = hexString.trim();
  157. if (hexString.length() % 2 != 0) {
  158. throw new IllegalArgumentException("Invalid hex string");
  159. }
  160. BigInteger bigInt = new BigInteger(hexString, 16);
  161. byte[] byteArray = bigInt.toByteArray();
  162. if (byteArray.length > hexString.length() / 2) {
  163. byte[] trimmedArray = new byte[hexString.length() / 2];
  164. System.arraycopy(byteArray, 1, trimmedArray, 0, trimmedArray.length);
  165. return trimmedArray;
  166. }
  167. return byteArray;
  168. }
  169. // 以下方法继电器驱动不支持
  170. @Override public void signalReady() { }
  171. @Override public void startHeartbeat() { }
  172. @Override public void stopHeartbeat() { }
  173. @Override public Map<String, Object> readStatus() { return new HashMap<>(); }
  174. @Override public boolean isWorkComplete() { return false; }
  175. @Override public int getPresetCount() { return 0; }
  176. @Override public int getFinishedCount() { return 0; }
  177. @Override public int getQualifiedCount() { return 0; }
  178. @Override public void setPresetCount(int count) { }
  179. @Override public void writeRegister(int address, int value) { }
  180. @Override public int readRegister(int address) { return 0; }
  181. @Override
  182. public String getDriverType() {
  183. return "relay";
  184. }
  185. // Getters & Setters
  186. public String getPortName() { return portName; }
  187. public void setPortName(String portName) { this.portName = portName; }
  188. public int getBaudrate() { return baudrate; }
  189. public void setBaudrate(int baudrate) { this.baudrate = baudrate; }
  190. public String getOpenCommand() { return openCommand; }
  191. public void setOpenCommand(String openCommand) { this.openCommand = openCommand; }
  192. public String getCloseCommand() { return closeCommand; }
  193. public void setCloseCommand(String closeCommand) { this.closeCommand = closeCommand; }
  194. }