This commit is contained in:
高云鹏 2024-11-05 14:53:45 +08:00
commit 12fe28a2a8
12 changed files with 266 additions and 32 deletions

View File

@ -0,0 +1,19 @@
package com.das.common.constant;
/**
* 事件等级
*
*/
public interface EventLevelConstant {
/**
* 告警
*/
Integer ALARM = 0;
/**
* 故障
*/
Integer FAULT = 1;
}

View File

@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator; import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.boot.configurationprocessor.json.JSONTokener;
import org.springframework.util.AntPathMatcher; import org.springframework.util.AntPathMatcher;
import java.util.*; import java.util.*;
@ -355,7 +355,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
*/ */
public static boolean isJsonString(String jsonString) { public static boolean isJsonString(String jsonString) {
try { try {
new JSONTokener(jsonString).nextValue(); JSONObject.parseObject(jsonString);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -1,13 +1,19 @@
package com.das.modules.data.domain; package com.das.modules.data.domain;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data; import lombok.Data;
@Data @Data
public class DeviceEventInfo { public class DeviceEventInfo {
private Long updateTime; @JsonSerialize(using = ToStringSerializer.class)
private Long eventTime;
@JsonSerialize(using = ToStringSerializer.class)
private Long eventId; private Long eventId;
private Integer eventType;
private Integer eventLevel; private Integer eventLevel;
private String eventText; private String eventText;
@ -16,6 +22,7 @@ public class DeviceEventInfo {
private String confirmAccount; private String confirmAccount;
@JsonSerialize(using = ToStringSerializer.class)
private Long confirmTime; private Long confirmTime;
private String deviceId; private String deviceId;

View File

@ -18,6 +18,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.sql.*; import java.sql.*;
@ -95,7 +96,7 @@ public class TDEngineService {
} }
} }
public void createCalStable(String iotmodel, String iotModelField,String dataType) { public void createCalStable(String iotmodel, String iotModelField, String dataType) {
try (Connection conn = hikariDataSource.getConnection(); try (Connection conn = hikariDataSource.getConnection();
Statement pstmt = conn.createStatement()) { Statement pstmt = conn.createStatement()) {
StringBuilder sb = new StringBuilder(1024 * 1024); StringBuilder sb = new StringBuilder(1024 * 1024);
@ -251,9 +252,9 @@ public class TDEngineService {
for (IotModelFieldVo info : list) { for (IotModelFieldVo info : list) {
String iotModelCode = info.getIotModelCode(); String iotModelCode = info.getIotModelCode();
Map<String, String> calFieldMap = calculateIotFieldMap.get(iotModelCode); Map<String, String> calFieldMap = calculateIotFieldMap.get(iotModelCode);
if (calFieldMap.keySet().size() != 0){ if (calFieldMap.keySet().size() != 0) {
for (String key : calFieldMap.keySet()){ for (String key : calFieldMap.keySet()) {
createCalStable(iotModelCode,key,calFieldMap.get(key)); createCalStable(iotModelCode, key, calFieldMap.get(key));
} }
} }
} }
@ -385,15 +386,19 @@ public class TDEngineService {
for (DeviceEventInfo dv : list) { for (DeviceEventInfo dv : list) {
sb.append("E_"); sb.append("E_");
sb.append(dv.getDeviceId()); sb.append(dv.getDeviceId());
sb.append(" using event_info tags ('"); sb.append(" using event_info tags (");
sb.append(dv.getDeviceId());
sb.append(",'");
sb.append(dv.getDeviceCode()); sb.append(dv.getDeviceCode());
sb.append("','"); sb.append("','");
sb.append(dv.getDeviceName()); sb.append(dv.getDeviceName());
sb.append("') values ("); sb.append("') values (");
sb.append(dv.getUpdateTime()); sb.append(dv.getEventTime());
sb.append(","); sb.append(",");
sb.append(dv.getEventId()); sb.append(dv.getEventId());
sb.append(","); sb.append(",");
sb.append(dv.getEventType());
sb.append(",");
sb.append(dv.getEventLevel()); sb.append(dv.getEventLevel());
sb.append(",'"); sb.append(",'");
sb.append(dv.getEventText()); sb.append(dv.getEventText());
@ -460,11 +465,11 @@ public class TDEngineService {
Map<String, Map<String, Map<String, Object>>> result = new HashMap<>(); Map<String, Map<String, Map<String, Object>>> result = new HashMap<>();
Map<String, Map<String, Object>> valueMap = new HashMap<>(); Map<String, Map<String, Object>> valueMap = new HashMap<>();
for (String item : fieldList) { for (String item : fieldList) {
Map<String,Object> timeValueMap = new HashMap<>(); Map<String, Object> timeValueMap = new HashMap<>();
List<Long> times = new ArrayList<>(); List<Long> times = new ArrayList<>();
List<Object> objects = new ArrayList<>(); List<Object> objects = new ArrayList<>();
timeValueMap.put("times",times); timeValueMap.put("times", times);
timeValueMap.put("values",objects); timeValueMap.put("values", objects);
valueMap.put(item, timeValueMap); valueMap.put(item, timeValueMap);
} }
StringBuffer sb = new StringBuffer(2048); StringBuffer sb = new StringBuffer(2048);
@ -529,7 +534,6 @@ public class TDEngineService {
public Map<String, Map<String, Map<String, Object>>> fetchLowHistoryCurve(Long irn, Date startTime, Date endTime, String interval, List<String> fieldList) { public Map<String, Map<String, Map<String, Object>>> fetchLowHistoryCurve(Long irn, Date startTime, Date endTime, String interval, List<String> fieldList) {
SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String tbName = String.format("l%d", irn); String tbName = String.format("l%d", irn);
Date now = new Date(); Date now = new Date();
if (endTime.after(now)) { if (endTime.after(now)) {
@ -538,11 +542,11 @@ public class TDEngineService {
Map<String, Map<String, Map<String, Object>>> result = new HashMap<>(); Map<String, Map<String, Map<String, Object>>> result = new HashMap<>();
Map<String, Map<String, Object>> valueMap = new HashMap<>(); Map<String, Map<String, Object>> valueMap = new HashMap<>();
for (String item : fieldList) { for (String item : fieldList) {
Map<String,Object> timeValueMap = new HashMap<>(); Map<String, Object> timeValueMap = new HashMap<>();
List<Long> times = new ArrayList<>(); List<Long> times = new ArrayList<>();
List<Object> objects = new ArrayList<>(); List<Object> objects = new ArrayList<>();
timeValueMap.put("times",times); timeValueMap.put("times", times);
timeValueMap.put("values",objects); timeValueMap.put("values", objects);
valueMap.put(item, timeValueMap); valueMap.put(item, timeValueMap);
} }
StringBuffer sb = new StringBuffer(2048); StringBuffer sb = new StringBuffer(2048);
@ -605,6 +609,73 @@ public class TDEngineService {
return result; return result;
} }
public List<DeviceEventInfo> queryEvent(Integer eventLevel, Long startTime, Long endTime, List<String> deviceCodeList) {
List<DeviceEventInfo> result = new ArrayList<>();
StringBuffer sb = new StringBuffer(2048);
sb.append("select t.* from event_info t where ");
sb.append(String.format(" t.event_time >= %d and t.event_time < %d", startTime, endTime));
if (eventLevel != null) {
sb.append(String.format(" and t.event_level = %d", eventLevel));
}
if (!CollectionUtils.isEmpty(deviceCodeList)) {
sb.append(" and t.device_code in (");
for (int i = 0; i < deviceCodeList.size(); i++) {
if (i == deviceCodeList.size() - 1) {
sb.append("'").append(deviceCodeList.get(i)).append("')");
} else {
sb.append("'").append(deviceCodeList.get(i)).append("',");
}
}
}
sb.append(" order by t.event_time");
log.debug(sb.toString());
try (Connection conn = hikariDataSource.getConnection();
Statement smt = conn.createStatement();
ResultSet rs = smt.executeQuery(sb.toString())) {
while (rs.next()) {
DeviceEventInfo deviceEventInfo = new DeviceEventInfo();
deviceEventInfo.setEventTime(rs.getLong("event_time"));
deviceEventInfo.setEventId(rs.getLong("event_id"));
deviceEventInfo.setEventLevel(rs.getInt("event_level"));
deviceEventInfo.setEventType(rs.getInt("event_type"));
deviceEventInfo.setEventText(rs.getString("event_text"));
deviceEventInfo.setConfirmed(rs.getInt("confirmed"));
deviceEventInfo.setConfirmAccount(rs.getString("confirm_account"));
deviceEventInfo.setConfirmTime(rs.getLong("confirm_time"));
deviceEventInfo.setDeviceCode(rs.getString("device_code"));
deviceEventInfo.setDeviceId(rs.getString("device_id"));
result.add(deviceEventInfo);
}
} catch (Exception e) {
log.error("获取数据异常", e);
return result;
}
return result;
}
public void confirmEvent(DeviceEventInfo deviceEventInfo) {
StringBuffer sb = new StringBuffer(2048);
sb.append("insert into e_");
sb.append(deviceEventInfo.getDeviceId());
sb.append(" USING event_info (device_id)TAGS (null) (event_time,event_id,confirmed,confirm_account,confirm_time) VALUES (");
sb.append(deviceEventInfo.getEventTime());
sb.append(",");
sb.append(deviceEventInfo.getEventId());
sb.append(",");
sb.append(deviceEventInfo.getConfirmed());
sb.append(",'");
sb.append(deviceEventInfo.getConfirmAccount());
sb.append("',");
sb.append(deviceEventInfo.getConfirmTime());
sb.append(")");
try (Connection conn = hikariDataSource.getConnection();
Statement pstmt = conn.createStatement()) {
pstmt.executeUpdate(sb.toString());
} catch (Exception e) {
log.error("新增超级表列失败:{},失败原因{}", sb.toString(), e);
}
}
private String convertInterval(String interval) { private String convertInterval(String interval) {
if (!StringUtils.hasText(interval)) { if (!StringUtils.hasText(interval)) {
interval = "1m"; interval = "1m";

View File

@ -51,7 +51,7 @@ public class DataServiceImpl implements DataService {
//key:modelId value:modelCode //key:modelId value:modelCode
public ConcurrentHashMap<String, String> iotModelMap = new ConcurrentHashMap<>(10000); public ConcurrentHashMap<String, String> iotModelMap = new ConcurrentHashMap<>(10000);
//key:modelId value:fieldCode fieldName //key:modelCode value:fieldCode fieldName
public ConcurrentHashMap<String, Map<String, String>> fieldCodeNameMap = new ConcurrentHashMap<>(10000); public ConcurrentHashMap<String, Map<String, String>> fieldCodeNameMap = new ConcurrentHashMap<>(10000);
//key:modelCode value:FiledCode,dataType //key:modelCode value:FiledCode,dataType

View File

@ -0,0 +1,53 @@
package com.das.modules.event.controller;
import com.das.common.result.R;
import com.das.common.utils.JsonUtils;
import com.das.modules.data.domain.DeviceEventInfo;
import com.das.modules.event.domain.EventQueryParam;
import com.das.modules.event.service.EventService;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 告警event相关controller
*/
@Slf4j
@RequestMapping("/api/event")
@RestController
public class EventController {
@Autowired
private EventService eventService;
/**
* 查询设备告警信息列表
* @param param 查询条件
* @return TD数据库数据
*/
@PostMapping("/query")
public R<List<DeviceEventInfo>> queryEvent(@RequestBody @Valid EventQueryParam param) {
if (log.isDebugEnabled()){
log.debug("/api/event/query is calling");
log.debug(JsonUtils.toJsonString(param));
}
return R.success(eventService.queryEvent(param));
}
/**
* 确认告警信息
* @param deviceEventInfo 确认信息
*/
@PostMapping("/confirm")
public R<Void> confirmEvent(@RequestBody DeviceEventInfo deviceEventInfo){
eventService.confirmEvent(deviceEventInfo);
return R.success();
}
}

View File

@ -0,0 +1,33 @@
package com.das.modules.event.domain;
import com.das.modules.data.domain.SnapshotValueQueryParam;
import lombok.Data;
import java.util.List;
/**
* 时序数据查询实体
*/
@Data
public class EventQueryParam
{
/**
* 开始时间
*/
private String startTime;
/**
* 结束时间
*/
private String endTime;
/**
* 事件等级
*/
private Integer eventLevel;
/**
* 设备编码列表
*/
private List<String> deviceCode;
}

View File

@ -0,0 +1,13 @@
package com.das.modules.event.service;
import com.das.modules.data.domain.DeviceEventInfo;
import com.das.modules.event.domain.EventQueryParam;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
public interface EventService {
List<DeviceEventInfo> queryEvent(EventQueryParam param);
void confirmEvent(DeviceEventInfo deviceEventInfo);
}

View File

@ -0,0 +1,41 @@
package com.das.modules.event.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.das.common.config.SessionUtil;
import com.das.common.exceptions.ServiceException;
import com.das.modules.auth.domain.vo.SysUserVo;
import com.das.modules.data.domain.DeviceEventInfo;
import com.das.modules.data.service.TDEngineService;
import com.das.modules.event.domain.EventQueryParam;
import com.das.modules.event.service.EventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class EventServiceImpl implements EventService {
@Autowired
private TDEngineService tdEngineService;
@Override
public List<DeviceEventInfo> queryEvent(EventQueryParam param) {
if (param.getStartTime() == null || param.getEndTime() ==null){
throw new ServiceException("查询时间不能为空");
}
List<DeviceEventInfo> deviceEventInfos = tdEngineService.queryEvent(param.getEventLevel(), Long.valueOf(param.getStartTime()), Long.valueOf(param.getEndTime()), param.getDeviceCode());
return deviceEventInfos;
}
@Override
public void confirmEvent(DeviceEventInfo deviceEventInfo) {
Long confirmTime = System.currentTimeMillis();
deviceEventInfo.setConfirmTime(confirmTime);
SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY);
deviceEventInfo.setConfirmAccount(sysUserVo.getAccount());
tdEngineService.confirmEvent(deviceEventInfo);
}
}

View File

@ -301,7 +301,7 @@ public class NodeMessageServiceImpl implements NodeMessageService {
for (DeviceEventVo item : list){ for (DeviceEventVo item : list){
DeviceInfoCache deviceInfoCache = cacheService.getEquipmentCache().getDeviceInfoCacheById(Long.valueOf(item.getDeviceId())); DeviceInfoCache deviceInfoCache = cacheService.getEquipmentCache().getDeviceInfoCacheById(Long.valueOf(item.getDeviceId()));
DeviceEventInfo deviceEventInfo = new DeviceEventInfo(); DeviceEventInfo deviceEventInfo = new DeviceEventInfo();
deviceEventInfo.setUpdateTime(item.getEventTime()); deviceEventInfo.setEventTime(item.getEventTime());
deviceEventInfo.setEventId(IdWorker.getId()); deviceEventInfo.setEventId(IdWorker.getId());
deviceEventInfo.setDeviceId(item.getDeviceId()); deviceEventInfo.setDeviceId(item.getDeviceId());
deviceEventInfo.setDeviceName(deviceInfoCache.getDeviceName()); deviceEventInfo.setDeviceName(deviceInfoCache.getDeviceName());
@ -315,6 +315,7 @@ public class NodeMessageServiceImpl implements NodeMessageService {
if (StringUtils.isEmpty(fieldName)){ if (StringUtils.isEmpty(fieldName)){
log.debug("未查询到物模型属性code设备id{}",item.getDeviceId()); log.debug("未查询到物模型属性code设备id{}",item.getDeviceId());
} }
deviceEventInfo.setEventType(item.getEventType());
deviceEventInfo.setEventLevel(0); deviceEventInfo.setEventLevel(0);
deviceEventInfo.setConfirmed(0); deviceEventInfo.setConfirmed(0);
if (!StringUtils.isEmpty(eventType) && eventType.equals("遥信变位")){ if (!StringUtils.isEmpty(eventType) && eventType.equals("遥信变位")){
@ -334,20 +335,16 @@ public class NodeMessageServiceImpl implements NodeMessageService {
}catch (Exception e){ }catch (Exception e){
log.error("事件信息存入Td失败,失败原因{}",e); log.error("事件信息存入Td失败,失败原因{}",e);
} }
} }
private String getEventType(int eventType) { private String getEventType(int eventType) {
switch (eventType) { return switch (eventType) {
case 0: case 0 -> "遥信变位";
return "遥信变位"; case 1 -> "越上限";
case 1: case 2 -> "越下限";
return "越上限"; case 3 -> "越上上限";
case 2: case 4 -> "越下下限";
return "越下限"; default -> null;
default: };
return null;
}
} }
} }

View File

@ -315,7 +315,7 @@ PS: 同一节点只允许建立一条连接。
"attrCode": "stop", "attrCode": "stop",
//属性值 //属性值
"attrValue": 0, "attrValue": 0,
//事件类型 ( 0-遥信变位 1-越上限 2-越下限) //事件类型 ( 0-遥信变位 1-越上限 2-越下限 3-越上上限 4-越下下限 5-越限复归)
"eventType": 0, "eventType": 0,
//事件发生时刻 //事件发生时刻
"eventTime": 12321351235123, "eventTime": 12321351235123,

View File

@ -523,7 +523,7 @@ const initpowerChart = () => {
top: 50, top: 50,
right: 23, right: 23,
bottom: 10, bottom: 10,
left: 18, left: 25,
containLabel: true, containLabel: true,
}, },
tooltip: { tooltip: {