| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- package com.mes.device;
- import com.fazecast.jSerialComm.SerialPort;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.math.BigInteger;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * 继电器驱动(Modbus RTU串口通信)
- * 用于控制继电器开关
- */
- public class RelayDriver implements IDeviceDriver {
- private static final Logger log = LoggerFactory.getLogger(RelayDriver.class);
- private SerialPort serialPort;
- private String portName = "COM2";
- private int baudrate = 38400;
- private String openCommand = "010600000000"; // 开继电器命令
- private String closeCommand = "010600000001"; // 关继电器命令
- private volatile boolean connected = false;
- public RelayDriver() {
- }
- public RelayDriver(String portName, int baudrate) {
- this.portName = portName;
- this.baudrate = baudrate;
- }
- @Override
- public void connect(Map<String, Object> config) {
- if (config != null) {
- if (config.containsKey("port")) {
- this.portName = config.get("port").toString();
- }
- if (config.containsKey("baudrate")) {
- this.baudrate = ((Number) config.get("baudrate")).intValue();
- }
- if (config.containsKey("open_command")) {
- this.openCommand = config.get("open_command").toString();
- }
- if (config.containsKey("close_command")) {
- this.closeCommand = config.get("close_command").toString();
- }
- }
- try {
- serialPort = SerialPort.getCommPort(portName);
- serialPort.setComPortParameters(baudrate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
- serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 1000, 0);
- if (serialPort.openPort()) {
- connected = true;
- log.info("继电器串口{}打开成功", portName);
- } else {
- connected = false;
- log.error("继电器串口{}打开失败", portName);
- }
- } catch (Exception e) {
- log.error("继电器连接失败: {}", e.getMessage());
- connected = false;
- }
- }
- @Override
- public void disconnect() {
- if (serialPort != null && serialPort.isOpen()) {
- serialPort.closePort();
- log.info("继电器串口已关闭");
- }
- connected = false;
- }
- @Override
- public boolean isConnected() {
- return connected && serialPort != null && serialPort.isOpen();
- }
- /**
- * 开继电器
- */
- public void open() {
- sendCommand(openCommand);
- log.info("继电器已开启");
- }
- /**
- * 关继电器
- */
- public void close() {
- sendCommand(closeCommand);
- log.info("继电器已关闭");
- }
- /**
- * 发送命令
- */
- private void sendCommand(String command) {
- if (!isConnected()) {
- reconnect();
- }
- if (!isConnected()) {
- log.error("继电器未连接,无法发送命令");
- return;
- }
- try {
- String crc = getCRC16ModbusStr(command);
- byte[] writeBuffer = hexStringToByteArray(command + crc);
- serialPort.writeBytes(writeBuffer, writeBuffer.length);
- // 读取响应
- byte[] readBuffer = new byte[512];
- int numRead = serialPort.readBytes(readBuffer, readBuffer.length);
- log.debug("继电器响应: {} bytes", numRead);
- } catch (Exception e) {
- log.error("发送继电器命令失败: {}", e.getMessage());
- }
- }
- /**
- * 重新连接
- */
- private void reconnect() {
- disconnect();
- Map<String, Object> config = new HashMap<>();
- config.put("port", portName);
- config.put("baudrate", baudrate);
- connect(config);
- }
- /**
- * CRC16 Modbus校验
- */
- private String getCRC16ModbusStr(String data) {
- data = data.replace(" ", "");
- int len = data.length();
- if (len % 2 != 0) {
- return "0000";
- }
- int num = len / 2;
- byte[] para = new byte[num];
- for (int i = 0; i < num; i++) {
- int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
- para[i] = (byte) value;
- }
- return getCRC(para);
- }
- private String getCRC(byte[] bytes) {
- int CRC = 0x0000ffff;
- int POLYNOMIAL = 0x0000a001;
- for (byte b : bytes) {
- CRC ^= ((int) b & 0x000000ff);
- for (int j = 0; j < 8; j++) {
- if ((CRC & 0x00000001) != 0) {
- CRC >>= 1;
- CRC ^= POLYNOMIAL;
- } else {
- CRC >>= 1;
- }
- }
- }
- String result = Integer.toHexString(CRC).toUpperCase();
- if (result.length() != 4) {
- StringBuilder sb = new StringBuilder("0000");
- result = sb.replace(4 - result.length(), 4, result).toString();
- }
- return result.substring(2, 4) + result.substring(0, 2);
- }
- private byte[] hexStringToByteArray(String hexString) {
- hexString = hexString.trim();
- if (hexString.length() % 2 != 0) {
- throw new IllegalArgumentException("Invalid hex string");
- }
- BigInteger bigInt = new BigInteger(hexString, 16);
- byte[] byteArray = bigInt.toByteArray();
- if (byteArray.length > hexString.length() / 2) {
- byte[] trimmedArray = new byte[hexString.length() / 2];
- System.arraycopy(byteArray, 1, trimmedArray, 0, trimmedArray.length);
- return trimmedArray;
- }
- return byteArray;
- }
- // 以下方法继电器驱动不支持
- @Override public void signalReady() { }
- @Override public void startHeartbeat() { }
- @Override public void stopHeartbeat() { }
- @Override public Map<String, Object> readStatus() { return new HashMap<>(); }
- @Override public boolean isWorkComplete() { return false; }
- @Override public int getPresetCount() { return 0; }
- @Override public int getFinishedCount() { return 0; }
- @Override public int getQualifiedCount() { return 0; }
- @Override public void setPresetCount(int count) { }
- @Override public void writeRegister(int address, int value) { }
- @Override public int readRegister(int address) { return 0; }
- @Override
- public String getDriverType() {
- return "relay";
- }
- // Getters & Setters
- public String getPortName() { return portName; }
- public void setPortName(String portName) { this.portName = portName; }
- public int getBaudrate() { return baudrate; }
- public void setBaudrate(int baudrate) { this.baudrate = baudrate; }
- public String getOpenCommand() { return openCommand; }
- public void setOpenCommand(String openCommand) { this.openCommand = openCommand; }
- public String getCloseCommand() { return closeCommand; }
- public void setCloseCommand(String closeCommand) { this.closeCommand = closeCommand; }
- }
|