This commit is contained in:
2026-02-16 13:41:35 +08:00
parent 71d0b0f609
commit 8806473080
11 changed files with 783 additions and 53 deletions

View File

@ -14,7 +14,9 @@ import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsAlarmRecords;
import com.xzzn.ems.domain.EmsFaultProtectionPlan;
import com.xzzn.ems.domain.vo.ProtectionConstraintVo;
import com.xzzn.ems.domain.vo.ProtectionPlanVo;
import com.xzzn.ems.domain.vo.ProtectionSettingVo;
import com.xzzn.ems.domain.vo.ProtectionSettingsGroupVo;
import com.xzzn.ems.mapper.EmsAlarmRecordsMapper;
import com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper;
import com.xzzn.ems.service.IEmsFaultProtectionPlanService;
@ -75,11 +77,12 @@ public class ProtectionPlanTask {
if (StringUtils.isEmpty(siteId)) {
continue;
}
List<ProtectionSettingVo> protSettings = parseProtectionSettings(plan.getProtectionSettings());
if (CollectionUtils.isEmpty(protSettings)) {
ProtectionSettingsGroupVo settingGroup = parseProtectionSettings(plan.getProtectionSettings());
if (CollectionUtils.isEmpty(settingGroup.getFaultSettings())
&& CollectionUtils.isEmpty(settingGroup.getReleaseSettings())) {
continue;
}
dealWithProtectionPlan(plan, protSettings);
dealWithProtectionPlan(plan, settingGroup);
}
refreshProtectionConstraintCache(planList);
} catch (Exception e) {
@ -88,20 +91,22 @@ public class ProtectionPlanTask {
}
@SyncAfterInsert
private void dealWithProtectionPlan(EmsFaultProtectionPlan plan, List<ProtectionSettingVo> protSettings) {
private void dealWithProtectionPlan(EmsFaultProtectionPlan plan, ProtectionSettingsGroupVo settingGroup) {
logger.info("<轮询保护方案> 站点:{}方案ID:{}", plan.getSiteId(), plan.getId());
String siteId = plan.getSiteId();
Integer isAlertAlarm = plan.getIsAlert();
List<ProtectionSettingVo> faultSettings = settingGroup.getFaultSettings();
List<ProtectionSettingVo> releaseSettings = settingGroup.getReleaseSettings();
Long status = plan.getStatus();
if (status == null) {
status = ProtPlanStatus.STOP.getCode();
}
if (Objects.equals(status, ProtPlanStatus.STOP.getCode())) {
if (checkIsNeedIssuedPlan(protSettings, siteId)) {
if (checkIsNeedIssuedPlan(faultSettings, siteId)) {
int faultDelay = safeDelaySeconds(plan.getFaultDelaySeconds(), 0);
scheduledExecutorService.schedule(() -> {
if (!checkIsNeedIssuedPlan(protSettings, siteId)) {
if (!checkIsNeedIssuedPlan(faultSettings, siteId)) {
return;
}
if (Integer.valueOf(1).equals(isAlertAlarm)) {
@ -117,7 +122,7 @@ public class ProtectionPlanTask {
return;
}
if (checkIsNeedCancelPlan(protSettings, siteId)) {
if (checkIsNeedCancelPlan(releaseSettings, siteId)) {
int releaseDelay = safeDelaySeconds(plan.getReleaseDelaySeconds(), 0);
scheduledExecutorService.schedule(() -> {
if (Integer.valueOf(1).equals(isAlertAlarm)) {
@ -146,14 +151,58 @@ public class ProtectionPlanTask {
return delay.intValue();
}
private List<ProtectionSettingVo> parseProtectionSettings(String settingsJson) {
private ProtectionSettingsGroupVo parseProtectionSettings(String settingsJson) {
if (StringUtils.isEmpty(settingsJson)) {
return ProtectionSettingsGroupVo.empty();
}
try {
if (settingsJson.trim().startsWith("[")) {
List<ProtectionSettingVo> legacy = objectMapper.readValue(
settingsJson,
new TypeReference<List<ProtectionSettingVo>>() {}
);
ProtectionSettingsGroupVo groupVo = ProtectionSettingsGroupVo.empty();
groupVo.setFaultSettings(legacy);
groupVo.setReleaseSettings(legacy);
return groupVo;
}
ProtectionSettingsGroupVo groupVo = objectMapper.readValue(settingsJson, ProtectionSettingsGroupVo.class);
if (groupVo == null) {
return ProtectionSettingsGroupVo.empty();
}
if (groupVo.getFaultSettings() == null) {
groupVo.setFaultSettings(new ArrayList<>());
}
if (groupVo.getReleaseSettings() == null) {
groupVo.setReleaseSettings(new ArrayList<>());
}
return groupVo;
} catch (Exception e) {
logger.error("解析保护前提失败json:{}", settingsJson, e);
return ProtectionSettingsGroupVo.empty();
}
}
private List<ProtectionPlanVo> parseProtectionPlan(String planJson) {
if (StringUtils.isEmpty(planJson)) {
return new ArrayList<>();
}
try {
return objectMapper.readValue(settingsJson, new TypeReference<List<ProtectionSettingVo>>() {});
if (planJson.trim().startsWith("[")) {
List<ProtectionPlanVo> plans = objectMapper.readValue(
planJson,
new TypeReference<List<ProtectionPlanVo>>() {}
);
return plans == null ? new ArrayList<>() : plans;
}
ProtectionPlanVo plan = objectMapper.readValue(planJson, ProtectionPlanVo.class);
List<ProtectionPlanVo> plans = new ArrayList<>();
if (plan != null) {
plans.add(plan);
}
return plans;
} catch (Exception e) {
logger.error("解析保护前提失败json:{}", settingsJson, e);
logger.error("解析执行保护失败json:{}", planJson, e);
return new ArrayList<>();
}
}
@ -256,9 +305,98 @@ public class ProtectionPlanTask {
vo.setPowerLimitRatio(BigDecimal.ZERO);
}
// 执行保护配置优先于描述文本配置
List<ProtectionPlanVo> protectionPlans = parseProtectionPlan(plan.getProtectionPlan());
applyCapabilityByProtectionPlan(vo, protectionPlans);
return vo;
}
private void applyCapabilityByProtectionPlan(ProtectionConstraintVo vo, List<ProtectionPlanVo> protectionPlans) {
if (CollectionUtils.isEmpty(protectionPlans)) {
return;
}
for (ProtectionPlanVo item : protectionPlans) {
if (item == null) {
continue;
}
String marker = ((item.getPointName() == null ? "" : item.getPointName()) + " "
+ (item.getPoint() == null ? "" : item.getPoint())).toLowerCase();
if (StringUtils.isEmpty(marker)) {
continue;
}
if (containsAny(marker, "降功率", "derate", "power_limit", "powerlimit")) {
BigDecimal ratio = parseDerateRatioByPlan(item);
if (ratio != null) {
vo.setPowerLimitRatio(minRatio(vo.getPowerLimitRatio(), ratio));
}
}
if (!isCapabilityEnabled(item.getValue())) {
continue;
}
if (containsAny(marker, "禁止充放电", "forbid_charge_discharge", "disable_charge_discharge")) {
vo.setAllowCharge(false);
vo.setAllowDischarge(false);
continue;
}
if (containsAny(marker, "禁止充电", "forbid_charge", "disable_charge")) {
vo.setAllowCharge(false);
}
if (containsAny(marker, "禁止放电", "forbid_discharge", "disable_discharge")) {
vo.setAllowDischarge(false);
}
if (containsAny(marker, "允许充电", "allow_charge")) {
vo.setAllowCharge(true);
}
if (containsAny(marker, "允许放电", "allow_discharge")) {
vo.setAllowDischarge(true);
}
if (containsAny(marker, "待机", "standby")) {
vo.setForceStandby(true);
}
if (containsAny(marker, "关机", "停机", "切断", "shutdown", "stop")) {
vo.setForceStop(true);
vo.setForceStandby(true);
vo.setAllowCharge(false);
vo.setAllowDischarge(false);
vo.setPowerLimitRatio(BigDecimal.ZERO);
}
}
}
private BigDecimal parseDerateRatioByPlan(ProtectionPlanVo planVo) {
BigDecimal value = planVo.getValue();
if (value == null || value.compareTo(BigDecimal.ZERO) < 0) {
return null;
}
if (value.compareTo(BigDecimal.ONE) <= 0) {
return value;
}
if (value.compareTo(new BigDecimal("100")) <= 0) {
return value.divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
}
return null;
}
private boolean isCapabilityEnabled(BigDecimal value) {
return value == null || value.compareTo(BigDecimal.ZERO) != 0;
}
private boolean containsAny(String text, String... markers) {
if (StringUtils.isEmpty(text) || markers == null) {
return false;
}
for (String marker : markers) {
if (!StringUtils.isEmpty(marker) && text.contains(marker)) {
return true;
}
}
return false;
}
private BigDecimal parseDerateRatio(String text) {
if (StringUtils.isEmpty(text)) {
return null;

View File

@ -575,9 +575,6 @@ public class StrategyPoller {
ChargeStatus targetStatus,
EmsStrategyRuntimeConfig runtimeConfig,
ProtectionConstraintVo constraint) {
if (!Integer.valueOf(1).equals(runtimeConfig.getProtectInterveneEnable())) {
return new StrategyCommandDecision(targetStatus, safePower(targetPower));
}
if (constraint == null || nullSafeInt(constraint.getLevel()) <= 0) {
return new StrategyCommandDecision(targetStatus, safePower(targetPower));
}