package eirb.pg203; import org.json.JSONArray; import org.json.JSONObject; import eirb.pg203.utils.JSONFetcher; import java.io.IOException; import java.net.URI; import java.net.URL; import java.time.Instant; import java.util.ArrayList; import eirb.pg203.WeatherData.Condition; // https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m public class OpenMeteo implements WeatherDataAPI { private static final String forecastBaseURL = "https://api.open-meteo.com/v1/forecast"; private static final String dailyQuery = "weather_code,temperature_2m_max,temperature_2m_min,wind_speed_10m_max,wind_direction_10m_dominant"; // https://www.nodc.noaa.gov/archive/arc0021/0002199/1.1/data/0-data/HTML/WMO-CODE/WMO4677.HTM private JSONObject fetchWeather(int days, City city) throws IOException { URL url = URI.create( String.format(forecastBaseURL + "?latitude=%.2f&longitude=%.2f&forecast_days=%d&daily=" + dailyQuery, city.getCityCoords().getLat(), city.getCityCoords().getLon(), days ) ).toURL(); JSONArray jsonArray = JSONFetcher.fetchArray(url); return jsonArray.getJSONObject(0); } private static Condition getConditionFromCode(int WMOCode) { if (WMOCode < 20) return Condition.SUNNY; else if (WMOCode < 30) return Condition.RAINY; else if (WMOCode < 50) return Condition.CLOUDY; else return Condition.RAINY; } private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) { JSONObject daily = response.getJSONObject("daily"); float max_temp = daily.getJSONArray("temperature_2m_max").getFloat(day); float min_temp = daily.getJSONArray("temperature_2m_min").getFloat(day); float temp_c = (min_temp + max_temp) / 2; float windSpeed = daily.getJSONArray("wind_speed_10m_max").getFloat(day); float windDirection = daily.getJSONArray("wind_direction_10m_dominant").getFloat(day); int conditionCode = daily.getJSONArray("weather_code").getInt(day); return new WeatherData( new City(city), Instant.now(), temp_c, windSpeed, windDirection, getConditionFromCode(conditionCode) ); } /** * @param day Day, 0 ≤ day ≤ 14 */ @Override public WeatherData getTemperature(int day, String city) throws IOException { JSONObject result = fetchWeather(day + 1, new City(city)); return getWeatherDataFromForecast(result, day, city); } @Override public WeatherData getTemperature(int day, int hour, String city) throws IOException{ return getTemperature(day, city); } @Override public ArrayList getTemperatures(int days, String city) throws IOException { JSONObject result = fetchWeather(days, new City(city)); ArrayList weatherDatas = new ArrayList<>(); for (int day = 0; day < days; ++day) { weatherDatas.add( getWeatherDataFromForecast(result, day, city) ); } return weatherDatas; } @Override public String getAPIName() { return "OpenMeteo"; } }