package com.se.nsl.service; import com.fasterxml.jackson.databind.ObjectMapper; 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.vo.ConfigVo; import com.se.nsl.domain.vo.RealTimeSimuParam; import com.se.nsl.domain.vo.ResultVo; import com.se.nsl.utils.TimeFormatUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.*; import java.nio.file.Files; 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; @Slf4j @Service public class RealTimeSimulationService { public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; @Resource PropertiesConfig config; @Resource TestService testService; private ObjectMapper mapper = new ObjectMapper(); public String realTimeSimulate(RealTimeSimuParam input) throws IOException { // List deviceIds = input.getDeviceIds(); InputStream stream = RealTimeSimulationService.class.getResourceAsStream("/a_test_device_info.json"); List 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); //生成一个新的生成zarr的配置文件 ConfigVo configVo = generateNewZarrConfigFile(serviceNameDir, serviceName, currentTime, newDatFile); File newConfigFile = new File(serviceNameDir, serviceName + ".json"); mapper.writeValue(newConfigFile, configVo); //执行求解器运算 String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), newConfigFile); callBat2(cmd); //生成一个新的zarr转tif的json文件 ResultVo result = configVo.getResult(); Integer fromFrame = result.getLastFrames(); Integer toFrame = result.getSave_frames() - 1; File newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime, fromFrame, toFrame); //执行zarr转tif String zarr2TifCmd = String.format("%s \"%s\"", config.getZarr2tifBat(), newZarr2TifJson); callBat2(zarr2TifCmd); //返回新的layer.json名称 return generateLayerJsonAndPng(serviceName, serviceNameDir, currentTime); } 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"); resultDto.setTerrainFile(dem.getAbsolutePath()); File 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.setName(newLayerJsonName); testService.processRealTime(resultDto, layerDto); 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"; zarr2Tif.setZarr_file(newZarrPath); zarr2Tif.setGeotiff_dir(serviceNameDir + File.separator + "depth_" + currentTime); File newZarr2TifJson = new File(serviceNameDir, "zarr2tif_" + currentTime + ".json"); mapper.writeValue(newZarr2TifJson, zarr2Tif); return newZarr2TifJson; } private ConfigVo generateNewZarrConfigFile(File serviceNameDir, String serviceName, long currentTime, File newDatFile) throws IOException { File configFile = new File(serviceNameDir, serviceName + ".json"); ConfigVo configVo = mapper.readValue(configFile, ConfigVo.class); File stationFile = new File(serviceNameDir, "Station.tif"); if (stationFile.exists()) { configVo.setStation(stationFile.getAbsolutePath()); } int realTimeSimulateTime = 300; //模拟时间,默认为5min,即300s int realTimeInterval = 60; //每帧的间隔时间,默认为60s,60s生成一帧 configVo.getRaingage().set(0, newDatFile.getAbsolutePath()); //raingage file ResultVo result = configVo.getResult(); Integer lastFrames = result.getLastFrames(); if (lastFrames == null) { lastFrames = 0; } Integer saveStart = result.getSave_start(); Integer saveInterval = result.getSave_interval(); Integer saveFrames = result.getSave_frames(); Integer 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 deviceInfos, File serviceNameDir, long currentTime) throws IOException { String title = config.getRainfallTitle(); List 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)); 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(); Files.write(newDatFile.toPath(), newLines, StandardOpenOption.TRUNCATE_EXISTING); 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 static String[] readTheOldFirstLineRainfallValue(File serviceNameDir) throws IOException { File srcRailfallFile = new File(serviceNameDir, "rainfall.dat"); List lines = Files.readAllLines(srcRailfallFile.toPath()); String secondLine = lines.get(1); return secondLine.split(" "); } private String callBat2(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(); } catch (Exception ex) { log.error(ex.getMessage(), ex); return null; } } }