添加地面风力等级

refactor
shiyi 9 months ago
parent 2ec081e80f
commit 4520c5c24d

@ -2,6 +2,7 @@ package com.htfp.weather.utils;
import java.time.*; import java.time.*;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
/** /**
* @Author : shiyi * @Author : shiyi
@ -11,6 +12,8 @@ import java.time.format.DateTimeFormatter;
public class DateTimeUtils { public class DateTimeUtils {
public static final String DEFAULT_PATTERN = "yyyy-MM-dd'T'HH:mm:ssxxx"; 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 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()); ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
return zonedDateTime.format(DEFAULT_FORMATTER); 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);
}
} }

@ -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 {
}

@ -8,7 +8,7 @@ import java.util.Arrays;
/** /**
* @Author : shiyi * @Author : shiyi
* @Date : 2024/1/24 11:32 * @Date : 2024/1/24 11:32
* @Description : * @Description :
*/ */
public class MeteoUtils { public class MeteoUtils {
@ -30,6 +30,54 @@ public class MeteoUtils {
return kph / 3.6; 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) { // public static double pressure2Height(double pressure) {
// //
// } // }
@ -62,7 +110,7 @@ public class MeteoUtils {
// //
// @Deprecated // @Deprecated
// public static Array calculateWindSpeed(Array u, Array v) { // public static Array calculateWindSpeed(Array u, Array v) {
// // // FIXME 2024/5/13: io耗时太多对于一般大小的矩阵不使 // // note 2024/5/13: io耗时太多对于一般大小的矩阵不实
// uvValid(u, v); // uvValid(u, v);
// try (NDManager manager = NDManager.newBaseManager()) { // try (NDManager manager = NDManager.newBaseManager()) {
// int[] shapeArray = u.getShape(); // int[] shapeArray = u.getShape();

@ -17,7 +17,7 @@ public class NowWeatherStatus {
Float windSpeed; // 风速m/s Float windSpeed; // 风速m/s
Float wind360; // 风向360角度 Float wind360; // 风向360角度
// String windDir; // 风向, 文字描述,如“西北风” // String windDir; // 风向, 文字描述,如“西北风”
// String windScale; // 风力等级 Integer windScale; // 风力等级
Float humidity; // 相对湿度 % Float humidity; // 相对湿度 %
// Float pressure; // 大气压强,默认单位:百帕 // Float pressure; // 大气压强,默认单位:百帕
Float cloud; // 云量 Float cloud; // 云量

@ -15,11 +15,9 @@ public class ProfileDataset {
// int[ pressureHeight; // int[ pressureHeight;
double latitude; double latitude;
double longitude; double longitude;
float[] temp; float[] temp;
float[] windSpeed; float[] windSpeed;
float[] wind360; float[] wind360;
// List<String> windScale;
float[] humidity; float[] humidity;
// float[] pressure; // float[] pressure;
float[] cloud; float[] cloud;
@ -33,7 +31,6 @@ public class ProfileDataset {
temp = new float[size]; temp = new float[size];
windSpeed = new float[size]; windSpeed = new float[size];
wind360 = new float[size]; wind360 = new float[size];
// windScale = new float[size;
humidity = new float[size]; humidity = new float[size];
// pressure = new float[size; // pressure = new float[size;
cloud = new float[size]; cloud = new float[size];

@ -19,7 +19,7 @@ public class TimeSeriesDataset {
float[] temp; float[] temp;
float[] windSpeed; float[] windSpeed;
float[] wind360; float[] wind360;
// List<String> windScale; int[] windScale;
float[] humidity; float[] humidity;
// float[] pressure; // float[] pressure;
float[] cloud; float[] cloud;
@ -31,7 +31,7 @@ public class TimeSeriesDataset {
temp = new float[size]; temp = new float[size];
windSpeed = new float[size]; windSpeed = new float[size];
wind360 = new float[size]; wind360 = new float[size];
// windScale = new float[size; windScale = new int[size];
humidity = new float[size]; humidity = new float[size];
// pressure = new float[size; // pressure = new float[size;
cloud = new float[size]; cloud = new float[size];

@ -4,27 +4,26 @@ import com.aliyun.tablestore.grid.consts.AttributionEnum;
import com.aliyun.tablestore.grid.model.GridDataSet; import com.aliyun.tablestore.grid.model.GridDataSet;
import com.aliyun.tablestore.grid.model.GridDataSetMeta; import com.aliyun.tablestore.grid.model.GridDataSetMeta;
import com.aliyun.tablestore.grid.model.grid.Grid4D; 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.GfsVariableHeightEnum;
import com.htfp.weather.download.gfs.GfsVariableIsobaricEnum; import com.htfp.weather.download.gfs.GfsVariableIsobaricEnum;
import com.htfp.weather.griddata.common.TableConfig; 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.common.ValueRange;
import com.htfp.weather.griddata.operation.GfsDataFetcher;
import com.htfp.weather.info.Constant; import com.htfp.weather.info.Constant;
import com.htfp.weather.download.gfs.GfsLevelsEnum;
import com.htfp.weather.utils.DateTimeUtils; 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.AppException;
import com.htfp.weather.web.exception.ErrorCode; import com.htfp.weather.web.exception.ErrorCode;
import com.htfp.weather.web.pojo.response.*; import com.htfp.weather.web.pojo.response.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import ucar.ma2.Array; import ucar.ma2.Array;
import ucar.ma2.Index4D; import ucar.ma2.Index4D;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneOffset; import java.time.ZoneOffset;
@ -325,6 +324,7 @@ public class GfsDataServiceImpl implements IDataService {
Method method = aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(variableNameInApi).getType()); Method method = aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(variableNameInApi).getType());
// TODO 2024/6/20: 这里的toArray操作在数据量较大的时候会比较吃内存和cpu // TODO 2024/6/20: 这里的toArray操作在数据量较大的时候会比较吃内存和cpu
float[] storage = (float[]) grid4D.toArray().section( 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} new int[]{0, levIndexGlobal-origin[1], latIndexGlobal-origin[2], lonIndexGlobal-origin[3]}, new int[]{tSize, 1, 1, 1}
).copyTo1DJavaArray(); ).copyTo1DJavaArray();
method.invoke(result, storage); method.invoke(result, storage);
@ -340,6 +340,17 @@ public class GfsDataServiceImpl implements IDataService {
List<String> timeList = getResultTimeStringList(gridDataSet, tSize, origin[0]); List<String> timeList = getResultTimeStringList(gridDataSet, tSize, origin[0]);
result.setTime(timeList); 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; return result;
} }
@ -400,6 +411,11 @@ public class GfsDataServiceImpl implements IDataService {
throw new AppException(ErrorCode.RESPONSE_DATA_BUILD_ERROR); throw new AppException(ErrorCode.RESPONSE_DATA_BUILD_ERROR);
} }
} }
if (levelFlag == GfsLevelsEnum.SURFACE) {
if (result.getWindSpeed() != null) {
result.setWindScale(MeteoUtils.mPerSecond2WindScale(result.getWindSpeed()));
}
}
return result; return result;
} }
@ -446,41 +462,4 @@ public class GfsDataServiceImpl implements IDataService {
return variableNameInApi; return variableNameInApi;
} }
private Map<String, List> 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<String> forecastHours = lastGridDataSetMeta.getForecastHours();
List<Integer> iTimeList = new ArrayList<>();
List<String> 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<String, List> 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();
}
} }

