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