| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package com.zksy.api.service.impl;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.zksy.api.domain.EarlyWarning;
- import com.zksy.api.domain.EquipmentBase;
- import com.zksy.api.mapper.EarlyWarningApiMapper;
- import com.zksy.api.mapper.EquipmentBaseApiMapper;
- import com.zksy.api.service.EarlyWarningAutoService;
- import com.zksy.api.utils.EarlyWarningLevelUtil;
- import com.zksy.api.utils.EarlyWarningLevelUtil.EarlyWarningLevelResult;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import java.math.BigDecimal;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Random;
- /**
- * 采集数据接近阈值时自动写入 early_warning
- */
- @Slf4j
- @Service
- public class EarlyWarningAutoServiceImpl implements EarlyWarningAutoService {
- private static final String AUTO_PREFIX = "AUTO|";
- private static final String SYSTEM_USER = "系统自动";
- private static final List<String> OPEN_STATUS = Arrays.asList(
- "DRAFT", "PENDING", "PROCESSING", "RELEASED"
- );
- @Autowired
- private EarlyWarningApiMapper earlyWarningApiMapper;
- @Autowired
- private EquipmentBaseApiMapper equipmentBaseApiMapper;
- @Override
- public Integer checkAndGenerate(String deviceCode, String warningType, String warningCode,
- BigDecimal minValue, BigDecimal maxValue, BigDecimal actualValue,
- String extraRemark) {
- if (deviceCode == null || deviceCode.isEmpty() || warningCode == null || warningCode.isEmpty()) {
- return null;
- }
- if (actualValue == null || (minValue == null && maxValue == null)) {
- return null;
- }
- try {
- // 已越限或回到安全区:关闭自动预警
- if (EarlyWarningLevelUtil.isOverThreshold(actualValue, minValue, maxValue)) {
- closeAutoWarning(deviceCode, warningCode, "已达报警阈值,转报警处理");
- return null;
- }
- EarlyWarningLevelResult result = EarlyWarningLevelUtil.calculate(actualValue, minValue, maxValue);
- if (result == null) {
- closeAutoWarning(deviceCode, warningCode, "监测值已回落至安全区间");
- return null;
- }
- EarlyWarning existing = findOpenAutoWarning(deviceCode, warningCode);
- String content = buildContent(deviceCode, warningType, warningCode,
- minValue, maxValue, actualValue, result, extraRemark);
- if (existing != null) {
- updateExisting(existing, result, content, warningType, deviceCode, actualValue, minValue, maxValue);
- return result.getLevel();
- }
- createNew(deviceCode, warningType, warningCode, result, content, minValue, maxValue, actualValue);
- return result.getLevel();
- } catch (Exception e) {
- log.error("自动生成预警失败: deviceCode={}, warningCode={}", deviceCode, warningCode, e);
- return null;
- }
- }
- @Override
- public void closeAutoWarning(String deviceCode, String warningCode, String reason) {
- try {
- EarlyWarning existing = findOpenAutoWarning(deviceCode, warningCode);
- if (existing == null) {
- return;
- }
- existing.setStatus("CLOSED");
- existing.setUpdateBy(SYSTEM_USER);
- existing.setUpdateTime(LocalDateTime.now());
- if (reason != null && !reason.isEmpty()) {
- String content = existing.getWarningContent() == null ? "" : existing.getWarningContent();
- existing.setWarningContent(content + "【系统自动解除】" + reason);
- }
- earlyWarningApiMapper.updateById(existing);
- log.info("自动关闭预警: warningNo={}, deviceCode={}, warningCode={}, reason={}",
- existing.getWarningNo(), deviceCode, warningCode, reason);
- } catch (Exception e) {
- log.error("关闭自动预警失败: deviceCode={}, warningCode={}", deviceCode, warningCode, e);
- }
- }
- private EarlyWarning findOpenAutoWarning(String deviceCode, String warningCode) {
- String marker = buildRemarkMarker(deviceCode, warningCode);
- return earlyWarningApiMapper.selectOne(new LambdaQueryWrapper<EarlyWarning>()
- .eq(EarlyWarning::getRemark, marker)
- .in(EarlyWarning::getStatus, OPEN_STATUS)
- .orderByDesc(EarlyWarning::getCreateTime)
- .last("LIMIT 1"));
- }
- private void updateExisting(EarlyWarning existing, EarlyWarningLevelResult result,
- String content, String warningType, String deviceCode,
- BigDecimal actualValue, BigDecimal minValue, BigDecimal maxValue) {
- String newLevel = String.valueOf(result.getLevel());
- boolean levelChanged = !newLevel.equals(existing.getWarningLevel());
- existing.setWarningLevel(newLevel);
- existing.setWarningContent(content);
- existing.setDeviceCode(deviceCode);
- if (warningType != null && !warningType.isEmpty()) {
- existing.setWarningType(warningType);
- existing.setWarningName(buildWarningName(warningType, result.getLevel()));
- }
- EquipmentBase equipment = findEquipment(deviceCode);
- if (equipment != null && equipment.getEquipmentName() != null) {
- existing.setDeviceName(equipment.getEquipmentName());
- }
- existing.setUpdateBy(SYSTEM_USER);
- existing.setUpdateTime(LocalDateTime.now());
- earlyWarningApiMapper.updateById(existing);
- if (levelChanged) {
- log.info("自动更新预警级别: warningNo={}, level={}级, approachRatio={}%",
- existing.getWarningNo(), result.getLevel(), result.getApproachRatio());
- }
- }
- private void createNew(String deviceCode, String warningType, String warningCode,
- EarlyWarningLevelResult result, String content,
- BigDecimal minValue, BigDecimal maxValue, BigDecimal actualValue) {
- EquipmentBase equipment = findEquipment(deviceCode);
- LocalDateTime now = LocalDateTime.now();
- EarlyWarning warning = new EarlyWarning();
- warning.setWarningNo(generateWarningNo());
- warning.setWarningName(buildWarningName(
- warningType != null ? warningType : warningCode, result.getLevel()));
- warning.setWarningType(warningType != null && !warningType.isEmpty() ? warningType : warningCode);
- warning.setWarningLevel(String.valueOf(result.getLevel()));
- warning.setWarningSpecial(warningCode);
- warning.setDeviceCode(deviceCode);
- warning.setStatus("RELEASED");
- warning.setPublisher(SYSTEM_USER);
- warning.setPublishTime(now);
- warning.setCreateBy(SYSTEM_USER);
- warning.setCreateTime(now);
- warning.setUpdateTime(now);
- warning.setWarningContent(content);
- warning.setRemark(buildRemarkMarker(deviceCode, warningCode));
- if (equipment != null) {
- warning.setDeviceName(equipment.getEquipmentName());
- warning.setLocation(equipment.getEquipmentLocation());
- warning.setLongitude(equipment.getLongitude());
- warning.setLatitude(equipment.getLatitude());
- warning.setOwnershipUnit(equipment.getOwnershipUnit());
- warning.setHandler(equipment.getMaintainer());
- if (equipment.getEquipmentName() != null) {
- warning.setWarningName(equipment.getEquipmentName() + "-"
- + buildWarningName(warningType != null ? warningType : warningCode, result.getLevel()));
- }
- } else {
- warning.setLocation("设备编码:" + deviceCode);
- }
- earlyWarningApiMapper.insert(warning);
- log.info("自动生成预警成功: warningNo={}, deviceCode={}, warningCode={}, level={}级, actual={}, min={}, max={}",
- warning.getWarningNo(), deviceCode, warningCode, result.getLevel(),
- actualValue, minValue, maxValue);
- }
- private EquipmentBase findEquipment(String deviceCode) {
- try {
- return equipmentBaseApiMapper.selectOne(new LambdaQueryWrapper<EquipmentBase>()
- .eq(EquipmentBase::getEquipmentCode, deviceCode)
- .last("LIMIT 1"));
- } catch (Exception e) {
- log.warn("查询设备信息失败: deviceCode={}", deviceCode);
- return null;
- }
- }
- private static String buildRemarkMarker(String deviceCode, String warningCode) {
- return AUTO_PREFIX + deviceCode + "|" + warningCode;
- }
- private static String buildWarningName(String warningType, int level) {
- return warningType + "-接近阈值预警(" + EarlyWarningLevelUtil.getLevelName(level) + ")";
- }
- private static String buildContent(String deviceCode, String warningType, String warningCode,
- BigDecimal minValue, BigDecimal maxValue, BigDecimal actualValue,
- EarlyWarningLevelResult result, String extraRemark) {
- StringBuilder sb = new StringBuilder();
- sb.append("【系统自动预警】设备[").append(deviceCode).append("]");
- if (warningType != null) {
- sb.append(" ").append(warningType);
- }
- sb.append("(").append(warningCode).append(")");
- sb.append(" 当前值=").append(actualValue);
- sb.append(",阈值范围=[")
- .append(minValue != null ? minValue : "-")
- .append(", ")
- .append(maxValue != null ? maxValue : "-")
- .append("]");
- sb.append(",逼近侧=").append("UPPER".equals(result.getSide()) ? "上限" : "下限");
- sb.append(",逼近率=").append(result.getApproachRatio()).append("%");
- sb.append(",级别=").append(EarlyWarningLevelUtil.getLevelName(result.getLevel()));
- sb.append("。数据已接近阈值但尚未越限,请关注。");
- if (extraRemark != null && !extraRemark.isEmpty()) {
- sb.append(" 备注:").append(extraRemark);
- }
- return sb.toString();
- }
- private static String generateWarningNo() {
- String ts = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
- String random = String.format("%04d", new Random().nextInt(10000));
- return "YJ" + ts + random;
- }
- }
|