@ -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.SurfaceWeatherWarning;
import com.htfp.weather.web.pojo.response.TimeSeriesDataset; import com.htfp.weather.web.pojo.response.TimeSeriesDataset;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
@ -30,11 +31,8 @@ import static com.htfp.weather.utils.HttpClientUtils.sendGet;
*/ */
@Service("caiyun") @Slf4j @Service("caiyun") @Slf4j
public class CaiYunServiceImpl implements ISurfaceDataService { public class CaiYunServiceImpl implements ISurfaceDataService {
@Value("${caiyun.key}")
private final String key = "Tc9tgOYr5jlPPlEw"; private String key;
private final HashMap<String, String> variableNameMap =
new HashMap<String, String>() {{
}};
static final String STATUS_OK = "ok"; static final String STATUS_OK = "ok";
public <T extends CaiYunBaseResponse> T caiYunRequest(String url, HashMap<String, String> params, Class<T> responseClass) { public <T extends CaiYunBaseResponse> T caiYunRequest(String url, HashMap<String, String> params, Class<T> responseClass) {
params.put("units", "metric:v2"); params.put("units", "metric:v2");
@ -126,6 +124,7 @@ public class CaiYunServiceImpl implements ISurfaceDataService {
nowWeatherStatus.setTemp(realtime.getTemperature()); nowWeatherStatus.setTemp(realtime.getTemperature());
nowWeatherStatus.setWindSpeed((float) MeteoUtils.kmPerHour2mPerSecond(realtime.getWind().getSpeed())); nowWeatherStatus.setWindSpeed((float) MeteoUtils.kmPerHour2mPerSecond(realtime.getWind().getSpeed()));
nowWeatherStatus.setWind360(realtime.getWind().getDirection()); nowWeatherStatus.setWind360(realtime.getWind().getDirection());
nowWeatherStatus.setWindScale(MeteoUtils.kmPerHour2WindScale(realtime.getWind().getSpeed()));
nowWeatherStatus.setHumidity(realtime.getHumidity()); nowWeatherStatus.setHumidity(realtime.getHumidity());
nowWeatherStatus.setCloud(realtime.getCloudrate()); nowWeatherStatus.setCloud(realtime.getCloudrate());

@ -178,13 +178,13 @@ public class HeFengServiceImpl implements ISurfaceDataService {
private NowWeatherStatus buildNowSurfaceWeatherStatus(HeFengNow now) { private NowWeatherStatus buildNowSurfaceWeatherStatus(HeFengNow now) {
NowWeatherStatus nowWeatherStatus = new NowWeatherStatus(); NowWeatherStatus nowWeatherStatus = new NowWeatherStatus();
processHeFengData(now); processHeFengData(now);
nowWeatherStatus.setTime(now.getObsTime()); nowWeatherStatus.setTime(DateTimeUtils.offsetDateTimeToSystemZone(OffsetDateTime.parse(now.getObsTime())).format(Constant.API_TIME_FORMATTER));
nowWeatherStatus.setWeatherText(now.getText()); nowWeatherStatus.setWeatherText(now.getText());
nowWeatherStatus.setTemp(now.getTemp()); nowWeatherStatus.setTemp(now.getTemp());
nowWeatherStatus.setWindSpeed(now.getWindSpeed()); nowWeatherStatus.setWindSpeed(now.getWindSpeed());
nowWeatherStatus.setWind360(now.getWind360()); nowWeatherStatus.setWind360(now.getWind360());
// nowSurfaceWeatherStatus.setWindDir(now.getWindDir()); // nowWeatherStatus.setWindDir(now.getWindDir());
// nowSurfaceWeatherStatus.setWindScale(now.getWindScale()); nowWeatherStatus.setWindScale(MeteoUtils.mPerSecond2WindScale(now.getWindSpeed()));
nowWeatherStatus.setHumidity(now.getHumidity()); nowWeatherStatus.setHumidity(now.getHumidity());
// nowWeatherStatus.setPressure(now.getPressure()); // nowWeatherStatus.setPressure(now.getPressure());
nowWeatherStatus.setCloud(now.getCloud()); nowWeatherStatus.setCloud(now.getCloud());

Loading…
Cancel
Save