解决保护方案告警不触发问题
This commit is contained in:
@ -28,6 +28,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -51,12 +52,12 @@ public class ModbusProcessor {
|
||||
public boolean writeDataToDevice(DeviceConfig config) {
|
||||
logger.info("writeDataToDevice: {}", JSON.toJSONString(config));
|
||||
ModbusMaster master = null;
|
||||
boolean result = true;
|
||||
boolean result;
|
||||
try {
|
||||
master = connectionManager.borrowMaster(config);
|
||||
// 设置了Modbus通信的超时时间为3000毫秒(3秒)。当主设备与从设备通信时,若在3秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
|
||||
master.setTimeout(5000);
|
||||
writeTagValue(master, config, config.getWriteTags());
|
||||
// 设置了Modbus通信的超时时间为1000毫秒(1秒)。当主设备与从设备通信时,若在1秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
|
||||
master.setTimeout(1000);
|
||||
result = writeTagValue(master, config, config.getWriteTags());
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to borrow connection or write to devices '{}'", config.getDeviceName(), e);
|
||||
result = false;
|
||||
@ -70,7 +71,33 @@ public class ModbusProcessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void writeTagValue(ModbusMaster master, DeviceConfig config, List<WriteTagConfig> tags) {
|
||||
public boolean writeDataToDeviceWithRetry(DeviceConfig config) {
|
||||
logger.info("writeDataToDevice: {}", JSON.toJSONString(config));
|
||||
ModbusMaster master = null;
|
||||
boolean result;
|
||||
|
||||
try {
|
||||
master = connectionManager.borrowMaster(config);
|
||||
master.setTimeout(1000); // 设置超时时间
|
||||
|
||||
// 使用重试装饰器
|
||||
ModbusMaster finalMaster = master;
|
||||
result = RetryableModbusOperation.executeWithRetry(() -> {
|
||||
return writeTagValue(finalMaster, config, config.getWriteTags());
|
||||
}, 1); // 最大重试1次(共2次尝试)
|
||||
|
||||
} 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 boolean 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));
|
||||
@ -79,7 +106,8 @@ public class ModbusProcessor {
|
||||
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())));
|
||||
boolean result = writeCoilRequest(master, config.getSlaveId(), address, Boolean.parseBoolean(String.valueOf(tag.getValue())));
|
||||
tag.setWrite(result);
|
||||
break;
|
||||
}
|
||||
case HOLDING_REGISTER: {
|
||||
@ -89,7 +117,8 @@ public class ModbusProcessor {
|
||||
if (doubleValue < -32768 || doubleValue > 32767) {
|
||||
logger.warn("Value {} out of range for 16-bit signed register at address {}", doubleValue, address);
|
||||
}
|
||||
writeRegisterRequest(master, config.getSlaveId(), address, (int) doubleValue);
|
||||
boolean result = writeRegisterRequest(master, config.getSlaveId(), address, (int) doubleValue);
|
||||
tag.setWrite(result);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -97,9 +126,15 @@ public class ModbusProcessor {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
List<WriteTagConfig> collect = tags.stream().filter(tag -> !Objects.equals(tag.isWrite(), true)).collect(Collectors.toList());
|
||||
if (!collect.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void writeCoilRequest(ModbusMaster master, int slaveId, int address, boolean value) {
|
||||
public static boolean writeCoilRequest(ModbusMaster master, int slaveId, int address, boolean value) {
|
||||
try {
|
||||
WriteCoilRequest request = new WriteCoilRequest(slaveId, address, value);
|
||||
WriteCoilResponse response = (WriteCoilResponse)master.send(request);
|
||||
@ -107,10 +142,12 @@ public class ModbusProcessor {
|
||||
logger.info("Write coil failed: " + response.getExceptionMessage());
|
||||
} else {
|
||||
logger.info("Write coil successful");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to write coil value '{}' to address '{}'", value, address, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void writeCoilsRequest(ModbusMaster master, int slaveId, int address, boolean[] values) {
|
||||
@ -127,7 +164,7 @@ public class ModbusProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeRegisterRequest(ModbusMaster master, int slaveId, int address, int value) {
|
||||
public static boolean writeRegisterRequest(ModbusMaster master, int slaveId, int address, int value) {
|
||||
try {
|
||||
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value);
|
||||
WriteRegisterResponse response = (WriteRegisterResponse)master.send(request);
|
||||
@ -135,10 +172,12 @@ public class ModbusProcessor {
|
||||
logger.info("Write register failed: " + response.getExceptionMessage());
|
||||
} else {
|
||||
logger.info("Write register successful");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to write register value '{}' to address '{}'", value, address, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void writeRegistersRequest(ModbusMaster master, int slaveId, int address, short[] values) {
|
||||
@ -181,8 +220,8 @@ public class ModbusProcessor {
|
||||
|
||||
public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
|
||||
ModbusMaster master = connectionManager.borrowMaster(config);
|
||||
// 设置了Modbus通信的超时时间为3000毫秒(3秒)。当主设备与从设备通信时,若在3秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
|
||||
master.setTimeout(10000);
|
||||
// 设置了Modbus通信的超时时间为5000毫秒(5秒)。当主设备与从设备通信时,若在5秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
|
||||
master.setTimeout(5000);
|
||||
return master;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.xzzn.common.core.modbus;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Modbus重试
|
||||
*
|
||||
*/
|
||||
public class RetryableModbusOperation {
|
||||
private static final Logger logger = LoggerFactory.getLogger(RetryableModbusOperation.class);
|
||||
|
||||
public interface ModbusOperation<T> {
|
||||
T execute() throws Exception;
|
||||
}
|
||||
|
||||
public static <T> T executeWithRetry(ModbusOperation<T> operation, int maxRetries) {
|
||||
int retryCount = 0;
|
||||
Exception lastException = null;
|
||||
|
||||
while (retryCount <= maxRetries) {
|
||||
try {
|
||||
return operation.execute();
|
||||
} catch (Exception e) {
|
||||
lastException = e;
|
||||
retryCount++;
|
||||
if (retryCount <= maxRetries) {
|
||||
logger.info("Operation failed, retrying... (Attempt {})", retryCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.error("Max retries ({}) reached. Last error: {}", maxRetries,
|
||||
lastException != null ? lastException.getMessage() : "Unknown");
|
||||
throw new RuntimeException("Operation failed after " + maxRetries + " retries", lastException);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.xzzn.common.core.modbus.domain;
|
||||
public class WriteTagConfig {
|
||||
private Object value;
|
||||
private String address;
|
||||
private boolean isWrite;
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
@ -19,4 +20,12 @@ public class WriteTagConfig {
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public boolean isWrite() {
|
||||
return isWrite;
|
||||
}
|
||||
|
||||
public void setWrite(boolean write) {
|
||||
isWrite = write;
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +230,7 @@ public class ModbusPoller {
|
||||
// 存放mqtt原始每个设备最晚一次数据,便于后面点位获取数据
|
||||
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber, obj);
|
||||
// 存放每次同步数据,失效时间(同同步时间)-用于判断是否正常同步数据和保护策略查询
|
||||
redisCache.setCacheObject(RedisKeyConstants.SYNC_DATA_ALARM + siteId + "_" + deviceNumber, obj, 1, TimeUnit.MINUTES);
|
||||
redisCache.setCacheObject(RedisKeyConstants.SYNC_DATA + siteId + "_" + deviceNumber, obj, 1, TimeUnit.MINUTES);
|
||||
log.info("数据已成功存储在Redis: {}", deviceNumber);
|
||||
} catch (Exception e) {
|
||||
log.error("无法在设备的Redis中存储数据: {}", deviceNumber, e);
|
||||
|
||||
@ -89,9 +89,7 @@ public class ProtectionPlanTask {
|
||||
Long planId = 0L;
|
||||
try {
|
||||
// 获取所有方案,轮询
|
||||
EmsFaultProtectionPlan emsFaultProtectionPlan = new EmsFaultProtectionPlan();
|
||||
emsFaultProtectionPlan.setSiteId("021_DDS_01");
|
||||
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(emsFaultProtectionPlan);
|
||||
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(null);
|
||||
|
||||
for (EmsFaultProtectionPlan plan : planList) {
|
||||
planId = plan.getId();
|
||||
@ -154,7 +152,7 @@ public class ProtectionPlanTask {
|
||||
|
||||
// 是否有保护方案,有则通过modbus连接设备下发方案
|
||||
String protPlanJson = plan.getProtectionPlan();
|
||||
if (protPlanJson != null && !protPlanJson.isEmpty()) {
|
||||
if (protPlanJson != null && !protPlanJson.isEmpty() && !"[]".equals(protPlanJson)) {
|
||||
logger.info("<下发保护方案> 方案内容:{}", protPlanJson);
|
||||
executeProtectionActions(protPlanJson,siteId,plan.getId(),plan.getFaultLevel()); // 执行Modbus指令
|
||||
}
|
||||
|
||||
@ -161,6 +161,7 @@ public class StrategyPoller {
|
||||
}
|
||||
// 判断当前时间是否在时间段内
|
||||
if (!isTimeInRange(LocalTime.now(), emsStrategyTemp.getStartTime(), emsStrategyTemp.getEndTime())) {
|
||||
logger.info("当前站点: {}, 策略: {}, 时间段:{} 不在时间段内", siteId, strategyId, emsStrategyTemp.getStartTime() + "-" + emsStrategyTemp.getEndTime());
|
||||
continue;
|
||||
}
|
||||
// 查询PCS设备信息
|
||||
@ -420,10 +421,14 @@ public class StrategyPoller {
|
||||
boolean result = modbusProcessor.writeDataToDevice(deviceConfig);
|
||||
if (!result) {
|
||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
|
||||
continue;
|
||||
} else {
|
||||
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
|
||||
// 待机,先写功率值,再关机
|
||||
switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP);
|
||||
if (!switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP)) {
|
||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, WorkStatus.STOP.getInfo());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 记录策略执行日志
|
||||
@ -432,18 +437,19 @@ public class StrategyPoller {
|
||||
}
|
||||
|
||||
//设备开关机
|
||||
private void switchDevice(EmsDevicesSetting pcsDevice, EmsPcsSetting pcsSetting, WorkStatus workStatus) {
|
||||
private boolean switchDevice(EmsDevicesSetting pcsDevice, EmsPcsSetting pcsSetting, WorkStatus workStatus) {
|
||||
String siteId = pcsDevice.getSiteId();
|
||||
String deviceId = pcsDevice.getDeviceId();
|
||||
pcsDevice.setWorkStatus(workStatus.getCode());
|
||||
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
|
||||
if (deviceConfig == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
boolean result = modbusProcessor.writeDataToDevice(deviceConfig);
|
||||
if (!result) {
|
||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceConfig, workStatus.getInfo());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断当前时间是否在时间范围内
|
||||
|
||||
Reference in New Issue
Block a user