From 043d1bd4860bbee636b3935e94a71246091cbf3f Mon Sep 17 00:00:00 2001 From: dcb <xgybdcb@163.com> Date: 星期二, 24 六月 2025 15:29:24 +0800 Subject: [PATCH] 实时模拟功能实现 --- src/main/java/com/se/nsl/service/RealTimeSimulationService.java | 284 ++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 193 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/se/nsl/service/RealTimeSimulationService.java b/src/main/java/com/se/nsl/service/RealTimeSimulationService.java index a6b3bc7..c835224 100644 --- a/src/main/java/com/se/nsl/service/RealTimeSimulationService.java +++ b/src/main/java/com/se/nsl/service/RealTimeSimulationService.java @@ -1,16 +1,21 @@ package com.se.nsl.service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.se.nsl.config.GaugeServer; import com.se.nsl.config.PropertiesConfig; -import com.se.nsl.domain.dto.DeviceInfo; -import com.se.nsl.domain.dto.LayerDto; -import com.se.nsl.domain.dto.ResultDto; -import com.se.nsl.domain.dto.Zarr2Tif; +import com.se.nsl.domain.dto.*; +import com.se.nsl.domain.po.RainGauge; +import com.se.nsl.domain.po.Simu; +import com.se.nsl.domain.po.SimuData; import com.se.nsl.domain.vo.ConfigVo; -import com.se.nsl.domain.vo.RealTimeSimuParam; import com.se.nsl.domain.vo.ResultVo; +import com.se.nsl.mapper.SimuMapper; +import com.se.nsl.utils.HttpRequestUtil; import com.se.nsl.utils.TimeFormatUtil; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -19,89 +24,187 @@ import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; @Slf4j @Service public class RealTimeSimulationService { public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + public static final String JSON_EXT = ".json"; + public static final String DEM_TIF = "DEM.tif"; + public static final String RESULT_ZARR = "result.zarr"; @Resource PropertiesConfig config; @Resource TestService testService; + @Resource + ResolveService resolveService; + @Resource + SimuMapper simuMapper; - private ObjectMapper mapper = new ObjectMapper(); + private final ObjectMapper mapper = new ObjectMapper(); + @Resource + private GaugeServer gaugeServer; + private static final long MILLIS_OF_ONE_DAY = 86400000; - public String realTimeSimulate(RealTimeSimuParam input) throws IOException { -// List<String> deviceIds = input.getDeviceIds(); - InputStream stream = RealTimeSimulationService.class.getResourceAsStream("/a_test_device_info.json"); + public String realTimeSimulate(Simu simu) throws IOException { + InputStream stream = RealTimeSimulationService.class.getResourceAsStream("/device_info.json"); List<DeviceInfo> deviceInfos = mapper.readValue(stream, mapper.getTypeFactory().constructCollectionType(List.class, DeviceInfo.class)); - String startTime = input.getStartTime(); - long currentTime = TimeFormatUtil.toMillis(startTime, YYYY_MM_DD_HH_MM_SS); - //鏍规嵁鏈嶅姟鎵惧埌鎸囧畾鐨勬枃浠跺す - String serviceName = input.getServiceName(); - File serviceNameDir = new File(config.getInPath(), serviceName); - //鏍规嵁闆ㄩ噺璁¤鍙栦綑閲忔暟鎹� - File newDatFile = generateNewRainfallFile(deviceInfos, serviceNameDir, currentTime); + String serviceName = simu.getServiceName(); + long currentTime = getCurrentTime(); + if (serviceName == null) { //娌℃湁杩涜杩囨ā鎷熻绠� + serviceName = TimeFormatUtil.formatTime(currentTime, "yyyyMMddHHmmss"); + simu.setServiceName(serviceName); + File serviceNameDir = new File(config.getInPath(), serviceName); + serviceNameDir.mkdir(); + String layerJsonName = executeSimulateTask(simu, deviceInfos, serviceNameDir, currentTime, serviceName, true); + simuMapper.updates(Collections.singletonList(simu)); + return layerJsonName; + } else { + File serviceNameDir = new File(config.getInPath(), serviceName); + return executeSimulateTask(simu, deviceInfos, serviceNameDir, currentTime, serviceName ,false); + } + } + private long getCurrentTime() { + double offsetDays = gaugeServer.getOffsetDays(); + long millis = (long) (offsetDays * MILLIS_OF_ONE_DAY); + return System.currentTimeMillis() - millis; + } + + private String executeSimulateTask(Simu simu, List<DeviceInfo> deviceInfos, File serviceNameDir, + long currentTime, String serviceName, boolean firstTime) throws IOException { + SimuData simuData = mapper.readValue(simu.getData(), SimuData.class); + simuData.setOutPath(serviceName); + simuData.setInPath(serviceName); + List<RainGauge> gauges = simuData.getGauges(); //闆ㄩ噺璁′俊鎭� + if (firstTime) { + resolveService.initArgs(simu, simuData); + } + //鏍规嵁闆ㄩ噺璁¤鍙栦綑閲忔暟鎹� + File newDatFile = generateNewRainfallFile(gauges, deviceInfos, serviceNameDir, currentTime); //鐢熸垚涓�涓柊鐨勭敓鎴恴arr鐨勯厤缃枃浠� - ConfigVo configVo = generateNewZarrConfigFile(serviceNameDir, serviceName, currentTime, newDatFile); - File newConfigFile = new File(serviceNameDir, serviceName + ".json"); + ConfigVo configVo; + if (firstTime) { + configVo = firstTimeZarrConfigFile(serviceNameDir, currentTime, newDatFile); + } else { + configVo = generateNewZarrConfigFile(serviceNameDir, serviceName, currentTime, newDatFile); + } + File newConfigFile = new File(serviceNameDir, serviceName + JSON_EXT); mapper.writeValue(newConfigFile, configVo); //鎵ц姹傝В鍣ㄨ繍绠� String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), newConfigFile); - callBat2(cmd); + callBat(cmd); - //鐢熸垚涓�涓柊鐨剒arr杞瑃if鐨刯son鏂囦欢 - ResultVo result = configVo.getResult(); - Integer fromFrame = result.getLastFrames(); - Integer toFrame = result.getSave_frames() - 1; - File newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime, fromFrame, toFrame); + File newZarr2TifJson; + if (firstTime) { + newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime, Collections.emptyList()); + } else { + //鐢熸垚涓�涓柊鐨剒arr杞瑃if鐨刯son鏂囦欢 + ResultVo result = configVo.getResult(); + Integer fromFrame = result.getLastFrames(); + Integer toFrame = result.getSave_frames() - 1; + newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime, Arrays.asList(fromFrame, toFrame)); + } //鎵цzarr杞瑃if String zarr2TifCmd = String.format("%s \"%s\"", config.getZarr2tifBat(), newZarr2TifJson); - callBat2(zarr2TifCmd); + callBat(zarr2TifCmd); //杩斿洖鏂扮殑layer.json鍚嶇О - return generateLayerJsonAndPng(serviceName, serviceNameDir, currentTime); + if (firstTime) { + return generateLayerJsonAndPng(serviceName, serviceNameDir, -1); + } else { + return generateLayerJsonAndPng(serviceName, serviceNameDir, currentTime); + } } - private String generateLayerJsonAndPng(String serviceName, File serviceNameDir, long currentTime) throws IOException { + private String generateLayerJsonAndPng(String serviceName, File serviceNameDir, + long currentTime) throws IOException { ResultDto resultDto = new ResultDto(); resultDto.setServiceName(serviceName); File temp = Paths.get(config.getOutPath(), serviceName, "temp").toFile(); - if (!temp.exists()) temp.mkdir(); resultDto.setTemp(temp.getAbsolutePath()); resultDto.setOutPath(Paths.get(config.getOutPath(), serviceName).toString()); - File dem = new File(serviceNameDir, "DEM.tif"); + File dem = new File(serviceNameDir, DEM_TIF); resultDto.setTerrainFile(dem.getAbsolutePath()); - File newDepthDir = new File(serviceNameDir + File.separator + "depth_" + currentTime); + File newDepthDir; + if (currentTime < 0) { + newDepthDir = new File(serviceNameDir + File.separator + "depth"); + } else { + newDepthDir = new File(serviceNameDir + File.separator + "depth_" + currentTime); + } resultDto.setWaterPath(newDepthDir.getAbsolutePath()); - LayerDto layerDto = new LayerDto(config.getVer(), 4548, config.getSizes()); - String newLayerJsonName = "layer_" + currentTime + ".json"; + LayerDto layerDto = new LayerDto(config.getVer(), config.getEpsg(), config.getSizes()); + String newLayerJsonName; + if (currentTime < 0) { + newLayerJsonName = "layer.json"; + } else { + newLayerJsonName = "layer_" + currentTime + JSON_EXT; + } layerDto.setName(newLayerJsonName); testService.processRealTime(resultDto, layerDto); + log.info("瀹炴椂妯℃嫙瀹屾垚"); return newLayerJsonName; } - private File generateNewZarr2TifJson(File serviceNameDir, long currentTime, int fromFrame, int toFrame) throws IOException { - File srcZarr2TifJson = new File(serviceNameDir, "zarr2tif.json"); - Zarr2Tif zarr2Tif = mapper.readValue(srcZarr2TifJson, Zarr2Tif.class); - //淇敼zarr2tif瀵硅薄涓殑瀛楁 - zarr2Tif.setRange(Arrays.asList(fromFrame ,toFrame)); - String newZarrPath = serviceNameDir + File.separator + "result.zarr"; + private File generateNewZarr2TifJson(File serviceNameDir, long currentTime, List<Object> range) throws IOException { + Zarr2Tif zarr2Tif; + File newZarr2TifJson; + String newZarrPath; + String geotiffDir; + if (range.isEmpty()) { + zarr2Tif = new Zarr2Tif(); + newZarrPath = serviceNameDir + File.separator + RESULT_ZARR; + geotiffDir = serviceNameDir + File.separator + "depth"; + zarr2Tif.setTerrain_file(serviceNameDir + File.separator + DEM_TIF); + newZarr2TifJson = new File(serviceNameDir, "zarr2tif.json"); + } else { + File srcZarr2TifJson = new File(serviceNameDir, "zarr2tif.json"); + zarr2Tif = mapper.readValue(srcZarr2TifJson, Zarr2Tif.class); + //淇敼zarr2tif瀵硅薄涓殑瀛楁 + newZarrPath = serviceNameDir + File.separator + RESULT_ZARR; + geotiffDir = serviceNameDir + File.separator + "depth_" + currentTime; + newZarr2TifJson = new File(serviceNameDir, "zarr2tif_" + currentTime + JSON_EXT); + } + zarr2Tif.setGeotiff_dir(geotiffDir); zarr2Tif.setZarr_file(newZarrPath); - zarr2Tif.setGeotiff_dir(serviceNameDir + File.separator + "depth_" + currentTime); - File newZarr2TifJson = new File(serviceNameDir, "zarr2tif_" + currentTime + ".json"); + zarr2Tif.setRange(range); mapper.writeValue(newZarr2TifJson, zarr2Tif); return newZarr2TifJson; } + private ConfigVo firstTimeZarrConfigFile(File serviceNameDir, long currentTime, File newDatFile) { + ConfigVo configVo = new ConfigVo(); + String serviceNameDirPath = serviceNameDir.getAbsolutePath(); + configVo.setTerrain(serviceNameDirPath + File.separator + DEM_TIF); + configVo.setLanduse(serviceNameDirPath + File.separator + "Landuse.tif"); + File stationFile = new File(serviceNameDir, "Station.tif"); + if (stationFile.exists()) { + configVo.setStation(stationFile.getAbsolutePath()); + } + int realTimeSimulateTime = 300; //妯℃嫙鏃堕棿锛岄粯璁や负5min锛屽嵆300s + int realTimeInterval = 60; //姣忓抚鐨勯棿闅旀椂闂达紝榛樿涓�60s,60s鐢熸垚涓�甯� + List<String> rainGauge = new ArrayList<>(); + rainGauge.add(newDatFile.getAbsolutePath());//raingage file + rainGauge.add("mm/min"); + configVo.setRaingage(rainGauge); + String saveName = serviceNameDir + File.separator + RESULT_ZARR; + ResultVo result = new ResultVo(saveName, realTimeSimulateTime / realTimeInterval, + realTimeInterval,"continue", null); + result.setSave_interval(realTimeInterval); + result.setSave_timestamp0(TimeFormatUtil.formatTime(currentTime, YYYY_MM_DD_HH_MM_SS)); + configVo.setDuration(realTimeSimulateTime); + result.setSave_name(saveName); + result.setSave_filter(config.getSaveFilter()); + configVo.setResult(result); + return configVo; + } + private ConfigVo generateNewZarrConfigFile(File serviceNameDir, String serviceName, long currentTime, File newDatFile) throws IOException { - File configFile = new File(serviceNameDir, serviceName + ".json"); + File configFile = new File(serviceNameDir, serviceName + JSON_EXT); ConfigVo configVo = mapper.readValue(configFile, ConfigVo.class); File stationFile = new File(serviceNameDir, "Station.tif"); if (stationFile.exists()) { @@ -118,49 +221,27 @@ Integer saveStart = result.getSave_start(); Integer saveInterval = result.getSave_interval(); Integer saveFrames = result.getSave_frames(); - Integer newStartPoint = saveStart + (saveFrames - lastFrames) * saveInterval; + int newStartPoint = saveStart + (saveFrames - lastFrames) * saveInterval; int newSaveFrames = saveFrames + (realTimeSimulateTime / realTimeInterval); result.setSave_start(newStartPoint); //璧峰鏃堕棿瑕佸湪涓婃鏃堕棿鐨勫熀纭�涓婂紑濮� - result.setSave_interval(realTimeInterval); result.setLastFrames(saveFrames); result.setSave_frames(newSaveFrames); //淇濈暀5甯э紝鍦ㄥ師鏉ョ殑鍩虹涓婂鍔�5甯� - result.setSave_mode("continue"); result.setSave_timestamp0(TimeFormatUtil.formatTime(currentTime, YYYY_MM_DD_HH_MM_SS)); configVo.setDuration(newStartPoint + realTimeSimulateTime); - String newZarrPath = serviceNameDir + File.separator + "result.zarr"; - result.setSave_name(newZarrPath); return configVo; } - private File generateNewRainfallFile(List<DeviceInfo> deviceInfos, + private File generateNewRainfallFile(List<RainGauge> gauges, List<DeviceInfo> deviceInfos, File serviceNameDir, long currentTime) throws IOException { String title = config.getRainfallTitle(); List<String> newLines = new ArrayList<>(); newLines.add(title); - for (DeviceInfo deviceInfo : deviceInfos) { - int stationId = deviceInfo.getMappingId(); - double lon = deviceInfo.getX(); - double lat = deviceInfo.getY(); - LocalDateTime dateTime = TimeFormatUtil.toDate(currentTime); - int year = dateTime.getYear(); - int month = dateTime.getMonthValue(); - int day = dateTime.getDayOfMonth(); - int hour = dateTime.getHour(); - int minute = dateTime.getMinute(); - double intensity = randomIntensity(); //淇濈暀鎸囧畾浣嶆暟灏忔暟 - String l = String.format("%s %s %s %s %s %s %s %s %s", - stationId, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity)); + Map<String, Integer> deviceInfoMap = deviceInfos.stream().collect(Collectors.toMap(DeviceInfo::getId, DeviceInfo::getMappingId)); + for (RainGauge gauge : gauges) { + String id = gauge.getId(); + Integer mappingId = deviceInfoMap.getOrDefault(id, 0); + String l = getRainGaugeResult(gauge, mappingId, currentTime); newLines.add(l); - LocalDateTime dateTime1 = dateTime.plusMinutes(5); - year = dateTime1.getYear(); - month = dateTime1.getMonthValue(); - day = dateTime1.getDayOfMonth(); - hour = dateTime1.getHour(); - minute = dateTime1.getMinute(); - intensity = randomIntensity(); - String l2 = String.format("%s %s %s %s %s %s %s %s %s", - stationId, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity)); - newLines.add(l2); } File newDatFile = new File(serviceNameDir, "rainfall_" + currentTime + ".dat"); if (!newDatFile.exists()) newDatFile.createNewFile(); @@ -168,39 +249,60 @@ return newDatFile; } - private double randomIntensity() { - Random random = new Random(); - // 鐢熸垚0.2鍒�1涔嬮棿鐨勯殢鏈烘暟 - double min = 0.2; - double max = 1.0; - return min + random.nextDouble() * (max - min); + private String getRainGaugeResult(RainGauge gauge,int stationId, long currentTime) throws JsonProcessingException { + double lon = gauge.getX(); + double lat = gauge.getY(); + LocalDateTime dateTime = TimeFormatUtil.toDate(currentTime); + int year = dateTime.getYear(); + int month = dateTime.getMonthValue(); + int day = dateTime.getDayOfMonth(); + int hour = dateTime.getHour(); + int minute = dateTime.getMinute(); + String id = gauge.getId(); + long someMinutesAgo = currentTime - TimeUnit.MINUTES.toMillis(gaugeServer.getRequestOffsetMinutes()); + String startTime = TimeFormatUtil.formatTime(someMinutesAgo, YYYY_MM_DD_HH_MM_SS); + String endTime = TimeFormatUtil.formatTime(currentTime, YYYY_MM_DD_HH_MM_SS); + double intensity = getIntensityByDeviceId(id, startTime, endTime); //淇濈暀鎸囧畾浣嶆暟灏忔暟 + return String.format("%s %s %s %s %s %s %s %s %s", + stationId, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity)); } - private static String[] readTheOldFirstLineRainfallValue(File serviceNameDir) throws IOException { - File srcRailfallFile = new File(serviceNameDir, "rainfall.dat"); - List<String> lines = Files.readAllLines(srcRailfallFile.toPath()); - String secondLine = lines.get(1); - return secondLine.split(" "); + //鏍规嵁闆ㄩ噺璁℃爣璇嗘煡璇㈤洦閲忔暟鎹� + private double getIntensityByDeviceId(String deviceId, String startTime, String endTime) throws JsonProcessingException { + RemoteGaugeInput input = new RemoteGaugeInput(); + input.setCurrentPage(1); + input.setPageSize(2); + RemoteGaugeInput.FilterObject filterObject = new RemoteGaugeInput.FilterObject(); + filterObject.setDeviceCode(deviceId); + filterObject.setSendTimeList(Arrays.asList(startTime, endTime)); + input.setFilterObject(filterObject); + String url = gaugeServer.getUrl(); + String token = gaugeServer.getToken(); + ResponseEntity<String> post = HttpRequestUtil.post(url, input, String.class, token); + String body = post.getBody(); + JsonNode jsonNode = mapper.readTree(body); + JsonNode pageData = jsonNode.get("data").get("pageData"); + if (!pageData.isEmpty()) { + return pageData.get(0).get("value").asDouble(); + } + return 0; } - private String callBat2(String cmd) { + + private String callBat(String cmd) { try { ProcessBuilder pb = new ProcessBuilder("cmd", "/c", cmd); pb.redirectErrorStream(true); // 鍚堝苟閿欒娴佸埌鏍囧噯杈撳嚭 - Process process = pb.start(); process.getOutputStream().close(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"))) { String line; while ((line = reader.readLine()) != null) { log.info(line); } } - int exitCode = process.waitFor(); - - return "ok"; // sb.toString(); + return "" + exitCode; // sb.toString(); } catch (Exception ex) { log.error(ex.getMessage(), ex); return null; -- Gitblit v1.9.3