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.airquality.internal.api;
15 import java.io.IOException;
16 import java.util.Objects;
17 import java.util.concurrent.TimeUnit;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.binding.airquality.internal.AirQualityException;
21 import org.openhab.binding.airquality.internal.api.dto.AirQualityData;
22 import org.openhab.binding.airquality.internal.api.dto.AirQualityResponse;
23 import org.openhab.core.io.net.http.HttpUtil;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import com.google.gson.Gson;
28 import com.google.gson.JsonSyntaxException;
31 * The {@link ApiBridge} is the interface between handlers
32 * and the actual web service
34 * @author Gaƫl L'hopital - Initial contribution
37 public class ApiBridge {
38 private static final Gson GSON = new Gson();
39 private static final String URL = "http://api.waqi.info/feed/%query%/?token=%apiKey%";
40 private static final int REQUEST_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(30);
42 private final Logger logger = LoggerFactory.getLogger(ApiBridge.class);
43 private final String apiKey;
45 public ApiBridge(String apiKey) {
50 * Build request URL from configuration data
52 * @return a valid URL for the aqicn.org service
53 * @throws AirQualityException
55 private String buildRequestURL(String key, int stationId, String location) {
56 String geoStr = stationId != 0 ? String.format("@%d", stationId)
57 : String.format("geo:%s",
58 location.replace(" ", "").replace(",", ";").replace("\"", "").replace("'", "").trim());
60 return URL.replace("%apiKey%", key).replace("%query%", geoStr);
64 * Request new air quality data to the aqicn.org service
66 * @return an air quality data object mapping the JSON response
67 * @throws AirQualityException
69 public AirQualityData getData(int stationId, String location) throws AirQualityException {
70 String urlStr = buildRequestURL(apiKey, stationId, location);
71 logger.debug("URL = {}", urlStr);
74 String response = HttpUtil.executeUrl("GET", urlStr, null, null, null, REQUEST_TIMEOUT_MS);
75 if (response != null) {
76 logger.debug("aqiResponse = {}", response);
77 AirQualityResponse result = GSON.fromJson(response, AirQualityResponse.class);
79 String error = result.getErrorMessage();
80 if (error.isEmpty()) {
81 return Objects.requireNonNull(result.getData());
83 throw new AirQualityException("Error raised : %s", error);
86 throw new JsonSyntaxException("API response is null");
87 } catch (IOException | JsonSyntaxException e) {
88 throw new AirQualityException("Communication error", e);