dcb
2025-06-18 4c4d0f591f94428ed7e5d2f4ae5df5c5087d8c26
求解器版本升级到2.2
已添加5个文件
已修改7个文件
697 ■■■■■ 文件已修改
src/main/java/com/se/nsl/controller/SimuController.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/dto/DeviceInfo.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/dto/Zarr2Tif.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/vo/ConfigVo.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/vo/RealTimeSimuParam.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/vo/ResultVo.java 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/RealTimeSimulationService.java 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/ResolveService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/utils/HttpRequestUtil.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/utils/TimeFormatUtil.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/a_test_device_info.json 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/controller/SimuController.java
@@ -5,10 +5,8 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.se.nsl.domain.po.Simu;
import com.se.nsl.domain.po.SimuData;
import com.se.nsl.domain.vo.R;
import com.se.nsl.domain.vo.RealTimeInput;
import com.se.nsl.domain.vo.SimuResult;
import com.se.nsl.domain.vo.SimuVo;
import com.se.nsl.domain.vo.*;
import com.se.nsl.service.RealTimeSimulationService;
import com.se.nsl.service.ResolveService;
import com.se.nsl.service.SimuService;
import io.swagger.annotations.Api;
@@ -39,6 +37,9 @@
    @Resource
    ResolveService resolveService;
    @Resource
    RealTimeSimulationService rts;
    /**
     * åˆ†é¡µæŸ¥è¯¢æŽ¨æ¼”模拟
@@ -223,4 +224,16 @@
            return fail("实时模拟异常");
        }
    }
    @ApiOperation(value = "realTime")
    @PostMapping("/realTime2")
    public R<Object> realTimeSimulate(@RequestBody RealTimeSimuParam param) {
        try {
            String layerJsonName = rts.realTimeSimulate(param);
            return success(layerJsonName);
        } catch (IOException e) {
            log.error("real-time simulate exception:", e);
            return fail("实时模拟异常");
        }
    }
}
src/main/java/com/se/nsl/domain/dto/DeviceInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.se.nsl.domain.dto;
public class DeviceInfo {
    private String id;
    private String name;
    private double x; //经度
    private double y; //维度
    private double r;
    private int mappingId;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getX() {
        return x;
    }
    public void setX(double x) {
        this.x = x;
    }
    public double getY() {
        return y;
    }
    public void setY(double y) {
        this.y = y;
    }
    public double getR() {
        return r;
    }
    public void setR(double r) {
        this.r = r;
    }
    public int getMappingId() {
        return mappingId;
    }
    public void setMappingId(int mappingId) {
        this.mappingId = mappingId;
    }
}
src/main/java/com/se/nsl/domain/dto/Zarr2Tif.java
@@ -17,9 +17,11 @@
    private String terrain_file;
    private String start_timestamp;
//    private String start_timestamp;
    private List<Integer> frame_range;
//    private List<Integer> frame_range;
    private List<Object> range;
    private boolean fliplr;
@@ -27,23 +29,32 @@
    public Zarr2Tif() {
        variables = new ArrayList<>(Arrays.asList("depth", "xmomentum", "ymomentum"));
        frame_range = null;
//        frame_range = null;
        fliplr = false;
        flipud = false;
    }
    public Zarr2Tif(String zarrFile, String geotiffDir, String terrainFile, String startTimestamp) {
//    public Zarr2Tif(String zarrFile, String geotiffDir, String terrainFile, String startTimestamp) {
//        this();
//
//        this.zarr_file = zarrFile.replace("\\", "/");
//        this.geotiff_dir = geotiffDir.replace("\\", "/");
//        this.terrain_file = terrainFile.replace("\\", "/");
//        this.start_timestamp = startTimestamp;
//    }
    public Zarr2Tif(String zarrFile, String geotiffDir, String terrainFile, List<Object> range) {
        this();
        this.zarr_file = zarrFile.replace("\\", "/");
        this.geotiff_dir = geotiffDir.replace("\\", "/");
        this.terrain_file = terrainFile.replace("\\", "/");
        this.start_timestamp = startTimestamp;
        this.range = range;
    }
    public Zarr2Tif(String zarrFile, String geotiffDir, String terrainFile, Date startTime) {
        this(zarrFile, geotiffDir, terrainFile, StringHelper.YMDHMS_FORMAT.format(startTime));
    }
//    public Zarr2Tif(String zarrFile, String geotiffDir, String terrainFile, Date startTime) {
//        this(zarrFile, geotiffDir, terrainFile, StringHelper.YMDHMS_FORMAT.format(startTime));
//    }
    public List<String> getVariables() {
        return variables;
@@ -77,20 +88,28 @@
        this.terrain_file = terrain_file;
    }
    public String getStart_timestamp() {
        return start_timestamp;
//    public String getStart_timestamp() {
//        return start_timestamp;
//    }
//
//    public void setStart_timestamp(String start_timestamp) {
//        this.start_timestamp = start_timestamp;
//    }
//    public List<Integer> getFrame_range() {
//        return frame_range;
//    }
//
//    public void setFrame_range(List<Integer> frame_range) {
//        this.frame_range = frame_range;
//    }
    public List<Object> getRange() {
        return range;
    }
    public void setStart_timestamp(String start_timestamp) {
        this.start_timestamp = start_timestamp;
    }
    public List<Integer> getFrame_range() {
        return frame_range;
    }
    public void setFrame_range(List<Integer> frame_range) {
        this.frame_range = frame_range;
    public void setRange(List<Object> range) {
        this.range = range;
    }
    public boolean isFliplr() {
src/main/java/com/se/nsl/domain/vo/ConfigVo.java
@@ -9,7 +9,7 @@
    private String landuse;
    private int station;
    private Object station;
    private Integer kSt;
@@ -48,7 +48,7 @@
    public ConfigVo(String terrain, String landuse, String station,
                    String raingage, String saveName, int duration,
                    int frames, String saveMode) {
                    int frames, String saveMode, String startTime) {
        this();
//        this.terrain.set(0, terrain.replace("\\", "/")); // åœ°å½¢é«˜ç¨‹æ•°æ®
@@ -60,7 +60,7 @@
        this.raingage = Arrays.asList(raingage, "mm/min");
        this.duration = duration;
        int saveInterval = duration / frames - 5; // ä¿®è®¢æœ€åŽä¸€å¸§å¯èƒ½ä¸ºç©ºæ•°æ®
        this.result = new ResultVo(saveName, frames, saveInterval, saveMode);
        this.result = new ResultVo(saveName, frames, saveInterval, saveMode, startTime);
    }
    public String getTerrain() {
@@ -79,11 +79,11 @@
        this.landuse = landuse;
    }
    public int getStation() {
    public Object getStation() {
        return station;
    }
    public void setStation(int station) {
    public void setStation(Object station) {
        this.station = station;
    }
src/main/java/com/se/nsl/domain/vo/RealTimeSimuParam.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.se.nsl.domain.vo;
import java.util.List;
public class RealTimeSimuParam {
    private String startTime;
    private String serviceName;
    private List<String> deviceIds;
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public String getServiceName() {
        return serviceName;
    }
    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }
    public List<String> getDeviceIds() {
        return deviceIds;
    }
    public void setDeviceIds(List<String> deviceIds) {
        this.deviceIds = deviceIds;
    }
}
src/main/java/com/se/nsl/domain/vo/ResultVo.java
@@ -1,5 +1,7 @@
package com.se.nsl.domain.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -12,21 +14,27 @@
    private List<String> save_variables;
    private String save_timestamp0;
    private Integer save_frames;
//    @JsonIgnore
    private Integer lastFrames;
    private Integer save_interval;
    private Integer save_start;
    private Integer save_filter;
    private Double save_filter;
    public ResultVo() {
        this.save_variables = new ArrayList<>(Arrays.asList("depth", "xmomentum", "ymomentum"));
        this.save_start = 0;
        this.save_filter = 0;
        this.save_filter = 0D;
    }
    public ResultVo(String saveName, int frames, int saveInterval, String saveMode) {
    public ResultVo(String saveName, int frames, int saveInterval,
                    String saveMode, String startTime) {
        this();
        this.save_name = saveName.replace("\\", "/");
@@ -34,6 +42,7 @@
        // ç»“果数据中相邻帧的模拟时间间隔(单位:秒),save_start + save_frames * save_interval <= duration
        this.save_interval = saveInterval;
        this.save_mode = saveMode;
        this.save_timestamp0 = startTime;
    }
    public String getSave_name() {
@@ -60,12 +69,28 @@
        this.save_variables = save_variables;
    }
    public String getSave_timestamp0() {
        return save_timestamp0;
    }
    public void setSave_timestamp0(String save_timestamp0) {
        this.save_timestamp0 = save_timestamp0;
    }
    public Integer getSave_frames() {
        return save_frames;
    }
    public void setSave_frames(Integer save_frames) {
        this.save_frames = save_frames;
    }
    public Integer getLastFrames() {
        return lastFrames;
    }
    public void setLastFrames(Integer lastFrames) {
        this.lastFrames = lastFrames;
    }
    public Integer getSave_interval() {
@@ -84,11 +109,11 @@
        this.save_start = save_start;
    }
    public Integer getSave_filter() {
    public Double getSave_filter() {
        return save_filter;
    }
    public void setSave_filter(Integer save_filter) {
    public void setSave_filter(Double save_filter) {
        this.save_filter = save_filter;
    }
}
src/main/java/com/se/nsl/service/RealTimeSimulationService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,210 @@
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<String> deviceIds = input.getDeviceIds();
        InputStream stream = RealTimeSimulationService.class.getResourceAsStream("/a_test_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);
        //生成一个新的生成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<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));
            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<String> 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;
        }
    }
}
src/main/java/com/se/nsl/service/ResolveService.java
@@ -69,6 +69,8 @@
    @Resource
    TestService testService;
    private ObjectMapper mapper = new ObjectMapper();
    Integer DIGIT = 1000000;
    SimpleDateFormat YYYYMDHM = new SimpleDateFormat("yyyy M d H m ");
@@ -165,6 +167,7 @@
        AreaType at = AreaType.of(areaType);
        String terrainTif = config.getSourceDem();
        String landuseTif = config.getSourceLanduse();
        String stationTif = null;
        if (at == AreaType.KEY_DITCH) {
            File keyDitchDir = new File(config.getKeyDitch());
            String areaName = simu.getAreaName();
@@ -179,6 +182,9 @@
                    }
                    if (name.toLowerCase().contains("landuse")) {
                        landuseTif = file.getAbsolutePath();
                    }
                    if (name.toLowerCase().contains("station")) {
                        stationTif = file.getAbsolutePath();
                    }
                }
            }
@@ -203,9 +209,14 @@
        Dataset dsLanduse = gdal.Open(landuseTif, gdalconstConstants.GA_ReadOnly);
        ComHelper.Resample(dsLanduse, null, landuseFile, null, wkt, null, null);
        dsLanduse.delete();
        String stationFile = inPath + File.separator + "Station.tif";
        Dataset dsStation = gdal.Open(stationTif, gdalconstConstants.GA_ReadOnly);
        ComHelper.Resample(dsStation, null, stationFile, null, wkt, null, null);
        dsStation.delete();
    }
    public void updateTif(Simu simu, SimuData data2) throws IOException {
    public void updateTif(Simu simu, SimuData data2) {
        Dataset ds = gdal.Open(config.getSourceLanduse(), gdalconstConstants.GA_Update); // ä»¥è¯»å†™æ¨¡å¼æ‰“å¼€TIFF文件
        Band band = ds.GetRasterBand(1);
@@ -332,13 +343,13 @@
        Short type = simu.getType();
        SimulateType simulateType = SimulateType.of(type);
        String saveMode = simulateType.getSaveMode();
        ConfigVo vo = new ConfigVo(terrainFile, landuseFile, terrainFile, rainfallFile, saveName, duration, saveFrames, saveMode);
        String startTime = TimeFormatUtil.formatDate(data.getStartTime());
        ConfigVo vo = new ConfigVo(terrainFile, landuseFile, terrainFile, rainfallFile,
                saveName, duration, saveFrames, saveMode, startTime);
        String configFile = config.getInPath() + File.separator + data.getInPath() + File.separator + data.getInPath() + ".json";
        ComHelper.writeJson(configFile, JSON.toJSONString(vo));
//        ComHelper.writeJson(configFile, JSON.toJSONString(vo));
        mapper.writeValue(new File(configFile), vo);
        String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), configFile);
        return callBat2(cmd);
    }
@@ -351,10 +362,9 @@
        String geotiffDir = inPath + File.separator + "depth";
        String terrainFile = inPath + File.separator + config.getTerrainFile();
        String jsonPath = inPath + File.separator + "zarr2tif.json";
        Zarr2Tif zarr2Tif = new Zarr2Tif(zarrFile, geotiffDir, terrainFile, data.getStartTime());
        ComHelper.writeJson(jsonPath, JSON.toJSONString(zarr2Tif));
        Zarr2Tif zarr2Tif = new Zarr2Tif(zarrFile, geotiffDir, terrainFile, Collections.emptyList());
//        ComHelper.writeJson(jsonPath, JSON.toJSONString(zarr2Tif));
        mapper.writeValue(new File(jsonPath), zarr2Tif);
        String cmd = String.format("%s \"%s\"", config.getZarr2tifBat(), jsonPath);
        return callBat2(cmd);
@@ -556,13 +566,12 @@
        return newLayerJsonName;
    }
    private static File generateNewZarr2TifJson(File serviceNameDir, long currentTime) throws IOException {
    private File generateNewZarr2TifJson(File serviceNameDir, long currentTime) throws IOException {
        File srcZarr2TifJson = new File(serviceNameDir, "zarr2tif.json");
        ObjectMapper mapper = new ObjectMapper();
        Zarr2Tif zarr2Tif = mapper.readValue(srcZarr2TifJson, Zarr2Tif.class);
        //修改zarr2tif对象中的字段
        String stamp = TimeFormatUtil.formatTime(currentTime, "yyyy-MM-dd HH:mm:ss");
        zarr2Tif.setStart_timestamp(stamp);
//        String stamp = TimeFormatUtil.formatTime(currentTime, "yyyy-MM-dd HH:mm:ss");
//        zarr2Tif.setStart_timestamp(stamp);
//        String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr";
        String newZarrPath = serviceNameDir + File.separator + "result.zarr";
        zarr2Tif.setZarr_file(newZarrPath);
@@ -574,13 +583,16 @@
    private File generateNewZarrConfigFile(File serviceNameDir, String serviceName, long currentTime, File newDatFile) throws IOException {
        File configFile = new File(serviceNameDir, serviceName + ".json");
        ObjectMapper mapper = new ObjectMapper();
        ConfigVo configVo = mapper.readValue(configFile, ConfigVo.class);
        configVo.setDuration(configVo.getDuration() + 300); //固定为5min
        int simulateTime = 300; //模拟时间,默认为5min,即300s
        int intervalTime = 60; //每帧的间隔时间,默认为60s,60s生成一帧
        configVo.getRaingage().set(0, newDatFile.getAbsolutePath()); //raingage file
        ResultVo result = configVo.getResult();
        result.setSave_interval(60); //60s生成一帧
        result.setSave_frames(result.getSave_frames() + 5); //保留5帧,在原来的基础上增加5帧
        Integer oldDuration = configVo.getDuration();
//        result.setSave_start(oldDuration); //起始时间要在上次时间的基础上开始
        configVo.setDuration(oldDuration + simulateTime); //固定为5min
        result.setSave_interval(intervalTime);
        result.setSave_frames(result.getSave_frames() + (simulateTime / intervalTime)); //保留5帧,在原来的基础上增加5帧
//        String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr";
        String newZarrPath = serviceNameDir + File.separator + "result.zarr";
        result.setSave_name(newZarrPath);
src/main/java/com/se/nsl/utils/HttpRequestUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,133 @@
package com.se.nsl.utils;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import java.util.Optional;
/**
 * HTTP è¯·æ±‚工具类,支持带/不带 Token çš„请求
 */
