|
@@ -115,7 +115,7 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
run(deviceCode, "在线状态同步", () -> deviceOfflineCheckTask.markDeviceOnline(deviceCode));
|
|
run(deviceCode, "在线状态同步", () -> deviceOfflineCheckTask.markDeviceOnline(deviceCode));
|
|
|
- run(deviceCode, "压力报警预警评估", () -> evaluatePressure(resultData, resolveDeviceCode(resultData)));
|
|
|
|
|
|
|
+ run(deviceCode, "报警预警评估", () -> evaluateTelemetry(resultData));
|
|
|
|
|
|
|
|
} else if (frameType == 0x34) {
|
|
} else if (frameType == 0x34) {
|
|
|
/*logger.info("收到结束通讯帧,准备发送回应包");
|
|
/*logger.info("收到结束通讯帧,准备发送回应包");
|
|
@@ -140,28 +140,40 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 平升遥测终端的供水压力使用数值阈值判断 WARN-PRESSURE。
|
|
|
|
|
- * 压力值来自本次采集报文,阈值范围来自 warning_threshold 表。
|
|
|
|
|
|
|
+ * 三项指标独立评估,只汇总一次设备报警状态,避免正常指标覆盖其他指标的报警。
|
|
|
*/
|
|
*/
|
|
|
- private void evaluatePressure(TelemetryData data, String deviceCode) {
|
|
|
|
|
|
|
+ private void evaluateTelemetry(TelemetryData data) {
|
|
|
|
|
+ String deviceCode = resolveDeviceCode(data);
|
|
|
|
|
+ Integer status = alarmStatus(
|
|
|
|
|
+ evaluateMetric(deviceCode, "WARN-PRESSURE", "供水压力", data.getPressure()),
|
|
|
|
|
+ evaluateMetric(deviceCode, "WARN-INSTANT-FLOW-SUPPLY", "供水瞬时流量", data.getMeter1InstantFlow()),
|
|
|
|
|
+ evaluateMetric(deviceCode, "WARN-FLOW-SPEED-SUPPLY", "供水流速", data.getFlowSpeed()));
|
|
|
|
|
+ if (status != null) {
|
|
|
|
|
+ run(deviceCode, "报警状态同步", () -> deviceNotifier.updateAlarmStatus(deviceCode, status));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Boolean evaluateMetric(String deviceCode, String warningCode, String warningType, String value) {
|
|
|
|
|
+ return evaluate(deviceCode, warningCode, () -> evaluateThreshold(deviceCode, warningCode, warningType, value));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 数值直接使用本次采集字段,范围按设备源地址和各自指标编码查询阈值表。 */
|
|
|
|
|
+ private boolean evaluateThreshold(String deviceCode, String warningCode, String warningType, String value) {
|
|
|
if (warningThresholdService == null || alarmDataService == null || earlyWarningAutoService == null) {
|
|
if (warningThresholdService == null || alarmDataService == null || earlyWarningAutoService == null) {
|
|
|
- throw new IllegalStateException("压力告警依赖未注入");
|
|
|
|
|
|
|
+ throw new IllegalStateException("阈值告警依赖未注入");
|
|
|
}
|
|
}
|
|
|
- if (data.getPressure() == null || data.getPressure().trim().isEmpty()) {
|
|
|
|
|
- throw new IllegalArgumentException("采集报文缺少压力值");
|
|
|
|
|
|
|
+ if (value == null || value.trim().isEmpty()) {
|
|
|
|
|
+ throw new IllegalArgumentException("采集报文缺少指标值: " + warningCode);
|
|
|
}
|
|
}
|
|
|
- BigDecimal actual = new BigDecimal(data.getPressure().trim());
|
|
|
|
|
- String warningCode = "WARN-PRESSURE";
|
|
|
|
|
|
|
+ BigDecimal actual = new BigDecimal(value.trim());
|
|
|
WarningThreshold threshold = warningThresholdService
|
|
WarningThreshold threshold = warningThresholdService
|
|
|
.getWarningThresholdByDeviceAndCode(deviceCode, warningCode);
|
|
.getWarningThresholdByDeviceAndCode(deviceCode, warningCode);
|
|
|
if (threshold == null || (threshold.getMinValue() == null && threshold.getMaxValue() == null)) {
|
|
if (threshold == null || (threshold.getMinValue() == null && threshold.getMaxValue() == null)) {
|
|
|
- log.warn("未配置供水压力阈值,跳过 WARN-PRESSURE 评估: deviceCode={}", deviceCode);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ throw new IllegalStateException("阈值缺失,不能判断设备已恢复正常: " + warningCode);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BigDecimal min = threshold.getMinValue() == null ? null : BigDecimal.valueOf(threshold.getMinValue());
|
|
BigDecimal min = threshold.getMinValue() == null ? null : BigDecimal.valueOf(threshold.getMinValue());
|
|
|
BigDecimal max = threshold.getMaxValue() == null ? null : BigDecimal.valueOf(threshold.getMaxValue());
|
|
BigDecimal max = threshold.getMaxValue() == null ? null : BigDecimal.valueOf(threshold.getMaxValue());
|
|
|
- String warningType = "压力预警";
|
|
|
|
|
boolean over = (min != null && actual.compareTo(min) <= 0)
|
|
boolean over = (min != null && actual.compareTo(min) <= 0)
|
|
|
|| (max != null && actual.compareTo(max) >= 0);
|
|
|| (max != null && actual.compareTo(max) >= 0);
|
|
|
if (over) {
|
|
if (over) {
|
|
@@ -177,7 +189,6 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
|
|
|
alarm.setDeviationRatio(AlarmLevelUtil.calculateDeviationRatio(actual, min, max));
|
|
alarm.setDeviationRatio(AlarmLevelUtil.calculateDeviationRatio(actual, min, max));
|
|
|
alarm.setAlarmStatus(0);
|
|
alarm.setAlarmStatus(0);
|
|
|
alarm.setCreateTime(java.time.LocalDateTime.now());
|
|
alarm.setCreateTime(java.time.LocalDateTime.now());
|
|
|
- alarm.setCreateTime(java.time.LocalDateTime.now());
|
|
|
|
|
requireSaved(alarmDataService.saveAlarmData(alarm));
|
|
requireSaved(alarmDataService.saveAlarmData(alarm));
|
|
|
});
|
|
});
|
|
|
run(deviceCode, warningCode + ":关闭预警", () ->
|
|
run(deviceCode, warningCode + ":关闭预警", () ->
|
|
@@ -192,7 +203,7 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
|
|
|
earlyWarningAutoService.checkAndGenerate(deviceCode, warningType, warningCode,
|
|
earlyWarningAutoService.checkAndGenerate(deviceCode, warningType, warningCode,
|
|
|
min, max, actual, null));
|
|
min, max, actual, null));
|
|
|
}
|
|
}
|
|
|
- run(deviceCode, "报警状态同步", () -> deviceNotifier.updateAlarmStatus(deviceCode, over ? 1 : 0));
|
|
|
|
|
|
|
+ return over;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private String resolveDeviceCode(TelemetryData data) {
|
|
private String resolveDeviceCode(TelemetryData data) {
|
|
@@ -202,7 +213,7 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
|
|
|
if (data.getDeviceCode() != null && !data.getDeviceCode().trim().isEmpty()) {
|
|
if (data.getDeviceCode() != null && !data.getDeviceCode().trim().isEmpty()) {
|
|
|
return data.getDeviceCode().trim();
|
|
return data.getDeviceCode().trim();
|
|
|
}
|
|
}
|
|
|
- throw new IllegalArgumentException("供水压力报文缺少设备源地址");
|
|
|
|
|
|
|
+ throw new IllegalArgumentException("供水遥测报文缺少设备源地址");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void sendAlarmSms(String deviceCode, String warningType, BigDecimal actual,
|
|
private void sendAlarmSms(String deviceCode, String warningType, BigDecimal actual,
|
|
@@ -221,7 +232,7 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
|
|
|
params.put("location", "当前值:" + actual + ",正常范围:" + min + "~" + max);
|
|
params.put("location", "当前值:" + actual + ",正常范围:" + min + "~" + max);
|
|
|
Map<String, Boolean> result = smsUtil.sendBatchSms(phones, params.toJSONString());
|
|
Map<String, Boolean> result = smsUtil.sendBatchSms(phones, params.toJSONString());
|
|
|
long successCount = result == null ? 0 : result.values().stream().filter(Boolean.TRUE::equals).count();
|
|
long successCount = result == null ? 0 : result.values().stream().filter(Boolean.TRUE::equals).count();
|
|
|
- log.info("一级压力告警短信发送完成: deviceCode={}, success={}/{}", deviceCode, successCount, phones.size());
|
|
|
|
|
|
|
+ log.info("一级告警短信发送完成: deviceCode={}, warningType={}, success={}/{}", deviceCode, warningType, successCount, phones.size());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|