sige 1 year ago
parent
commit
e9b2202227
  1. 42
      src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActLcLtcCondenser.java
  2. 198
      src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java
  3. 157
      src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConModbusRTUOverTCP.java

42
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);
}
}

198
src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java

@ -1,21 +1,8 @@
package com.my.graphiteDigesterBg.diframe.actuator.impl; package com.my.graphiteDigesterBg.diframe.actuator.impl;
import com.my.graphiteDigesterBg.diframe.DiActuatorBase; import com.my.graphiteDigesterBg.diframe.DiActuatorBase;
import com.my.graphiteDigesterBg.diframe.actuator.DiActHeater; 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 { 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 // host
private String host; private String host;
// port // port
@ -24,78 +11,10 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement
private Integer slaveId; private Integer slaveId;
// heater key // heater key
private String ioKey; private String ioKey;
// connections
private static final Map<String, Connection> 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 @Override
public void setEnable( Boolean enable ) { 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 @Override
@ -113,119 +32,14 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement
@Override @Override
public void setTemperature(Integer temperature) { 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); LOG.info("[Actuator {}({})] {} set temperature : {}", this.key, this.type, this.name, temperature);
} }
@Override @Override
public Integer getTemperature() { 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<Integer> 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<Integer> 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<Integer> readCmdResponse ( Connection con ) {
try {
List<Integer> 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);
} }
} }

157
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<String, DiConModbusRTUOverTCP> 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<Integer> 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<Integer> 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<Integer> readCmdResponse ( ) {
try {
List<Integer> 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;
}
}
Loading…
Cancel
Save