2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.weathercompany.internal.handler;
15 import java.io.IOException;
16 import java.util.concurrent.Future;
17 import java.util.concurrent.TimeUnit;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.jetty.client.HttpResponseException;
22 import org.openhab.binding.weathercompany.internal.config.WeatherCompanyBridgeConfig;
23 import org.openhab.binding.weathercompany.internal.util.ExceptionUtils;
24 import org.openhab.core.io.net.http.HttpUtil;
25 import org.openhab.core.thing.Bridge;
26 import org.openhab.core.thing.ChannelUID;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.openhab.core.thing.binding.BaseBridgeHandler;
30 import org.openhab.core.types.Command;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * The {@link WeatherCompanyBridgeHandler} is responsible for validating the API key
36 * used to access the Weather Company API.
38 * @author Mark Hilbush - Initial contribution
41 public class WeatherCompanyBridgeHandler extends BaseBridgeHandler {
42 private static final long KEY_VALIDATION_FREQ_SECONDS = 120L;
43 private static final String BASE_URL = "https://api.weather.com/v3/location/search?query=chicago&locationType=locid&language=en-US&format=json&apiKey=";
45 private final Logger logger = LoggerFactory.getLogger(WeatherCompanyBridgeHandler.class);
47 private @Nullable Future<?> validateApiKeyJob;
49 private final Runnable validateApiKeyRunnable = new Runnable() {
52 logger.debug("Bridge: Attempting to validate API key");
54 String url = BASE_URL + getConfigAs(WeatherCompanyBridgeConfig.class).apiKey;
55 String response = HttpUtil.executeUrl("GET", url, 10000);
56 // If we get a response, we know the API key is valid
57 logger.debug("Bridge: Got a successful response to key validation: '{}'", response);
58 updateStatus(ThingStatus.ONLINE);
59 cancelValidateApiKeyJob();
60 } catch (IOException e) {
61 Throwable rootcause = ExceptionUtils.getRootThrowable(e);
62 if (rootcause instanceof HttpResponseException
63 && rootcause.getMessage().contains("Authentication challenge without")) {
64 logger.debug("Bridge: HttpResponseException: API key is not valid");
65 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
66 "@text/offline.config-error-invalid-api-key");
68 logger.debug("Bridge: IOException trying to validate Api key: {}", e.getMessage());
69 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, e.getMessage());
75 public WeatherCompanyBridgeHandler(Bridge thing) {
80 public void initialize() {
81 scheduleValidateApiKeyJob();
85 public void dispose() {
86 cancelValidateApiKeyJob();
90 public void handleCommand(ChannelUID channelUID, Command command) {
91 // Bridge doesn't handle any commands
94 public @Nullable String getApiKey() {
95 return getConfigAs(WeatherCompanyBridgeConfig.class).apiKey;
98 private void scheduleValidateApiKeyJob() {
99 cancelValidateApiKeyJob();
100 validateApiKeyJob = scheduler.scheduleWithFixedDelay(validateApiKeyRunnable, 0L, KEY_VALIDATION_FREQ_SECONDS,
102 logger.debug("Bridge: Scheduling job to validate API key");
105 private void cancelValidateApiKeyJob() {
106 if (validateApiKeyJob != null) {
107 validateApiKeyJob.cancel(true);
108 validateApiKeyJob = null;
109 logger.debug("Bridge: Canceling job to validate API key");