瀏覽代碼

甘肃日天气数据
变成
星图15天+星图120小时+曦谋

xiaowang 1 月之前
父節點
當前提交
dd02e51390
共有 1 個文件被更改,包括 197 次插入42 次删除
  1. 197 42
      src/main/java/com/example/getweather/service/GetWeatherGeovisearth.java

+ 197 - 42
src/main/java/com/example/getweather/service/GetWeatherGeovisearth.java

@@ -1,5 +1,6 @@
 package com.example.getweather.service;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.db.Db;
 import cn.hutool.db.Entity;
 import cn.hutool.http.HttpUtil;
@@ -24,6 +25,7 @@ import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -113,8 +115,8 @@ public class GetWeatherGeovisearth {
     }
 
     public static Timestamp convertStringToTimestampHH(String dateStr) {
-        LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMddHH")); // 解析 yyyyMMddHH
-        return Timestamp.valueOf(localDate.atStartOfDay()); // 转换为当天的开始时间
+        LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+        return Timestamp.valueOf(localDateTime);
     }
 
     public static int extractLevel(String levelStr) {
@@ -138,6 +140,8 @@ public class GetWeatherGeovisearth {
         List<DistrictCodeDO> districtCodeDOList = new ArrayList<>();
         List<DistrictCodeDO> districtCodeDOList1 = new ArrayList<>();
         boolean isApiQuotaExhausted = false; // 引入标志变量
+        String startDate = DateUtil.today();
+        String endDate = DateUtil.offsetDay(DateUtil.date(), 15).toString("yyyy-MM-dd");
         try {
             List<Entity> dictList = Db.use().findAll("system_dict_data");
             for (Entity entity : dictList) {
@@ -188,22 +192,22 @@ public class GetWeatherGeovisearth {
                         List<DistrictCodeDO> quList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(d.getCode())).collect(Collectors.toList());
                         String url;
                         String url120;
-                        String caiyunUrl;
+                        String xmoUrl;
                         String location = d.getLng() + "," + d.getLat();
                         //xmo综合数据查询
                         url = "https://api.open.geovisearth.com/v2/cn/city/basic?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location + "&yesterday=false";
-                        url120 = "https://api.open.geovisearth.com/v2/precision_grid/forecast/day?start=" + getNowDateString() + "&end=" + getSevenDaysLater() + "&token=15d7d762ca3eca516c8344a24c8af2b6&meteCodes=ws_day,ws_night,wd_day,wd_night&location=" + location;
-                        caiyunUrl = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + location + "/weather?alert=true&dailysteps=7&hourlysteps=72";
-                        isApiQuotaExhausted = analysisGeovisearth(url, url120, caiyunUrl, d.getCode(), d.getName(), conn); // 传递标志变量
+                        url120 = "https://api.open.geovisearth.com/v2/cn/hourly/professional?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location;
+                        xmoUrl = "https://weather-api.xm-opt.com/v1/forecastDaily?latitude=" + d.getLat() + "&longitude=" + d.getLng() + "&daily=wind_speed_10m_max,shortwave_radiation_sum&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
+                        isApiQuotaExhausted = analysisGeovisearth(url, url120, xmoUrl, d.getCode(), d.getName(), conn); // 传递标志变量
                         if (isApiQuotaExhausted) break; // 检查标志变量
                         //区
                         for (DistrictCodeDO q : quList) {
                             if (isApiQuotaExhausted) break; // 检查标志变量
                             location = q.getLng() + "," + q.getLat();
                             url = "https://api.open.geovisearth.com/v2/cn/city/basic?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location + "&yesterday=false";
-                            url120 = "https://api.open.geovisearth.com/v2/precision_grid/forecast/day?start=" + getNowDateString() + "&end=" + getSevenDaysLater() + "&token=15d7d762ca3eca516c8344a24c8af2b6&meteCodes=ws_day,ws_night,wd_day,wd_night&location=" + location;
-                            caiyunUrl = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + location + "/weather?alert=true&dailysteps=7&hourlysteps=72";
-                            isApiQuotaExhausted = analysisGeovisearth(url, url120, caiyunUrl, q.getCode(), q.getName(), conn); // 传递标志变量
+                            url120 = "https://api.open.geovisearth.com/v2/cn/hourly/professional?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location;
+                            xmoUrl = "https://weather-api.xm-opt.com/v1/forecastDaily?latitude=" + q.getLat() + "&longitude=" + q.getLng() + "&daily=wind_speed_10m_max,shortwave_radiation_sum&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
+                            isApiQuotaExhausted = analysisGeovisearth(url, url120, xmoUrl, q.getCode(), q.getName(), conn); // 传递标志变量
                             if (isApiQuotaExhausted) break; // 检查标志变量
                             //线程睡5秒 防止请求过快
                             //花钱了 硬气 不管他
@@ -215,9 +219,9 @@ public class GetWeatherGeovisearth {
                         String location = d.getLng() + "," + d.getLat();
                         String url = "https://api.open.geovisearth.com/v2/cn/city/basic?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location + "&yesterday=false";
                         String url120 = "https://api.open.geovisearth.com/v2/precision_grid/forecast/day?start=" + getNowDateString() + "&end=" + getSevenDaysLater() + "&token=15d7d762ca3eca516c8344a24c8af2b6&meteCodes=ws_day,ws_night,wd_day,wd_night&location=" + location;
-                        String caiyunUrl = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + location + "/weather?alert=true&dailysteps=7&hourlysteps=72";
+                        String xmoUrl = "https://weather-api.xm-opt.com/v1/forecastDaily?latitude=" + d.getLat() + "&longitude=" + d.getLng() + "&daily=wind_speed_10m_max,shortwave_radiation_sum&timezone=Asia%2FShanghai&start_date=" + startDate + "&end_date=" + endDate;
                         if (isApiQuotaExhausted) break; // 检查标志变量
-                        isApiQuotaExhausted = analysisGeovisearth(url, url120, caiyunUrl, d.getCode(), d.getName(), conn); // 传递标志变量
+                        isApiQuotaExhausted = analysisGeovisearth(url, url120, xmoUrl, d.getCode(), d.getName(), conn); // 传递标志变量
                         if (isApiQuotaExhausted) break; // 检查标志变量
                     }
                 }
@@ -246,11 +250,11 @@ public class GetWeatherGeovisearth {
      * @param areaCode
      * @param name
      * @param conn      星图15天数据没有风速风向辐照度
-     *                  星图网格7天没有辐照度
-     *                  彩云7天只用辐照度
+     *                  星图120小时拼风速和风力等级
+     *                  曦谋15天拼后面的风速和辐照度
      * @return
      */
-    public boolean analysisGeovisearth(String url, String url120, String caiyunUrl, String areaCode, String name, Connection conn) {
+    public boolean analysisGeovisearth(String url, String url120, String xmoUrl, String areaCode, String name, Connection conn) {
         log.info("开始下载地区:{} 的天气数据", name);
         try {
             Statement ps = conn.createStatement();
@@ -258,11 +262,16 @@ public class GetWeatherGeovisearth {
             String body120 = HttpUtil.createGet(url120).execute().charset("utf-8").body();
             JSONObject jsonObject = JSONUtil.parseObj(body);
             JSONObject jsonObject120 = JSONUtil.parseObj(body120);
-            String bodyCaiyun = HttpUtil.createGet(caiyunUrl).header("apikey", "51bcabf8-3a5e-41e9-8bf2-b7676936cb22").execute().charset("utf-8").body();
-            JSONObject jsonObjectCaiyun = JSONUtil.parseObj(bodyCaiyun);
-            JSONObject resultCaiyun = JSONUtil.parseObj(jsonObjectCaiyun.get("result"));
-            JSONObject dailyCaiyun = JSONUtil.parseObj(resultCaiyun.get("daily"));
-            JSONArray dswrf = JSONUtil.parseArray(dailyCaiyun.get("dswrf"));
+            String bodyXmo = HttpUtil.createGet(xmoUrl).header("apikey", "c615a8f6-f5dd-4a81-86fe-db2a42862c15").execute().charset("utf-8").body();
+            JSONObject jsonObjectXmo = JSONUtil.parseObj(bodyXmo);
+            //日数据 7d
+            JSONObject xmoDaily = JSONUtil.parseObj(jsonObjectXmo.get("daily"));
+            //日期
+            JSONArray xmoDate = JSONUtil.parseArray(xmoDaily.get("time"));
+            //日->辐照度
+            JSONArray dswrfDay = JSONUtil.parseArray(xmoDaily.get("shortwave_radiation_sum"));
+            //日->风速
+            JSONArray windSpeedDay = JSONUtil.parseArray(xmoDaily.get("wind_speed_10m_max"));
             //log.info("获取到的数据为:{}", body);
             if (jsonObject.toString().contains("API call limit has been reached") || jsonObject120.toString().contains("API call limit has been reached")) {
                 return true;
@@ -275,7 +284,7 @@ public class GetWeatherGeovisearth {
             //日数据写入
             List<HeFengDay> heFengDayList = new ArrayList<>();
             List<HeFengDay> heFengDay120List = new ArrayList<>();
-            List<HeFengDay> caiyunList = new ArrayList<>();
+            List<HeFengDay> xmoList = new ArrayList<>();
             //数据结果是16天 D-1 到 D+14
             if (datas.size() == 15) {
                 for (int i = 0; i < datas.size(); i++) {
@@ -286,10 +295,10 @@ public class GetWeatherGeovisearth {
                     heFengDay.setTextNight(data.get("wp_night").toString());
                     heFengDay.setTempMax(Float.parseFloat(data.get("tem_max").toString()));
                     heFengDay.setTempMin(Float.parseFloat(data.get("tem_min").toString()));
-                    heFengDay.setWindDirDay(data.get("wd_day").toString());
-                    heFengDay.setWindDirNight(data.get("wd_night").toString());
-                    heFengDay.setWindScaleDay(extractLevel(data.get("ws_day").toString()));
-                    heFengDay.setWindScaleNight(extractLevel(data.get("ws_night").toString()));
+                    //heFengDay.setWindDirDay(data.get("wd_day").toString());
+                    //heFengDay.setWindDirNight(data.get("wd_night").toString());
+                    /*heFengDay.setWindScaleDay(extractLevel(data.get("ws_day").toString()));
+                    heFengDay.setWindScaleNight(extractLevel(data.get("ws_night").toString()));*/
                     heFengDay.setPrecip(Integer.parseInt(data.get("rh_max").toString()));
                     heFengDay.setPressure(Integer.parseInt(data.get("prs").toString()));
                     heFengDay.setHumidity(Float.parseFloat(data.get("pre_day").toString()) + Float.parseFloat(data.get("pre_night").toString()));
@@ -298,33 +307,173 @@ public class GetWeatherGeovisearth {
             } else {
                 log.info("{} 的星图日数据不足15天,不入库!", name);
             }
-            if (datas120.size() == 7) {
+            if (datas120.size() == 120) {
                 for (int i = 0; i < datas120.size(); i++) {
                     JSONObject data = (JSONObject) datas120.get(i);
                     HeFengDay heFengDay = new HeFengDay();
-                    heFengDay.setTs(convertStringToTimestampYMD(data.get("fc_time").toString()));
-                    JSONArray hour = JSONUtil.parseArray(data.get("values"));
-                    heFengDay.setWindSpeedDay(Float.parseFloat(hour.get(0).toString()));
-                    heFengDay.setWindSpeedNight(Float.parseFloat(hour.get(1).toString()));
-                    heFengDay.setWindSpeedMDay(Float.parseFloat(hour.get(0).toString()));
-                    heFengDay.setWindSpeedMNight(Float.parseFloat(hour.get(1).toString()));
-                    heFengDay.setWind360Day(Float.parseFloat(hour.get(2).toString()));
-                    heFengDay.setWind360Night(Float.parseFloat(hour.get(3).toString()));
+                    heFengDay.setTs(convertStringToTimestampHH(data.get("fc_time").toString()));
+                    heFengDay.setWindSpeedDay(Float.parseFloat(data.get("ws").toString()));
+                    heFengDay.setWindSpeedMDay(Float.parseFloat(data.get("ws").toString()));
+                    heFengDay.setWindSpeedNight(Float.parseFloat(data.get("ws").toString()));
+                    heFengDay.setWindSpeedMNight(Float.parseFloat(data.get("ws").toString()));
+                    heFengDay.setWindDirDay(data.get("wd_desc").toString());
+                    heFengDay.setWindDirNight(data.get("wd_desc").toString());
+                    heFengDay.setWindScaleDay(extractLevel(data.get("ws_desc").toString()));
+                    heFengDay.setWindScaleNight(extractLevel(data.get("ws_desc").toString()));
                     heFengDay120List.add(heFengDay);
                 }
+                //循环heFengDay120List 里面同一天的数据整合成一条 数据求平均值
+                // 创建一个新的列表来存储按天聚合后的数据
+                List<HeFengDay> aggregatedList = new ArrayList<>();
+
+                // 获取今天的日期
+                LocalDate today = LocalDate.now();
+
+                // 使用Map按日期分组数据
+                Map<LocalDate, List<HeFengDay>> groupedByDate = heFengDay120List.stream()
+                        .collect(Collectors.groupingBy(day -> day.getTs().toLocalDateTime().toLocalDate()));
+
+                // 遍历每一天的数据,计算平均值
+                for (Map.Entry<LocalDate, List<HeFengDay>> entry : groupedByDate.entrySet()) {
+                    LocalDate date = entry.getKey();
+
+                    // 排除今天的数据
+                    if (date.equals(today)) {
+                        continue;
+                    }
+
+                    List<HeFengDay> dailyData = entry.getValue();
+
+                    // 如果只有一天的数据,直接添加到结果列表
+                    if (dailyData.size() == 1) {
+                        aggregatedList.add(dailyData.get(0));
+                    } else {
+                        // 创建新的HeFengDay对象存储聚合后的数据
+                        HeFengDay aggregatedDay = new HeFengDay();
+
+                        // 设置日期为当天的开始时间
+                        aggregatedDay.setTs(Timestamp.valueOf(date.atStartOfDay()));
+
+                        // 计算各字段的平均值
+                        double windSpeedDaySum = 0;
+                        double windSpeedMDaySum = 0;
+                        double windSpeedNightSum = 0;
+                        double windSpeedMNightSum = 0;
+                        double wind360DaySum = 0;
+                        double wind360NightSum = 0;
+                        int windScaleDaySum = 0;
+                        int windScaleNightSum = 0;
+
+                        int validWindSpeedDayCount = 0;
+                        int validWindSpeedMDayCount = 0;
+                        int validWindSpeedNightCount = 0;
+                        int validWindSpeedMNightCount = 0;
+                        int validWind360DayCount = 0;
+                        int validWind360NightCount = 0;
+                        int validWindScaleDayCount = 0;
+                        int validWindScaleNightCount = 0;
+
+                        StringBuilder windDirDayBuilder = new StringBuilder();
+                        StringBuilder windDirNightBuilder = new StringBuilder();
+
+                        for (HeFengDay day : dailyData) {
+                            // 风速处理
+                            if (!Float.isNaN(day.getWindSpeedDay()) && day.getWindSpeedDay() != -0.99f) {
+                                windSpeedDaySum += day.getWindSpeedDay();
+                                validWindSpeedDayCount++;
+                            }
+                            if (!Float.isNaN(day.getWindSpeedMDay()) && day.getWindSpeedMDay() != -0.99f) {
+                                windSpeedMDaySum += day.getWindSpeedMDay();
+                                validWindSpeedMDayCount++;
+                            }
+                            if (!Float.isNaN(day.getWindSpeedNight()) && day.getWindSpeedNight() != -0.99f) {
+                                windSpeedNightSum += day.getWindSpeedNight();
+                                validWindSpeedNightCount++;
+                            }
+                            if (!Float.isNaN(day.getWindSpeedMNight()) && day.getWindSpeedMNight() != -0.99f) {
+                                windSpeedMNightSum += day.getWindSpeedMNight();
+                                validWindSpeedMNightCount++;
+                            }
+
+                            // 风向处理
+                            if (day.getWind360Day() != 0.0f) {
+                                wind360DaySum += day.getWind360Day();
+                                validWind360DayCount++;
+                            }
+                            if (day.getWind360Night() != 0.0f) {
+                                wind360NightSum += day.getWind360Night();
+                                validWind360NightCount++;
+                            }
+
+                            // 风力等级处理
+                            if (day.getWindScaleDay() != 0) {
+                                windScaleDaySum += day.getWindScaleDay();
+                                validWindScaleDayCount++;
+                            }
+                            if (day.getWindScaleNight() != 0) {
+                                windScaleNightSum += day.getWindScaleNight();
+                                validWindScaleNightCount++;
+                            }
+
+                            // 风向描述处理
+                            if (day.getWindDirDay() != null && !day.getWindDirDay().isEmpty()) {
+                                if (windDirDayBuilder.length() > 0) {
+                                    windDirDayBuilder.append(",");
+                                }
+                                windDirDayBuilder.append(day.getWindDirDay());
+                            }
+                            if (day.getWindDirNight() != null && !day.getWindDirNight().isEmpty()) {
+                                if (windDirNightBuilder.length() > 0) {
+                                    windDirNightBuilder.append(",");
+                                }
+                                windDirNightBuilder.append(day.getWindDirNight());
+                            }
+                        }
+
+                        // 设置平均值到聚合对象
+                        aggregatedDay.setWindSpeedDay(validWindSpeedDayCount > 0 ?
+                                (float) (windSpeedDaySum / validWindSpeedDayCount) : -0.99f);
+                        aggregatedDay.setWindSpeedMDay(validWindSpeedMDayCount > 0 ?
+                                (float) (windSpeedMDaySum / validWindSpeedMDayCount) : -0.99f);
+                        aggregatedDay.setWindSpeedNight(validWindSpeedNightCount > 0 ?
+                                (float) (windSpeedNightSum / validWindSpeedNightCount) : -0.99f);
+                        aggregatedDay.setWindSpeedMNight(validWindSpeedMNightCount > 0 ?
+                                (float) (windSpeedMNightSum / validWindSpeedMNightCount) : -0.99f);
+                        aggregatedDay.setWind360Day(validWind360DayCount > 0 ?
+                                (float) (wind360DaySum / validWind360DayCount) : 0.0f);
+                        aggregatedDay.setWind360Night(validWind360NightCount > 0 ?
+                                (float) (wind360NightSum / validWind360NightCount) : 0.0f);
+                        aggregatedDay.setWindScaleDay(validWindScaleDayCount > 0 ?
+                                (int) Math.round((double) windScaleDaySum / validWindScaleDayCount) : 0);
+                        aggregatedDay.setWindScaleNight(validWindScaleNightCount > 0 ?
+                                (int) Math.round((double) windScaleNightSum / validWindScaleNightCount) : 0);
+
+                        // 设置风向描述(这里简单地取第一个非空值)
+                        aggregatedDay.setWindDirDay(windDirDayBuilder.length() > 0 ?
+                                windDirDayBuilder.toString().split(",")[0] : "");
+                        aggregatedDay.setWindDirNight(windDirNightBuilder.length() > 0 ?
+                                windDirNightBuilder.toString().split(",")[0] : "");
+
+                        aggregatedList.add(aggregatedDay);
+                    }
+                }
+                // 用聚合后的数据替换原始列表
+                heFengDay120List = aggregatedList;
             } else {
                 log.info("{} 的星图精细化网格日数据不足7天,不入库!", name);
             }
-            if (dswrf.size() == 7) {
-                for (int j = 0; j < dswrf.size(); j++) {
-                    JSONObject data = JSONUtil.parseObj(dswrf.get(j));
+            if (!xmoDate.isEmpty()) {
+                for (int i = 0; i < xmoDate.size(); i++) {
+                    String time = xmoDate.get(i).toString();
                     HeFengDay heFengDay = new HeFengDay();
-                    heFengDay.setTs(getTimestamp(data.get("date").toString()));
-                    heFengDay.setDswrf(Float.parseFloat(data.get("avg").toString()));
-                    caiyunList.add(heFengDay);
+                    heFengDay.setTs(convertStringToTimestampYMD(time));
+                    heFengDay.setWindSpeedDay(windSpeedDay.get(i).toString().equals("null") ? -0.99f : new BigDecimal(windSpeedDay.get(i).toString()).floatValue());
+                    heFengDay.setWindSpeedMDay(windSpeedDay.get(i).toString().equals("null") ? -0.99f : new BigDecimal(windSpeedDay.get(i).toString()).floatValue() * 1000 / 3600);
+                    heFengDay.setDswrf(dswrfDay.get(i).toString().equals("null") ? -0.99f : new BigDecimal(dswrfDay.get(i).toString()).floatValue());
+                    xmoList.add(heFengDay);
                 }
             } else {
-                log.info("{} 的彩云综合预报数据不足7天,不入库!", name);
+                log.info("{} 的没有曦谋日数据,不入库!", name);
             }
             //捏合数据
             // 使用Map按日期进行数据合并,更加精确
@@ -352,11 +501,17 @@ public class GetWeatherGeovisearth {
             }
 
             // 合并第三个列表数据
-            for (HeFengDay item : caiyunList) {
+            for (HeFengDay item : xmoList) {
                 Timestamp date = item.getTs();
                 if (mergedMap.containsKey(date)) {
                     HeFengDay existing = mergedMap.get(date);
-                    existing.setDswrf(item.getDswrf());
+                    if (Float.isNaN(existing.getWindSpeedDay()) || existing.getWindSpeedDay() == 0) {
+                        existing.setWindSpeedMDay(item.getWindSpeedMDay());
+                        existing.setWindSpeedDay(item.getWindSpeedDay());
+                    }
+                    if (Float.isNaN(existing.getDswrf()) || existing.getDswrf() == 0) {
+                        existing.setDswrf(item.getDswrf());
+                    }
                 } else {
                     mergedMap.put(date, item);
                 }