dcb
2025-06-24 043d1bd4860bbee636b3935e94a71246091cbf3f
实时模拟功能实现
已重命名1个文件
已添加2个文件
已修改5个文件
488 ■■■■ 文件已修改
src/main/java/com/se/nsl/config/GaugeServer.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/controller/SimuController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/dto/RemoteGaugeInput.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/domain/po/RainGauge.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/RealTimeSimulationService.java 284 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/TestService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/device_info.json 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/config/GaugeServer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
package com.se.nsl.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "gauge-server")
public class GaugeServer {
    private String url;
    private String token;
    private int requestOffsetMinutes; //雨量计请求间隔的时间,为了便于获取一个范围内雨量数据
    private double offsetDays;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }
    public int getRequestOffsetMinutes() {
        return requestOffsetMinutes;
    }
    public void setRequestOffsetMinutes(int requestOffsetMinutes) {
        this.requestOffsetMinutes = requestOffsetMinutes;
    }
    public double getOffsetDays() {
        return offsetDays;
    }
    public void setOffsetDays(double offsetDays) {
        this.offsetDays = offsetDays;
    }
}
src/main/java/com/se/nsl/controller/SimuController.java
@@ -9,9 +9,8 @@
import com.se.nsl.service.RealTimeSimulationService;
import com.se.nsl.service.ResolveService;
import com.se.nsl.service.SimuService;
import com.se.nsl.utils.SimulateType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.gdal.ogr.Geometry;
@@ -20,10 +19,6 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
@Api(tags = "03-推演模拟")
@@ -105,10 +100,13 @@
            int rows = simuService.insert(simu);
            System.out.println(String.format("id:%s", simu.getId()));
            if (rows > 0 && (null == data.getRainfalls() || data.getRainfalls().size() < 2)) {
                resolveService.createRainfall(simu);
                simuService.updateById(simu);
            Integer type = data.getType();
            SimulateType simulateType = SimulateType.of(type);
            if (simulateType == SimulateType.HISTORY) {
                if (rows > 0 && (null == data.getRainfalls() || data.getRainfalls().size() < 2)) {
                    resolveService.createRainfall(simu);
                    simuService.updateById(simu);
                }
            }
            JSONObject json = new JSONObject();
            json.put("id", simu.getId());
@@ -134,9 +132,16 @@
            //if (simu.getStatus() != 0) return fail("方案正在运行或已完成");
            if (StringUtils.isEmpty(simu.getGeom())) return fail("方案的图形为空");
            int rows = resolveService.start(simu);
            return success("ok");
            Short type = simu.getType();
            SimulateType simulateType = SimulateType.of(type);
            if (simulateType == SimulateType.HISTORY) {
                int rows = resolveService.start(simu);
                return success("ok");
            } else if (simulateType == SimulateType.REAL_TIME) {
                String s = rts.realTimeSimulate(simu);
                return success(s);
            }
            return fail("模拟类型暂不支持");
        } catch (Exception ex) {
            return fail(ex, null);
        }
src/main/java/com/se/nsl/domain/dto/RemoteGaugeInput.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
package com.se.nsl.domain.dto;
import java.util.List;
public class RemoteGaugeInput {
    private int currentPage;
    private int pageSize;
    private FilterObject filterObject;
    public int getCurrentPage() {
        return currentPage;
    }
    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
    public FilterObject getFilterObject() {
        return filterObject;
    }
    public void setFilterObject(FilterObject filterObject) {
        this.filterObject = filterObject;
    }
    public static class FilterObject {
        private String deviceCode;
        private List<String> sendTimeList;
        private String dictPacketsDataStatus = "1887255639886540806";
        public String getDeviceCode() {
            return deviceCode;
        }
        public void setDeviceCode(String deviceCode) {
            this.deviceCode = deviceCode;
        }
        public List<String> getSendTimeList() {
            return sendTimeList;
        }
        public void setSendTimeList(List<String> sendTimeList) {
            this.sendTimeList = sendTimeList;
        }
        public String getDictPacketsDataStatus() {
            return dictPacketsDataStatus;
        }
        public void setDictPacketsDataStatus(String dictPacketsDataStatus) {
            this.dictPacketsDataStatus = dictPacketsDataStatus;
        }
    }
}
src/main/java/com/se/nsl/domain/po/RainGauge.java
@@ -20,4 +20,44 @@
    @ApiModelProperty("影响半径")
    private Double r;
    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;
    }
}
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);
        //生成一个新的生成zarr的配置文件
        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);
        //生成一个新的zarr转tif的json文件
        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 {
            //生成一个新的zarr转tif的json文件
            ResultVo result = configVo.getResult();
            Integer fromFrame = result.getLastFrames();
            Integer toFrame = result.getSave_frames() - 1;
            newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime, Arrays.asList(fromFrame, toFrame));
        }
        //执行zarr转tif
        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;
src/main/java/com/se/nsl/service/TestService.java
@@ -141,6 +141,8 @@
        String terrainPath = dto.getOutPath() + File.separator + "terrain";
        File f = new File(terrainPath);
        if (!f.exists() || !f.isDirectory()) f.mkdirs();
        File tempDir = new File(dto.getTemp());
        if (!tempDir.exists()) tempDir.mkdir();
        for (int[] sizes : layer.getTerrain().getSize()) {
            String tif = dto.getTemp() + File.separator + "terrain_" + sizes[0] + "_" + sizes[1] + ".tif";
src/main/resources/application-dev.yml
@@ -141,9 +141,9 @@
  flowUnits: CMS
  solverBat: D:\other\simu\uwsolver\run_solver.bat
  sww2tifBat: D:\other\simu\uwsolver\sww2tif.bat
  uwSolverBat: D:\other\simu\CudaUWSolver-2.2\cuws.bat
  uwSolverBat: D:\other\simu\CudaUWSolver-2.2.1\cuws.bat
#  uwSolverBat: D:\other\simu\CudaUWSolver-2.0\start.bat
  zarr2tifBat: D:\other\simu\CudaUWSolver-2.2\zarr2tif.bat
  zarr2tifBat: D:\other\simu\CudaUWSolver-2.2.1\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
@@ -155,7 +155,7 @@
  # åœŸåœ°åˆ©ç”¨ï¼š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
  sizes: 1024,2048,4096
  sizes: 1024
  # è¾“出文件
  terrainFile: DEM.tif
  buildingFile: buildings_inside.shp
@@ -164,10 +164,18 @@
  waterPath: depth
  flowPath: velocity
  landuseFile: Landuse.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
  sourceDem: D:\other\simu\CudaUWSolver-2.2.1\Beijing-Data-10m\Beijing-4548-ASTERDEMV3-10m-f32.tif
  sourceLanduse: D:\other\simu\CudaUWSolver-2.2.1\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.2\KeyDitch
  keyDitch: D:\other\simu\CudaUWSolver-2.2.1\KeyDitch
gauge-server:
  url: http://192.168.56.106:9522/ylclyPacket/getData
  token: YjhhYjAwOWFhMjk1MTM1ZDA0NGU3ZWZlMDQzMzUzZDE1MGJmY2Q4ZWEyYjliNjQzZjcwMjhlNDY0ZjAxNWZjOTZmNzMwYmNmZDA2YmVmNTIzNjU0ZDgzODRjYTUxYTM1
  #请求雨量计数据时,时间范围相差多少分钟
  requestOffsetMinutes: 10
  #往前偏移多少天,为了方便实时模拟以前的降雨情况,设置为0表示,从当前时间开始计算
  offsetDays: 0
src/main/resources/device_info.json