2 * Copyright (c) 2010-2022 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.hccrubbishcollection.internal;
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;
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;
32 import com.google.gson.JsonElement;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonParser;
37 * The {@link API} contains all code relating to accessing the online rubbish collection API.
39 * @author Stewart Cossey - Initial contribution
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;
47 private final Logger logger = LoggerFactory.getLogger(API.class);
49 private final HttpClient httpClient;
50 private final String address;
52 private String errorDetailMessage = "";
53 private ThingStatusDetail errorDetail = ThingStatusDetail.NONE;
55 private @Nullable Integer collectionWeek = null;
56 private @Nullable Integer day = null;
57 private @Nullable ZonedDateTime recycling = null;
58 private @Nullable ZonedDateTime general = null;
61 * Create a new API class.
63 * @param httpClient The common http client provided from openHAB.
64 * @param address The address of the premises.
66 public API(HttpClient httpClient, String address) {
67 this.httpClient = httpClient;
68 this.address = address;
72 * Connects to the web service and gets the data.
74 * @return boolean Success.
76 public boolean update() {
78 final String url = REQUEST_URL + URLEncoder.encode(address, StandardCharsets.UTF_8);
80 logger.debug("Fetching data from URL {} (address hidden)", REQUEST_URL);
82 ContentResponse response = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT, TimeUnit.SECONDS).send();
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);
90 JsonObject jsonResponse = JsonParser.parseString(cleanedContent).getAsJsonObject();
92 JsonElement dayElement = jsonResponse.get("CollectionDay");
93 JsonElement collectionWeekElement = jsonResponse.get("CollectionWeek");
94 JsonElement generalElement = jsonResponse.get("RedBin");
95 JsonElement recyclingElement = jsonResponse.get("YellowBin");
97 // The elements are missing if the address is invalid or council does not service (due to address being
99 if (generalElement == null || recyclingElement == null) {
100 logger.debug("RedBin or YellowBin object is missing. Invalid premises or address");
102 errorDetail = ThingStatusDetail.CONFIGURATION_ERROR;
103 errorDetailMessage = "Invalid address";
107 // Get API dates as LocalDateTime objects.
108 LocalDateTime localGeneralDate = LocalDateTime.parse(generalElement.getAsString());
109 LocalDateTime localRecyclingDate = LocalDateTime.parse(recyclingElement.getAsString());
111 ZoneId zone = ZonedDateTime.now().getZone(); // Gets the local time zone.
113 // Convert LocalDateTime objects to be compatible with openHAB
114 ZonedDateTime zonedGeneralDate = ZonedDateTime.of(localGeneralDate, zone);
115 ZonedDateTime zonedRecyclingDate = ZonedDateTime.of(localRecyclingDate, zone);
117 errorDetail = ThingStatusDetail.NONE; // Sets to no error since we have successfully parsed response.
119 // Set the local properties with values from API.
120 recycling = zonedRecyclingDate;
121 general = zonedGeneralDate;
123 day = dayElement.getAsInt();
124 collectionWeek = collectionWeekElement.getAsInt();
128 logger.error("Data fetch failed, got HTTP Code {}", response.getStatus());
129 errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
130 errorDetailMessage = "HTTP Code " + response.getStatus();
133 } catch (TimeoutException to) {
134 errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
135 errorDetailMessage = "Response Timeout (will try again soon)";
137 } catch (InterruptedException | ExecutionException e) {
143 * Returns the last request status.
145 * @return ThingStatusDetail The openHAB error type.
147 public ThingStatusDetail getErrorDetail() {
152 * Gets the error, if occurred.
154 * @return String The error message.
156 public String getErrorDetailMessage() {
157 return errorDetailMessage;
161 * The collection week.
163 * @return Integer The week number.
165 public @Nullable Integer getCollectionWeek() {
166 return collectionWeek;
170 * Gets the collection day of week.
172 * @return Integer The day of the week. 1 = Monday.
174 public @Nullable Integer getDay() {
179 * The upcoming recycling collection date.
181 * @return ZonedDateTime
183 public @Nullable ZonedDateTime getRecyclingDate() {
188 * The upcoming general rubbish collection date.
190 * @return ZonedDateTime
192 public @Nullable ZonedDateTime getGeneralDate() {