解决保护方案告警不触发问题

This commit is contained in:
zq
2026-01-16 17:06:31 +08:00
parent fb64be5a5a
commit dd0132ab2f
6 changed files with 108 additions and 19 deletions

View File

@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -51,12 +52,12 @@ public class ModbusProcessor {
public boolean writeDataToDevice(DeviceConfig config) { public boolean writeDataToDevice(DeviceConfig config) {
logger.info("writeDataToDevice: {}", JSON.toJSONString(config)); logger.info("writeDataToDevice: {}", JSON.toJSONString(config));
ModbusMaster master = null; ModbusMaster master = null;
boolean result = true; boolean result;
try { try {
master = connectionManager.borrowMaster(config); master = connectionManager.borrowMaster(config);
// 设置了Modbus通信的超时时间为3000毫秒3秒)。当主设备与从设备通信时,若在3秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。 // 设置了Modbus通信的超时时间为1000毫秒1秒)。当主设备与从设备通信时,若在1秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
master.setTimeout(5000); master.setTimeout(1000);
writeTagValue(master, config, config.getWriteTags()); result = writeTagValue(master, config, config.getWriteTags());
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to borrow connection or write to devices '{}'", config.getDeviceName(), e); logger.error("Failed to borrow connection or write to devices '{}'", config.getDeviceName(), e);
result = false; result = false;
@ -70,7 +71,33 @@ public class ModbusProcessor {
return result; 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 -> { tags.forEach(tag -> {
Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE; Map<Integer, RegisterType> type = ModBusType.REGISTER_TYPE;
int firstDigit = Integer.parseInt(tag.getAddress().substring(0, 1)); 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); logger.info("Register type: {}, address: {}, firstDigit: {}", registerType, tag.getAddress(), firstDigit);
switch (registerType) { switch (registerType) {
case COIL: { 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; break;
} }
case HOLDING_REGISTER: { case HOLDING_REGISTER: {
@ -89,7 +117,8 @@ public class ModbusProcessor {
if (doubleValue < -32768 || doubleValue > 32767) { if (doubleValue < -32768 || doubleValue > 32767) {
logger.warn("Value {} out of range for 16-bit signed register at address {}", doubleValue, address); 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; break;
} }
default: default:
@ -97,9 +126,15 @@ public class ModbusProcessor {
break; 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 { try {
WriteCoilRequest request = new WriteCoilRequest(slaveId, address, value); WriteCoilRequest request = new WriteCoilRequest(slaveId, address, value);
WriteCoilResponse response = (WriteCoilResponse)master.send(request); WriteCoilResponse response = (WriteCoilResponse)master.send(request);
@ -107,10 +142,12 @@ public class ModbusProcessor {
logger.info("Write coil failed: " + response.getExceptionMessage()); logger.info("Write coil failed: " + response.getExceptionMessage());
} else { } else {
logger.info("Write coil successful"); logger.info("Write coil successful");
return true;
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to write coil value '{}' to address '{}'", value, address, 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) { 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 { try {
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value); WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value);
WriteRegisterResponse response = (WriteRegisterResponse)master.send(request); WriteRegisterResponse response = (WriteRegisterResponse)master.send(request);
@ -135,10 +172,12 @@ public class ModbusProcessor {
logger.info("Write register failed: " + response.getExceptionMessage()); logger.info("Write register failed: " + response.getExceptionMessage());
} else { } else {
logger.info("Write register successful"); logger.info("Write register successful");
return true;
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to write register value '{}' to address '{}'", value, address, 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) { 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 { public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
ModbusMaster master = connectionManager.borrowMaster(config); ModbusMaster master = connectionManager.borrowMaster(config);
// 设置了Modbus通信的超时时间为3000毫秒3秒)。当主设备与从设备通信时,若在3秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。 // 设置了Modbus通信的超时时间为5000毫秒5秒)。当主设备与从设备通信时,若在5秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
master.setTimeout(10000); master.setTimeout(5000);
return master; return master;
} }

View File

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

View File

@ -3,6 +3,7 @@ package com.xzzn.common.core.modbus.domain;
public class WriteTagConfig { public class WriteTagConfig {
private Object value; private Object value;
private String address; private String address;
private boolean isWrite;
public Object getValue() { public Object getValue() {
return value; return value;
@ -19,4 +20,12 @@ public class WriteTagConfig {
public void setAddress(String address) { public void setAddress(String address) {
this.address = address; this.address = address;
} }
public boolean isWrite() {
return isWrite;
}
public void setWrite(boolean write) {
isWrite = write;
}
} }

View File

@ -230,7 +230,7 @@ public class ModbusPoller {
// 存放mqtt原始每个设备最晚一次数据便于后面点位获取数据 // 存放mqtt原始每个设备最晚一次数据便于后面点位获取数据
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceNumber, obj); 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); log.info("数据已成功存储在Redis: {}", deviceNumber);
} catch (Exception e) { } catch (Exception e) {
log.error("无法在设备的Redis中存储数据: {}", deviceNumber, e); log.error("无法在设备的Redis中存储数据: {}", deviceNumber, e);

View File

@ -89,9 +89,7 @@ public class ProtectionPlanTask {
Long planId = 0L; Long planId = 0L;
try { try {
// 获取所有方案,轮询 // 获取所有方案,轮询
EmsFaultProtectionPlan emsFaultProtectionPlan = new EmsFaultProtectionPlan(); List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(null);
emsFaultProtectionPlan.setSiteId("021_DDS_01");
List<EmsFaultProtectionPlan> planList = iEmsFaultProtectionPlanService.selectEmsFaultProtectionPlanList(emsFaultProtectionPlan);
for (EmsFaultProtectionPlan plan : planList) { for (EmsFaultProtectionPlan plan : planList) {
planId = plan.getId(); planId = plan.getId();
@ -154,7 +152,7 @@ public class ProtectionPlanTask {
// 是否有保护方案有则通过modbus连接设备下发方案 // 是否有保护方案有则通过modbus连接设备下发方案
String protPlanJson = plan.getProtectionPlan(); String protPlanJson = plan.getProtectionPlan();
if (protPlanJson != null && !protPlanJson.isEmpty()) { if (protPlanJson != null && !protPlanJson.isEmpty() && !"[]".equals(protPlanJson)) {
logger.info("<下发保护方案> 方案内容:{}", protPlanJson); logger.info("<下发保护方案> 方案内容:{}", protPlanJson);
executeProtectionActions(protPlanJson,siteId,plan.getId(),plan.getFaultLevel()); // 执行Modbus指令 executeProtectionActions(protPlanJson,siteId,plan.getId(),plan.getFaultLevel()); // 执行Modbus指令
} }

View File

@ -161,6 +161,7 @@ public class StrategyPoller {
} }
// 判断当前时间是否在时间段内 // 判断当前时间是否在时间段内
if (!isTimeInRange(LocalTime.now(), emsStrategyTemp.getStartTime(), emsStrategyTemp.getEndTime())) { if (!isTimeInRange(LocalTime.now(), emsStrategyTemp.getStartTime(), emsStrategyTemp.getEndTime())) {
logger.info("当前站点: {}, 策略: {}, 时间段:{} 不在时间段内", siteId, strategyId, emsStrategyTemp.getStartTime() + "-" + emsStrategyTemp.getEndTime());
continue; continue;
} }
// 查询PCS设备信息 // 查询PCS设备信息
@ -420,10 +421,14 @@ public class StrategyPoller {
boolean result = modbusProcessor.writeDataToDevice(deviceConfig); boolean result = modbusProcessor.writeDataToDevice(deviceConfig);
if (!result) { if (!result) {
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo()); logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
continue;
} else { } else {
if (ChargeStatus.STANDBY.equals(chargeStatus)) { 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 siteId = pcsDevice.getSiteId();
String deviceId = pcsDevice.getDeviceId(); String deviceId = pcsDevice.getDeviceId();
pcsDevice.setWorkStatus(workStatus.getCode()); pcsDevice.setWorkStatus(workStatus.getCode());
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1); DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
if (deviceConfig == null) { if (deviceConfig == null) {
return; return false;
} }
boolean result = modbusProcessor.writeDataToDevice(deviceConfig); boolean result = modbusProcessor.writeDataToDevice(deviceConfig);
if (!result) { if (!result) {
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceConfig, workStatus.getInfo()); logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceConfig, workStatus.getInfo());
} }
return result;
} }
// 判断当前时间是否在时间范围内 // 判断当前时间是否在时间范围内