集成modbus连接本地设备读取数据代码-配置文件方式读取;

PCS开关机功能通过modbus连接设备发送控制命令;
This commit is contained in:
zq
2025-12-19 11:38:04 +08:00
parent 16d414f092
commit ff487f1b05
26 changed files with 1286 additions and 216 deletions

View File

@ -119,6 +119,12 @@
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- modbus -->
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,61 @@
package com.xzzn.common.core.modbus;
import com.serotonin.modbus4j.ModbusMaster;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PreDestroy;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class Modbus4jConnectionManager {
private static final Logger logger = LoggerFactory.getLogger(Modbus4jConnectionManager.class);
private final Map<String, GenericObjectPool<ModbusMaster>> connectionPools = new ConcurrentHashMap<>();
public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
String poolKey = getPoolKey(config);
GenericObjectPool<ModbusMaster> pool = connectionPools.computeIfAbsent(poolKey, key -> {
PooledModbusMasterFactory factory = new PooledModbusMasterFactory(config.getHost(), config.getPort());
GenericObjectPoolConfig<ModbusMaster> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(5); // 池中最大连接数
poolConfig.setMinIdle(1); // 最小空闲连接数
poolConfig.setTestOnBorrow(true); // 借用时测试连接有效性
return new GenericObjectPool<>(factory, poolConfig);
});
return pool.borrowObject();
}
public void returnMaster(DeviceConfig config, ModbusMaster master) {
if (master == null) {
return;
}
String poolKey = getPoolKey(config);
GenericObjectPool<ModbusMaster> pool = connectionPools.get(poolKey);
if (pool != null) {
pool.returnObject(master);
}
}
private String getPoolKey(DeviceConfig config) {
return config.getHost() + ":" + config.getPort();
}
@PreDestroy
public void shutdown() {
connectionPools.values().forEach(GenericObjectPool::close);
}
}

View File

