From 4520c5c24d7f7bb0a93d264a6543370f5c67a261 Mon Sep 17 00:00:00 2001 From: shiyi Date: Tue, 2 Jul 2024 14:11:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9C=B0=E9=9D=A2=E9=A3=8E?= =?UTF-8?q?=E5=8A=9B=E7=AD=89=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/htfp/weather/utils/DateTimeUtils.java | 12 ++++ .../com/htfp/weather/utils/DownloadUtils.java | 9 --- .../com/htfp/weather/utils/MeteoUtils.java | 52 +++++++++++++++- .../web/pojo/response/NowWeatherStatus.java | 2 +- .../web/pojo/response/ProfileDataset.java | 3 - .../web/pojo/response/TimeSeriesDataset.java | 4 +- .../web/service/GfsDataServiceImpl.java | 61 ++++++------------- .../service/surfaceapi/CaiYunServiceImpl.java | 9 ++- .../service/surfaceapi/HeFengServiceImpl.java | 6 +- 9 files changed, 92 insertions(+), 66 deletions(-) delete mode 100644 weather-service/src/main/java/com/htfp/weather/utils/DownloadUtils.java diff --git a/weather-service/src/main/java/com/htfp/weather/utils/DateTimeUtils.java b/weather-service/src/main/java/com/htfp/weather/utils/DateTimeUtils.java index 7161c0f..b2f02b6 100644 --- a/weather-service/src/main/java/com/htfp/weather/utils/DateTimeUtils.java +++ b/weather-service/src/main/java/com/htfp/weather/utils/DateTimeUtils.java @@ -2,6 +2,7 @@ package com.htfp.weather.utils; import java.time.*; import java.time.format.DateTimeFormatter; +import java.util.TimeZone; /** * @Author : shiyi @@ -11,6 +12,8 @@ import java.time.format.DateTimeFormatter; public class DateTimeUtils { public static final String DEFAULT_PATTERN = "yyyy-MM-dd'T'HH:mm:ssxxx"; public static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_PATTERN); + public static final ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.ofHours(TimeZone.getDefault().getRawOffset()/3600000); + public static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault(); /** * 将某时区的时间字符串更改为其他时区的时间字符串, * @@ -132,4 +135,13 @@ public class DateTimeUtils { ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault()); return zonedDateTime.format(DEFAULT_FORMATTER); } + + /** 将OffsetDateTime对象转换为指定时区*/ + public static OffsetDateTime offsetDateTimeToTargetZone(OffsetDateTime offsetDateTime, int ZoneTo) { + return offsetDateTime.withOffsetSameInstant(ZoneOffset.ofHours(ZoneTo)); + } + /** 将OffsetDateTime对象转换为系统时区*/ + public static OffsetDateTime offsetDateTimeToSystemZone(OffsetDateTime offsetDateTime) { + return offsetDateTime.withOffsetSameInstant(DEFAULT_ZONE_OFFSET); + } } diff --git a/weather-service/src/main/java/com/htfp/weather/utils/DownloadUtils.java b/weather-service/src/main/java/com/htfp/weather/utils/DownloadUtils.java deleted file mode 100644 index 5870944..0000000 --- a/weather-service/src/main/java/com/htfp/weather/utils/DownloadUtils.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.htfp.weather.utils; - -/** - * @Author : shiyi - * @Date : 2024/4/25 18:31 - * @Description : 文件下载https://www.jianshu.com/p/3b269082cbbb - */ -public class DownloadUtils { -} diff --git a/weather-service/src/main/java/com/htfp/weather/utils/MeteoUtils.java b/weather-service/src/main/java/com/htfp/weather/utils/MeteoUtils.java index 7836822..e360682 100644 --- a/weather-service/src/main/java/com/htfp/weather/utils/MeteoUtils.java +++ b/weather-service/src/main/java/com/htfp/weather/utils/MeteoUtils.java @@ -8,7 +8,7 @@ import java.util.Arrays; /** * @Author : shiyi * @Date : 2024/1/24 11:32 - * @Description : 气象数据处理工具类 + * @Description : 地理信息与气象数据处理工具类 */ public class MeteoUtils { @@ -30,6 +30,54 @@ public class MeteoUtils { return kph / 3.6; } + /** + * 风力等级转换 + * @param kph–风速 (km/h) + * @return 蒲福风力等级 + */ + public static int kmPerHour2WindScale(double kph) { + return mPerSecond2WindScale(kmPerHour2mPerSecond(kph)); + } + /** + * 风力等级转换 + * @param mps–风速 (m/s) + * @return 蒲福风力等级 + */ + public static int mPerSecond2WindScale(double mps) { + if (mps < 0) { + throw new IllegalArgumentException("风力等级计算错误风速不能为负值"); + } + if (mps <= 0.2) { + return 0; + } else if (mps <= 1.5) { + return 1; + } else if (mps <= 3.3) { + return 2; + } else if (mps <= 5.4) { + return 3; + } else if (mps <= 7.9) { + return 4; + } else if (mps <= 10.7) { + return 5; + } else if (mps <= 13.8) { + return 6; + } else if (mps <= 17.1) { + return 7; + } else if (mps <= 20.7) { + return 8; + } else if (mps <= 24.4) { + return 9; + } else if (mps <= 28.4) { + return 10; + } else if (mps <= 32.6) { + return 11; + } else if (mps <= 36.9){ + return 12; + } else { + return 13; + } + } + // public static double pressure2Height(double pressure) { // // } @@ -62,7 +110,7 @@ public class MeteoUtils { // // @Deprecated // public static Array calculateWindSpeed(Array u, Array v) { - // // // FIXME 2024/5/13: io耗时太多,对于一般大小的矩阵不使用 + // // note 2024/5/13: io耗时太多,对于一般大小的矩阵不实用 // uvValid(u, v); // try (NDManager manager = NDManager.newBaseManager()) { // int[] shapeArray = u.getShape(); diff --git a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/NowWeatherStatus.java b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/NowWeatherStatus.java index 99e96e0..19d327a 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/NowWeatherStatus.java +++ b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/NowWeatherStatus.java @@ -17,7 +17,7 @@ public class NowWeatherStatus { Float windSpeed; // 风速,m/s Float wind360; // 风向360角度 // String windDir; // 风向, 文字描述,如“西北风” - // String windScale; // 风力等级 + Integer windScale; // 风力等级 Float humidity; // 相对湿度 % // Float pressure; // 大气压强,默认单位:百帕 Float cloud; // 云量 diff --git a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/ProfileDataset.java b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/ProfileDataset.java index 0e8fafe..cb65bcf 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/ProfileDataset.java +++ b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/ProfileDataset.java @@ -15,11 +15,9 @@ public class ProfileDataset { // int[ pressureHeight; double latitude; double longitude; - float[] temp; float[] windSpeed; float[] wind360; - // List windScale; float[] humidity; // float[] pressure; float[] cloud; @@ -33,7 +31,6 @@ public class ProfileDataset { temp = new float[size]; windSpeed = new float[size]; wind360 = new float[size]; - // windScale = new float[size; humidity = new float[size]; // pressure = new float[size; cloud = new float[size]; diff --git a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java index c2211a8..7668a0d 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java +++ b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java @@ -19,7 +19,7 @@ public class TimeSeriesDataset { float[] temp; float[] windSpeed; float[] wind360; - // List windScale; + int[] windScale; float[] humidity; // float[] pressure; float[] cloud; @@ -31,7 +31,7 @@ public class TimeSeriesDataset { temp = new float[size]; windSpeed = new float[size]; wind360 = new float[size]; - // windScale = new float[size; + windScale = new int[size]; humidity = new float[size]; // pressure = new float[size; cloud = new float[size]; diff --git a/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java b/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java index 0d6dc7a..92edd6e 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java +++ b/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java @@ -4,27 +4,26 @@ import com.aliyun.tablestore.grid.consts.AttributionEnum; import com.aliyun.tablestore.grid.model.GridDataSet; import com.aliyun.tablestore.grid.model.GridDataSetMeta; import com.aliyun.tablestore.grid.model.grid.Grid4D; +import com.htfp.weather.download.gfs.GfsLevelsEnum; import com.htfp.weather.download.gfs.GfsVariableHeightEnum; import com.htfp.weather.download.gfs.GfsVariableIsobaricEnum; import com.htfp.weather.griddata.common.TableConfig; -import com.htfp.weather.griddata.operation.GfsDataFetcher; import com.htfp.weather.griddata.common.ValueRange; +import com.htfp.weather.griddata.operation.GfsDataFetcher; import com.htfp.weather.info.Constant; -import com.htfp.weather.download.gfs.GfsLevelsEnum; import com.htfp.weather.utils.DateTimeUtils; +import com.htfp.weather.utils.MeteoUtils; import com.htfp.weather.web.exception.AppException; import com.htfp.weather.web.exception.ErrorCode; import com.htfp.weather.web.pojo.response.*; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; import ucar.ma2.Array; import ucar.ma2.Index4D; import javax.annotation.Resource; import java.lang.reflect.Method; -import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -325,6 +324,7 @@ public class GfsDataServiceImpl implements IDataService { Method method = aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(variableNameInApi).getType()); // TODO 2024/6/20: 这里的toArray操作在数据量较大的时候会比较吃内存和cpu float[] storage = (float[]) grid4D.toArray().section( + // levIndexGlobal-origin[1] 获取目标点在子区域中的索引 new int[]{0, levIndexGlobal-origin[1], latIndexGlobal-origin[2], lonIndexGlobal-origin[3]}, new int[]{tSize, 1, 1, 1} ).copyTo1DJavaArray(); method.invoke(result, storage); @@ -340,6 +340,17 @@ public class GfsDataServiceImpl implements IDataService { List timeList = getResultTimeStringList(gridDataSet, tSize, origin[0]); result.setTime(timeList); } + // 计算地面风力等级 + if (levelFlag == GfsLevelsEnum.SURFACE) { + float[] windSpeed = result.getWindSpeed(); + if (windSpeed != null) { + int[] windScale = new int[windSpeed.length]; + for (int i = 0; i < windScale.length; i++) { + windScale[i] = MeteoUtils.mPerSecond2WindScale(windSpeed[i]); + } + result.setWindScale(windScale); + } + } } return result; } @@ -400,6 +411,11 @@ public class GfsDataServiceImpl implements IDataService { throw new AppException(ErrorCode.RESPONSE_DATA_BUILD_ERROR); } } + if (levelFlag == GfsLevelsEnum.SURFACE) { + if (result.getWindSpeed() != null) { + result.setWindScale(MeteoUtils.mPerSecond2WindScale(result.getWindSpeed())); + } + } return result; } @@ -446,41 +462,4 @@ public class GfsDataServiceImpl implements IDataService { return variableNameInApi; } - private Map getFutureTimeIndexList(GridDataSetMeta lastGridDataSetMeta) { - long milli = (long) lastGridDataSetMeta.getAttributes().get(AttributionEnum.REFERENCE_TIME.getName()); - OffsetDateTime refTime = OffsetDateTime.ofInstant(Instant.ofEpochMilli(milli), ZoneOffset.ofHours(0)); - OffsetDateTime currentTime = DateTimeUtils.getUTCDateTime(OffsetDateTime.now()); - if (currentTime.isBefore(refTime)) { - throw new AppException(ErrorCode.QUERY_TIME_ERROR); - } - int startHour = getForecastHourFromTargetTime(currentTime, refTime); - List forecastHours = lastGridDataSetMeta.getForecastHours(); - List iTimeList = new ArrayList<>(); - List timeList = new ArrayList<>(); - - for (int i = 0; i < forecastHours.size(); i++) { - int hour = Integer.parseInt(forecastHours.get(i)); - if (hour >= startHour) { - iTimeList.add(i); - String timeStr = DateTimeUtils.getLocalZoneDateTime(refTime.plusHours(hour)) - .format(Constant.API_TIME_FORMATTER); - timeList.add(timeStr); - } - if (iTimeList.size() >= 24) { - break; - } - } - if (CollectionUtils.isEmpty(iTimeList) || CollectionUtils.isEmpty(timeList)) { - throw new AppException(ErrorCode.QUERY_TIME_ERROR); - } - Map map = new HashMap<>(2); - map.put("iTimeList", iTimeList); - map.put("timeList", timeList); - return map; - } - - private int getForecastHourFromTargetTime(OffsetDateTime targetTime, OffsetDateTime refTime) { - return (int) Duration.between(refTime, targetTime).toHours(); - } - } diff --git a/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/CaiYunServiceImpl.java b/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/CaiYunServiceImpl.java index 4e7c2b7..b527adc 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/CaiYunServiceImpl.java +++ b/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/CaiYunServiceImpl.java @@ -13,6 +13,7 @@ import com.htfp.weather.web.pojo.response.NowWeatherStatus; import com.htfp.weather.web.pojo.response.SurfaceWeatherWarning; import com.htfp.weather.web.pojo.response.TimeSeriesDataset; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.time.OffsetDateTime; @@ -30,11 +31,8 @@ import static com.htfp.weather.utils.HttpClientUtils.sendGet; */ @Service("caiyun") @Slf4j public class CaiYunServiceImpl implements ISurfaceDataService { - - private final String key = "Tc9tgOYr5jlPPlEw"; - private final HashMap variableNameMap = - new HashMap() {{ - }}; + @Value("${caiyun.key}") + private String key; static final String STATUS_OK = "ok"; public T caiYunRequest(String url, HashMap params, Class responseClass) { params.put("units", "metric:v2"); @@ -126,6 +124,7 @@ public class CaiYunServiceImpl implements ISurfaceDataService { nowWeatherStatus.setTemp(realtime.getTemperature()); nowWeatherStatus.setWindSpeed((float) MeteoUtils.kmPerHour2mPerSecond(realtime.getWind().getSpeed())); nowWeatherStatus.setWind360(realtime.getWind().getDirection()); + nowWeatherStatus.setWindScale(MeteoUtils.kmPerHour2WindScale(realtime.getWind().getSpeed())); nowWeatherStatus.setHumidity(realtime.getHumidity()); nowWeatherStatus.setCloud(realtime.getCloudrate()); diff --git a/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/HeFengServiceImpl.java b/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/HeFengServiceImpl.java index 7e2eb8e..499de5b 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/HeFengServiceImpl.java +++ b/weather-service/src/main/java/com/htfp/weather/web/service/surfaceapi/HeFengServiceImpl.java @@ -178,13 +178,13 @@ public class HeFengServiceImpl implements ISurfaceDataService { private NowWeatherStatus buildNowSurfaceWeatherStatus(HeFengNow now) { NowWeatherStatus nowWeatherStatus = new NowWeatherStatus(); processHeFengData(now); - nowWeatherStatus.setTime(now.getObsTime()); + nowWeatherStatus.setTime(DateTimeUtils.offsetDateTimeToSystemZone(OffsetDateTime.parse(now.getObsTime())).format(Constant.API_TIME_FORMATTER)); nowWeatherStatus.setWeatherText(now.getText()); nowWeatherStatus.setTemp(now.getTemp()); nowWeatherStatus.setWindSpeed(now.getWindSpeed()); nowWeatherStatus.setWind360(now.getWind360()); - // nowSurfaceWeatherStatus.setWindDir(now.getWindDir()); - // nowSurfaceWeatherStatus.setWindScale(now.getWindScale()); + // nowWeatherStatus.setWindDir(now.getWindDir()); + nowWeatherStatus.setWindScale(MeteoUtils.mPerSecond2WindScale(now.getWindSpeed())); nowWeatherStatus.setHumidity(now.getHumidity()); // nowWeatherStatus.setPressure(now.getPressure()); nowWeatherStatus.setCloud(now.getCloud());