]> git.basschouten.com Git - openhab-addons.git/blob
884a453c19570407c2743e1ab3a25ec10b005d54
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.airquality.internal.api;
14
15 import java.io.IOException;
16 import java.util.concurrent.TimeUnit;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.airquality.internal.AirQualityException;
20 import org.openhab.binding.airquality.internal.api.dto.AirQualityData;
21 import org.openhab.binding.airquality.internal.api.dto.AirQualityResponse;
22 import org.openhab.binding.airquality.internal.api.dto.AirQualityResponse.ResponseStatus;
23 import org.openhab.core.io.net.http.HttpUtil;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import com.google.gson.Gson;
28 import com.google.gson.JsonSyntaxException;
29
30 /**
31  * The {@link ApiBridge} is the interface between handlers
32  * and the actual web service
33  *
34  * @author GaĆ«l L'hopital - Initial contribution
35  */
36 @NonNullByDefault
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);
41
42     private final Logger logger = LoggerFactory.getLogger(ApiBridge.class);
43     private final String apiKey;
44
45     public ApiBridge(String apiKey) {
46         this.apiKey = apiKey;
47     }
48
49     /**
50      * Build request URL from configuration data
51      *
52      * @return a valid URL for the aqicn.org service
53      * @throws AirQualityException
54      */
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());
59
60         return URL.replace("%apiKey%", key).replace("%query%", geoStr);
61     }
62
63     /**
64      * Request new air quality data to the aqicn.org service
65      *
66      * @return an air quality data object mapping the JSON response
67      * @throws AirQualityException
68      */
69     public AirQualityData getData(int stationId, String location, int retryCounter) throws AirQualityException {
70         String urlStr = buildRequestURL(apiKey, stationId, location);
71         logger.debug("URL = {}", urlStr);
72
73         try {
74             String response = HttpUtil.executeUrl("GET", urlStr, null, null, null, REQUEST_TIMEOUT_MS);
75             logger.debug("aqiResponse = {}", response);
76             AirQualityResponse result = GSON.fromJson(response, AirQualityResponse.class);
77             if (result != null && result.getStatus() == ResponseStatus.OK) {
78                 return result.getData();
79             } else if (retryCounter == 0) {
80                 logger.debug("Error in aqicn.org, retrying once");
81                 return getData(stationId, location, retryCounter + 1);
82             }
83             throw new AirQualityException("Error in aqicn.org response: Missing data sub-object");
84         } catch (IOException | JsonSyntaxException e) {
85             throw new AirQualityException("Communication error", e);
86         }
87     }
88 }