public class HttpRequestUtil {
    private static final RestTemplate restTemplate = new RestTemplate();
    /**
     * å‘送 GET è¯·æ±‚(不带 Token)
     */
    public static <T> ResponseEntity<T> get(String url, Map<String, String> params, Class<T> responseType) {
        return get(url, params, responseType, null);
    }
    /**
     * å‘送 GET è¯·æ±‚(带 Token)
     */
    public static <T> ResponseEntity<T> get(String url, Map<String, String> params, Class<T> responseType, String token) {
        HttpEntity<String> entity = new HttpEntity<>(null, createHeaders(token));
        // æž„建带参数的 URL
        if (params != null && !params.isEmpty()) {
            StringBuilder urlBuilder = new StringBuilder(url).append("?");
            params.forEach((key, value) -> urlBuilder.append(key).append("=").append(value).append("&"));
            url = urlBuilder.substring(0, urlBuilder.length() - 1);
        }
        return restTemplate.exchange(url, HttpMethod.GET, entity, responseType);
    }
    /**
     * å‘送 POST è¯·æ±‚(不带 Token)
     */
    public static <T, B> ResponseEntity<T> post(String url, B body, Class<T> responseType) {
        return post(url, body, responseType, null);
    }
    /**
     * å‘送 POST è¯·æ±‚(带 Token)
     */
    public static <T, B> ResponseEntity<T> post(String url, B body, Class<T> responseType, String token) {
        HttpHeaders headers = createHeaders(token);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<B> entity = new HttpEntity<>(body, headers);
        return restTemplate.exchange(url, HttpMethod.POST, entity, responseType);
    }
    /**
     * å‘送表单 POST è¯·æ±‚(不带 Token)
     */
    public static <T> ResponseEntity<T> postForm(String url, Map<String, Object> formData, Class<T> responseType) {
        return postForm(url, formData, responseType, null);
    }
    /**
     * å‘送表单 POST è¯·æ±‚(带 Token)
     */
    public static <T> ResponseEntity<T> postForm(String url, Map<String, Object> formData, Class<T> responseType, String token) {
        HttpHeaders headers = createHeaders(token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        if (formData != null) {
            formData.forEach(map::add);
        }
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(map, headers);
        return restTemplate.exchange(url, HttpMethod.POST, entity, responseType);
    }
    /**
     * å‘送 PUT è¯·æ±‚(不带 Token)
     */
    public static <T, B> ResponseEntity<T> put(String url, B body, Class<T> responseType) {
        return put(url, body, responseType, null);
    }
    /**
     * å‘送 PUT è¯·æ±‚(带 Token)
     */
    public static <T, B> ResponseEntity<T> put(String url, B body, Class<T> responseType, String token) {
        HttpHeaders headers = createHeaders(token);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<B> entity = new HttpEntity<>(body, headers);
        return restTemplate.exchange(url, HttpMethod.PUT, entity, responseType);
    }
    /**
     * å‘送 DELETE è¯·æ±‚(不带 Token)
     */
    public static <T> ResponseEntity<T> delete(String url, Class<T> responseType) {
        return delete(url, responseType, null);
    }
    /**
     * å‘送 DELETE è¯·æ±‚(带 Token)
     */
    public static <T> ResponseEntity<T> delete(String url, Class<T> responseType, String token) {
        HttpEntity<String> entity = new HttpEntity<>(null, createHeaders(token));
        return restTemplate.exchange(url, HttpMethod.DELETE, entity, responseType);
    }
    /**
     * åˆ›å»º HTTP å¤´
     * @param token è®¤è¯ Token,可为 null
     * @return HTTP å¤´
     */
    private static HttpHeaders createHeaders(String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
        // å¦‚果提供了 Token,则添加到请求头
        Optional.ofNullable(token)
                .ifPresent(t -> headers.set("Authorization", "Bearer " + t));
        return headers;
    }
}
src/main/java/com/se/nsl/utils/TimeFormatUtil.java
@@ -2,6 +2,7 @@
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
/**
 * @author dcb
@@ -22,6 +23,16 @@
        return dateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }
    public static LocalDateTime toDate(long time) {
        Instant instant = Instant.ofEpochMilli(time);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime;
    }
    public static String formatDate(Date date) {
        return formatTime(date.getTime(), "yyyy-MM-dd HH:mm:ss");
    }
    public static void main(String[] args) {
        String s = "20250606142122";
        String pattern = "yyyyMMddHHmmss";
src/main/resources/a_test_device_info.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
[
  {
    "id": "1101161102180100010065",
    "name": "怀柔区琉璃庙镇孙胡沟椴树底下东沟雨量计0065",
    "x": 116.59585,
    "y": 40.543104,
    "r": 10000,
    "mappingId": 0
  },
  {
    "id": "1101161102180100010064",
    "name": "怀柔区琉璃庙镇孙胡沟村上台子河东南沟雨量计0064",
    "x": 116.586304,
    "y": 40.545741,
    "r": 10000,
    "mappingId": 1
  },
  {
    "id": "1101161102180100010063",
    "name": "怀柔区琉璃庙镇孙胡沟尹家西沟雨量计0063",
    "x": 116.579459,
    "y": 40.556589,
    "r": 10000,
    "mappingId": 2
  },
  {
    "id": "1101161102180100010062",
    "name": "怀柔区琉璃庙镇孙胡沟村于家西沟雨量计0062",
    "x": 116.586892,
    "y": 40.558778,
    "r": 10000,
    "mappingId": 3
  },
  {
    "id": "1101160300550102",
    "name": "怀柔区琉璃庙镇孙胡沟尹家西沟雨量计0063",
    "x": 116.57845,
    "y": 40.56715,
    "r": 10000,
    "mappingId": 4
  },
  {
    "id": "1101160300540101",
    "name": "怀柔区琉璃庙镇孙胡沟村于家西沟雨量计0062",
    "x": 116.59064,
    "y": 40.56122,
    "r": 10000,
    "mappingId": 5
  },
  {
    "id": "1101160300420103",
    "name": "怀柔区琉璃庙镇孙胡沟村上台子河东南沟雨量计0064",
    "x": 116.60498,
    "y": 40.56032,
    "r": 10000,
    "mappingId": 6
  },
  {
    "id": "1101160300400103",
    "name": "怀柔区琉璃庙镇孙胡沟椴树底下东沟雨量计0065",
    "x": 116.60578,
    "y": 40.55423,
    "r": 10000,
    "mappingId": 7
  }
]
src/main/resources/application-dev.yml
@@ -141,16 +141,16 @@
  flowUnits: CMS
  solverBat: D:\other\simu\uwsolver\run_solver.bat
  sww2tifBat: D:\other\simu\uwsolver\sww2tif.bat
  uwSolverBat: D:\other\simu\CudaUWSolver-2.1.1\cuws.bat
  uwSolverBat: D:\other\simu\CudaUWSolver-2.2\cuws.bat
#  uwSolverBat: D:\other\simu\CudaUWSolver-2.0\start.bat
  zarr2tifBat: D:\other\simu\zarr2tif-2.1\start.bat
  zarr2tifBat: D:\other\simu\CudaUWSolver-2.2\zarr2tif.bat
  createRainfall: '"C:\Program Files\Python310\python.exe" D:\terrait\NslServer\data\CreatRainfall.py'
  rainfallTitle: Station Longitude Latitude Year Month Day Hour Minute Intensity
  rainfallSite: beijing
  epsg: 4548
#  saveFrames: 3
  #生成帧数的间隔时间,单位是分钟,设置为5表示每隔5分钟生成一帧
  saveFrameInterval: 10
  saveFrameInterval: 20
  # åœŸåœ°åˆ©ç”¨ï¼š1-Cropland,2-Forest,3-Shrub,4-Grassland,5-Water,6-Snow/Ice,7-Barren,8-Impervious,9-Wetland
  landuse: 2
  #sizes: 64,128,256,512,1024,2048,4096
@@ -163,10 +163,10 @@
  waterPath: depth
  flowPath: velocity
  landuseFile: Landuse.tif
  sourceDem: D:\other\simu\CudaUWSolver-2.1.1\Beijing-Data-10m\Beijing-4548-ASTERDEMV3-10m.tif
  sourceLanduse: D:\other\simu\CudaUWSolver-2.1.1\Beijing-Data-10m\Beijing-4548-Landuse-10m-Nonodata.tif
  sourceDem: D:\other\simu\CudaUWSolver-2.2\Beijing-Data-10m\Beijing-4548-ASTERDEMV3-10m-f32.tif
  sourceLanduse: D:\other\simu\CudaUWSolver-2.2\Beijing-Data-10m\Beijing-4548-Landuse-10m-Nonodata.tif
  copyTif: false
  tifPath: D:\other\simu\uwsolver\5ca43c87cd8e48c5a9c5399a5da46dbc\tongzhou_raster_4548_1m_clip_river_fill.tif
  #tif中的高程文件名要含有dem,土地利用要含有landuse,站点要含有station,不限制大小写,文字尽量用英文字母表达
  keyDitch: D:\other\simu\CudaUWSolver-2.1.1\KeyDitch
  keyDitch: D:\other\simu\CudaUWSolver-2.2\KeyDitch