diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActLcLtcCondenser.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActLcLtcCondenser.java new file mode 100644 index 0000000..cade796 --- /dev/null +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActLcLtcCondenser.java @@ -0,0 +1,42 @@ +package com.my.graphiteDigesterBg.diframe.actuator; +import com.my.graphiteDigesterBg.diframe.DiActuatorBase; +import com.my.graphiteDigesterBg.diframe.connection.DiConModbusRTUOverTCP; +public class DiActLcLtcCondenser extends DiActuatorBase { + // host + private String host; + // port + private Integer port; + // slave id + private Integer slaveId; + // heater key + private String ioKey; + + // set enable + public void setEnable( Boolean enable ) { + // nothing to do here + } + + // set temperature + public void setTemperature( Integer temperature ) { + temperature = temperature * 10; + var con = DiConModbusRTUOverTCP.getConnection(this.host, this.port); + con.writeHoldingRegister(this.slaveId, 2, temperature); + } + + // start + public void start() { + int status = 0; + status = status | 0x4000; // 设置第14位为1 允许制冷 + status = status | 0x2000; // 设置13位为1开启循环 + status = status | 0x0800; // 设置第11为为1 接通电源 + var con = DiConModbusRTUOverTCP.getConnection(this.host, this.port); + con.writeHoldingRegister(this.slaveId, 5, status); + } + + // stop + public void stop() { + int status = 0; + var con = DiConModbusRTUOverTCP.getConnection(this.host, this.port); + con.writeHoldingRegister(this.slaveId, 5, status); + } +} diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java index 288b6f3..9b123d1 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java @@ -1,21 +1,8 @@ package com.my.graphiteDigesterBg.diframe.actuator.impl; import com.my.graphiteDigesterBg.diframe.DiActuatorBase; import com.my.graphiteDigesterBg.diframe.actuator.DiActHeater; -import java.io.*; -import java.net.Socket; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.my.graphiteDigesterBg.diframe.connection.DiConModbusRTUOverTCP; public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implements DiActHeater { - // connection - private static class Connection { - public Socket socket; - public DataOutputStream writer; - public InputStream reader; - public Boolean isBusy; - } - // host private String host; // port @@ -24,78 +11,10 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement private Integer slaveId; // heater key private String ioKey; - // connections - private static final Map connections = new HashMap<>(); - - // get connection - private Connection getConnection() { - String key = this.host + ":" + this.port; - if ( connections.containsKey(key) ) { - return connections.get(key); - } - return null; - } @Override public void setEnable( Boolean enable ) { - if ( enable ) { - this.onEnable(); - } else { - this.onDisable(); - } - } - - @Override - protected void onEnable() { - var con = this.getConnection(); - if ( null != con ) { - LOG.info("[Actuator {}({})] {} enable -- OK", this.key, this.type, this.name); - return ; - } - - con = new Connection(); - con.isBusy = false; - try { - con.socket = new Socket(this.host, this.port); - } catch (IOException e) { - throw new RuntimeException(e); - } - - try { - con.writer = new DataOutputStream(con.socket.getOutputStream()); - } catch (IOException e) { - throw new RuntimeException(e); - } - - try { - con.reader = con.socket.getInputStream(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - String key = this.host + ":" + this.port; - connections.put(key, con); - LOG.info("[Actuator {}({})] {} enable -- OK", this.key, this.type, this.name); - } - - @Override - protected void onDisable() { - var con = this.getConnection(); - if ( null == con ) { - LOG.info("[Actuator {}({})] {} disable -- OK", this.key, this.type, this.name); - return ; - } - - try { - con.writer.close(); - con.reader.close(); - con.socket.close(); - connections.remove(this.host + ":" + this.port); - } catch (IOException e) { - throw new RuntimeException(e); - } - - LOG.info("[Actuator {}({})] {} disable -- OK", this.key, this.type, this.name); + // nothing to do here } @Override @@ -113,119 +32,14 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement @Override public void setTemperature(Integer temperature) { - byte[] cmd = new byte[8]; - cmd[0] = (byte)(this.slaveId & 0xFF); // slave id - cmd[1] = 0x06; // function code - cmd[2] = 0x20; // address high - cmd[3] = 0x00; // address low - cmd[4] = (byte)(temperature >> 8); // value high - cmd[5] = (byte)(temperature & 0xFF); // value low - this.call(cmd); + var con = DiConModbusRTUOverTCP.getConnection(this.host, this.port); + con.writeHoldingRegister(this.slaveId, 0x2000, temperature); LOG.info("[Actuator {}({})] {} set temperature : {}", this.key, this.type, this.name, temperature); } @Override public Integer getTemperature() { - byte[] cmd = new byte[8]; - cmd[0] = (byte)(this.slaveId & 0xFF); // slave id - cmd[1] = 0x03; // function code - cmd[2] = 0x20; // address high - cmd[3] = 0x10; // address low - cmd[4] = 0x00; // length high - cmd[5] = 0x01; // length low - var response = this.call(cmd); - - int temperature = 0; - if (!response.isEmpty()) { - temperature = response.get(3) << 8 | response.get(4); - } -// LOG.info("[Actuator {}({})] {} get temperature : {}", this.key, this.type, this.name, temperature); - return temperature; - } - - // call - private List call( byte[] cmd ) { - var con = this.getConnection(); - if ( null == con ) { - throw new RuntimeException("加热器"+this.key+"未启用"); - } - - if ( con.isBusy ) { - synchronized ( con ) { - try { - con.wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - - con.isBusy = true; - this.writeCmd(con, cmd); - List response = this.readCmdResponse(con); - con.isBusy = false; - synchronized ( con ) { - con.notify(); - } - return response; - } - - // write command - private void writeCmd( Connection con, byte[] cmd ) { - var size = cmd.length; - var crc = this.calculateCRC(cmd, size - 2); - cmd[size-2] = (byte)(crc & 0xFF); - cmd[size-1] = (byte)(crc >> 8); - - try { - con.writer.write(cmd); - con.writer.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - try { - Thread.sleep(300); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - // read command response - private List readCmdResponse ( Connection con ) { - try { - List result = new ArrayList<>(); - while ( 0 < con.reader.available() ) { - result.add(con.reader.read()); - } - return result; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * 计算输入数据的CRC16 (Modbus) - * @param data 要计算CRC的字节数组 - * @param length 数组中需要计算的长度 - * @return 计算出的CRC16值 - */ - public int calculateCRC(byte[] data, int length) { - int crc = 0xFFFF; // CRC的初始值 - - for (int pos = 0; pos < length; pos++) { - crc ^= data[pos] & 0xFF; // 将数据与CRC寄存器异或 - for (int i = 8; i != 0; i--) { // 循环处理每个位 - if ((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; // 0xA001是预设的多项式 - } else { - crc >>= 1; - } - } - } - - // 高低位不交换,直接返回 - return crc & 0xFFFF; + var con = DiConModbusRTUOverTCP.getConnection(this.host, this.port); + return con.readHoldingRegister(this.slaveId,0x2010); } } diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConModbusRTUOverTCP.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConModbusRTUOverTCP.java new file mode 100644 index 0000000..98ee6e8 --- /dev/null +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConModbusRTUOverTCP.java @@ -0,0 +1,157 @@ +package com.my.graphiteDigesterBg.diframe.connection; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +public class DiConModbusRTUOverTCP { + // connection + private Socket socket; + // writer + private DataOutputStream writer; + // reader + private InputStream reader; + // busy + private Boolean isBusy = false; + + // connections + private static final Map connections = new HashMap<>(); + + // get connection + public static DiConModbusRTUOverTCP getConnection( String host, Integer port) { + String key = host + ":" + port; + if ( connections.containsKey(key) ) { + return connections.get(key); + } + + DiConModbusRTUOverTCP con = new DiConModbusRTUOverTCP(); + con.connect(host, port); + connections.put(key, con); + return con; + } + + // constructor + private DiConModbusRTUOverTCP() { + this.isBusy = false; + } + + // connect + public void connect( String host, Integer port ) { + try { + this.socket = new Socket(host, port); + this.writer = new DataOutputStream(this.socket.getOutputStream()); + this.reader = this.socket.getInputStream(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // write holding register + public void writeHoldingRegister( Integer slaveId, Integer address, Integer value ) { + byte[] cmd = new byte[8]; + cmd[0] = (byte)(slaveId & 0xFF); // slave id + cmd[1] = 0x06; // function code + cmd[2] = (byte)(address >> 8); // address high + cmd[3] = (byte)(address & 0xFF); // address low + cmd[4] = (byte)(value >> 8); // value high + cmd[5] = (byte)(value & 0xFF); // value low + this.call(cmd); + } + + // read holding register + public Integer readHoldingRegister( Integer slaveId, Integer address ) { + byte[] cmd = new byte[8]; + cmd[0] = (byte)(slaveId & 0xFF); // slave id + cmd[1] = 0x03; // function code + cmd[2] = (byte)(address >> 8); // address high + cmd[3] = (byte)(address & 0xFF); // address low + cmd[4] = 0x00; // value high + cmd[5] = 0x01; // value low + var response = this.call(cmd); + return response.get(3) << 8 | response.get(4); + } + + // call + private List call(byte[] cmd) { + if ( this.isBusy ) { + synchronized ( this ) { + try { + this.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + this.isBusy = true; + this.writeCmd(cmd); + List response = this.readCmdResponse(); + this.isBusy = false; + synchronized ( this ) { + this.notify(); + } + return response; + } + + // write command + private void writeCmd(byte[] cmd) { + var size = cmd.length; + var crc = this.calculateCRC(cmd, size - 2); + cmd[size-2] = (byte)(crc & 0xFF); + cmd[size-1] = (byte)(crc >> 8); + + try { + this.writer.write(cmd); + this.writer.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + try { + Thread.sleep(300); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // read command response + private List readCmdResponse ( ) { + try { + List result = new ArrayList<>(); + while ( 0 < this.reader.available() ) { + result.add(this.reader.read()); + } + return result; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 计算输入数据的CRC16 (Modbus) + * @param data 要计算CRC的字节数组 + * @param length 数组中需要计算的长度 + * @return 计算出的CRC16值 + */ + public int calculateCRC(byte[] data, int length) { + int crc = 0xFFFF; // CRC的初始值 + + for (int pos = 0; pos < length; pos++) { + crc ^= data[pos] & 0xFF; // 将数据与CRC寄存器异或 + for (int i = 8; i != 0; i--) { // 循环处理每个位 + if ((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; // 0xA001是预设的多项式 + } else { + crc >>= 1; + } + } + } + + // 高低位不交换,直接返回 + return crc & 0xFFFF; + } +}