2 changed files with 199 additions and 0 deletions
-
12src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActHeater.java
-
187src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/impl/DiActHeaterTokyGteModbusRtuOverTcp.java
@ -0,0 +1,12 @@ |
|||
package com.my.graphiteDigesterBg.diframe.actuator; |
|||
public interface DiActHeater { |
|||
// set temperature |
|||
void setTemperature( Integer temperature ); |
|||
|
|||
// get temperature |
|||
Integer getTemperature(); |
|||
|
|||
void start(); |
|||
|
|||
void stop(); |
|||
} |
@ -0,0 +1,187 @@ |
|||
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.nio.ByteBuffer; |
|||
import java.nio.ByteOrder; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
public class DiActHeaterTokyGteModbusRtuOverTcp extends DiActuatorBase implements DiActHeater { |
|||
// host |
|||
private String host; |
|||
// port |
|||
private Integer port; |
|||
// slave id |
|||
private Integer slaveId; |
|||
// heater key |
|||
private String ioKey; |
|||
// connection |
|||
private Socket connection; |
|||
// writer |
|||
private DataOutputStream writer; |
|||
// reader |
|||
private InputStream reader; |
|||
|
|||
@Override |
|||
public void setEnable( Boolean enable ) { |
|||
if ( enable ) { |
|||
this.onEnable(); |
|||
} else { |
|||
this.onDisable(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
protected void onEnable() { |
|||
if ( null != this.connection ) { |
|||
return ; |
|||
} |
|||
|
|||
try { |
|||
this.connection = new Socket(this.host, this.port); |
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
try { |
|||
this.writer = new DataOutputStream(this.connection.getOutputStream()); |
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
try { |
|||
this.reader = this.connection.getInputStream(); |
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
LOG.info("[Actuator {}({})] {} enable -- OK", this.key, this.type, this.name); |
|||
} |
|||
|
|||
@Override |
|||
protected void onDisable() { |
|||
if ( null == this.connection ) { |
|||
return ; |
|||
} |
|||
|
|||
try { |
|||
this.connection.close(); |
|||
this.connection = null; |
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
try { |
|||
this.writer.close(); |
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
LOG.info("[Actuator {}({})] {} disable -- OK", this.key, this.type, this.name); |
|||
} |
|||
|
|||
@Override |
|||
public void start() { |
|||
this.device.getIO().setValue(this.ioKey, 1); |
|||
LOG.info("[Actuator {}({})] {} heating : start", this.key, this.type, this.name); |
|||
} |
|||
|
|||
@Override |
|||
public void stop() { |
|||
this.device.getIO().setValue(this.ioKey, 0); |
|||
LOG.info("[Actuator {}({})] {} heating : stop", this.key, this.type, this.name); |
|||
this.setTemperature(10); |
|||
} |
|||
|
|||
@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.writeCmd(cmd); |
|||
this.readCmdResponse(); |
|||
LOG.info("[Actuator {}({})] {} set temperature : {}", this.key, this.type, this.name, temperature); |
|||
} |
|||
|
|||
// get temperature |
|||
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 |
|||
this.writeCmd(cmd); |
|||
var response = this.readCmdResponse(); |
|||
Integer temperature = response.get(3) << 8 | response.get(4); |
|||
LOG.info("[Actuator {}({})] {} get temperature : {}", this.key, this.type, this.name, temperature); |
|||
return temperature; |
|||
} |
|||
|
|||
/** |
|||
* 计算输入数据的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; |
|||
} |
|||
|
|||
// write command |
|||
private void writeCmd( byte[] cmd ) { |
|||
if ( null == this.connection ) { |
|||
throw new RuntimeException("加热器"+this.key+"未启用"); |
|||
} |
|||
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
// read command response |
|||
private List<Integer> readCmdResponse () { |
|||
if ( null == this.connection ) { |
|||
throw new RuntimeException("加热器"+this.key+"未启用"); |
|||
} |
|||
|
|||
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); |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue