Browse Source

feat:集中告警模块

pull/50/head
xjf 4 weeks ago
parent
commit
1731d16304
  1. 16
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/warn/vo/WarnPageReqVO.java
  2. 48
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/warn/vo/WarnRespVO.java
  3. 10
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/warn/warnController.java
  4. 18
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/dataobject/warn/WarnDO.java
  5. 26
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/mysql/warn/WarnMapper.java
  6. 10
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/instant/InstantServiceImpl.java
  7. 14
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/warn/WarnService.java
  8. 135
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/warn/WarnServiceImpl.java
  9. 1
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
  10. 4
      yudao-server/src/main/resources/application-local.yaml

16
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/warn/vo/WarnPageReqVO.java

@ -12,5 +12,21 @@ public class WarnPageReqVO extends PageParam {
@Schema(description = "实例id", example = "id")
private Long mpId;
@Schema(description = "机组id", example = "id")
private Integer unit;
@Schema(description = "系统id", example = "id")
private Integer type;
@Schema(description = "子系统id", example = "id")
private Integer system;
@Schema(description = "实例名称", example = "id")
private String mpName;
//下面这俩个字段是为了集中告警筛选条件
@Schema(description = "预警状态", example = "id")
private Long warnStatus1;
@Schema(description = "实时状态", example = "id")
private Long statusRealTime;
}

48
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/warn/vo/WarnRespVO.java

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.alert.controller.admin.warn.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@ -20,19 +22,22 @@ public class WarnRespVO {
private Long mpId;
@Schema(description = "点号", example = "id")
private String pointId;
@Schema(description = "点号描述", example = "id")
@Schema(description = "点号描述", example = "id")
private String pointName;
@Schema(description = "实例名称", example = "id")
@Schema(description = "实例名称", example = "id")
private String mpName;
private String equation;
@Schema(description = "输出值点号", example = "id")
private String outputPoint;
private String unit;
@ -68,11 +73,13 @@ public class WarnRespVO {
private Double uplimit;
private String uplimit;
private String lowlimit;
private Double lowlimit;
private String systemName;
private String unitName;
/**
* 创建者-名称
@ -81,6 +88,16 @@ public class WarnRespVO {
*/
private String createName;
/**
* 创建者-名称
*
*
*/
@Schema(description = "创建时间", example = "2025-01-01 12:00:00")
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
* 更新者-名称
*
@ -88,4 +105,25 @@ public class WarnRespVO {
*/
private String updateName;
private Long warnStatus1;
private Long statusRealtime;
//集中告警新增的字段
@Schema(description = "点号值", example = "id")
private Double pointValue;
@Schema(description = "输出值点号值", example = "id")
private Double outputPointValue;
// 偏差值=输入值-重构值
@Schema(description = "偏差值", example = "id")
private Double biasValue;
// 时间差=当前时间-创建时间(单位:秒)--总秒数
@Schema(description = "时间差", example = "id")
private Long timeDiff;
// 时间差=当前时间-创建时间(单位:秒)--时间字符串
@Schema(description = "持续时长", example = "id")
private String timeDiffStr;
}

10
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/warn/warnController.java

@ -40,7 +40,15 @@ public class warnController {
PageResult<WarnDO> pageResult = warnService.getWarnPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, WarnRespVO.class));
}
@GetMapping("/page-real")
@Operation(summary = "获得预警分页列表")
@PreAuthorize("@ss.hasPermission('run:warn:query')")
public CommonResult<PageResult<WarnRespVO>> getWarnPageReal(@Valid WarnPageReqVO pageReqVO) {
pageReqVO.setStatusRealTime(0L);
pageReqVO.setWarnStatus1(1L);
PageResult<WarnRespVO> pageResult = warnService.getWarnPageReal(pageReqVO);
return success(pageResult);
}
@GetMapping("/get")
@Operation(summary = "获得预警信息")
@PreAuthorize("@ss.hasPermission('run:warn:query')")

18
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/dataobject/warn/WarnDO.java

@ -59,13 +59,25 @@ public class WarnDO extends BaseDO {
private Long warnStatus;
//这里得是String,因为可能是表达式
private String uplimit;
private Double uplimit;
private Double lowlimit;
//这里得是String,因为可能是表达式
private String lowlimit;
private String systemName;
private String createName;
private String updateName;
private LocalDateTime createTime;
private String unitName;
private String systemTypeName;
private Long unitId;
private Long systemTypeId;
private Long algorithmId;
private Long systemId;
private Long warnStatus1;
private Long statusRealtime;
}

26
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/mysql/warn/WarnMapper.java

@ -9,12 +9,36 @@ import cn.iocoder.yudao.module.alert.dal.dataobject.instant.InstantDO;
import cn.iocoder.yudao.module.alert.dal.dataobject.warn.WarnDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface WarnMapper extends BaseMapperX<WarnDO> {
default PageResult<WarnDO> selectPage(WarnPageReqVO reqVO) {
//计算当前时间与create_time的时间差(秒),并筛选出大于阈值的记录
// 筛选出时间差大于阈值的记录
return selectPage(reqVO, new LambdaQueryWrapperX<WarnDO>()
.likeIfPresent(WarnDO::getMpId, reqVO.getMpId().toString())
.eqIfPresent(WarnDO::getMpId, reqVO.getMpId())
.likeIfPresent(WarnDO::getMpName, reqVO.getMpName())
.eqIfPresent(WarnDO::getUnitId,reqVO.getUnit())
.eqIfPresent(WarnDO::getSystemTypeId,reqVO.getType())
.eqIfPresent(WarnDO::getSystemId,reqVO.getSystem())
.orderByAsc(WarnDO::getWarnId));
}
default PageResult<WarnDO> selectPageReal(WarnPageReqVO reqVO) {
//计算当前时间与create_time的时间差(秒),并筛选出大于阈值的记录
// 筛选出时间差大于阈值的记录
return selectPage(reqVO, new LambdaQueryWrapperX<WarnDO>()
.eqIfPresent(WarnDO::getMpId, reqVO.getMpId())
.likeIfPresent(WarnDO::getMpName, reqVO.getMpName())
.eqIfPresent(WarnDO::getUnitId,reqVO.getUnit())
.eqIfPresent(WarnDO::getSystemTypeId,reqVO.getType())
.eqIfPresent(WarnDO::getSystemId,reqVO.getSystem())
.eqIfPresent(WarnDO::getWarnStatus1,reqVO.getWarnStatus1())
.eqIfPresent(WarnDO::getStatusRealtime,reqVO.getStatusRealTime())
// ⭐ 核心条件:当前时间 - create_time < 表字段阈值
.apply("TIMESTAMPDIFF(SECOND, create_time, NOW()) > time_duration_threshold")
.orderByAsc(WarnDO::getWarnId));
}
}

10
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/instant/InstantServiceImpl.java

@ -69,6 +69,9 @@ public class InstantServiceImpl implements InstantService {
@Value("${EXA.ip}")
private String EXA_IP;
//PCA回算的http请求地址
@Value("${PCA.calcurl}")
private String PCA_CALC_URL;
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_INSTANT_TYPE, subType = SYSTEM_INSTANT_CREATE_SUB_TYPE, bizNo = "{{#role.id}}",
@ -241,9 +244,6 @@ public class InstantServiceImpl implements InstantService {
Long modelId = instant.getModelId();
String version = instant.getModelVersion();
// modelId=11L;
// version="v-test";
// 调用reportMapper获取对应记录(假设存在selectByModelIdAndVersion方法)
ReportDO report = reportMapper.selectByModelIdAndVersion(modelId, version);
@ -528,10 +528,10 @@ public class InstantServiceImpl implements InstantService {
calcReqVO.setWarn_Instants_Str(warnInstantsJson); // 假设InstantCalcResultVO有此setter方法
//调用http接口,获取计算结果 http://120.26.116.243:8098/api/PCA/deepTrack
String url = "http://120.26.116.243:8098/api/PCA/deepTrack";
// String url = "http://120.26.116.243:8098/api/PCA/deepTrack";
String params = JsonUtils.toJsonString(calcReqVO);
// 调用http接口,获取计算结果
String httpResult = HttpUtils.post(url, null, params);
String httpResult = HttpUtils.post(PCA_CALC_URL, null, params);
JSONObject jsonResult = JsonUtils.parseObject(httpResult, JSONObject.class);
try {
String result = jsonResult.getString("result");

14
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/warn/WarnService.java

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.alert.service.warn;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.alert.controller.admin.instant.vo.InstantSaveReqVO;
import cn.iocoder.yudao.module.alert.controller.admin.warn.vo.WarnPageReqVO;
import cn.iocoder.yudao.module.alert.controller.admin.warn.vo.WarnRespVO;
import cn.iocoder.yudao.module.alert.controller.admin.warn.vo.WarnSaveReqVO;
import cn.iocoder.yudao.module.alert.dal.dataobject.instant.InstantDO;
import cn.iocoder.yudao.module.alert.dal.dataobject.warn.WarnDO;
@ -17,7 +18,20 @@ public interface WarnService {
*/
PageResult<WarnDO> getWarnPage(WarnPageReqVO reqVO);
/**
* 获得预警分页包含已获取实时值
*
* @param reqVO 预警分页查询
* @return 预警分页结果
*/
PageResult<WarnRespVO> getWarnPageReal(WarnPageReqVO reqVO);
/**
* 获得预警
*
* @param id 预警编号
* @return 预警
*/
WarnDO getWarn(Long id);
/**

135
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/warn/WarnServiceImpl.java

@ -6,12 +6,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.alert.controller.admin.instant.vo.InstantSaveReqVO;
import cn.iocoder.yudao.module.alert.controller.admin.warn.vo.WarnPageReqVO;
import cn.iocoder.yudao.module.alert.controller.admin.warn.vo.WarnRespVO;
import cn.iocoder.yudao.module.alert.controller.admin.warn.vo.WarnSaveReqVO;
import cn.iocoder.yudao.module.alert.dal.dataobject.instant.InstantDO;
import cn.iocoder.yudao.module.alert.dal.dataobject.warn.WarnDO;
import cn.iocoder.yudao.module.alert.dal.dataobject.warn.WarnTableDO;
import cn.iocoder.yudao.module.alert.dal.mysql.warn.WarnMapper;
import cn.iocoder.yudao.module.alert.dal.mysql.warn.WarnTableMapper;
import cn.iocoder.yudao.module.alert.utils.EXAUtils;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@ -22,13 +24,23 @@ import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.WARN_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;
@Service
@ -38,18 +50,127 @@ public class WarnServiceImpl implements WarnService {
private WarnMapper warnMapper;
@Resource
private WarnTableMapper warnTableMapper;
@Value("${EXA.ip}")
private String EXA_IP;
@Override
public PageResult<WarnDO> getWarnPage(WarnPageReqVO reqVO) {
return warnMapper.selectPage(reqVO);
}
@Override
public PageResult<WarnRespVO> getWarnPageReal(WarnPageReqVO reqVO) {
PageResult<WarnDO> warnPage = warnMapper.selectPageReal(reqVO);
EXAUtils exaUtils = new EXAUtils();
// 2. 循环处理每个预警,读取实时值并转换为WarnRespVO
List<WarnRespVO> respVOList = warnPage.getList().stream().map(warnDO -> {
// 2.1 基础属性拷贝
WarnRespVO respVO = BeanUtils.toBean(warnDO, WarnRespVO.class);
// 2.2 读取pointId和outpointPoint的实时值(假设实时服务方法为getRealTimeValue)
List<String> pointValue = null;
List<String> outpointValue = null;
try {
pointValue = exaUtils.getNowData(EXA_IP, warnDO.getPointId());
outpointValue = exaUtils.getNowData(EXA_IP, warnDO.getPointId());
} catch (Exception e) {
throw exception(EXA_REAL_FAILED, "EXA实时值读取失败: " + e.getMessage());
}
// 2.3 实时值到value字段
respVO.setPointValue(Double.parseDouble(pointValue.get(0)));
respVO.setOutputPointValue(Double.parseDouble(outpointValue.get(0)));
//偏差值
//偏差值=输入值-重构值
double point = Double.parseDouble(pointValue.get(0));
double outpoint = Double.parseDouble(outpointValue.get(0));
respVO.setBiasValue(point - outpoint);
//2.4处理uplimit、lowlimit
if (warnDO.getUplimit() != null) {
String originalUplimit = warnDO.getUplimit();
// 检查是否包含[]格式的点号
if (originalUplimit.contains("[") && originalUplimit.contains("]")) {
// 使用正则提取[]内的点号(例如:[point123] -> point123)
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(originalUplimit);
if (matcher.find()) {
String innerPoint = matcher.group(1); // 获取括号内的点号
// 读取内点的实时值
List<String> innerPointValue = null;
try {
innerPointValue = exaUtils.getNowData(EXA_IP, innerPoint);
} catch (Exception e) {
throw exception(EXA_REAL_FAILED, "EXA实时值读取失败: " + e.getMessage());
}
String realValue = innerPointValue.get(0); // 取第一个值
// 替换[]内的点号为实时值(例如:"温度>[temp_point]" -> "温度>25.5")
String processedUplimit = originalUplimit.replace("[" + innerPoint + "]", realValue);
respVO.setUplimit(processedUplimit);
} else {
// 未匹配到有效格式,保留原始值
respVO.setUplimit(originalUplimit);
}
} else {
// 不包含[],直接使用原始值
respVO.setUplimit(originalUplimit);
}
}
if (warnDO.getLowlimit() != null) {
String originalLowlimit = warnDO.getLowlimit();
// 检查是否包含[]格式的点号
if (originalLowlimit.contains("[") && originalLowlimit.contains("]")) {
// 使用正则提取[]内的点号(例如:[point123] -> point123)
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(originalLowlimit);
if (matcher.find()) {
String innerPoint = matcher.group(1); // 获取括号内的点号
// 读取内点的实时值
List<String> innerPointValue = null;
try {
innerPointValue = exaUtils.getNowData(EXA_IP, innerPoint);
} catch (Exception e) {
throw exception(EXA_REAL_FAILED, "EXA实时值读取失败: " + e.getMessage());
}
String realValue = innerPointValue.get(0); // 取第一个值
// 替换[]内的点号为实时值(例如:"温度>[temp_point]" -> "温度>25.5")
String processedLowlimit = originalLowlimit.replace("[" + innerPoint + "]", realValue);
respVO.setLowlimit(processedLowlimit);
} else {
// 未匹配到有效格式,保留原始值
respVO.setLowlimit(originalLowlimit);
}
} else {
// 不包含[],直接使用原始值
respVO.setLowlimit(originalLowlimit);
}
}
//计算当前时间与create_time的时间差(单位:秒)
long totalSeconds = ChronoUnit.SECONDS.between(warnDO.getCreateTime(), LocalDateTime.now());
respVO.setTimeDiff(totalSeconds);
// 转换为天、时、分、秒
long days = totalSeconds / 86400; // 1天 = 86400秒
long remainingSeconds = totalSeconds % 86400;
long hours = remainingSeconds / 3600; // 1小时 = 3600秒
remainingSeconds %= 3600;
long minutes = remainingSeconds / 60; // 1分钟 = 60秒
long seconds = remainingSeconds % 60;
// 格式化时间差字符串(例如:1天2小时3分4秒)
String timeDiffStr = String.format("%d天%d小时%d分%d秒", days, hours, minutes, seconds);
respVO.setTimeDiffStr(timeDiffStr);
return respVO;
}).collect(Collectors.toList());
// 3. 构建并返回包含实时值的分页结果
return new PageResult<>(respVOList, warnPage.getTotal());
}
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_WARN_TYPE, subType = SYSTEM_WARN_CREATE_SUB_TYPE, bizNo = "{{#warn.id}}",
success = SYSTEM_WARN_CREATE_SUCCESS)
@LogRecord(type = SYSTEM_WARN_TYPE, subType = SYSTEM_WARN_CREATE_SUB_TYPE, bizNo = "{{#warn.id}}", success = SYSTEM_WARN_CREATE_SUCCESS)
public Long createWarn(WarnSaveReqVO createReqVO) {
// 1.1 校验账户配合
// tenantService.handleTenantInfo(tenant -> {
@ -72,16 +193,14 @@ public class WarnServiceImpl implements WarnService {
}
@Override
public WarnDO getWarn(Long id) {
return warnMapper.selectById(id);
}
@Override
@CacheEvict(value = RedisKeyConstants.WARN, key = "#updateReqVO.warnId")
@LogRecord(type = SYSTEM_WARN_TYPE, subType = SYSTEM_WARN_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
success = SYSTEM_WARN_UPDATE_SUCCESS)
@LogRecord(type = SYSTEM_WARN_TYPE, subType = SYSTEM_WARN_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = SYSTEM_WARN_UPDATE_SUCCESS)
public void updateWarn(WarnSaveReqVO updateReqVO) {
//为简单--省去检验步骤,之后根据情况增加
// 1.1 校验是否可以更新

1
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java

@ -194,5 +194,6 @@ public interface ErrorCodeConstants {
// ========== EXA模块 1-002-034-000 ==========
ErrorCode EXA_POINT_IMPORT_LIST_IS_EMPTY = new ErrorCode(6_001_000, "导入EXA测点数据不能为空!");
ErrorCode EXA_POINT_IMPORT_FAILED = new ErrorCode(6_001_001, "导入EXA测点数据失败!失败测点:({})");
ErrorCode EXA_REAL_FAILED = new ErrorCode(6_001_002, "读取EXA测点实时数据失败!失败测点:({})");
}

4
yudao-server/src/main/resources/application-local.yaml

@ -278,4 +278,6 @@ point:
algorithm:
host: 120.26.116.243:8082
assess-report:
host: 120.26.116.243:8098
host: 120.26.116.243:8098
PCA:
calcurl: http://120.26.116.243:8098/api/PCA/deepTrack

Loading…
Cancel
Save