mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[hccrubbishcollection] HCC Rubbish Collection Binding - Initial Contribution (#9975)
Signed-off-by: Stewart Cossey <stewart.cossey@gmail.com>
This commit is contained in:
parent
710aa760d0
commit
02b4943a11
@ -101,6 +101,7 @@
|
||||
/bundles/org.openhab.binding.haassohnpelletstove/ @chingon007
|
||||
/bundles/org.openhab.binding.harmonyhub/ @digitaldan
|
||||
/bundles/org.openhab.binding.haywardomnilogic/ @matchews
|
||||
/bundles/org.openhab.binding.hccrubbishcollection/ @cossey
|
||||
/bundles/org.openhab.binding.hdanywhere/ @kgoderis
|
||||
/bundles/org.openhab.binding.hdpowerview/ @beowulfe
|
||||
/bundles/org.openhab.binding.helios/ @kgoderis
|
||||
|
@ -491,6 +491,11 @@
|
||||
<artifactId>org.openhab.binding.haywardomnilogic</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.hccrubbishcollection</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.hdanywhere</artifactId>
|
||||
|
13
bundles/org.openhab.binding.hccrubbishcollection/NOTICE
Normal file
13
bundles/org.openhab.binding.hccrubbishcollection/NOTICE
Normal file
@ -0,0 +1,13 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab-addons
|
46
bundles/org.openhab.binding.hccrubbishcollection/README.md
Normal file
46
bundles/org.openhab.binding.hccrubbishcollection/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# HCC Rubbish Collection Binding
|
||||
|
||||
A Hamilton City Council (NZ) _"Fight the Landfill"_ binding.
|
||||
This binding will keep track of your rubbish collection days and uses the [Fight the Landfill](https://www.fightthelandfill.co.nz/) website API to fetch the upcoming collection dates.
|
||||
|
||||
## Supported Things
|
||||
|
||||
A single supported thing called `collection`.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The thing supports one setting labelled `address` which is your street number and name as it appears on Google.
|
||||
*For Example:
|
||||
1 Victoria Street*
|
||||
|
||||
> Note: The above address example is not valid as it is a business address.
|
||||
|
||||
*__If the address is not valid or rubbish collection service does not apply (for example, a business address) then a `CONFIGURATION_ERROR` will occur.__*
|
||||
|
||||
## Channels
|
||||
|
||||
| channel | type | description |
|
||||
| ---------------- | ------ | -------------------------------------------------------------------- |
|
||||
| day | Number | The upcoming rubbish collection day of the week (1=Monday, 7=Sunday) |
|
||||
| general | Date | The next general household (red bin) collection day |
|
||||
| recycling | Date | The next recycling (yellow bin, glass bin) colleciton day |
|
||||
| collection-event | Event | Event trigger on the day of the rubbish |
|
||||
|
||||
### Collection Event
|
||||
|
||||
The collection event `collection-event` triggers on the day of rubbish collection.
|
||||
|
||||
#### Events
|
||||
|
||||
| event | description |
|
||||
| --------- | ------------------------------- |
|
||||
| GENERAL | General household rubbish event |
|
||||
| RECYCLING | Recycling rubbish event |
|
||||
|
||||
#### Configuration
|
||||
|
||||
You can set an `offset` in minutes.
|
||||
This can then trigger the collection event before or after the normal time of 12:00am on the day of the collection.
|
||||
|
||||
*For Example:
|
||||
If you want the event to trigger at 7pm the day before, to remind you to take out the bins, then set the `offset` to `-300` (5 hours x 60 minutes).*
|
17
bundles/org.openhab.binding.hccrubbishcollection/pom.xml
Normal file
17
bundles/org.openhab.binding.hccrubbishcollection/pom.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.hccrubbishcollection</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: HCC Rubbish Collection Binding</name>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.hccrubbishcollection-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-hccrubbishcollection" description="HCC Rubbish Collection Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.hccrubbishcollection/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hccrubbishcollection.internal;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link API} contains all code relating to accessing the online rubbish collection API.
|
||||
*
|
||||
* @author Stewart Cossey - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class API {
|
||||
private static final int REQUEST_TIMEOUT = 10;
|
||||
private static final String REQUEST_URL = "https://hccfightthelandfill.azure-api.net/get_Collection_Dates?address_string=";
|
||||
private static final int HTTP_OK = 200;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(API.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final String address;
|
||||
|
||||
private String errorDetailMessage = "";
|
||||
private ThingStatusDetail errorDetail = ThingStatusDetail.NONE;
|
||||
|
||||
private @Nullable Integer collectionWeek = null;
|
||||
private @Nullable Integer day = null;
|
||||
private @Nullable ZonedDateTime recycling = null;
|
||||
private @Nullable ZonedDateTime general = null;
|
||||
|
||||
/**
|
||||
* Create a new API class.
|
||||
*
|
||||
* @param httpClient The common http client provided from openHAB.
|
||||
* @param address The address of the premises.
|
||||
*/
|
||||
public API(HttpClient httpClient, String address) {
|
||||
this.httpClient = httpClient;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the web service and gets the data.
|
||||
*
|
||||
* @return boolean Success.
|
||||
*/
|
||||
public boolean update() {
|
||||
try {
|
||||
final String url = REQUEST_URL + URLEncoder.encode(address, StandardCharsets.UTF_8.toString());
|
||||
|
||||
logger.debug("Fetching data from URL {} (address hidden)", REQUEST_URL);
|
||||
|
||||
ContentResponse response = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT, TimeUnit.SECONDS).send();
|
||||
|
||||
if (response.getStatus() == HTTP_OK) {
|
||||
String content = response.getContentAsString();
|
||||
// Return response is encapsulated in square brackets, remove to create valid json.
|
||||
String cleanedContent = content.trim().substring(1, content.length() - 1);
|
||||
logger.trace("Got cleaned content: {}", cleanedContent);
|
||||
|
||||
JsonObject jsonResponse = JsonParser.parseString(cleanedContent).getAsJsonObject();
|
||||
|
||||
JsonElement dayElement = jsonResponse.get("CollectionDay");
|
||||
JsonElement collectionWeekElement = jsonResponse.get("CollectionWeek");
|
||||
JsonElement generalElement = jsonResponse.get("RedBin");
|
||||
JsonElement recyclingElement = jsonResponse.get("YellowBin");
|
||||
|
||||
// The elements are missing if the address is invalid or council does not service (due to address being
|
||||
// a business)
|
||||
if (generalElement == null || recyclingElement == null) {
|
||||
logger.debug("RedBin or YellowBin object is missing. Invalid premises or address");
|
||||
|
||||
errorDetail = ThingStatusDetail.CONFIGURATION_ERROR;
|
||||
errorDetailMessage = "Invalid address";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get API dates as LocalDateTime objects.
|
||||
LocalDateTime localGeneralDate = LocalDateTime.parse(generalElement.getAsString());
|
||||
LocalDateTime localRecyclingDate = LocalDateTime.parse(recyclingElement.getAsString());
|
||||
|
||||
ZoneId zone = ZonedDateTime.now().getZone(); // Gets the local time zone.
|
||||
|
||||
// Convert LocalDateTime objects to be compatible with openHAB
|
||||
ZonedDateTime zonedGeneralDate = ZonedDateTime.of(localGeneralDate, zone);
|
||||
ZonedDateTime zonedRecyclingDate = ZonedDateTime.of(localRecyclingDate, zone);
|
||||
|
||||
errorDetail = ThingStatusDetail.NONE; // Sets to no error since we have successfully parsed response.
|
||||
|
||||
// Set the local properties with values from API.
|
||||
recycling = zonedRecyclingDate;
|
||||
general = zonedGeneralDate;
|
||||
|
||||
day = dayElement.getAsInt();
|
||||
collectionWeek = collectionWeekElement.getAsInt();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
logger.error("Data fetch failed, got HTTP Code {}", response.getStatus());
|
||||
errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
|
||||
errorDetailMessage = "HTTP Code " + response.getStatus();
|
||||
return false;
|
||||
}
|
||||
} catch (UnsupportedEncodingException ue) {
|
||||
errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
|
||||
errorDetailMessage = "Encoding not supported!";
|
||||
return false;
|
||||
} catch (TimeoutException to) {
|
||||
errorDetail = ThingStatusDetail.COMMUNICATION_ERROR;
|
||||
errorDetailMessage = "Response Timeout (will try again soon)";
|
||||
return false;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last request status.
|
||||
*
|
||||
* @return ThingStatusDetail The openHAB error type.
|
||||
*/
|
||||
public ThingStatusDetail getErrorDetail() {
|
||||
return errorDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error, if occurred.
|
||||
*
|
||||
* @return String The error message.
|
||||
*/
|
||||
public String getErrorDetailMessage() {
|
||||
return errorDetailMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* The collection week.
|
||||
*
|
||||
* @return Integer The week number.
|
||||
*/
|
||||
public @Nullable Integer getCollectionWeek() {
|
||||
return collectionWeek;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collection day of week.
|
||||
*
|
||||
* @return Integer The day of the week. 1 = Monday.
|
||||
*/
|
||||
public @Nullable Integer getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
/**
|
||||
* The upcoming recycling collection date.
|
||||
*
|
||||
* @return ZonedDateTime
|
||||
*/
|
||||
public @Nullable ZonedDateTime getRecyclingDate() {
|
||||
return recycling;
|
||||
}
|
||||
|
||||
/**
|
||||
* The upcoming general rubbish collection date.
|
||||
*
|
||||
* @return ZonedDateTime
|
||||
*/
|
||||
public @Nullable ZonedDateTime getGeneralDate() {
|
||||
return general;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hccrubbishcollection.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link HCCRubbishCollectionBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Stewart Cossey - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HCCRubbishCollectionBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "hccrubbishcollection";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_COLLECTION = new ThingTypeUID(BINDING_ID, "collection");
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_DAY = "day";
|
||||
public static final String CHANNEL_BIN_GENERAL = "general";
|
||||
public static final String CHANNEL_BIN_RECYCLING = "recycling";
|
||||
|
||||
public static final String TRIGGER_COLLECTION = "collection-event";
|
||||
public static final String EVENT_RECYCLING = "RECYCLING";
|
||||
public static final String EVENT_GENERAL = "GENERAL";
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hccrubbishcollection.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link HCCRubbishCollectionConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Stewart Cossey - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HCCRubbishCollectionConfiguration {
|
||||
public String address = "";
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hccrubbishcollection.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link HCCRubbishCollectionEventConfiguration} class defines configuration for the collection event channel.
|
||||
*
|
||||
* @author Stewart Cossey - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HCCRubbishCollectionEventConfiguration {
|
||||
public int offset;
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hccrubbishcollection.internal;
|
||||
|
||||
import static org.openhab.binding.hccrubbishcollection.internal.HCCRubbishCollectionBindingConstants.*;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link HCCRubbishCollectionHandler} is responsible for handling commands,
|
||||
* updating the channels and polling the API.
|
||||
*
|
||||
* @author Stewart Cossey - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HCCRubbishCollectionHandler extends BaseThingHandler {
|
||||
private static final int DELAY_NETWORKERROR = 3; // On network error tries again in 3 minutes.
|
||||
private static final int DELAY_UPDATE = 480; // Polls API every 8 hours.
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HCCRubbishCollectionHandler.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private @Nullable API api;
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshScheduler; // The API refresh scheduler
|
||||
private @Nullable ScheduledFuture<?> collectionScheduler; // The Collection event trigger scheduler
|
||||
|
||||
/** Object disposing flag */
|
||||
private boolean isDisposing = false;
|
||||
|
||||
/**
|
||||
* Create Handler.
|
||||
*
|
||||
* @param thing The thing type passed from the Handler Factory.
|
||||
* @param httpClient The common http client provided from openHAB.
|
||||
*/
|
||||
public HCCRubbishCollectionHandler(Thing thing, HttpClient httpClient) {
|
||||
super(thing);
|
||||
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a command coming from openHAB.
|
||||
* Only RefreshType is supported as all channels are read only.
|
||||
*
|
||||
* @param channelUID The channel UID.
|
||||
* @param command The command.
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
updateNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the data immediately.
|
||||
*/
|
||||
private void updateNow() {
|
||||
if (isDisposing) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Updating data immediately");
|
||||
stopUpdate(false);
|
||||
startUpdate(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
final HCCRubbishCollectionConfiguration config = getConfigAs(HCCRubbishCollectionConfiguration.class);
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
api = new API(httpClient, config.address);
|
||||
startUpdate(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Rubbish collection data from the {@link API} and updates the
|
||||
* channels with the data.
|
||||
*/
|
||||
private void updateData() {
|
||||
logger.debug("Fetching new data");
|
||||
final API localApi = api;
|
||||
if (localApi != null) {
|
||||
if (isDisposing) {
|
||||
return;
|
||||
}
|
||||
if (localApi.update()) {
|
||||
if (isDisposing) {
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE); // Updates Thing to online since API update was successful.
|
||||
|
||||
Integer localDay = localApi.getDay();
|
||||
if (localDay != null) {
|
||||
updateState(CHANNEL_DAY, new DecimalType(localDay));
|
||||
}
|
||||
|
||||
ZonedDateTime localGeneralDate = localApi.getGeneralDate();
|
||||
if (localGeneralDate != null) {
|
||||
updateState(CHANNEL_BIN_GENERAL, new DateTimeType(localGeneralDate));
|
||||
}
|
||||
|
||||
ZonedDateTime localRecyclingDate = localApi.getRecyclingDate();
|
||||
if (localRecyclingDate != null) {
|
||||
updateState(CHANNEL_BIN_RECYCLING, new DateTimeType(localRecyclingDate));
|
||||
}
|
||||
|
||||
if (localGeneralDate != null && localRecyclingDate != null) {
|
||||
setupCollectionEvent(localGeneralDate, localRecyclingDate);
|
||||
} else {
|
||||
logger.debug("Cannot setup Collection Event, one or both collection dates are null.");
|
||||
}
|
||||
} else {
|
||||
if (localApi.getErrorDetail() != ThingStatusDetail.COMMUNICATION_ERROR) {
|
||||
updateStatus(ThingStatus.OFFLINE, localApi.getErrorDetail(), localApi.getErrorDetailMessage());
|
||||
stopUpdate(false);
|
||||
} else {
|
||||
stopUpdate(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.error("API object is null, cannot update");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates some values for the Collection Event before setting up the
|
||||
* Collection trigger {@link #scheduleCollectionEvent}.
|
||||
*
|
||||
* @param generalDate The General Rubbish Collection Date and Time.
|
||||
* @param recyclingDate The Recycling Collection Date and Time.
|
||||
*/
|
||||
private void setupCollectionEvent(ZonedDateTime generalDate, ZonedDateTime recyclingDate) {
|
||||
logger.trace("Setup Collection Trigger");
|
||||
|
||||
String event;
|
||||
ZonedDateTime dateTime;
|
||||
if (generalDate.compareTo(recyclingDate) < 0) {
|
||||
logger.trace("Using General Date {} for Event", generalDate);
|
||||
dateTime = generalDate;
|
||||
event = EVENT_GENERAL;
|
||||
} else {
|
||||
logger.trace("Using Recycling Date {} for Event", recyclingDate);
|
||||
dateTime = recyclingDate;
|
||||
event = EVENT_RECYCLING;
|
||||
}
|
||||
|
||||
logger.trace("Loading channel config");
|
||||
Channel collectionTriggerChannel = getThing().getChannel(TRIGGER_COLLECTION);
|
||||
HCCRubbishCollectionEventConfiguration collectionEventConfig = (collectionTriggerChannel == null) ? null
|
||||
: collectionTriggerChannel.getConfiguration().as(HCCRubbishCollectionEventConfiguration.class);
|
||||
|
||||
long offset = 0;
|
||||
if (collectionEventConfig != null) {
|
||||
offset = (long) collectionEventConfig.offset;
|
||||
} else {
|
||||
logger.debug("Could not get event config, default offset of {} set", offset);
|
||||
}
|
||||
|
||||
ZonedDateTime offsettedDateTime = dateTime.plusMinutes(offset);
|
||||
logger.trace("Event offset by {} minutes, new datetime {}", offset, offsettedDateTime);
|
||||
scheduleCollectionEvent(offsettedDateTime, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the collection event trigger.
|
||||
*
|
||||
* @param dateTime The Date and time to trigger the Collection Event.
|
||||
* @param event The name of the Event to be triggered.
|
||||
*/
|
||||
private void scheduleCollectionEvent(ZonedDateTime dateTime, String event) {
|
||||
stopScheduleCollectionEvent(); // Stop the currently scheduled event
|
||||
|
||||
if (isDisposing) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.trace("Setup Collection Trigger Scheduler");
|
||||
|
||||
logger.trace("Local Time {}", ZonedDateTime.now());
|
||||
long delay = dateTime.toEpochSecond() - ZonedDateTime.now().toEpochSecond();
|
||||
|
||||
logger.debug("Start collection scheduler, delay {} seconds ({} minutes)", delay, delay / 60);
|
||||
if (delay > 0) {
|
||||
collectionScheduler = scheduler.schedule(() -> {
|
||||
if (isDisposing) {
|
||||
return;
|
||||
}
|
||||
triggerChannel(TRIGGER_COLLECTION, event);
|
||||
}, delay, TimeUnit.SECONDS);
|
||||
} else {
|
||||
logger.debug("Collection trigger delay already in past, ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the data update scheduler.
|
||||
*
|
||||
* @param delay The start delay in minutes. 0 executes an immediate update.
|
||||
*/
|
||||
private void startUpdate(int delay) {
|
||||
if (isDisposing) {
|
||||
return;
|
||||
}
|
||||
logger.debug("Start refresh scheduler, delay {}", delay);
|
||||
|
||||
refreshScheduler = scheduler.scheduleWithFixedDelay(this::updateData, delay, DELAY_UPDATE, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the scheduler for the collection event trigger.
|
||||
*/
|
||||
private void stopScheduleCollectionEvent() {
|
||||
ScheduledFuture<?> localCollectionScheduler = collectionScheduler;
|
||||
logger.debug("Stopping Collection Trigger Scheduler");
|
||||
if (localCollectionScheduler != null) {
|
||||
localCollectionScheduler.cancel(true);
|
||||
collectionScheduler = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the data update scheduler (stops updating data). If stopping due to a
|
||||
* network error, then resets the update scheduler {@link #startUpdate(int)}
|
||||
* with an initial delay to wait a short period then try again.
|
||||
*
|
||||
* @param networkError Set to true if a network error. False if terminating.
|
||||
*/
|
||||
private void stopUpdate(boolean networkError) {
|
||||
final ScheduledFuture<?> localRefreshScheduler = refreshScheduler;
|
||||
logger.debug("Stopping updater scheduler, networkError = {}", networkError);
|
||||
if (localRefreshScheduler != null) {
|
||||
localRefreshScheduler.cancel(true);
|
||||
refreshScheduler = null;
|
||||
}
|
||||
if (networkError) {
|
||||
logger.debug("Waiting {} minutes to try again", DELAY_NETWORKERROR);
|
||||
startUpdate(DELAY_NETWORKERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
isDisposing = true; // Set true to exit any running functions
|
||||
stopUpdate(false);
|
||||
stopScheduleCollectionEvent();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hccrubbishcollection.internal;
|
||||
|
||||
import static org.openhab.binding.hccrubbishcollection.internal.HCCRubbishCollectionBindingConstants.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link HCCRubbishCollectionHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Stewart Cossey - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.hccrubbishcollection", service = ThingHandlerFactory.class)
|
||||
public class HCCRubbishCollectionHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_COLLECTION);
|
||||
|
||||
@Activate
|
||||
public HCCRubbishCollectionHandlerFactory(final @Reference HttpClientFactory httpClientFactory) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_COLLECTION.equals(thingTypeUID)) {
|
||||
return new HCCRubbishCollectionHandler(thing, httpClient);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="hccrubbishcollection" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>HCC Rubbish Collection Binding</name>
|
||||
<description>Get the rubbish collection dates for Hamilton City Council (New Zealand).</description>
|
||||
|
||||
</binding:binding>
|
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="hccrubbishcollection"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="collection">
|
||||
<label>HCC NZ Rubbish Collection</label>
|
||||
<description>Rubbish collection days for Hamilton City Council (NZ).</description>
|
||||
|
||||
<channels>
|
||||
<channel id="day" typeId="day"/>
|
||||
<channel id="recycling" typeId="bin">
|
||||
<label>Recycling Bin Collection Date</label>
|
||||
<description>The next collection date of the recycling (yellow bin and green bin).</description>
|
||||
</channel>
|
||||
<channel id="general" typeId="bin">
|
||||
<label>General Bin Collection Date</label>
|
||||
<description>The next collection date of the general rubbish (red bin).</description>
|
||||
</channel>
|
||||
<channel id="collection-event" typeId="collection-event"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The street address to get rubbish collection dates for.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="day">
|
||||
<item-type>Number</item-type>
|
||||
<label>Collection Day</label>
|
||||
<description>The rubbish collection Day of the Week</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="1">Monday</option>
|
||||
<option value="2">Tuesday</option>
|
||||
<option value="3">Wednesday</option>
|
||||
<option value="4">Thursday</option>
|
||||
<option value="5">Friday</option>
|
||||
<option value="6">Saturday</option>
|
||||
<option value="7">Sunday</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="bin">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Collection Date</label>
|
||||
<state pattern="%1$tY-%1$tm-%1$td" readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="collection-event">
|
||||
<kind>trigger</kind>
|
||||
<label>Collection Event</label>
|
||||
<description>Event for the day when collection occurs.</description>
|
||||
<event>
|
||||
<options>
|
||||
<option value="RECYCLING">RECYCLING</option>
|
||||
<option value="GENERAL">GENERAL</option>
|
||||
</options>
|
||||
</event>
|
||||
<config-description>
|
||||
<parameter name="offset" type="integer" min="-2880" max="2880" unit="min">
|
||||
<label>Offset</label>
|
||||
<description>Moves the event forward or backward (in minutes).</description>
|
||||
<default>0</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -133,6 +133,7 @@
|
||||
<module>org.openhab.binding.haassohnpelletstove</module>
|
||||
<module>org.openhab.binding.harmonyhub</module>
|
||||
<module>org.openhab.binding.haywardomnilogic</module>
|
||||
<module>org.openhab.binding.hccrubbishcollection</module>
|
||||
<module>org.openhab.binding.hdanywhere</module>
|
||||
<module>org.openhab.binding.hdpowerview</module>
|
||||
<module>org.openhab.binding.helios</module>
|
||||
|
Loading…
Reference in New Issue
Block a user