]> git.basschouten.com Git - openhab-addons.git/blob
c7ca5d86ad299d74b28b40b8003b29fabbe43816
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.hccrubbishcollection.internal;
14
15 import java.io.UnsupportedEncodingException;
16 import java.net.URLEncoder;
17 import java.nio.charset.StandardCharsets;
18 import java.time.LocalDateTime;
19 import java.time.ZoneId;
20 import java.time.ZonedDateTime;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TimeoutException;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.eclipse.jetty.client.HttpClient;
28 import org.eclipse.jetty.client.api.ContentResponse;
29 import org.openhab.core.thing.ThingStatusDetail;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.gson.JsonElement;
34 import com.google.gson.JsonObject;
35 import com.google.gson.JsonParser;
36
37 /**
38  * The {@link API} contains all code relating to accessing the online rubbish collection API.
39  *
40  * @author Stewart Cossey - Initial contribution
41  */
42 @NonNullByDefault
43 public class API {
44     private static final int REQUEST_TIMEOUT = 10;
45     private static final String REQUEST_URL = "https://hccfightthelandfill.azure-api.net/get_Collection_Dates?address_string=";
46     private static final int HTTP_OK = 200;
47
48     private final Logger logger = LoggerFactory.getLogger(API.class);
49
50     private final HttpClient httpClient;
51     private final String address;
52
53     private String errorDetailMessage = "";
54     private ThingStatusDetail errorDetail = ThingStatusDetail.NONE;
55
56     private @Nullable Integer collectionWeek = null;
57     private @Nullable Integer day = null;
58     private @Nullable ZonedDateTime recycling = null;
59     private @Nullable ZonedDateTime general = null;
60
61     /**
62      * Create a new API class.
63      * 
64      * @param httpClient The common http client provided from openHAB.
65      * @param address The address of the premises.
66      */
67     public API(HttpClient httpClient, String address) {
68         this.httpClient = httpClient;
69         this.address = address;
70     }
71
72     /**
73      * Connects to the web service and gets the data.
74      * 
75      * @return boolean Success.
76      */
77     public boolean update() {
78         try {
79             final String url = REQUEST_URL + URLEncoder.encode(address, StandardCharsets.UTF_8.toString());
80
81             logger.debug("Fetching data from URL {} (address hidden)", REQUEST_URL);
82
83             ContentResponse response = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT, TimeUnit.SECONDS).send();
84
85             if (response.getStatus() == HTTP_OK) {
86                 String content = response.getContentAsString();
87                 // Return response is encapsulated in square brackets, remove to create valid json.
88                 String cleanedContent = content.trim().substring(1, content.length() - 1);
89                 logger.trace("Got cleaned content: {}", cleanedContent);
90
91                 JsonObject jsonResponse = JsonParser.parseString(cleanedContent).getAsJsonObject();
92
93                 JsonElement dayElement = jsonResponse.get("CollectionDay");
94                 JsonElement collectionWeekElement = jsonResponse.get("CollectionWeek");
95                 JsonElement generalElement = jsonResponse.get("RedBin");
96                 JsonElement recyclingElement = jsonResponse.get("YellowBin");
97
98                 // The elements are missing if the address is invalid or council does not service (due to address being
99                 // a business)
100                 if (generalElement == null || recyclingElement == null) {
101                     logger.debug("RedBin or YellowBin object is missing. Invalid premises or address");
102
103                     errorDetail = ThingStatusDetail.CONFIGURATION_ERROR;
104                     errorDetailMessage = "Invalid address";
105                     return false;
106                 }
107
108                 // Get API dates as LocalDateTime objects.
109                 LocalDateTime localGeneralDate = LocalDateTime.parse(generalElement.getAsString());
110                 LocalDateTime localRecyclingDate = LocalDateTime.parse(recyclingElement.getAsString());
111
112                 ZoneId zone = ZonedDateTime.now().getZone(); // Gets the local time zone.
113
114                 // Convert LocalDateTime objects to be compatible with openHAB
115                 ZonedDateTime zonedGeneralDate = ZonedDateTime.of(localGeneralDate, zone);
116                 ZonedDateTime zonedRecyclingDate = ZonedDateTime.of(localRecyclingDate, zone);
117
118                 errorDetail = ThingStatusDetail.NONE; // Sets to no error since we have successfully parsed response.
119
120                 // Set the local properties with values from API.
121                 recycling = zonedRecyclingDate;
122                 general = zonedGeneralDate;
123
124                 day = dayElement.getAsInt();
125                 collectionWeek = collectionWeekElement.getAsInt();
126
127                 return true;
128             } else {
129                 logger.error("Data fetch failed, got HTTP Code {}", response.getStatus());
130                 errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
131                 errorDetailMessage = "HTTP Code " + response.getStatus();
132                 return false;
133             }
134         } catch (UnsupportedEncodingException ue) {
135             errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
136             errorDetailMessage = "Encoding not supported!";
137             return false;
138         } catch (TimeoutException to) {
139             errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
140             errorDetailMessage = "Response Timeout (will try again soon)";
141             return false;
142         } catch (InterruptedException | ExecutionException e) {
143             return false;
144         }
145     }
146
147     /**
148      * Returns the last request status.
149      * 
150      * @return ThingStatusDetail The openHAB error type.
151      */
152     public ThingStatusDetail getErrorDetail() {
153         return errorDetail;
154     }
155
156     /**
157      * Gets the error, if occurred.
158      * 
159      * @return String The error message.
160      */
161     public String getErrorDetailMessage() {
162         return errorDetailMessage;
163     }
164
165     /**
166      * The collection week.
167      * 
168      * @return Integer The week number.
169      */
170     public @Nullable Integer getCollectionWeek() {
171         return collectionWeek;
172     }
173
174     /**
175      * Gets the collection day of week.
176      * 
177      * @return Integer The day of the week. 1 = Monday.
178      */
179     public @Nullable Integer getDay() {
180         return day;
181     }
182
183     /**
184      * The upcoming recycling collection date.
185      * 
186      * @return ZonedDateTime
187      */
188     public @Nullable ZonedDateTime getRecyclingDate() {
189         return recycling;
190     }
191
192     /**
193      * The upcoming general rubbish collection date.
194      * 
195      * @return ZonedDateTime
196      */
197     public @Nullable ZonedDateTime getGeneralDate() {
198         return general;
199     }
200 }