2024-07-03 16:11:21 +08:00

398 lines
17 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.zhgd.xmgl.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gexin.fastjson.JSON;
import com.gexin.fastjson.JSONObject;
import com.zhgd.redis.lock.RedisRepository;
import com.zhgd.xmgl.modules.basicdata.entity.SystemAreas;
import com.zhgd.xmgl.modules.basicdata.entity.SystemCities;
import com.zhgd.xmgl.modules.basicdata.mapper.SystemAreasMapper;
import com.zhgd.xmgl.modules.basicdata.mapper.SystemCitiesMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @program: wisdomSite
* @description: 空气质量分析AQI
* @author: Mr.Peng
* @create: 2020-09-28 09:56
**/
@Slf4j
@Component
public class AqiUtil {
private static SystemCitiesMapper systemCitiesMapper;
private static SystemAreasMapper systemAreasMapper;
private static RedisRepository redisRepository;
public static String SYSTEM_CITIES_KEY = "SYSTEM_CITIES";
public static String WEATHER_DATA = "WEATHER_DATA:";
private static String tianqiUrl;
private static String tianqiAppid;
private static String tianqiAppsecret;
/**
* 天气质量
*/
public static String WEATHER_QUALITY = "WEATHER_QUALITY:";
public static String WEATHER_LIVE = "WEATHER_LIVE:";
@Value("${tianqiUrl}")
public void setTianqiUrl(String tianqiUrl) {
AqiUtil.tianqiUrl = tianqiUrl;
}
@Value("${tianqiAppid}")
public void setTianqiAppid(String tianqiAppid) {
AqiUtil.tianqiAppid = tianqiAppid;
}
@Value("${tianqiAppsecret}")
public void setTianqiAppsecret(String tianqiAppsecret) {
AqiUtil.tianqiAppsecret = tianqiAppsecret;
}
@Autowired
public void setSystemCitiesMapper(SystemCitiesMapper systemCitiesMapper) {
AqiUtil.systemCitiesMapper = systemCitiesMapper;
}
@Autowired
public void setSystemAreasMapper(SystemAreasMapper systemAreasMapper) {
AqiUtil.systemAreasMapper = systemAreasMapper;
}
@Autowired
public void setRedisRepository(RedisRepository redisRepository) {
AqiUtil.redisRepository = redisRepository;
}
/**
* 计算aqi值对应的等级
*
* @param aqi
* @return
*/
public static int getPollutionDegree(Double aqi) {
int pollutionDegree = 1;
if (aqi <= 50) {
pollutionDegree = 1;
} else if (aqi > 50 && aqi <= 100) {
pollutionDegree = 2;
} else if (aqi > 100 && aqi <= 150) {
pollutionDegree = 3;
} else if (aqi > 150 && aqi <= 200) {
pollutionDegree = 4;
} else if (aqi > 200 && aqi <= 300) {
pollutionDegree = 5;
} else if (aqi > 300) {
pollutionDegree = 6;
}
return pollutionDegree;
}
/**
* @param @param pollutionDegree
* @param @return
* @return String @throws
* @Title: getDegree
* @Description: 计算aqi值对应的等级
*/
public static String getDegree(int pollutionDegree) {
if (pollutionDegree == 1) {
return "";
} else if (pollutionDegree == 2) {
return "";
} else if (pollutionDegree == 3) {
return "轻度污染";
} else if (pollutionDegree == 4) {
return "中度污染";
} else if (pollutionDegree == 5) {
return "重度污染";
} else if (pollutionDegree == 6) {
return "严重污染";
}
return "数据错误";
}
/**
* 计算每种污染物项目 P的空气质量分指数
*
* @param cp 污染物项目P的质量浓度
* @param r 污染物项目P所在数组中的行号
* @return
*/
public static double countPerIaqi(double cp, int r) {
double bph = 0; // 与 cp相近的污染物浓度限值的高位值
double bpl = 0; // 与 cp相近的污染物浓度限值的低位值
double iaqih = 0; // 与 bph对应的空气质量分指数
double iaqil = 0; // 与 bpl对应的空气质量分指数
double iaqip = 0; // 当前污染物项目P的空气质量分指数
// 空气质量分指数及对应的污染物项目浓度限值
int[][] aqiArr = {{0, 50, 100, 150, 200, 300, 400, 500}, {0, 35, 75, 115, 150, 250, 350, 500},
{0, 50, 150, 250, 350, 420, 500, 600}, {0, 2, 4, 14, 24, 36, 48, 60},
{0, 40, 80, 180, 280, 565, 750, 940}, {0, 160, 200, 300, 400, 800, 1000, 1200},
{0, 50, 150, 475, 800, 1600, 2100, 2620}, {0, 100, 160, 215, 265, 800}};
double min = aqiArr[r][0];
int index = aqiArr[r].length - 1;
double max = aqiArr[r][index];
if (cp <= min || cp >= max) {
return 0;
} else {
// 对每种污染物的bph、bpl、iaqih、iaqil进行赋值
for (int i = r; i < r + 1; i++) {
for (int j = 0; j < aqiArr[0].length; j++) {
if (cp < aqiArr[i][j]) {
bph = aqiArr[i][j];
bpl = aqiArr[i][j - 1];
iaqih = aqiArr[0][j];
iaqil = aqiArr[0][j - 1];
break;
}
}
}
// 计算污染物项目 P的空气质量分指数
iaqip = (iaqih - iaqil) / (bph - bpl) * (cp - bpl) + iaqil;
BigDecimal bg = new BigDecimal(Math.ceil(iaqip));
return bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
public static double getPm10IAQI(double pmte) {
if (pmte > 0) {
long round = Math.round(pmte);
return countPerIaqi(round, 2);
}
return 0;
}
public static double getPm25IAQI(double pmtw) {
if (pmtw > 0) {
long round = Math.round(pmtw);
return countPerIaqi(round, 1);
}
return 0;
}
/**
* 根据城市查询天气
*
* @param areaCode
* @return
*/
public static Double getWeatherInfo(String areaCode) {
String key = WEATHER_QUALITY + areaCode;
Object ro = redisRepository.get(key);
if (ro != null) {
return (Double) ro;
}
//空气指数
Double air = null;
try {
Map<String, Object> param = new HashMap<>(16);
param.put("appid", tianqiAppid);
param.put("appsecret", tianqiAppsecret);
List<SystemAreas> systemAreas = systemAreasMapper.selectList(new LambdaQueryWrapper<SystemAreas>()
.eq(SystemAreas::getAreaid, areaCode));
if (CollUtil.isNotEmpty(systemAreas)) {
param.put("cityid", systemAreas.get(0).getWeathercityid());
}
String urlString = tianqiUrl + "/free/day";
log.info("tianqi:url:{},param:{}", urlString, JSON.toJSONString(param));
String result = HttpUtil.get(urlString, param, 5000);
log.info("tianqi:rs:{}", result);
if (result != null && result.length() > 0) {
JSONObject obj = JSONObject.parseObject(result);
if (obj != null && obj.getString("air") != null) {
air = Double.valueOf(obj.getString("air"));
}
}
} catch (Exception e) {
log.error("error", e);
}
if (air == null) {
air = 80d;
}
redisRepository.set(key, air, 60 * 60L);
return air;
}
/**
* 实况天气
*
* @param cityCode cityid
* @return
*/
public static Object getLiveWeatherInfo(String cityCode) {
List<SystemCities> systemCities = redisRepository.getOrSet(SYSTEM_CITIES_KEY, () -> systemCitiesMapper.selectList(null), 60 * 60L);
String key = WEATHER_LIVE + cityCode;
Object ro = redisRepository.get(key);
if (ro != null) {
return (HashMap) ro;
}
Map<String, SystemCities> cityIdMap = systemCities.stream().collect(Collectors.toMap(e -> e.getCityid(), Function.identity(), (o, o2) -> o));
HashMap result = null;
try {
Map<String, Object> param = new HashMap<>(16);
param.put("appid", tianqiAppid);
param.put("appsecret", tianqiAppsecret);
String cityId = Optional.ofNullable(cityIdMap.get(cityCode)).map(e -> e.getWeathercityid()).orElse(null);
if (StringUtils.isNotBlank(cityId)) {
param.put("cityid", cityId);
}
String urlString = tianqiUrl + "/free/day";
log.info("tianqi:url:{},param:{}", urlString, JSON.toJSONString(param));
String rs = HttpUtil.get(urlString, param, 5000);
log.info("tianqi:rs:{}", rs);
result = JSON.parseObject(rs, HashMap.class);
} catch (Exception e) {
log.error("error", e);
}
redisRepository.set(key, result, 60 * 60L);
return result;
}
public static String getWeatherData(String cityid) {
String result = "";
try {
result = redisRepository.getOrSet(WEATHER_DATA + cityid, () -> {
Map<String, Object> param = new HashMap<>(16);
param.put("unescape", "1");
param.put("appid", tianqiAppid);
param.put("appsecret", tianqiAppsecret);
if (StringUtils.isNotEmpty(cityid)) {
param.put("cityid", cityid);
}
String r = HttpUtil.get(tianqiUrl + "/free/week", param);
log.info("tianqi-getWeatherDatars:{}", r);
JSONObject jsonObject = JSONObject.parseObject(r);
com.gexin.fastjson.JSONArray sevenDataArr = jsonObject.getJSONArray("data");
for (Object o : sevenDataArr) {
JSONObject jo = (JSONObject) o;
jo.put("cityid", jsonObject.get("cityid"));
jo.put("city", jsonObject.get("city"));
jo.put("cityEn", jsonObject.get("cityEn"));
jo.put("country", jsonObject.get("country"));
jo.put("countryEn", jsonObject.get("countryEn"));
jo.put("update_time", jsonObject.get("update_time"));
jo.put("tem1", jo.get("tem_day"));
jo.put("tem2", jo.get("tem_night"));
jo.put("day", jo.get("date"));
}
r = JSON.toJSONString(sevenDataArr);
log.info(r);
return r;
}, 60 * 60L);
} catch (Exception e) {
log.error("error", e);
result = "[{\"date\":\"2023-12-11\",\"tem_day\":\"29\",\"tem2\":\"20\",\"tem1\":\"29\",\"city\":\"深圳\",\"tem_night\":\"20\",\"cityid\":\"101280601\",\"wea\":\"多云\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yun\",\"win_speed\":\"<3级\",\"win\":\"无持续风向\",\"day\":\"2023-12-11\"},{\"date\":\"2023-12-12\",\"tem_day\":\"27\",\"tem2\":\"20\",\"tem1\":\"27\",\"city\":\"深圳\",\"tem_night\":\"20\",\"cityid\":\"101280601\",\"wea\":\"多云转阴\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yun\",\"win_speed\":\"<3级转3-4级\",\"win\":\"无持续风向\",\"day\":\"2023-12-12\"},{\"date\":\"2023-12-13\",\"tem_day\":\"25\",\"tem2\":\"20\",\"tem1\":\"25\",\"city\":\"深圳\",\"tem_night\":\"20\",\"cityid\":\"101280601\",\"wea\":\"多云\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yun\",\"win_speed\":\"3-4级转<3级\",\"win\":\"东风\",\"day\":\"2023-12-13\"},{\"date\":\"2023-12-14\",\"tem_day\":\"26\",\"tem2\":\"23\",\"tem1\":\"26\",\"city\":\"深圳\",\"tem_night\":\"23\",\"cityid\":\"101280601\",\"wea\":\"\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yin\",\"win_speed\":\"3-4级转<3级\",\"win\":\"东风\",\"day\":\"2023-12-14\"},{\"date\":\"2023-12-15\",\"tem_day\":\"28\",\"tem2\":\"16\",\"tem1\":\"28\",\"city\":\"深圳\",\"tem_night\":\"16\",\"cityid\":\"101280601\",\"wea\":\"多云转阴\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yun\",\"win_speed\":\"<3级\",\"win\":\"无持续风向\",\"day\":\"2023-12-15\"},{\"date\":\"2023-12-16\",\"tem_day\":\"25\",\"tem2\":\"11\",\"tem1\":\"25\",\"city\":\"深圳\",\"tem_night\":\"11\",\"cityid\":\"101280601\",\"wea\":\"\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yin\",\"win_speed\":\"3-4级\",\"win\":\"东北风\",\"day\":\"2023-12-16\"},{\"date\":\"2023-12-17\",\"tem_day\":\"15\",\"tem2\":\"10\",\"tem1\":\"15\",\"city\":\"深圳\",\"tem_night\":\"10\",\"cityid\":\"101280601\",\"wea\":\"小雨\",\"update_time\":\"2023-12-11 10:47:17\",\"wea_img\":\"yu\",\"win_speed\":\"3-4级\",\"win\":\"北风\",\"day\":\"2023-12-17\"}]";
}
return result;
}
/**
* 获取风速等级
*
* @param windSpeed
* @return
*/
public static String getWindSpeedLevel(Double windSpeed) {
//风级 名称 风速(m/s) (km/h) 陆地地面物象
//0 无风 0.0-0.2 <1 静,烟直上
//1 软风 0.3-1.5 1-5 烟示风向
//2 轻风 1.6-3.3 6-11 感觉有风
//3 微风 3.4-5.4 12-19 旌旗展开
//4 和风 5.5-7.9 20-28 吹起尘土
//5 清风 8.0-10.7 29-38 小树摇摆
//6 强风 10.8-13.8 39-49 电线有声
//7 劲风(疾风) 13.9-17.1 50-61 步行困难
//8 大风 17.2-20.7 62-74 折毁树枝
//9 烈风 20.8-24.4 75-88 小损房屋
//10 狂风 24.5-28.4 89-102 拔起树木
//11 暴风 28.5-32.6 103-117 损毁重大
//12 台风(一级飓风) 32.7-36.9 117-134 摧毁极大
//13 台风(一级飓风) 37.0-41.4 134-149
//14 强台风(二级飓风) 41.5-46.1 150-166
//15 强台风(三级飓风) 46.2-50.9 167-183
//16 超强台风(三级飓风) 51.0-56.0 184-201
//17 超强台风(四级飓风) 56.1-61.2 202-220
//17+ 超强台风(四级飓风) ≥61.3 ≥221
//超级台风(五级飓风) ≥250
if (windSpeed == null) {
return null;
}
if (windSpeed >= 0 && windSpeed < 0.3) {
return "0级";
} else if (windSpeed >= 0.3 && windSpeed < 1.6) {
return "1级";
} else if (windSpeed >= 1.6 && windSpeed < 3.4) {
return "2级";
} else if (windSpeed >= 3.4 && windSpeed < 5.5) {
return "3级";
} else if (windSpeed >= 5.5 && windSpeed < 8) {
return "4级";
} else if (windSpeed >= 8 && windSpeed < 10.8) {
return "5级";
} else if (windSpeed >= 10.8 && windSpeed < 13.9) {
return "6级";
} else if (windSpeed >= 13.9 && windSpeed < 17.2) {
return "7级";
} else if (windSpeed >= 17.2 && windSpeed < 20.8) {
return "8级";
} else if (windSpeed >= 20.8 && windSpeed < 24.5) {
return "9级";
} else if (windSpeed >= 24.5 && windSpeed < 28.5) {
return "10级";
} else if (windSpeed >= 28.5 && windSpeed < 32.7) {
return "11级";
} else if (windSpeed >= 32.7 && windSpeed < 37) {
return "12级";
} else if (windSpeed >= 37 && windSpeed < 41.5) {
return "13级";
} else if (windSpeed >= 41.5 && windSpeed < 46.2) {
return "14级";
} else if (windSpeed >= 46.2 && windSpeed < 51) {
return "15级";
} else if (windSpeed >= 51 && windSpeed < 56.1) {
return "16级";
} else if (windSpeed >= 56.1 && windSpeed < 61.3) {
return "17级";
} else if (windSpeed >= 61.3) {
return "17+级";
}
return null;
}
public static void main(String[] args) {
/*double temp=getPm25IAQI(85d);
log.info(temp);
log.info(getDegree(getPollutionDegree(temp)));级*/
//log.info(getWeatherInfo("110100"));
//log.info(getWeatherData("110100"));
//System.out.println(getWeatherInfo("11"));
//log.info(getDegree(getPollutionDegree(39d)));
try {
String result = HttpUtil.get("https://v0.yiketianqi.com/free/day", 1000);
} catch (HttpException e) {
log.error("error", e);
}
System.out.println(123);
}
}