From 7bc871cac74686b6eda3b64f2666615d44b58ebe Mon Sep 17 00:00:00 2001 From: weitang Date: Wed, 21 May 2025 14:45:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AlgorithmDeviceController.java | 6 +- .../service/IAlgorithmDeviceService.java | 2 +- .../impl/AlgorithmDeviceServiceImpl.java | 106 +++++++++++- .../controller/AlarmLogController.java | 153 +++++++++++++++++- .../auxcontrol/DeviceWorkDataMapper.xml | 4 +- 5 files changed, 262 insertions(+), 9 deletions(-) diff --git a/riis-system/src/main/java/com/yfd/platform/modules/algorithm/controller/AlgorithmDeviceController.java b/riis-system/src/main/java/com/yfd/platform/modules/algorithm/controller/AlgorithmDeviceController.java index e437207..a759e81 100644 --- a/riis-system/src/main/java/com/yfd/platform/modules/algorithm/controller/AlgorithmDeviceController.java +++ b/riis-system/src/main/java/com/yfd/platform/modules/algorithm/controller/AlgorithmDeviceController.java @@ -1,5 +1,6 @@ package com.yfd.platform.modules.algorithm.controller; +import cn.hutool.core.util.StrUtil; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.modules.algorithm.domain.AlgorithmClass; import com.yfd.platform.modules.algorithm.domain.AlgorithmDevice; @@ -53,9 +54,10 @@ public class AlgorithmDeviceController { @PostMapping("/getAlgorithmDeviceCurve") @ApiOperation("查询算法部件的参数曲线") - public ResponseResult getAlgorithmDeviceCurve(String algorithmId, String componentId) { + public ResponseResult getAlgorithmDeviceCurve(String algorithmId, String componentId,String type) { + type = StrUtil.isBlank(type) ? "1" : type; List> algorithmDeviceCurveList = algorithmDeviceService.getAlgorithmDeviceCurve(algorithmId, - componentId); + componentId,type); return ResponseResult.successData(algorithmDeviceCurveList); } } diff --git a/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/IAlgorithmDeviceService.java b/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/IAlgorithmDeviceService.java index dd1ce58..e627da6 100644 --- a/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/IAlgorithmDeviceService.java +++ b/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/IAlgorithmDeviceService.java @@ -37,6 +37,6 @@ public interface IAlgorithmDeviceService extends IService { * 参数说明 componentId 部件id * 返回值说明: java.util.List> ***********************************/ - List> getAlgorithmDeviceCurve(String algorithmId, String componentId); + List> getAlgorithmDeviceCurve(String algorithmId, String componentId,String type); } diff --git a/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/impl/AlgorithmDeviceServiceImpl.java b/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/impl/AlgorithmDeviceServiceImpl.java index 4179fc3..98b4129 100644 --- a/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/impl/AlgorithmDeviceServiceImpl.java +++ b/riis-system/src/main/java/com/yfd/platform/modules/algorithm/service/impl/AlgorithmDeviceServiceImpl.java @@ -10,6 +10,7 @@ import com.yfd.platform.modules.algorithm.service.IAlgorithmDeviceService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.modules.auxcontrol.domain.DeviceSignal; import com.yfd.platform.modules.auxcontrol.domain.DeviceWorkData; +import com.yfd.platform.modules.auxcontrol.domain.TimeConfig; import com.yfd.platform.modules.auxcontrol.mapper.DeviceSignalMapper; import com.yfd.platform.modules.auxcontrol.service.IDeviceWorkDataService; import com.yfd.platform.modules.basedata.domain.SubstationDevice; @@ -83,7 +84,7 @@ public class AlgorithmDeviceServiceImpl extends ServiceImpl> ***********************************/ @Override - public List> getAlgorithmDeviceCurve(String algorithmId, String componentId) { + public List> getAlgorithmDeviceCurve(String algorithmId, String componentId,String type) { List> list = algorithmDeviceMapper.getAlgorithmDeviceType(algorithmId, componentId); Map> groupedDevices = list.stream() .filter(map -> map.containsKey("sourceType") && map.get("sourceType") != null) @@ -115,7 +116,8 @@ public class AlgorithmDeviceServiceImpl extends ServiceImpl deviceWorkDataGroup = collect.getOrDefault(signalId, Collections.emptyList()); - Map map = processSignalData(deviceWorkDataGroup, signalId); +// Map map = processSignalData(deviceWorkDataGroup, signalId); + Map map = processDeviceData(deviceWorkDataGroup, signalId,type); deviceDataList.add(map); } @@ -124,6 +126,106 @@ public class AlgorithmDeviceServiceImpl extends ServiceImpl processDeviceData(List deviceWorkDataList, String signalId, + String type) { + // 根据类型生成时间槽和配置参数 + TimeConfig config = generateTimeConfig(type); + + // 按时间单位分组数据 + Map timeDataMap = groupDataByTimeUnit(deviceWorkDataList, config.getTruncateUnit()); + + // 构建xAxis和series数据 + List xAxisData = new ArrayList<>(); + List seriesData = new ArrayList<>(); + for (LocalDateTime slot : config.getTimeSlots()) { + xAxisData.add(slot.format(config.getFormatter())); + String value = timeDataMap.getOrDefault(slot, "0"); + seriesData.add(NumberUtil.parseDouble(NumberUtil.isNumber(value) ? value : "0")); + } + + // 构建ECharts数据结构 + return buildEChartsResult(xAxisData, seriesData, signalId); + } + + /** + * 按时间单位分组数据 + */ + private Map groupDataByTimeUnit(List dataList, ChronoUnit unit) { + Map map = new HashMap<>(); + for (DeviceWorkData data : dataList) { + LocalDateTime key = data.getStartTime().truncatedTo(unit); + map.put(key, data.getValue()); + } + return map; + } + + /** + * 构建ECharts结果 + */ + private Map buildEChartsResult(List xAxisData, List seriesData, String signalId) { + Map result = new HashMap<>(); + + // xAxis配置 + Map xAxis = new HashMap<>(); + xAxis.put("type", "category"); + xAxis.put("data", xAxisData); + result.put("xAxis", xAxis); + + // yAxis配置 + Map yAxis = new HashMap<>(); + yAxis.put("type", "value"); + result.put("yAxis", yAxis); + + // 系列数据配置 + DeviceSignal deviceSignal = deviceSignalMapper.selectById(signalId); + String seriesName = deviceSignal != null ? deviceSignal.getSignalName() : ""; + + List> seriesList = new ArrayList<>(); + Map series = new HashMap<>(); + series.put("name", seriesName); + series.put("type", "line"); + series.put("step", "start"); + series.put("data", seriesData); + seriesList.add(series); + + result.put("series", seriesList); + + return result; + } + + /** + * 生成时间配置 + */ + private TimeConfig generateTimeConfig(String type) { + List timeSlots = new ArrayList<>(); + DateTimeFormatter formatter; + ChronoUnit truncateUnit; + + if ("2".equals(type)) { + // 类型2:过去24小时(每小时一个点) + LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS); + LocalDateTime startTime = now.minusHours(23); + for (int i = 0; i < 24; i++) { + timeSlots.add(startTime.plusHours(i)); + } + formatter = DateTimeFormatter.ofPattern("HH时"); + truncateUnit = ChronoUnit.HOURS; + } else { + // 默认类型1:过去60分钟(每分钟一个点) + LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES); + LocalDateTime startTime = now.minusMinutes(59); + for (int i = 0; i < 60; i++) { + timeSlots.add(startTime.plusMinutes(i)); + } + formatter = DateTimeFormatter.ofPattern("HH时mm分"); + truncateUnit = ChronoUnit.MINUTES; + } + + return new TimeConfig(timeSlots, formatter, truncateUnit); + } + + /********************************** * 用途说明: 绘制信号ECharts折线图 * 参数说明 deviceWorkDataList 信号数据 diff --git a/riis-system/src/main/java/com/yfd/platform/modules/patroltask/controller/AlarmLogController.java b/riis-system/src/main/java/com/yfd/platform/modules/patroltask/controller/AlarmLogController.java index 79596ef..83053cb 100644 --- a/riis-system/src/main/java/com/yfd/platform/modules/patroltask/controller/AlarmLogController.java +++ b/riis-system/src/main/java/com/yfd/platform/modules/patroltask/controller/AlarmLogController.java @@ -2,15 +2,18 @@ package com.yfd.platform.modules.patroltask.controller; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.beanit.iec61850bean.BdaBoolean; -import com.beanit.iec61850bean.BdaTimestamp; import com.yfd.platform.component.WebSocketServer; +import com.yfd.platform.component.iec104.common.BasicInstruction104; +import com.yfd.platform.component.iec104.server.master.BootNettyClientChannel; +import com.yfd.platform.component.iec104.server.master.BootNettyClientChannelCache; +import com.yfd.platform.component.utils.OptimizedThreadPool; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.modules.auxcontrol.domain.AnalogData; import com.yfd.platform.modules.auxcontrol.mapper.DeviceSignalMapper; @@ -26,12 +29,19 @@ import com.yfd.platform.modules.patroltask.service.ITaskTodoService; import com.yfd.platform.utils.SecurityUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.apache.poi.ss.usermodel.*; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.io.FileInputStream; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -67,6 +77,8 @@ public class AlarmLogController { @Resource private TaskResultMapper taskResultMapper; + public static Map status = new ConcurrentHashMap<>(); + @GetMapping("/getAlarmLogList") @ApiOperation("查询报警信息") public ResponseResult getAlarmLogList(String stationId) { @@ -334,4 +346,141 @@ public class AlarmLogController { return ResponseResult.success(); } + @PostMapping("/sendExcelData") + @ApiOperation("批量发送excel数据") + public ResponseResult sendExcelData(String fileName) throws Exception { + boolean sendExcelData = status.containsKey("sendExcelData"); + if (sendExcelData) { + return ResponseResult.error("当前发送数据进程还没结束"); + } + status.put("sendExcelData", "1"); + ExecutorService executorService = Executors.newFixedThreadPool(1); + executorService.submit(()->{ + try { + processExcelWithSending("D:\\riis\\video\\excel\\" + fileName); + } catch (Exception e) { + e.printStackTrace(); + } + }); + executorService.shutdown(); + return ResponseResult.success(); + } + + public void processExcelWithSending(String filePath) throws Exception { + try (FileInputStream file = new FileInputStream(filePath); + Workbook workbook = WorkbookFactory.create(file)) { + + Sheet sheet = workbook.getSheetAt(1); + Row headerRow = sheet.getRow(1); // 英文注释行 + + // 获取列名映射(列索引 -> 英文列名) + Map columnNames = getColumnNames(headerRow); + + // 从数据行开始遍历(第三行) + for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) { + Row dataRow = sheet.getRow(rowIndex); + if (dataRow == null) { + continue; + } + + Map payload = buildPayload(columnNames, dataRow); + + System.out.println(payload.toString()); + if (!payload.isEmpty()) { + for (String address : payload.keySet()) { + String value = payload.get(address); + // 发送数据 + //更新信号数据值 + deviceSignalMapper.updateDeviceSignalValue_yc(address, value, getCurrentTime()); + //插入历史数据 + deviceWorkDataService.insertData("IEC61850", null, address, value, getCurrentTime()); + //执行报警处理 + alarmLogService.doAlaramRecord("IEC61850", "yc", null, address, value); + } + // 等待5秒 + waitForNextRequest(); + } + } + } + status.remove("sendExcelData"); + } + + // 获取列名映射(列索引 -> 英文列名) + private static Map getColumnNames(Row headerRow) { + Map map = new LinkedHashMap<>(); + if (headerRow != null) { + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell cell = headerRow.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + String trimName = cell.toString().trim(); + if (StrUtil.isNotBlank(trimName)) { + map.put(i, trimName); + } + + } + } + return map; + } + + // 构建请求负载 + private static Map buildPayload(Map columnNames, Row dataRow) { + Map payload = new LinkedHashMap<>(); + + columnNames.forEach((colIndex, colName) -> { + Cell cell = dataRow.getCell(colIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + Object parseCellValue = parseCellValue(cell); + String value = parseCellValue == null ? "0" : parseCellValue.toString(); + payload.put(colName, value); + + }); + + return payload; + } + + private static Object parseCellValue(Cell cell) { + // 获取公式计算器(需要从Workbook获取) + FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator(); + + switch (cell.getCellType()) { + case STRING: + return cell.getStringCellValue().trim(); + case NUMERIC: + return org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell) ? + cell.getLocalDateTimeCellValue() : + cell.getNumericCellValue(); + case BOOLEAN: + return cell.getBooleanCellValue(); + case FORMULA: { + // 计算公式的实际值 + CellValue cellValue = evaluator.evaluate(cell); + return convertCellValue(cellValue); + } + default: + return null; + } + } + + // 转换计算结果类型的方法 + private static Object convertCellValue(CellValue cellValue) { + switch (cellValue.getCellType()) { + case NUMERIC: + return cellValue.getNumberValue(); + case STRING: + return cellValue.getStringValue(); + case BOOLEAN: + return cellValue.getBooleanValue(); + default: + return null; + } + } + + // 等待间隔 + private static void waitForNextRequest() { + try { + TimeUnit.SECONDS.sleep(60); // 5秒间隔 + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Data sending interrupted", e); + } + } + } diff --git a/riis-system/src/main/resources/mapper/auxcontrol/DeviceWorkDataMapper.xml b/riis-system/src/main/resources/mapper/auxcontrol/DeviceWorkDataMapper.xml index 23928f2..39bb521 100644 --- a/riis-system/src/main/resources/mapper/auxcontrol/DeviceWorkDataMapper.xml +++ b/riis-system/src/main/resources/mapper/auxcontrol/DeviceWorkDataMapper.xml @@ -40,7 +40,7 @@ signal_id=#{signalId} AND start_time >= NOW() - INTERVAL 1 HOUR ORDER BY - start_time DESC + start_time @@ -110,6 +110,6 @@ AND start_time >= NOW() - INTERVAL 1 HOUR ORDER BY - start_time DESC + start_time