@ -0,0 +1,384 @@
package com.xzzn.common.core.modbus;
import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.WriteCoilRequest;
import com.serotonin.modbus4j.msg.WriteCoilResponse;
import com.serotonin.modbus4j.msg.WriteCoilsRequest;
import com.serotonin.modbus4j.msg.WriteCoilsResponse;
import com.serotonin.modbus4j.msg.WriteRegisterRequest;
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
import com.xzzn.common.core.modbus.domain.DeviceConfig;
import com.xzzn.common.core.modbus.domain.TagConfig;
import com.xzzn.common.core.modbus.domain.WriteTagConfig;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.ModBusType;
import com.xzzn.common.enums.RegisterType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static com.xzzn.common.enums.RegisterType.COIL;
import static com.xzzn.common.enums.RegisterType.DISCRETE_INPUT;
@Service
public class ModbusProcessor {
private static final Logger logger = LoggerFactory.getLogger(ModbusProcessor.class);
@Autowired
private RedisCache redisCache;
@Autowired
private Modbus4jConnectionManager connectionManager;
public boolean writeDataToDevice(DeviceConfig config) {
ModbusMaster master = null;
boolean result = true;
try {
master = connectionManager.borrowMaster(config);
// 设置了Modbus通信的超时时间为3000毫秒3秒。当主设备与从设备通信时若在3秒内未收到响应则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
master.setTimeout(5000);
writeTagValue(master, config, config.getWriteTags());
} catch (Exception e) {
logger.error("Failed to borrow connection or write to devices '{}'", config.getDeviceName(), e);
result = false;
}
finally {
// 关键:无论成功与否,都必须将连接归还到池中
if (master != null) {
connectionManager.returnMaster(config, master);
}
}
return result;
}
public void writeTagValue(ModbusMaster master, DeviceConfig config, List<WriteTagConfig> tags) {
tags.forEach(tag -> {
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1));
int address = 0;
int addressLength = tag.getAddress().length();
int exp = (int) Math.pow(10, addressLength-1);
if (firstDigit != 0){
int digit = Integer.parseInt(tag.getAddress());
address = digit % (exp);
}else {
address = Integer.parseInt(tag.getAddress());
}
RegisterType registerType = type.get(firstDigit);
logger.info("Register type: {}, address: {}, firstDigit: {}", registerType, tag.getAddress(), firstDigit);
switch (registerType) {
case COIL: {
writeCoilRequest(master, config.getSlaveId(), address, Boolean.parseBoolean(String.valueOf(tag.getValue())));
break;
}
case HOLDING_REGISTER: {
writeRegisterRequest(master, config.getSlaveId(), address, Integer.parseInt(String.valueOf(tag.getValue())));
break;
}
default:
logger.error("Unsupported register type: {}", registerType);
break;
}
});
}
public static void writeCoilRequest(ModbusMaster master, int slaveId, int address, boolean value) {
try {
WriteCoilRequest request = new WriteCoilRequest(slaveId, address, value);
WriteCoilResponse response = (WriteCoilResponse)master.send(request);
if (response.isException()) {
logger.info("Write coil failed: " + response.getExceptionMessage());
} else {
logger.info("Write coil successful");
}
} catch (Exception e) {
logger.error("Failed to write coil value '{}' to address '{}'", value, address, e);
}
}
public static void writeCoilsRequest(ModbusMaster master, int slaveId, int address, boolean[] values) {
try {
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, address, values);
WriteCoilsResponse response = (WriteCoilsResponse)master.send(request);
if (response.isException()) {
logger.info("Write coils failed: " + response.getExceptionMessage());
} else {
logger.info("Write coils successful");
}
} catch (Exception e) {
logger.error("Failed to write coils value '{}' to address '{}'", values, address, e);
}
}
public static void writeRegisterRequest(ModbusMaster master, int slaveId, int address, int value) {
try {
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value);
WriteRegisterResponse response = (WriteRegisterResponse)master.send(request);
if (response.isException()) {
logger.info("Write register failed: " + response.getExceptionMessage());
} else {
logger.info("Write register successful");
}
} catch (Exception e) {
logger.error("Failed to write register value '{}' to address '{}'", value, address, e);
}
}
public static void writeRegistersRequest(ModbusMaster master, int slaveId, int address, short[] values) {
try {
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, address, values);
WriteRegistersResponse response = (WriteRegistersResponse)master.send(request);
if (response.isException()) {
logger.info("Write registers failed: " + response.getExceptionMessage());
} else {
logger.info("Write registers successful");
}
} catch (Exception e) {
logger.error("Failed to write registers value '{}' to address '{}'", values, address, e);
}
}
public static void setCoilValue(ModbusMaster master, int slaveId, int address, int value) {
// 写入单个线圈(从站ID, 地址, 布尔值)
BaseLocator<Boolean> coilLocator = BaseLocator.coilStatus(slaveId, address);
try {
// 写入布尔值到线圈
master.setValue(coilLocator, value);
logger.info("set coil successful");
} catch (ModbusTransportException | ErrorResponseException e) {
logger.error("Failed to set coil value '{}' to address '{}'", value, address, e);
}
}
public static void setRegisterValue(ModbusMaster master, int slaveId, int address, int value) {
// 写入单个保持寄存器(从站, 地址, 16位整数)
BaseLocator<Number> holdingLocator = BaseLocator.holdingRegister(slaveId, address, DataType.TWO_BYTE_INT_UNSIGNED);
try {
// 写入整数值到保持寄存器
master.setValue(holdingLocator, value);
logger.info("set register successful");
} catch (ModbusTransportException | ErrorResponseException e) {
logger.error("Failed to set register value '{}' to address '{}'", value, address, e);
}
}
public Map<String, Object> readDataFromDevice(DeviceConfig config, ModbusMaster master) {
Map<String, Object> deviceData = new HashMap<>();
// ModbusMaster master = null; // 将master的声明提前
try {
master = connectionManager.borrowMaster(config);
// 设置了Modbus通信的超时时间为3000毫秒3秒。当主设备与从设备通信时若在3秒内未收到响应则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
master.setTimeout(5000);
BatchResults<String> results = readTagValues(master, config.getSlaveId(), config.getTags());
for (TagConfig tag : config.getTags()) {
if (Objects.equals(tag.getDataType(), "FOUR_BYTE_FLOAT_DBCA")){
Object value = results.getValue(tag.getKey());
value = convertValueToFloat(value);
deviceData.put(tag.getKey(), value);
}else {
deviceData.put(tag.getKey(), results.getValue(tag.getKey()));
}
// try {
// Object value = readTagValue(master, config.getSlaveId(), tag);
// if (value != null) {
// deviceData.put(tag.getKey(), value);
// }
// } catch (Exception e) {
// logger.error("Failed to read tag '{}' from devices '{}'", tag.getKey(), config.getDeviceName(), e);
// }
}
} catch (Exception e) {
logger.error("Failed to borrow connection or read from devices '{}'", config.getDeviceName(), e);
}
finally {
// 关键:无论成功与否,都必须将连接归还到池中
if (master != null) {
connectionManager.returnMaster(config, master);
}
}
String deviceNumber = config.getDeviceNumber();
redisCache.setCacheObject(deviceNumber, deviceData);
return deviceData;
}
private Object readTagValue(ModbusMaster master, int slaveId, TagConfig tag) throws Exception {
Object value;
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
Map<String, Integer> DATA_LENGTH = ModBusType.LENGTH;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1));
int address = 0;
int addressLength = tag.getAddress().length();
int exp = (int) Math.pow(10, addressLength-1);
if (firstDigit != 0){
int digit = Integer.parseInt(tag.getAddress());
address = digit % (exp);
}else {
address = Integer.parseInt(tag.getAddress());
}
RegisterType registerType = type.get(firstDigit);
int dataLength = DATA_LENGTH.get(tag.getDataType());
// 增加配置校验和警告
if ((Objects.equals(registerType, COIL) || Objects.equals(registerType, DISCRETE_INPUT))) {
logger.warn("Configuration warning for tag '{}': ModBusType is {} but DataType is {}. DataType should be BOOLEAN. Proceeding with BOOLEAN read.",
tag.getKey(), registerType, tag.getDataType());
}
try {
switch (registerType) {
case COIL: {
BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, address);
value = master.getValue(loc);
logger.info("读取线圈{}成功: {}",tag.getAddress(), value);
break;
}
case DISCRETE_INPUT: {
BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, address);
value = master.getValue(loc);
logger.info("读取输入{}成功: {}",tag.getAddress(), value);
break;
}
case HOLDING_REGISTER: {
if (dataLength == 28){
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, address, 4);
value = master.getValue(locator);
//将 value 转换为二进制数据
value = convertValueToFloat(value);
}else{
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, address, dataLength);
value = master.getValue(locator);
}
logger.info("读取保持寄存器{}成功: {}",tag.getAddress(), value);
break;
}
case INPUT_REGISTER: {
BaseLocator<Number> locator = BaseLocator.inputRegister(slaveId, address, dataLength);
value= master.getValue(locator);
logger.info("读取输入寄存器{}成功: {}",tag.getAddress(), value);
break;
}
default:
logger.error("Unsupported register type: {}", registerType);
value = null;
break;
}
}catch (Exception e){
logger.error("Failed to read tag '{}'", tag.getKey(), e);
value = null;
}
return value;
}
private BatchResults<String> readTagValues(ModbusMaster master, int slaveId, List<TagConfig> tags) throws Exception {
try {
BatchRead<String> batch = new BatchRead<>();
tags.forEach(tag -> {
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
Map<String, Integer> DATA_LENGTH = ModBusType.LENGTH;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1));
int address = 0;
int addressLength = tag.getAddress().length();
int exp = (int) Math.pow(10, addressLength-1);
if (firstDigit != 0){
int digit = Integer.parseInt(tag.getAddress());
address = digit % (exp);
}else {
address = Integer.parseInt(tag.getAddress());
}
RegisterType registerType = type.get(firstDigit);
int dataLength = DATA_LENGTH.get(tag.getDataType());
switch (registerType) {
case COIL: {
BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, address);
batch.addLocator(tag.getKey(), loc);
break;
}
case DISCRETE_INPUT: {
BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, address);
batch.addLocator(tag.getKey(), loc);
break;
}
case HOLDING_REGISTER: {
logger.info("HOLDING_REGISTER: {}",tag.getAddress());
if (dataLength == 28){
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, address, 4);
batch.addLocator(tag.getKey(), locator);
}else {
BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, address, dataLength);
batch.addLocator(tag.getKey(), loc);
}
break;
}
case INPUT_REGISTER: {
logger.info("INPUT_REGISTER: {}",tag.getAddress());
BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, address, dataLength);
batch.addLocator(tag.getKey(), loc);
break;
}
}
});
BatchResults<String> results = master.send(batch);
for (TagConfig tag : tags){
if (tag.getBit()!=null){
logger.info("批处理读取寄存器成功: {}",tag.getAddress() +"(" + tag.getBit() + "):" + results.getValue(tag.getKey()));
}else {
logger.info("批处理读取寄存器成功: {}",tag.getAddress() + ":" + results.getValue(tag.getKey()));
}
}
return results;
}catch (Exception e){
logger.error("Failed to read master '{}'", slaveId, e);
throw new Exception(e);
}
}
public static float convertValueToFloat(Object value) {
if (!(value instanceof Number)) {
throw new IllegalArgumentException("Input must be a Number");
}
int intValue = ((Number) value).intValue();
String binaryData = Integer.toBinaryString(intValue);
// 补足32位二进制字符串
if (binaryData.length() < 32) {
binaryData = String.format("%32s", binaryData).replace(' ', '0');
}
// 分割为4个字节并重组为 dcba 格式
byte[] reorderedBytes = new byte[4];
for (int i = 0; i < 4; i++) {
int start = i * 8;
String byteStr = binaryData.substring(start, start + 8);
reorderedBytes[3 - i] = (byte) Integer.parseInt(byteStr, 2);
}
// 使用 ByteBuffer 提高可读性和安全性
return Float.intBitsToFloat(
java.nio.ByteBuffer.wrap(reorderedBytes).getInt()
);
}
}

