Skip to content

Commit

Permalink
[openweathermap] Improved exception handling (openhab#11949)
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
Signed-off-by: Nick Waterton <n.waterton@outlook.com>
  • Loading branch information
cweitkamp authored and NickWaterton committed Apr 27, 2022
1 parent ea2b156 commit e7b07f6
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 208 deletions.

This file was deleted.

This file was deleted.

Expand Up @@ -15,7 +15,6 @@
import static org.eclipse.jetty.http.HttpMethod.GET;
import static org.eclipse.jetty.http.HttpStatus.*;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
Expand Down Expand Up @@ -46,6 +45,8 @@
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler;
import org.openhab.core.cache.ByteArrayFileCache;
import org.openhab.core.cache.ExpiringCacheMap;
import org.openhab.core.i18n.CommunicationException;
import org.openhab.core.i18n.ConfigurationException;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.library.types.PointType;
import org.openhab.core.library.types.RawType;
Expand Down Expand Up @@ -121,11 +122,11 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param location location represented as {@link PointType}
* @return the current weather data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapJsonWeatherData getWeatherData(@Nullable PointType location)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
throws JsonSyntaxException, CommunicationException, ConfigurationException {
return gson.fromJson(
getResponseFromCache(
buildURL(WEATHER_URL, getRequestParams(handler.getOpenWeatherMapAPIConfig(), location))),
Expand All @@ -139,14 +140,14 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param count number of hours
* @return the hourly forecast data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapJsonHourlyForecastData getHourlyForecastData(
@Nullable PointType location, int count)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
throws JsonSyntaxException, CommunicationException, ConfigurationException {
if (count <= 0) {
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-not-supported-number-of-hours");
throw new ConfigurationException("@text/offline.conf-error-not-supported-number-of-hours");
}

Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
Expand All @@ -163,14 +164,13 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param count number of days
* @return the daily forecast data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapJsonDailyForecastData getDailyForecastData(@Nullable PointType location,
int count)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
int count) throws JsonSyntaxException, CommunicationException, ConfigurationException {
if (count <= 0) {
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-not-supported-number-of-days");
throw new ConfigurationException("@text/offline.conf-error-not-supported-number-of-days");
}

Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
Expand All @@ -186,11 +186,11 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param location location represented as {@link PointType}
* @return the UV Index data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapJsonUVIndexData getUVIndexData(@Nullable PointType location)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
throws JsonSyntaxException, CommunicationException, ConfigurationException {
return gson.fromJson(
getResponseFromCache(
buildURL(UVINDEX_URL, getRequestParams(handler.getOpenWeatherMapAPIConfig(), location))),
Expand All @@ -203,15 +203,14 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param location location represented as {@link PointType}
* @return the UV Index forecast data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable List<OpenWeatherMapJsonUVIndexData> getUVIndexForecastData(
@Nullable PointType location, int count)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
throws JsonSyntaxException, CommunicationException, ConfigurationException {
if (count <= 0) {
throw new OpenWeatherMapConfigurationException(
"@text/offline.conf-error-not-supported-uvindex-number-of-days");
throw new ConfigurationException("@text/offline.conf-error-not-supported-uvindex-number-of-days");
}

Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
Expand All @@ -227,11 +226,11 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param location location represented as {@link PointType}
* @return the Air Pollution data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapJsonAirPollutionData getAirPollutionData(@Nullable PointType location)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
throws JsonSyntaxException, CommunicationException, ConfigurationException {
return gson.fromJson(
getResponseFromCache(
buildURL(AIR_POLLUTION_URL, getRequestParams(handler.getOpenWeatherMapAPIConfig(), location))),
Expand All @@ -245,12 +244,11 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param location location represented as {@link PointType}
* @return the Air Pollution forecast data
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapJsonAirPollutionData getAirPollutionForecastData(
@Nullable PointType location)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
@Nullable PointType location) throws JsonSyntaxException, CommunicationException, ConfigurationException {
return gson.fromJson(
getResponseFromCache(buildURL(AIR_POLLUTION_FORECAST_URL,
getRequestParams(handler.getOpenWeatherMapAPIConfig(), location))),
Expand Down Expand Up @@ -303,12 +301,12 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param excludeDaily if true, will not fetch hourly forecast data from the server
* @return
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapOneCallAPIData getOneCallAPIData(@Nullable PointType location,
boolean excludeMinutely, boolean excludeHourly, boolean excludeDaily, boolean excludeAlerts)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
throws JsonSyntaxException, CommunicationException, ConfigurationException {
Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
List<String> exclude = new ArrayList<>();
if (excludeMinutely) {
Expand Down Expand Up @@ -339,12 +337,11 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt
* @param days number of days in the past, relative to the current time.
* @return
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws CommunicationException
* @throws ConfigurationException
*/
public synchronized @Nullable OpenWeatherMapOneCallHistAPIData getOneCallHistAPIData(@Nullable PointType location,
int days)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
int days) throws JsonSyntaxException, CommunicationException, ConfigurationException {
Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
// the API requests the history as timestamp in Unix time format.
params.put(PARAM_HISTORY_DATE,
Expand All @@ -355,14 +352,14 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt

private Map<String, String> getRequestParams(OpenWeatherMapAPIConfiguration config, @Nullable PointType location) {
if (location == null) {
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-missing-location");
throw new ConfigurationException("@text/offline.conf-error-missing-location");
}

Map<String, String> params = new HashMap<>();
// API key (see https://openweathermap.org/appid)
String apikey = config.apikey;
if (apikey == null || (apikey = apikey.trim()).isEmpty()) {
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-missing-apikey");
throw new ConfigurationException("@text/offline.conf-error-missing-apikey");
}
params.put(PARAM_APPID, apikey);

Expand All @@ -387,15 +384,7 @@ private String buildURL(String url, Map<String, String> requestParams) {
}

private String encodeParam(@Nullable String value) {
if (value == null) {
return "";
}
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
logger.debug("UnsupportedEncodingException occurred during execution: {}", e.getLocalizedMessage(), e);
return "";
}
return value == null ? "" : URLEncoder.encode(value, StandardCharsets.UTF_8);
}

private @Nullable String getResponseFromCache(String url) {
Expand All @@ -421,26 +410,29 @@ private String getResponse(String url) {
case NOT_FOUND_404:
errorMessage = getErrorMessage(content);
logger.debug("OpenWeatherMap server responded with status code {}: {}", httpStatus, errorMessage);
throw new OpenWeatherMapConfigurationException(errorMessage);
throw new ConfigurationException(errorMessage);
case TOO_MANY_REQUESTS_429:
// TODO disable refresh job temporarily (see https://openweathermap.org/appid#Accesslimitation)
default:
errorMessage = getErrorMessage(content);
logger.debug("OpenWeatherMap server responded with status code {}: {}", httpStatus, errorMessage);
throw new OpenWeatherMapCommunicationException(errorMessage);
throw new CommunicationException(errorMessage);
}
} catch (ExecutionException e) {
String errorMessage = e.getLocalizedMessage();
logger.trace("Exception occurred during execution: {}", errorMessage, e);
String errorMessage = e.getMessage();
logger.debug("ExecutionException occurred during execution: {}", errorMessage, e);
if (e.getCause() instanceof HttpResponseException) {
logger.debug("OpenWeatherMap server responded with status code {}: Invalid API key.", UNAUTHORIZED_401);
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-invalid-apikey", e.getCause());
throw new ConfigurationException("@text/offline.conf-error-invalid-apikey", e.getCause());
} else {
throw new OpenWeatherMapCommunicationException(errorMessage, e.getCause());
throw new CommunicationException(
errorMessage == null ? "@text/offline.communication-error" : errorMessage, e.getCause());
}
} catch (InterruptedException | TimeoutException e) {
logger.debug("Exception occurred during execution: {}", e.getLocalizedMessage(), e);
throw new OpenWeatherMapCommunicationException(e.getLocalizedMessage(), e.getCause());
String errorMessage = e.getMessage();
logger.debug("InterruptedException or TimeoutException occurred during execution: {}", errorMessage, e);
throw new CommunicationException(errorMessage == null ? "@text/offline.communication-error" : errorMessage,
e.getCause());
}
}

Expand Down

0 comments on commit e7b07f6

Please sign in to comment.