sige 1 year ago
parent
commit
90e7d12942
  1. 162
      src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java

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

@ -3,12 +3,19 @@ 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.io.*;
import java.net.Socket; import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
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
@ -17,12 +24,17 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement
private Integer slaveId; private Integer slaveId;
// heater key // heater key
private String ioKey; private String ioKey;
// connection
private Socket connection;
// writer
private DataOutputStream writer;
// reader
private InputStream reader;
// 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 ) {
@ -35,45 +47,50 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement
@Override @Override
protected void onEnable() { protected void onEnable() {
if ( null != this.connection ) {
var con = this.getConnection();
if ( null != con ) {
LOG.info("[Actuator {}({})] {} enable -- OK", this.key, this.type, this.name);
return ; return ;
} }
con = new Connection();
con.isBusy = false;
try { try {
this.connection = new Socket(this.host, this.port);
con.socket = new Socket(this.host, this.port);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
try { try {
this.writer = new DataOutputStream(this.connection.getOutputStream());
con.writer = new DataOutputStream(con.socket.getOutputStream());
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
try { try {
this.reader = this.connection.getInputStream();
con.reader = con.socket.getInputStream();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(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); LOG.info("[Actuator {}({})] {} enable -- OK", this.key, this.type, this.name);
} }
@Override @Override
protected void onDisable() { protected void onDisable() {
if ( null == this.connection ) {
var con = this.getConnection();
if ( null == con ) {
LOG.info("[Actuator {}({})] {} disable -- OK", this.key, this.type, this.name);
return ; return ;
} }
try { try {
this.connection.close();
this.connection = null;
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
this.writer.close();
con.writer.close();
con.reader.close();
con.socket.close();
connections.remove(this.host + ":" + this.port);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -103,12 +120,11 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement
cmd[3] = 0x00; // address low cmd[3] = 0x00; // address low
cmd[4] = (byte)(temperature >> 8); // value high cmd[4] = (byte)(temperature >> 8); // value high
cmd[5] = (byte)(temperature & 0xFF); // value low cmd[5] = (byte)(temperature & 0xFF); // value low
this.writeCmd(cmd);
this.readCmdResponse();
this.call(cmd);
LOG.info("[Actuator {}({})] {} set temperature : {}", this.key, this.type, this.name, temperature); LOG.info("[Actuator {}({})] {} set temperature : {}", this.key, this.type, this.name, temperature);
} }
// get temperature
@Override
public Integer getTemperature() { public Integer getTemperature() {
byte[] cmd = new byte[8]; byte[] cmd = new byte[8];
cmd[0] = (byte)(this.slaveId & 0xFF); // slave id cmd[0] = (byte)(this.slaveId & 0xFF); // slave id
@ -117,71 +133,99 @@ public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implement
cmd[3] = 0x10; // address low cmd[3] = 0x10; // address low
cmd[4] = 0x00; // length high cmd[4] = 0x00; // length high
cmd[5] = 0x01; // length low cmd[5] = 0x01; // length low
this.writeCmd(cmd);
var response = this.readCmdResponse();
Integer temperature = response.get(3) << 8 | response.get(4);
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); LOG.info("[Actuator {}({})] {} get temperature : {}", this.key, this.type, this.name, temperature);
return temperature; return temperature;
} }
/**
* 计算输入数据的CRC16 (Modbus)
* @param data 要计算CRC的字节数组
* @param length 数组中需要计算的长度
* @return 计算出的CRC16值
*/
public int calculateCRC(byte[] data, int length) {
int crc = 0xFFFF; // CRC的初始值
// call
private List<Integer> call( byte[] cmd ) {
var con = this.getConnection();
if ( null == con ) {
throw new RuntimeException("加热器"+this.key+"未启用");
}
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;
if ( con.isBusy ) {
synchronized ( con ) {
try {
con.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} }
} }
} }
// 高低位不交换直接返回
return crc & 0xFFFF;
con.isBusy = true;
this.writeCmd(con, cmd);
List<Integer> response = this.readCmdResponse(con);
con.isBusy = false;
synchronized ( con ) {
con.notify();
} }
// write command
private void writeCmd( byte[] cmd ) {
if ( null == this.connection ) {
throw new RuntimeException("加热器"+this.key+"未启用");
return response;
} }
// write command
private void writeCmd( Connection con, byte[] cmd ) {
var size = cmd.length; var size = cmd.length;
var crc = this.calculateCRC(cmd, size - 2); var crc = this.calculateCRC(cmd, size - 2);
cmd[size-2] = (byte)(crc & 0xFF); cmd[size-2] = (byte)(crc & 0xFF);
cmd[size-1] = (byte)(crc >> 8); cmd[size-1] = (byte)(crc >> 8);
try { try {
this.writer.write(cmd);
this.writer.flush();
con.writer.write(cmd);
con.writer.flush();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
}
// read command response
private List<Integer> readCmdResponse () {
if ( null == this.connection ) {
throw new RuntimeException("加热器"+this.key+"未启用");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} }
// read command response
private List<Integer> readCmdResponse ( Connection con ) {
try { try {
List<Integer> result = new ArrayList<>(); List<Integer> result = new ArrayList<>();
while ( 0 < this.reader.available() ) {
result.add(this.reader.read());
while ( 0 < con.reader.available() ) {
result.add(con.reader.read());
} }
return result; return result;
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(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