View File

@ -0,0 +1,58 @@
package com.xzzn.common.core.modbus;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.ip.IpParameters;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
public class PooledModbusMasterFactory extends BasePooledObjectFactory<ModbusMaster> {
private final String host;
private final int port;
public PooledModbusMasterFactory(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public ModbusMaster create() throws Exception {
IpParameters params = new IpParameters();
params.setHost(this.host);
params.setPort(this.port);
params.setEncapsulated(false);
ModbusMaster master = new ModbusFactory().createTcpMaster(params, true);
master.init();
return master;
}
@Override
public PooledObject<ModbusMaster> wrap(ModbusMaster master) {
return new DefaultPooledObject<>(master);
}
@Override
public void destroyObject(PooledObject<ModbusMaster> p) throws Exception {
if (p.getObject() != null) {
p.getObject().destroy();
}
super.destroyObject(p);
}
@Override
public boolean validateObject(PooledObject<ModbusMaster> p) {
// testConnectivity() 方法在 modbus4j 中不存在。
// 一个真正的验证需要执行一次读操作,但这需要 slaveId而工厂是通用的不知道 slaveId。
// 因此,我们使用一个较弱的验证,只检查 master 对象是否已初始化。
// 这无法检测到被远程设备断开的连接,错误将在实际读取操作中被捕获。
if (p.getObject() == null) {
return false;
}
return p.getObject().isInitialized();
}
}

View File

@ -0,0 +1,91 @@
package com.xzzn.common.core.modbus.domain;
import java.util.List;
public class DeviceConfig {
private String deviceNumber;
private String deviceName;
private String host;
private int port;
private long time;
private int slaveId;
private boolean enabled;
private List<TagConfig> tags;
private List<WriteTagConfig> writeTags;
public String getDeviceNumber() {
return deviceNumber;
}
public void setDeviceNumber(String deviceNumber) {
this.deviceNumber = deviceNumber;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public int getSlaveId() {
return slaveId;
}
public void setSlaveId(int slaveId) {
this.slaveId = slaveId;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<TagConfig> getTags() {
return tags;
}
public void setTags(List<TagConfig> tags) {
this.tags = tags;
}
public List<WriteTagConfig> getWriteTags() {
return writeTags;
}
public void setWriteTags(List<WriteTagConfig> writeTags) {
this.writeTags = writeTags;
}
}

View File

@ -0,0 +1,78 @@
package com.xzzn.common.core.modbus.domain;
public class TagConfig {
private String key;
private String des;
private String address;
private String dataType;
private float a;
private float k;
private float b;
private Integer bit;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public float getA() {
return a;
}
public void setA(float a) {
this.a = a;
}
public float getK() {
return k;
}
public void setK(float k) {
this.k = k;
}
public float getB() {
return b;
}
public void setB(float b) {
this.b = b;
}
public Integer getBit() {
return bit;
}
public void setBit(Integer bit) {
this.bit = bit;
}
}

View File

@ -0,0 +1,22 @@
package com.xzzn.common.core.modbus.domain;
public class WriteTagConfig {
private Object value;
private String address;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,57 @@
package com.xzzn.common.enums;
import com.serotonin.modbus4j.code.DataType;
import java.util.HashMap;
import java.util.Map;
public class ModBusType {
public static final Map<Integer, RegisterType> REGISTER_TYPE = new HashMap<Integer, RegisterType>();
public static final Map<String, Integer> LENGTH = new HashMap<String, Integer>();
static {
REGISTER_TYPE.put(0, RegisterType.COIL);
REGISTER_TYPE.put(1, RegisterType.DISCRETE_INPUT);
REGISTER_TYPE.put(4, RegisterType.HOLDING_REGISTER);
REGISTER_TYPE.put(3, RegisterType.INPUT_REGISTER);
LENGTH.put("BINARY",DataType.BINARY);
LENGTH.put("TWO_BYTE_INT_UNSIGNED",DataType.TWO_BYTE_INT_UNSIGNED);
LENGTH.put("TWO_BYTE_INT_SIGNED",DataType.TWO_BYTE_INT_SIGNED);
LENGTH.put("TWO_BYTE_INT_UNSIGNED_SWAPPED",DataType.TWO_BYTE_INT_UNSIGNED_SWAPPED);
LENGTH.put("TWO_BYTE_INT_SIGNED_SWAPPED",DataType.TWO_BYTE_INT_SIGNED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_UNSIGNED",DataType.FOUR_BYTE_INT_UNSIGNED);
LENGTH.put("FOUR_BYTE_INT_SIGNED",DataType.FOUR_BYTE_INT_SIGNED);
LENGTH.put("FOUR_BYTE_INT_UNSIGNED_SWAPPED",DataType.FOUR_BYTE_INT_UNSIGNED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_SIGNED_SWAPPED",DataType.FOUR_BYTE_INT_SIGNED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_UNSIGNED_SWAPPED_SWAPPED",DataType.FOUR_BYTE_INT_UNSIGNED_SWAPPED_SWAPPED);
LENGTH.put("FOUR_BYTE_INT_SIGNED_SWAPPED_SWAPPED",DataType.FOUR_BYTE_INT_SIGNED_SWAPPED_SWAPPED);
LENGTH.put("FOUR_BYTE_FLOAT",DataType.FOUR_BYTE_FLOAT);
LENGTH.put("FOUR_BYTE_FLOAT_SWAPPED",DataType.FOUR_BYTE_FLOAT_SWAPPED);
LENGTH.put("FOUR_BYTE_FLOAT_SWAPPED_INVERTED",DataType.FOUR_BYTE_FLOAT_SWAPPED_INVERTED);
LENGTH.put("FOUR_BYTE_FLOAT_INVERTED",DataType.FOUR_BYTE_FLOAT_INVERTED);
LENGTH.put("FOUR_BYTE_FLOAT_SWAPPED_SWAPPED",DataType.FOUR_BYTE_FLOAT_SWAPPED_SWAPPED);
LENGTH.put("EIGHT_BYTE_INT_UNSIGNED",DataType.EIGHT_BYTE_INT_UNSIGNED);
LENGTH.put("EIGHT_BYTE_INT_SIGNED",DataType.EIGHT_BYTE_INT_SIGNED);
LENGTH.put("EIGHT_BYTE_INT_UNSIGNED_SWAPPED",DataType.EIGHT_BYTE_INT_UNSIGNED_SWAPPED);
LENGTH.put("EIGHT_BYTE_INT_SIGNED_SWAPPED",DataType.EIGHT_BYTE_INT_SIGNED_SWAPPED);
LENGTH.put("EIGHT_BYTE_FLOAT",DataType.EIGHT_BYTE_FLOAT);
LENGTH.put("EIGHT_BYTE_FLOAT_SWAPPED",DataType.EIGHT_BYTE_FLOAT_SWAPPED);
LENGTH.put("TWO_BYTE_BCD",DataType.TWO_BYTE_BCD);
LENGTH.put("FOUR_BYTE_BCD",DataType.FOUR_BYTE_BCD);
LENGTH.put("FOUR_BYTE_BCD_SWAPPED",DataType.FOUR_BYTE_BCD_SWAPPED);
LENGTH.put("CHAR",DataType.CHAR);
LENGTH.put("VARCHAR",DataType.VARCHAR);
LENGTH.put("FOUR_BYTE_FLOAT_DBCA",28);
}
}

View File

@ -0,0 +1,45 @@
package com.xzzn.common.enums;
public enum PcsControlCommand {
TOTAL_START(0x0004, "总运行"),
TOTAL_STOP(0x0010, "总停机"),
TOTAL_RESET(0x0080, "总复位"),
// CLUSTER1_START(0x1004, "电池簇1运行"),
// CLUSTER1_STOP(0x1010, "电池簇1停机"),
// CLUSTER1_RESET(0x1080, "电池簇1复位"),
// CLUSTER2_START(0x2004, "电池簇2运行"),
// CLUSTER2_STOP(0x2010, "电池簇2停机"),
// CLUSTER2_RESET(0x2080, "电池簇2复位"),
// CLUSTER3_START(0x3004, "电池簇3运行"),
// CLUSTER3_STOP(0x3010, "电池簇3停机"),
// CLUSTER3_RESET(0x3080, "电池簇3复位"),
// CLUSTER4_START(0x4004, "电池簇4运行"),
// CLUSTER4_STOP(0x4010, "电池簇4停机"),
// CLUSTER4_RESET(0x4080, "电池簇4复位"),
;
private final int code;
private final String description;
PcsControlCommand(int code, String description) {
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
public static PcsControlCommand fromDeviceStatus(String deviceStatus) {
if (DeviceRunningStatus.RUNNING.getCode().equals(deviceStatus)) {
return PcsControlCommand.TOTAL_START;
} else if (DeviceRunningStatus.SHUTDOWN.getCode().equals(deviceStatus) ) {
return PcsControlCommand.TOTAL_STOP;
}
return null;
}
}

View File

@ -0,0 +1,8 @@
package com.xzzn.common.enums;
public enum RegisterType {
COIL,
DISCRETE_INPUT,
HOLDING_REGISTER,
INPUT_REGISTER
}