From 29596dedf077fc61f9d14c7b814fd7d7e44a473d Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Wed, 9 Aug 2023 17:23:39 +0930 Subject: [PATCH 01/30] Initial Commit Signed-off-by: Paul Smedley --- .../org.openhab.binding.amberelectric/NOTICE | 13 ++ .../README.md | 21 +++ .../org.openhab.binding.amberelectric/pom.xml | 17 +++ .../src/main/feature/feature.xml | 9 ++ .../AmberElectricBindingConstants.java | 43 ++++++ .../AmberElectricCommunicationException.java | 37 +++++ .../internal/AmberElectricConfiguration.java | 24 +++ .../internal/AmberElectricHandler.java | 143 ++++++++++++++++++ .../internal/AmberElectricHandlerFactory.java | 49 ++++++ .../internal/AmberElectricWebTargets.java | 89 +++++++++++ .../internal/api/CurrentPrices.java | 54 +++++++ .../amberelectric/internal/api/Sites.java | 47 ++++++ .../src/main/resources/OH-INF/addon/addon.xml | 11 ++ .../resources/OH-INF/thing/thing-types.xml | 68 +++++++++ 14 files changed, 625 insertions(+) create mode 100644 bundles/org.openhab.binding.amberelectric/NOTICE create mode 100644 bundles/org.openhab.binding.amberelectric/README.md create mode 100644 bundles/org.openhab.binding.amberelectric/pom.xml create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml diff --git a/bundles/org.openhab.binding.amberelectric/NOTICE b/bundles/org.openhab.binding.amberelectric/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/NOTICE @@ -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 diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md new file mode 100644 index 0000000000000..0d7c828dfc9dc --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -0,0 +1,21 @@ +# Amber Electric Binding +A binding that supports the Amber Electric API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. + +## Supported Things +Amber Electric API + + +## Discovery + +Auto-discover is not currently supported. +You need to manually add a new thing using your API key + +## Thing Configuration + + +## Channels + + +## Full Example + + diff --git a/bundles/org.openhab.binding.amberelectric/pom.xml b/bundles/org.openhab.binding.amberelectric/pom.xml new file mode 100644 index 0000000000000..9a3715565e0f2 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.1.0-SNAPSHOT + + + org.openhab.binding.amberelectric + + openHAB Add-ons :: Bundles :: Amber Electric Binding + + diff --git a/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml b/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml new file mode 100644 index 0000000000000..5ccc50218ec2d --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.amberelectric/${project.version} + + diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java new file mode 100644 index 0000000000000..6952a26be2993 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link AmberElectricBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Paul Smedley - Initial contribution + */ +@NonNullByDefault +public class AmberElectricBindingConstants { + + private static final String BINDING_ID = "amberelectric"; + + // List of all Thing Type UIDs + public static final ThingTypeUID AMBERELECTRIC_THING = new ThingTypeUID(BINDING_ID, "amberelectric"); + + // List of all Channel ids + public static final String CHANNEL_AMBERELECTRIC_ELECPRICE = "elecprice"; + public static final String CHANNEL_AMBERELECTRIC_NEMTIME = "nemtime"; + public static final String CHANNEL_AMBERELECTRIC_RENEWABLES = "renewables"; + public static final String CHANNEL_AMBERELECTRIC_SPIKE = "spike"; + public static final String CHANNEL_AMBERELECTRIC_SPOTPRICE = "spotprice"; + + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(AMBERELECTRIC_THING); +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java new file mode 100644 index 0000000000000..9ec1b962b7305 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal; + +import java.io.IOException; + +/** + * Exception for when an unexpected response is received from the AmberAPI. + * + * @author Paul Smedley - Initial contribution + * + */ +public class AmberElectricCommunicationException extends IOException { + private static final long serialVersionUID = 529232811860854017L; + + public AmberElectricCommunicationException(String message) { + super(message); + } + + public AmberElectricCommunicationException(Throwable ex) { + super(ex); + } + + public AmberElectricCommunicationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java new file mode 100644 index 0000000000000..be0627a76b680 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal; + +/** + * The AmberElectricConfiguration class contains fields mapping thing configuration parameters. + * + * @author Paul Smedley - Initial contribution + */ +public class AmberElectricConfiguration { + public String apikey; + public String site; + public long refresh = 60; +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java new file mode 100644 index 0000000000000..b2378cb0e5a0f --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal; + +import java.io.IOException; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.amberelectric.internal.api.CurrentPrices; +import org.openhab.binding.amberelectric.internal.api.Sites; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.StringType; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link AmberElectricHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Paul Smedley - Initial contribution + */ +@NonNullByDefault +public class AmberElectricHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(AmberElectricHandler.class); + + private long refreshInterval; + private @Nullable String siteID; + private @Nullable String apikey; + + private @NonNullByDefault({}) AmberElectricWebTargets webTargets; + private @Nullable ScheduledFuture pollFuture; + + public AmberElectricHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.warn("This binding is read only"); + } + + @Override + public void initialize() { + AmberElectricConfiguration config = getConfigAs(AmberElectricConfiguration.class); + if (config.apikey == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "API Key must be set"); + } else { + webTargets = new AmberElectricWebTargets(config.site); + refreshInterval = config.refresh; + siteID = config.site; + apikey = config.apikey; + + schedulePoll(); + } + } + + @Override + public void dispose() { + super.dispose(); + stopPoll(); + } + + private void schedulePoll() { + if (pollFuture != null) { + pollFuture.cancel(false); + } + logger.debug("Scheduling poll for 1 second out, then every {} s", refreshInterval); + pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 1, refreshInterval, TimeUnit.SECONDS); + } + + private void poll() { + try { + logger.debug("Polling for state"); + pollStatus(); + } catch (IOException e) { + logger.debug("Could not connect to AmberAPI", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } catch (RuntimeException e) { + logger.warn("Unexpected error connecting to AmberAPI", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + private void stopPoll() { + final Future future = pollFuture; + if (future != null && !future.isCancelled()) { + future.cancel(true); + pollFuture = null; + } + } + + private void pollStatus() throws IOException { + + if (siteID == null) { + Sites sites = webTargets.getSites(apikey); + // add error handling + siteID = sites.siteid; + logger.debug("Detected amber siteid is {}", sites.siteid); + } + + CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apikey); + updateStatus(ThingStatus.ONLINE); + if (currentPrices != null) { + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, + new DecimalType(currentPrices.perKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, + new StringType(currentPrices.nemTime)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, + new DecimalType(currentPrices.renewables)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPOTPRICE, + new DecimalType(currentPrices.spotPerKwh)); + switch (currentPrices.spikeStatus) { + case "none": + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); + break; + default: + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.ON); + break; + } + } + } +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java new file mode 100644 index 0000000000000..f60ac44749315 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +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.Component; + +/** + * The {@link AmberElectricHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Paul Smedley - Initial contribution + */ +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.amberelectric") +@NonNullByDefault +public class AmberElectricHandlerFactory extends BaseThingHandlerFactory { + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return AmberElectricBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(AmberElectricBindingConstants.AMBERELECTRIC_THING)) { + return new AmberElectricHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java new file mode 100644 index 0000000000000..d66157ced7c37 --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.openhab.binding.amberelectric.internal.api.CurrentPrices; +import org.openhab.binding.amberelectric.internal.api.Sites; +import org.openhab.core.io.net.http.HttpUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles performing the actual HTTP requests for communicating with the AmberAPI. + * + * @author Paul Smedley - Initial Contribution + * + */ +public class AmberElectricWebTargets { + private static final int TIMEOUT_MS = 30000; + + private String getSitesUri; + private String getCurrentPricesUri; + private final Logger logger = LoggerFactory.getLogger(AmberElectricWebTargets.class); + + public AmberElectricWebTargets(String siteid) { + String getSitesUri = "https://api.amber.com.au/v1/sites"; + String getCurrentPricesUri = getSitesUri + "/" + siteid + "/prices/current"; + } + + public Sites getSites(String apikey) throws AmberElectricCommunicationException { + String getSitesUri = "https://api.amber.com.au/v1/sites"; + String response = invoke("GET", getSitesUri, apikey); + return Sites.parse(response); + } + + public CurrentPrices getCurrentPrices(String siteid, String apikey) throws AmberElectricCommunicationException { + String getCurrentPricesUri = "https://api.amber.com.au/v1/sites/" + siteid + "/prices/current"; + String response = invoke("GET", getCurrentPricesUri, apikey); + return CurrentPrices.parse(response); + } + + protected Properties getHttpHeaders(String accessToken) { + Properties httpHeaders = new Properties(); + httpHeaders.put("Authorization", "Bearer " + accessToken); + httpHeaders.put("Content-Type", "application/json"); + return httpHeaders; + } + + private String invoke(String httpMethod, String uri, String accessToken) + throws AmberElectricCommunicationException { + return invoke(httpMethod, uri, accessToken, null, null); + } + + private String invoke(String httpMethod, String uri, String apikey, InputStream content, String contentType) + throws AmberElectricCommunicationException { + logger.debug("Calling url: {}", uri); + String response; + synchronized (this) { + try { + response = HttpUtil.executeUrl(httpMethod, uri, getHttpHeaders(apikey), content, contentType, + TIMEOUT_MS); + } catch (IOException ex) { + logger.debug("{}", ex.getLocalizedMessage(), ex); + // Response will also be set to null if parsing in executeUrl fails so we use null here to make the + // error check below consistent. + response = null; + } + } + + if (response.isEmpty()) { + throw new AmberElectricCommunicationException( + String.format("AmberElectric returned no response while invoking %s", uri)); + } + return response; + } +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java new file mode 100644 index 0000000000000..d99c1e73fb34d --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * Container class for Current Pricing, related to amberelectric + * + * @author Paul Smedley - Initial contribution + * + */ +public class CurrentPrices { + private static Logger LOGGER = LoggerFactory.getLogger(CurrentPrices.class); + + public Double perKwh; + public Double renewables; + public Double spotPerKwh; + public String spikeStatus; + public String nemTime; + + private CurrentPrices() { + } + + public static CurrentPrices parse(String response) { + LOGGER.debug("Parsing string: \"{}\"", response); + /* parse json string */ + JsonArray jsonArray = JsonParser.parseString(response).getAsJsonArray(); + JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); + CurrentPrices currentprices = new CurrentPrices(); + currentprices.nemTime = jsonObject.get("nemTime").getAsString(); + currentprices.perKwh = jsonObject.get("perKwh").getAsDouble(); + currentprices.renewables = jsonObject.get("renewables").getAsDouble(); + currentprices.spotPerKwh = jsonObject.get("spotPerKwh").getAsDouble(); + currentprices.spikeStatus = jsonObject.get("spikeStatus").getAsString(); + + return currentprices; + } +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java new file mode 100644 index 0000000000000..f3c0da66d41be --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2023 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.amberelectric.internal.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * Class for holding the set of parameters used to read the controller variables. + * + * @author Paul Smedley - Initial Contribution + * + */ +public class Sites { + private static Logger LOGGER = LoggerFactory.getLogger(Sites.class); + + public String siteid; + public String nmi; + + private Sites() { + } + + public static Sites parse(String response) { + LOGGER.debug("Parsing string: \"{}\"", response); + /* parse json string */ + JsonArray jsonArray = JsonParser.parseString(response).getAsJsonArray(); + JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); + Sites sites = new Sites(); + sites.siteid = jsonObject.get("id").getAsString(); + sites.nmi = jsonObject.get("nmi").getAsString(); + return sites; + } +} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 0000000000000..9060180a089fb --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + AmberElectric Binding + This is the binding for AmberElectric. + cloud + + diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..043002a8e10ad --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,68 @@ + + + + + + Amber Electric - wholesale access to power prices + + + + + + + + + + + + + API key from the Amber website + + + + Site ID for your address (Optional) + + + + Specifies the refresh interval in seconds. + 120 + + + + + + + Number + + Current price to import power from the grid + + + + String + + NEM time of last pricing update + + + + Number + + Current level of renewables in the grid + + + + Switch + + Report if the grid has a current price spike + + + + Number + + Current price to export power from the grid + + + + From 512c2742ed3277ed3a9c0bc0cb2abbc29e999733 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Wed, 9 Aug 2023 18:36:50 +0930 Subject: [PATCH 02/30] Update default refresh interval to 60s Signed-off-by: Paul Smedley --- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 043002a8e10ad..713313eaa3b62 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -28,7 +28,7 @@ Specifies the refresh interval in seconds. - 120 + 60 From b7053e1599508752af8dd69eb9009baf8dc009d2 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Wed, 9 Aug 2023 19:06:36 +0930 Subject: [PATCH 03/30] Fix typo Signed-off-by: Paul Smedley --- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 713313eaa3b62..9f031c9859653 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -61,7 +61,7 @@ Number - Current price to export power from the grid + Current price to export power to the grid From ffaad3b07fc194b56d8f3cb93450c6260e9d93ac Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 12 Aug 2023 18:24:36 +0930 Subject: [PATCH 04/30] Support extra channels Signed-off-by: Paul Smedley --- .../AmberElectricBindingConstants.java | 6 ++- .../internal/AmberElectricHandler.java | 16 +++++-- .../internal/api/CurrentPrices.java | 26 +++++++++--- .../resources/OH-INF/thing/thing-types.xml | 42 +++++++++++++++---- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java index 6952a26be2993..205fa3ecb41e5 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java @@ -34,10 +34,14 @@ public class AmberElectricBindingConstants { // List of all Channel ids public static final String CHANNEL_AMBERELECTRIC_ELECPRICE = "elecprice"; + public static final String CHANNEL_AMBERELECTRIC_CLPRICE = "clprice"; + public static final String CHANNEL_AMBERELECTRIC_FEEDINPRICE = "feedinprice"; + public static final String CHANNEL_AMBERELECTRIC_ELECSTATUS = "elecstatus"; + public static final String CHANNEL_AMBERELECTRIC_CLSTATUS = "clstatus"; + public static final String CHANNEL_AMBERELECTRIC_FEEDINSTATUS = "feedinstatus"; public static final String CHANNEL_AMBERELECTRIC_NEMTIME = "nemtime"; public static final String CHANNEL_AMBERELECTRIC_RENEWABLES = "renewables"; public static final String CHANNEL_AMBERELECTRIC_SPIKE = "spike"; - public static final String CHANNEL_AMBERELECTRIC_SPOTPRICE = "spotprice"; public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(AMBERELECTRIC_THING); } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index b2378cb0e5a0f..440cf2954d3ef 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -123,13 +123,23 @@ private void pollStatus() throws IOException { updateStatus(ThingStatus.ONLINE); if (currentPrices != null) { updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, - new DecimalType(currentPrices.perKwh)); + new DecimalType(currentPrices.elecPerKwh)); + if (currentPrices.clPerKwh != null) { + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, + new DecimalType(currentPrices.clPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, + new StringType(currentPrices.clStatus)); + } + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, + new DecimalType(currentPrices.feedInPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, + new StringType(currentPrices.elecStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, + new StringType(currentPrices.feedInStatus)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, new StringType(currentPrices.nemTime)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, new DecimalType(currentPrices.renewables)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPOTPRICE, - new DecimalType(currentPrices.spotPerKwh)); switch (currentPrices.spikeStatus) { case "none": updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java index d99c1e73fb34d..96e3402012d24 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java @@ -28,9 +28,13 @@ public class CurrentPrices { private static Logger LOGGER = LoggerFactory.getLogger(CurrentPrices.class); - public Double perKwh; + public Double elecPerKwh; + public Double clPerKwh; + public Double feedInPerKwh; + public String elecStatus; + public String clStatus; + public String feedInStatus; public Double renewables; - public Double spotPerKwh; public String spikeStatus; public String nemTime; @@ -44,11 +48,23 @@ public static CurrentPrices parse(String response) { JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); CurrentPrices currentprices = new CurrentPrices(); currentprices.nemTime = jsonObject.get("nemTime").getAsString(); - currentprices.perKwh = jsonObject.get("perKwh").getAsDouble(); currentprices.renewables = jsonObject.get("renewables").getAsDouble(); - currentprices.spotPerKwh = jsonObject.get("spotPerKwh").getAsDouble(); currentprices.spikeStatus = jsonObject.get("spikeStatus").getAsString(); - + for (int i = 0; i < jsonArray.size(); i++) { + jsonObject = jsonArray.get(i).getAsJsonObject(); + if ("general".equals(jsonObject.get("channelType").getAsString())) { + currentprices.elecPerKwh = jsonObject.get("perKwh").getAsDouble(); + currentprices.elecStatus = jsonObject.get("descriptor").getAsString(); + } + if ("feedIn".equals(jsonObject.get("channelType").getAsString())) { + currentprices.feedInPerKwh = jsonObject.get("perKwh").getAsDouble(); + currentprices.feedInStatus = jsonObject.get("descriptor").getAsString(); + } + if ("controlledLoad".equals(jsonObject.get("channelType").getAsString())) { + currentprices.clPerKwh = jsonObject.get("perKwh").getAsDouble(); + currentprices.clStatus = jsonObject.get("descriptor").getAsString(); + } + } return currentprices; } } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 9f031c9859653..ca2bc48ff0eea 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -10,9 +10,13 @@ + + + + + - @@ -38,6 +42,36 @@ Number Current price to import power from the grid + + + + Number + + Current price to import power for Controlled Load + + + + Number + + Current price to export power to the grid + + + + String + + Current price status of grid import + + + + String + + Current price status of Controlled Load + + + + String + + Current price status of Feed-In @@ -58,11 +92,5 @@ Report if the grid has a current price spike - - Number - - Current price to export power to the grid - - From 4aabe49ff602db6c7bbf8fb714bdd2a9785b14f6 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 19 Aug 2023 10:42:12 +0930 Subject: [PATCH 05/30] Adjust code to configure site using NMI rather than siteid Signed-off-by: Paul Smedley --- .../internal/AmberElectricConfiguration.java | 2 +- .../internal/AmberElectricHandler.java | 11 ++++++----- .../internal/AmberElectricWebTargets.java | 7 +++---- .../internal/api/CurrentPrices.java | 3 ++- .../amberelectric/internal/api/Sites.java | 18 ++++++++++++++---- .../resources/OH-INF/thing/thing-types.xml | 6 +++--- 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java index be0627a76b680..4273a4595910a 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java @@ -19,6 +19,6 @@ */ public class AmberElectricConfiguration { public String apikey; - public String site; + public String nmi = ""; public long refresh = 60; } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 440cf2954d3ef..6955bcb7bf499 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -45,8 +45,9 @@ public class AmberElectricHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(AmberElectricHandler.class); private long refreshInterval; - private @Nullable String siteID; private @Nullable String apikey; + private @Nullable String nmi; + private @Nullable String siteID; private @NonNullByDefault({}) AmberElectricWebTargets webTargets; private @Nullable ScheduledFuture pollFuture; @@ -66,9 +67,9 @@ public void initialize() { if (config.apikey == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "API Key must be set"); } else { - webTargets = new AmberElectricWebTargets(config.site); + webTargets = new AmberElectricWebTargets(); refreshInterval = config.refresh; - siteID = config.site; + nmi = config.nmi; apikey = config.apikey; schedulePoll(); @@ -113,10 +114,10 @@ private void stopPoll() { private void pollStatus() throws IOException { if (siteID == null) { - Sites sites = webTargets.getSites(apikey); + Sites sites = webTargets.getSites(apikey, nmi); // add error handling siteID = sites.siteid; - logger.debug("Detected amber siteid is {}", sites.siteid); + logger.debug("Detected amber siteid is {}, for nmi {}", sites.siteid, sites.nmi); } CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apikey); diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index d66157ced7c37..b6a3aecea8aef 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -35,15 +35,14 @@ public class AmberElectricWebTargets { private String getCurrentPricesUri; private final Logger logger = LoggerFactory.getLogger(AmberElectricWebTargets.class); - public AmberElectricWebTargets(String siteid) { + public AmberElectricWebTargets() { String getSitesUri = "https://api.amber.com.au/v1/sites"; - String getCurrentPricesUri = getSitesUri + "/" + siteid + "/prices/current"; } - public Sites getSites(String apikey) throws AmberElectricCommunicationException { + public Sites getSites(String apikey, String nmi) throws AmberElectricCommunicationException { String getSitesUri = "https://api.amber.com.au/v1/sites"; String response = invoke("GET", getSitesUri, apikey); - return Sites.parse(response); + return Sites.parse(response, nmi); } public CurrentPrices getCurrentPrices(String siteid, String apikey) throws AmberElectricCommunicationException { diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java index 96e3402012d24..29b343beb9673 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java @@ -57,7 +57,8 @@ public static CurrentPrices parse(String response) { currentprices.elecStatus = jsonObject.get("descriptor").getAsString(); } if ("feedIn".equals(jsonObject.get("channelType").getAsString())) { - currentprices.feedInPerKwh = jsonObject.get("perKwh").getAsDouble(); + // Multiple value from API by -1 to make the value match the app + currentprices.feedInPerKwh = -1 * jsonObject.get("perKwh").getAsDouble(); currentprices.feedInStatus = jsonObject.get("descriptor").getAsString(); } if ("controlledLoad".equals(jsonObject.get("channelType").getAsString())) { diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java index f3c0da66d41be..be08e975bbc1f 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java @@ -34,14 +34,24 @@ public class Sites { private Sites() { } - public static Sites parse(String response) { + public static Sites parse(String response, String nem) { LOGGER.debug("Parsing string: \"{}\"", response); /* parse json string */ JsonArray jsonArray = JsonParser.parseString(response).getAsJsonArray(); - JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); Sites sites = new Sites(); - sites.siteid = jsonObject.get("id").getAsString(); - sites.nmi = jsonObject.get("nmi").getAsString(); + for (int i = 0; i < jsonArray.size(); i++) { + JsonObject jsonObject = jsonArray.get(i).getAsJsonObject(); + if (nem.equals(jsonObject.get("nmi").getAsString())) { + sites.siteid = jsonObject.get("id").getAsString(); + sites.nmi = jsonObject.get("nmi").getAsString(); + } + } + if ((nem == null) || (sites.siteid == null)) { // nem not specified, or not found so we take the first siteid + // found + JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); + sites.siteid = jsonObject.get("id").getAsString(); + sites.nmi = jsonObject.get("nmi").getAsString(); + } return sites; } } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index ca2bc48ff0eea..5ca4d6595f760 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -25,9 +25,9 @@ API key from the Amber website - - - Site ID for your address (Optional) + + + NMI for your address (Optional) From 38c6e9a6f915cfa9c0b59790c016140619b53ee4 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Tue, 4 Jun 2024 18:43:09 +0930 Subject: [PATCH 06/30] Updates Signed-off-by: Paul Smedley --- .../README.md | 45 +++++++++++++++++-- bundles/pom.xml | 1 + 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 0d7c828dfc9dc..04c2afabc7844 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -1,21 +1,58 @@ # Amber Electric Binding -A binding that supports the Amber Electric API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. +A binding that supports the Australian energy retailer Amber Electric's API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. ## Supported Things Amber Electric API - ## Discovery Auto-discover is not currently supported. You need to manually add a new thing using your API key ## Thing Configuration +As a minimum, the IP address is needed: +- `apikey` - The API key from the 'Developer' section of https://apps.amber.com.au +- 'nmi' optional - the NMI for your property. Required if you have multiple properties with Amber +- 'refresh' the refresh rate for querying the API. ## Channels - +| channel id | type | description | +|----------------------|---------------|---------------------------------------------------------------------------------------| +| ## Full Example - +amberelectric.things: + +```java +amberelectric:amberelectric:AmberElectric [ apikey="psk_xxxxxxxxxxxxxxxxxxxx" ] +``` + +amberelectric.items: + +```java +Number AmberElectric_ElecPrice { channel="amberelectric:amberelectric:AmberElectric:elecprice" } +Number AmberElectric_CLPrice { channel="amberelectric:amberelectric:AmberElectric:clprice" } +Number AmberElectric_FeedInPrice { channel="amberelectric:amberelectric:AmberElectric:feedinprice" } +String AmberElectric_ElecStatus { channel="amberelectric:amberelectric:AmberElectric:elecstatus" } +String AmberElectric_CLStatus { channel="amberelectric:amberelectric:AmberElectric:clstatus" } +String AmberElectric_FeedInStatus { channel="amberelectric:amberelectric:AmberElectric:feedinstatus" } +String AmberElectric_nemtime { channel="amberelectric:amberelectric:AmberElectric:nemtime" } +Number AmberElectric_Renewables { channel="amberelectric:amberelectric:AmberElectric:renewables" } +Switch AmberElectric_Spike { channel="amberelectric:amberelectric:AmberElectric:spike" } +``` + +amberelectric.sitemap: + +```perl +Text item=AmberElectric_ElecPrice label="Electricity Price" +Text item=AmberElectric_CLPrice label="Controlled Load Price" +Text item=AmberElectric_FeedInPrice label="Feed-In Price" +Text item=AmberElectric_ElecStatus label="Electricity Price Status" +Text item=AmberElectric_CLStatus label="Controlled Load Price Status" +Text item=AmberElectric_FeedInStatus label="Feed-In Price Status" +Text item=AmberElectric_nemtime label="Current time of NEM pricing" +Text item=AmberElectric_Renewables label="Renewables Level" +Switch item=AmberElectric_Spike label="Spike Status" +``` diff --git a/bundles/pom.xml b/bundles/pom.xml index 33b950b9ec09c..2b79885d95fc1 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -55,6 +55,7 @@ org.openhab.binding.allplay org.openhab.binding.amazondashbutton org.openhab.binding.amazonechocontrol + org.openhab.binding.amberelectric org.openhab.binding.ambientweather org.openhab.binding.amplipi org.openhab.binding.androiddebugbridge From 803ca894e78b614c23d529dd2cb52312671448a1 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Tue, 4 Jun 2024 19:27:31 +0930 Subject: [PATCH 07/30] Cleanups Signed-off-by: Paul Smedley --- .../README.md | 14 ++++- .../org.openhab.binding.amberelectric/pom.xml | 2 +- .../AmberElectricBindingConstants.java | 2 +- .../AmberElectricCommunicationException.java | 5 +- .../internal/AmberElectricConfiguration.java | 7 ++- .../internal/AmberElectricHandler.java | 56 +++++++++---------- .../internal/AmberElectricHandlerFactory.java | 2 +- .../internal/AmberElectricWebTargets.java | 5 +- .../internal/api/CurrentPrices.java | 22 ++++---- .../amberelectric/internal/api/Sites.java | 13 +++-- 10 files changed, 72 insertions(+), 56 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 04c2afabc7844..0cc7a23ce31d2 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -1,7 +1,9 @@ # Amber Electric Binding + A binding that supports the Australian energy retailer Amber Electric's API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. ## Supported Things + Amber Electric API ## Discovery @@ -10,6 +12,7 @@ Auto-discover is not currently supported. You need to manually add a new thing using your API key ## Thing Configuration + As a minimum, the IP address is needed: - `apikey` - The API key from the 'Developer' section of https://apps.amber.com.au @@ -17,9 +20,18 @@ As a minimum, the IP address is needed: - 'refresh' the refresh rate for querying the API. ## Channels + | channel id | type | description | |----------------------|---------------|---------------------------------------------------------------------------------------| -| +| elecprice | Number | Current price to import power from the grid +| clprice | Number | Current price to import power for Controlled Load +| feedinprice | Number | Current price to export power to the grid +| elecstatus | String | Current price status of grid import +| clstatus | String | Current price status of controlled load import +| feedinstatus | String | Current price status of Feed-In +| nemtime | String | NEM time of last pricing update +| renewables | Number | Current level of renewables in the grid +| spike | Switch | Report if the grid has a current price spike ## Full Example diff --git a/bundles/org.openhab.binding.amberelectric/pom.xml b/bundles/org.openhab.binding.amberelectric/pom.xml index 9a3715565e0f2..cdb9cdf25563f 100644 --- a/bundles/org.openhab.binding.amberelectric/pom.xml +++ b/bundles/org.openhab.binding.amberelectric/pom.xml @@ -7,7 +7,7 @@ org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 4.1.0-SNAPSHOT + 4.2.0-SNAPSHOT org.openhab.binding.amberelectric diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java index 205fa3ecb41e5..2c596a1b51952 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java index 9ec1b962b7305..3dec20a057f60 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -14,12 +14,15 @@ import java.io.IOException; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Exception for when an unexpected response is received from the AmberAPI. * * @author Paul Smedley - Initial contribution * */ +@NonNullByDefault public class AmberElectricCommunicationException extends IOException { private static final long serialVersionUID = 529232811860854017L; diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java index 4273a4595910a..cd15a564db296 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -12,13 +12,16 @@ */ package org.openhab.binding.amberelectric.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The AmberElectricConfiguration class contains fields mapping thing configuration parameters. * * @author Paul Smedley - Initial contribution */ +@NonNullByDefault public class AmberElectricConfiguration { - public String apikey; + public String apikey = ""; public String nmi = ""; public long refresh = 60; } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 6955bcb7bf499..b116db466a4dc 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -64,7 +64,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { AmberElectricConfiguration config = getConfigAs(AmberElectricConfiguration.class); - if (config.apikey == null) { + if (config.apikey.isEmpty()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "API Key must be set"); } else { webTargets = new AmberElectricWebTargets(); @@ -83,6 +83,7 @@ public void dispose() { } private void schedulePoll() { + ScheduledFuture pollFuture = this.pollFuture; if (pollFuture != null) { pollFuture.cancel(false); } @@ -113,7 +114,7 @@ private void stopPoll() { private void pollStatus() throws IOException { - if (siteID == null) { + if (siteID.isEmpty()) { Sites sites = webTargets.getSites(apikey, nmi); // add error handling siteID = sites.siteid; @@ -122,33 +123,28 @@ private void pollStatus() throws IOException { CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apikey); updateStatus(ThingStatus.ONLINE); - if (currentPrices != null) { - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, - new DecimalType(currentPrices.elecPerKwh)); - if (currentPrices.clPerKwh != null) { - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, - new DecimalType(currentPrices.clPerKwh)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, - new StringType(currentPrices.clStatus)); - } - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, - new DecimalType(currentPrices.feedInPerKwh)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, - new StringType(currentPrices.elecStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, - new StringType(currentPrices.feedInStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, - new StringType(currentPrices.nemTime)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, - new DecimalType(currentPrices.renewables)); - switch (currentPrices.spikeStatus) { - case "none": - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); - break; - default: - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.ON); - break; - } + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, + new DecimalType(currentPrices.elecPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, + new DecimalType(currentPrices.clPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, + new StringType(currentPrices.clStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, + new DecimalType(currentPrices.feedInPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, + new StringType(currentPrices.elecStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, + new StringType(currentPrices.feedInStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, new StringType(currentPrices.nemTime)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, + new DecimalType(currentPrices.renewables)); + switch (currentPrices.spikeStatus) { + case "none": + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); + break; + default: + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.ON); + break; } } } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java index f60ac44749315..d46f1f1bd6d4f 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandlerFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index b6a3aecea8aef..345c48a21c473 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -31,12 +31,9 @@ public class AmberElectricWebTargets { private static final int TIMEOUT_MS = 30000; - private String getSitesUri; - private String getCurrentPricesUri; private final Logger logger = LoggerFactory.getLogger(AmberElectricWebTargets.class); public AmberElectricWebTargets() { - String getSitesUri = "https://api.amber.com.au/v1/sites"; } public Sites getSites(String apikey, String nmi) throws AmberElectricCommunicationException { diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java index 29b343beb9673..e427dc949f9f1 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -12,6 +12,7 @@ */ package org.openhab.binding.amberelectric.internal.api; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,18 +26,19 @@ * @author Paul Smedley - Initial contribution * */ +@NonNullByDefault public class CurrentPrices { private static Logger LOGGER = LoggerFactory.getLogger(CurrentPrices.class); - public Double elecPerKwh; - public Double clPerKwh; - public Double feedInPerKwh; - public String elecStatus; - public String clStatus; - public String feedInStatus; - public Double renewables; - public String spikeStatus; - public String nemTime; + public double elecPerKwh; + public double clPerKwh; + public double feedInPerKwh; + public String elecStatus = ""; + public String clStatus = ""; + public String feedInStatus = ""; + public double renewables; + public String spikeStatus = ""; + public String nemTime = ""; private CurrentPrices() { } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java index be08e975bbc1f..7779b0d58f707 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2023 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -12,6 +12,7 @@ */ package org.openhab.binding.amberelectric.internal.api; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,11 +26,12 @@ * @author Paul Smedley - Initial Contribution * */ +@NonNullByDefault public class Sites { private static Logger LOGGER = LoggerFactory.getLogger(Sites.class); - public String siteid; - public String nmi; + public String siteid = ""; + public String nmi = ""; private Sites() { } @@ -46,8 +48,9 @@ public static Sites parse(String response, String nem) { sites.nmi = jsonObject.get("nmi").getAsString(); } } - if ((nem == null) || (sites.siteid == null)) { // nem not specified, or not found so we take the first siteid - // found + if ((nem.isEmpty()) || (sites.siteid.isEmpty())) { // nem not specified, or not found so we take the first + // siteid + // found JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); sites.siteid = jsonObject.get("id").getAsString(); sites.nmi = jsonObject.get("nmi").getAsString(); From 7c2e177a2051cbc4e79e336b7f1edd8c275a3927 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Tue, 4 Jun 2024 19:48:31 +0930 Subject: [PATCH 08/30] Fix warnings Signed-off-by: Paul Smedley --- .../amberelectric/internal/AmberElectricHandler.java | 6 +++--- .../internal/AmberElectricWebTargets.java | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index b116db466a4dc..88060f0226b06 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -45,9 +45,9 @@ public class AmberElectricHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(AmberElectricHandler.class); private long refreshInterval; - private @Nullable String apikey; - private @Nullable String nmi; - private @Nullable String siteID; + private String apikey = ""; + private String nmi = ""; + private String siteID = ""; private @NonNullByDefault({}) AmberElectricWebTargets webTargets; private @Nullable ScheduledFuture pollFuture; diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index 345c48a21c473..60ae30e3f3227 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -16,6 +16,8 @@ import java.io.InputStream; import java.util.Properties; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.amberelectric.internal.api.CurrentPrices; import org.openhab.binding.amberelectric.internal.api.Sites; import org.openhab.core.io.net.http.HttpUtil; @@ -28,6 +30,7 @@ * @author Paul Smedley - Initial Contribution * */ +@NonNullByDefault public class AmberElectricWebTargets { private static final int TIMEOUT_MS = 30000; @@ -60,9 +63,10 @@ private String invoke(String httpMethod, String uri, String accessToken) return invoke(httpMethod, uri, accessToken, null, null); } - private String invoke(String httpMethod, String uri, String apikey, InputStream content, String contentType) - throws AmberElectricCommunicationException { + private String invoke(String httpMethod, String uri, String apikey, @Nullable InputStream content, + @Nullable String contentType) throws AmberElectricCommunicationException { logger.debug("Calling url: {}", uri); + @Nullable String response; synchronized (this) { try { @@ -76,7 +80,7 @@ private String invoke(String httpMethod, String uri, String apikey, InputStream } } - if (response.isEmpty()) { + if (response == null) { throw new AmberElectricCommunicationException( String.format("AmberElectric returned no response while invoking %s", uri)); } From 064dccffd4afb0c6153413b6aaa0c153fbee2ea5 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Thu, 6 Jun 2024 19:24:15 +0930 Subject: [PATCH 09/30] Code cleanups Signed-off-by: Paul Smedley --- .../README.md | 11 ++- .../src/main/feature/feature.xml | 2 +- .../AmberElectricBindingConstants.java | 2 +- .../AmberElectricCommunicationException.java | 4 +- .../internal/AmberElectricHandler.java | 76 ++++++++++--------- .../internal/AmberElectricWebTargets.java | 17 ++--- .../src/main/resources/OH-INF/addon/addon.xml | 4 +- .../OH-INF/i18n/amberelectric.properties | 39 ++++++++++ .../resources/OH-INF/thing/thing-types.xml | 38 +++++----- 9 files changed, 117 insertions(+), 76 deletions(-) create mode 100644 bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 0cc7a23ce31d2..45bc38df3f1dc 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -4,12 +4,11 @@ A binding that supports the Australian energy retailer Amber Electric's API (htt ## Supported Things -Amber Electric API +- `amber-electric` Amber Electric API ## Discovery -Auto-discover is not currently supported. -You need to manually add a new thing using your API key +The binding does not support auto discovery. ## Thing Configuration @@ -35,13 +34,13 @@ As a minimum, the IP address is needed: ## Full Example -amberelectric.things: +### `amberelectric.things`: ```java amberelectric:amberelectric:AmberElectric [ apikey="psk_xxxxxxxxxxxxxxxxxxxx" ] ``` -amberelectric.items: +### `amberelectric.items`: ```java Number AmberElectric_ElecPrice { channel="amberelectric:amberelectric:AmberElectric:elecprice" } @@ -55,7 +54,7 @@ Number AmberElectric_Renewables { channel="amberelectric:amberelectric:AmberElec Switch AmberElectric_Spike { channel="amberelectric:amberelectric:AmberElectric:spike" } ``` -amberelectric.sitemap: +### `amberelectric.sitemap`: ```perl Text item=AmberElectric_ElecPrice label="Electricity Price" diff --git a/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml b/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml index 5ccc50218ec2d..233fe0394aacd 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/feature/feature.xml @@ -2,7 +2,7 @@ mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - + openhab-runtime-base mvn:org.openhab.addons.bundles/org.openhab.binding.amberelectric/${project.version} diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java index 2c596a1b51952..3ab6daa4cf21a 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java @@ -30,7 +30,7 @@ public class AmberElectricBindingConstants { private static final String BINDING_ID = "amberelectric"; // List of all Thing Type UIDs - public static final ThingTypeUID AMBERELECTRIC_THING = new ThingTypeUID(BINDING_ID, "amberelectric"); + public static final ThingTypeUID AMBERELECTRIC_THING = new ThingTypeUID(BINDING_ID, "amber-electric"); // List of all Channel ids public static final String CHANNEL_AMBERELECTRIC_ELECPRICE = "elecprice"; diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java index 3dec20a057f60..d8a9c45dec5b0 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricCommunicationException.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.amberelectric.internal; -import java.io.IOException; - import org.eclipse.jdt.annotation.NonNullByDefault; /** @@ -23,7 +21,7 @@ * */ @NonNullByDefault -public class AmberElectricCommunicationException extends IOException { +public class AmberElectricCommunicationException extends Exception { private static final long serialVersionUID = 529232811860854017L; public AmberElectricCommunicationException(String message) { diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 88060f0226b06..859300d3d1a27 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -49,6 +49,7 @@ public class AmberElectricHandler extends BaseThingHandler { private String nmi = ""; private String siteID = ""; + private @NonNullByDefault({}) AmberElectricConfiguration config; private @NonNullByDefault({}) AmberElectricWebTargets webTargets; private @Nullable ScheduledFuture pollFuture; @@ -63,11 +64,12 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { - AmberElectricConfiguration config = getConfigAs(AmberElectricConfiguration.class); - if (config.apikey.isEmpty()) { + config = getConfigAs(AmberElectricConfiguration.class); + if (config.apikey.isBlank()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "API Key must be set"); } else { webTargets = new AmberElectricWebTargets(); + updateStatus(ThingStatus.UNKNOWN); refreshInterval = config.refresh; nmi = config.nmi; apikey = config.apikey; @@ -88,7 +90,7 @@ private void schedulePoll() { pollFuture.cancel(false); } logger.debug("Scheduling poll for 1 second out, then every {} s", refreshInterval); - pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 1, refreshInterval, TimeUnit.SECONDS); + this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 1, refreshInterval, TimeUnit.SECONDS); } private void poll() { @@ -114,37 +116,43 @@ private void stopPoll() { private void pollStatus() throws IOException { - if (siteID.isEmpty()) { - Sites sites = webTargets.getSites(apikey, nmi); - // add error handling - siteID = sites.siteid; - logger.debug("Detected amber siteid is {}, for nmi {}", sites.siteid, sites.nmi); - } - - CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apikey); - updateStatus(ThingStatus.ONLINE); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, - new DecimalType(currentPrices.elecPerKwh)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, - new DecimalType(currentPrices.clPerKwh)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, - new StringType(currentPrices.clStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, - new DecimalType(currentPrices.feedInPerKwh)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, - new StringType(currentPrices.elecStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, - new StringType(currentPrices.feedInStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, new StringType(currentPrices.nemTime)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, - new DecimalType(currentPrices.renewables)); - switch (currentPrices.spikeStatus) { - case "none": - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); - break; - default: - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.ON); - break; + try { + if (siteID.isEmpty()) { + Sites sites = webTargets.getSites(apikey, nmi); + // add error handling + siteID = sites.siteid; + logger.debug("Detected amber siteid is {}, for nmi {}", sites.siteid, sites.nmi); + } + + CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apikey); + updateStatus(ThingStatus.ONLINE); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, + new DecimalType(currentPrices.elecPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, + new DecimalType(currentPrices.clPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, + new StringType(currentPrices.clStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, + new DecimalType(currentPrices.feedInPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, + new StringType(currentPrices.elecStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, + new StringType(currentPrices.feedInStatus)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, + new StringType(currentPrices.nemTime)); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, + new DecimalType(currentPrices.renewables)); + switch (currentPrices.spikeStatus) { + case "none": + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); + break; + default: + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.ON); + break; + } + } catch (AmberElectricCommunicationException e) { + logger.debug("Unexpected error connecting to Amber Electric API", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } } } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index 60ae30e3f3227..5f42239ceba90 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -68,16 +68,13 @@ private String invoke(String httpMethod, String uri, String apikey, @Nullable In logger.debug("Calling url: {}", uri); @Nullable String response; - synchronized (this) { - try { - response = HttpUtil.executeUrl(httpMethod, uri, getHttpHeaders(apikey), content, contentType, - TIMEOUT_MS); - } catch (IOException ex) { - logger.debug("{}", ex.getLocalizedMessage(), ex); - // Response will also be set to null if parsing in executeUrl fails so we use null here to make the - // error check below consistent. - response = null; - } + try { + response = HttpUtil.executeUrl(httpMethod, uri, getHttpHeaders(apikey), content, contentType, TIMEOUT_MS); + } catch (IOException ex) { + logger.debug("{}", ex.getLocalizedMessage(), ex); + // Response will also be set to null if parsing in executeUrl fails so we use null here to make the + // error check below consistent. + response = null; } if (response == null) { diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml index 9060180a089fb..a5af8ebd25c70 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/addon/addon.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd"> binding - AmberElectric Binding - This is the binding for AmberElectric. + Amber Electric Binding + This is the binding for Amber Electric. cloud diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties new file mode 100644 index 0000000000000..7378416625d4a --- /dev/null +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties @@ -0,0 +1,39 @@ +# add-on + +addon.amberelectric.name = Amber Electric Binding +addon.amberelectric.description = This is the binding for Amber Electric. + +# thing types + +thing-type.amberelectric.amber-electric.label = Amber Electric +thing-type.amberelectric.amber-electric.description = Amber Electric - wholesale access to power prices + +# thing types config + +thing-type.config.amberelectric.amber-electric.apikey.label = API Key +thing-type.config.amberelectric.amber-electric.apikey.description = API key from the Amber website +thing-type.config.amberelectric.amber-electric.nmi.label = NMI +thing-type.config.amberelectric.amber-electric.nmi.description = NMI for your address (Optional) +thing-type.config.amberelectric.amber-electric.refresh.label = Refresh Interval +thing-type.config.amberelectric.amber-electric.refresh.description = Specifies the refresh interval in seconds. + +# channel types + +channel-type.amberelectric.amber-electric-clprice.label = Current Controlled Load Price +channel-type.amberelectric.amber-electric-clprice.description = Current price to import power for Controlled Load +channel-type.amberelectric.amber-electric-clstatus.label = Current Controlled Load Status +channel-type.amberelectric.amber-electric-clstatus.description = Current price status of Controlled Load +channel-type.amberelectric.amber-electric-elecprice.label = Current Electricity Price +channel-type.amberelectric.amber-electric-elecprice.description = Current price to import power from the grid +channel-type.amberelectric.amber-electric-elecstatus.label = Current Electricity Status +channel-type.amberelectric.amber-electric-elecstatus.description = Current price status of grid import +channel-type.amberelectric.amber-electric-feedinprice.label = Current Feed-In Price +channel-type.amberelectric.amber-electric-feedinprice.description = Current price to export power to the grid +channel-type.amberelectric.amber-electric-feedinstatus.label = Current Feed-In Status +channel-type.amberelectric.amber-electric-feedinstatus.description = Current price status of Feed-In +channel-type.amberelectric.amber-electric-nemtime.label = NEM Time +channel-type.amberelectric.amber-electric-nemtime.description = NEM time of last pricing update +channel-type.amberelectric.amber-electric-renewables.label = Current Renewables +channel-type.amberelectric.amber-electric-renewables.description = Current level of renewables in the grid +channel-type.amberelectric.amber-electric-spike.label = Energy Price Spike +channel-type.amberelectric.amber-electric-spike.description = Report if the grid has a current price spike diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 5ca4d6595f760..51d83992f790a 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -4,20 +4,20 @@ 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"> - + Amber Electric - wholesale access to power prices - - - - - - - - - + + + + + + + + + @@ -38,55 +38,55 @@ - + Number Current price to import power from the grid - + Number Current price to import power for Controlled Load - + Number Current price to export power to the grid - + String Current price status of grid import - + String Current price status of Controlled Load - + String Current price status of Feed-In - + String NEM time of last pricing update - + Number Current level of renewables in the grid - + Switch Report if the grid has a current price spike From de072bedec2c8e56073995c183d898257869b491 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Thu, 6 Jun 2024 19:30:44 +0930 Subject: [PATCH 10/30] Fix business name Signed-off-by: Paul Smedley --- bundles/org.openhab.binding.amberelectric/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 45bc38df3f1dc..50222037ab147 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -1,6 +1,6 @@ # Amber Electric Binding -A binding that supports the Australian energy retailer Amber Electric's API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. +A binding that supports the Australian energy retailer Amber's API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. ## Supported Things From 8bbaf41575212dad14c75297fc4f96a67abd8074 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Thu, 6 Jun 2024 19:37:12 +0930 Subject: [PATCH 11/30] build fix Signed-off-by: Paul Smedley --- bom/openhab-addons/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 86fba92657263..959e35094ee87 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -101,6 +101,11 @@ org.openhab.binding.amazonechocontrol ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.amberelectric + ${project.version} + org.openhab.addons.bundles org.openhab.binding.ambientweather From f113fb2ffe8a476acc0ba9a0c02ff05ba1764666 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Fri, 7 Jun 2024 09:05:48 +0930 Subject: [PATCH 12/30] Code Improvements Signed-off-by: Paul Smedley --- .../README.md | 54 ++++++++-------- .../AmberElectricBindingConstants.java | 19 +++--- .../internal/AmberElectricConfiguration.java | 2 +- .../internal/AmberElectricHandler.java | 36 +++++------ .../internal/AmberElectricWebTargets.java | 18 +++--- .../OH-INF/i18n/amberelectric.properties | 4 ++ .../resources/OH-INF/thing/thing-types.xml | 62 +++++++++---------- 7 files changed, 96 insertions(+), 99 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 50222037ab147..8b946725f2e14 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -14,56 +14,56 @@ The binding does not support auto discovery. As a minimum, the IP address is needed: -- `apikey` - The API key from the 'Developer' section of https://apps.amber.com.au +- `apiKey` - The API key from the 'Developer' section of https://apps.amber.com.au - 'nmi' optional - the NMI for your property. Required if you have multiple properties with Amber - 'refresh' the refresh rate for querying the API. ## Channels -| channel id | type | description | -|----------------------|---------------|---------------------------------------------------------------------------------------| -| elecprice | Number | Current price to import power from the grid -| clprice | Number | Current price to import power for Controlled Load -| feedinprice | Number | Current price to export power to the grid -| elecstatus | String | Current price status of grid import -| clstatus | String | Current price status of controlled load import -| feedinstatus | String | Current price status of Feed-In -| nemtime | String | NEM time of last pricing update -| renewables | Number | Current level of renewables in the grid -| spike | Switch | Report if the grid has a current price spike +| channel id | type | description | +|------------------------|----------------------|---------------------------------------------------------------------------------| +| electricity-price | Number:EnergyPrice | Current price to import power from the grid +| controlled-load-price | Number:EnergyPrice | Current price to import power for Controlled Load +| feed-in-price | Number:EnergyPrice | Current price to export power to the grid +| electricity-status | String | Current price status of grid import +| controlled-load-status | String | Current price status of controlled load import +| feed-in-status | String | Current price status of Feed-In +| nem-time | String | NEM time of last pricing update +| renewables | Number:Dimensionless | Current level of renewables in the grid +| spike | Switch | Report if the grid has a current price spike ## Full Example ### `amberelectric.things`: ```java -amberelectric:amberelectric:AmberElectric [ apikey="psk_xxxxxxxxxxxxxxxxxxxx" ] +amberelectric:amberelectric:AmberElectric [ apiKey="psk_xxxxxxxxxxxxxxxxxxxx" ] ``` ### `amberelectric.items`: ```java -Number AmberElectric_ElecPrice { channel="amberelectric:amberelectric:AmberElectric:elecprice" } -Number AmberElectric_CLPrice { channel="amberelectric:amberelectric:AmberElectric:clprice" } -Number AmberElectric_FeedInPrice { channel="amberelectric:amberelectric:AmberElectric:feedinprice" } -String AmberElectric_ElecStatus { channel="amberelectric:amberelectric:AmberElectric:elecstatus" } -String AmberElectric_CLStatus { channel="amberelectric:amberelectric:AmberElectric:clstatus" } -String AmberElectric_FeedInStatus { channel="amberelectric:amberelectric:AmberElectric:feedinstatus" } -String AmberElectric_nemtime { channel="amberelectric:amberelectric:AmberElectric:nemtime" } -Number AmberElectric_Renewables { channel="amberelectric:amberelectric:AmberElectric:renewables" } -Switch AmberElectric_Spike { channel="amberelectric:amberelectric:AmberElectric:spike" } +Number AmberElectric_ElectricityPrice { channel="amberelectric:service:AmberElectric:electricity-price" } +Number AmberElectric_ControlledLoadPrice { channel="amberelectric:service:AmberElectric:controlled-load-price" } +Number AmberElectric_FeedInPrice { channel="amberelectric:service:AmberElectric:feed-in-price" } +String AmberElectric_ElectricityStatus { channel="amberelectric:service:AmberElectric:electricity-status" } +String AmberElectric_ControlledLoadStatus { channel="amberelectric:service:AmberElectric:controlled-load-status" } +String AmberElectric_FeedInStatus { channel="amberelectric:service:AmberElectric:feed-in-status" } +String AmberElectric_nem-time { channel="amberelectric:service:AmberElectric:nem-time" } +Number AmberElectric_Renewables { channel="amberelectric:service:AmberElectric:renewables" } +Switch AmberElectric_Spike { channel="amberelectric:service:AmberElectric:spike" } ``` ### `amberelectric.sitemap`: ```perl -Text item=AmberElectric_ElecPrice label="Electricity Price" -Text item=AmberElectric_CLPrice label="Controlled Load Price" +Text item=AmberElectric_ElectricityPrice label="Electricity Price" +Text item=AmberElectric_ControlledLoadPrice label="Controlled Load Price" Text item=AmberElectric_FeedInPrice label="Feed-In Price" -Text item=AmberElectric_ElecStatus label="Electricity Price Status" -Text item=AmberElectric_CLStatus label="Controlled Load Price Status" +Text item=AmberElectric_ElectricityStatus label="Electricity Price Status" +Text item=AmberElectric_ControlledLoadStatus label="Controlled Load Price Status" Text item=AmberElectric_FeedInStatus label="Feed-In Price Status" -Text item=AmberElectric_nemtime label="Current time of NEM pricing" +Text item=AmberElectric_nem-time label="Current time of NEM pricing" Text item=AmberElectric_Renewables label="Renewables Level" Switch item=AmberElectric_Spike label="Spike Status" ``` diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java index 3ab6daa4cf21a..8aafdbca67f4d 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java @@ -12,7 +12,6 @@ */ package org.openhab.binding.amberelectric.internal; -import java.util.Collections; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -30,18 +29,18 @@ public class AmberElectricBindingConstants { private static final String BINDING_ID = "amberelectric"; // List of all Thing Type UIDs - public static final ThingTypeUID AMBERELECTRIC_THING = new ThingTypeUID(BINDING_ID, "amber-electric"); + public static final ThingTypeUID AMBERELECTRIC_THING = new ThingTypeUID(BINDING_ID, "service"); // List of all Channel ids - public static final String CHANNEL_AMBERELECTRIC_ELECPRICE = "elecprice"; - public static final String CHANNEL_AMBERELECTRIC_CLPRICE = "clprice"; - public static final String CHANNEL_AMBERELECTRIC_FEEDINPRICE = "feedinprice"; - public static final String CHANNEL_AMBERELECTRIC_ELECSTATUS = "elecstatus"; - public static final String CHANNEL_AMBERELECTRIC_CLSTATUS = "clstatus"; - public static final String CHANNEL_AMBERELECTRIC_FEEDINSTATUS = "feedinstatus"; - public static final String CHANNEL_AMBERELECTRIC_NEMTIME = "nemtime"; + public static final String CHANNEL_AMBERELECTRIC_ELECPRICE = "electricity-price"; + public static final String CHANNEL_AMBERELECTRIC_CLPRICE = "controlled-load-price"; + public static final String CHANNEL_AMBERELECTRIC_FEEDINPRICE = "feed-in-price"; + public static final String CHANNEL_AMBERELECTRIC_ELECSTATUS = "electricity-status"; + public static final String CHANNEL_AMBERELECTRIC_CLSTATUS = "controlled-load-status"; + public static final String CHANNEL_AMBERELECTRIC_FEEDINSTATUS = "feed-in-status"; + public static final String CHANNEL_AMBERELECTRIC_NEMTIME = "nem-time"; public static final String CHANNEL_AMBERELECTRIC_RENEWABLES = "renewables"; public static final String CHANNEL_AMBERELECTRIC_SPIKE = "spike"; - public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(AMBERELECTRIC_THING); + public static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(AMBERELECTRIC_THING); } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java index cd15a564db296..eaf1157bfca7e 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricConfiguration.java @@ -21,7 +21,7 @@ */ @NonNullByDefault public class AmberElectricConfiguration { - public String apikey = ""; + public String apiKey = ""; public String nmi = ""; public long refresh = 60; } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 859300d3d1a27..61da6c0b317eb 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -23,7 +23,9 @@ import org.openhab.binding.amberelectric.internal.api.Sites; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.CurrencyUnits; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -45,7 +47,7 @@ public class AmberElectricHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(AmberElectricHandler.class); private long refreshInterval; - private String apikey = ""; + private String apiKey = ""; private String nmi = ""; private String siteID = ""; @@ -65,14 +67,15 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { config = getConfigAs(AmberElectricConfiguration.class); - if (config.apikey.isBlank()) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "API Key must be set"); + if (config.apiKey.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error.no-api-key"); } else { webTargets = new AmberElectricWebTargets(); updateStatus(ThingStatus.UNKNOWN); refreshInterval = config.refresh; nmi = config.nmi; - apikey = config.apikey; + apiKey = config.apiKey; schedulePoll(); } @@ -86,9 +89,6 @@ public void dispose() { private void schedulePoll() { ScheduledFuture pollFuture = this.pollFuture; - if (pollFuture != null) { - pollFuture.cancel(false); - } logger.debug("Scheduling poll for 1 second out, then every {} s", refreshInterval); this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 1, refreshInterval, TimeUnit.SECONDS); } @@ -108,7 +108,7 @@ private void poll() { private void stopPoll() { final Future future = pollFuture; - if (future != null && !future.isCancelled()) { + if (future != null) { future.cancel(true); pollFuture = null; } @@ -118,22 +118,22 @@ private void pollStatus() throws IOException { try { if (siteID.isEmpty()) { - Sites sites = webTargets.getSites(apikey, nmi); + Sites sites = webTargets.getSites(apiKey, nmi); // add error handling siteID = sites.siteid; logger.debug("Detected amber siteid is {}, for nmi {}", sites.siteid, sites.nmi); } - CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apikey); + CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apiKey); updateStatus(ThingStatus.ONLINE); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, - new DecimalType(currentPrices.elecPerKwh)); + new QuantityType<>(currentPrices.elecPerKwh / 100, CurrencyUnits.BASE_ENERGY_PRICE)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, - new DecimalType(currentPrices.clPerKwh)); + new QuantityType<>(currentPrices.clPerKwh / 100, CurrencyUnits.BASE_ENERGY_PRICE)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, new StringType(currentPrices.clStatus)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, - new DecimalType(currentPrices.feedInPerKwh)); + new QuantityType<>(currentPrices.feedInPerKwh / 100, CurrencyUnits.BASE_ENERGY_PRICE)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, new StringType(currentPrices.elecStatus)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, @@ -142,14 +142,8 @@ private void pollStatus() throws IOException { new StringType(currentPrices.nemTime)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, new DecimalType(currentPrices.renewables)); - switch (currentPrices.spikeStatus) { - case "none": - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.OFF); - break; - default: - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, OnOffType.ON); - break; - } + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, + OnOffType.from(!"none".equals(currentPrices.spikeStatus))); } catch (AmberElectricCommunicationException e) { logger.debug("Unexpected error connecting to Amber Electric API", e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index 5f42239ceba90..7d9f96d4802b5 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -33,21 +33,21 @@ @NonNullByDefault public class AmberElectricWebTargets { private static final int TIMEOUT_MS = 30000; - + String baseUri = "https://api.amber.com.au/v1/"; private final Logger logger = LoggerFactory.getLogger(AmberElectricWebTargets.class); public AmberElectricWebTargets() { } - public Sites getSites(String apikey, String nmi) throws AmberElectricCommunicationException { - String getSitesUri = "https://api.amber.com.au/v1/sites"; - String response = invoke("GET", getSitesUri, apikey); + public Sites getSites(String apiKey, String nmi) throws AmberElectricCommunicationException { + String getSitesUri = baseUri + "sites"; + String response = invoke("GET", getSitesUri, apiKey); return Sites.parse(response, nmi); } - public CurrentPrices getCurrentPrices(String siteid, String apikey) throws AmberElectricCommunicationException { - String getCurrentPricesUri = "https://api.amber.com.au/v1/sites/" + siteid + "/prices/current"; - String response = invoke("GET", getCurrentPricesUri, apikey); + public CurrentPrices getCurrentPrices(String siteid, String apiKey) throws AmberElectricCommunicationException { + String getCurrentPricesUri = baseUri + "sites/" + siteid + "/prices/current"; + String response = invoke("GET", getCurrentPricesUri, apiKey); return CurrentPrices.parse(response); } @@ -63,13 +63,13 @@ private String invoke(String httpMethod, String uri, String accessToken) return invoke(httpMethod, uri, accessToken, null, null); } - private String invoke(String httpMethod, String uri, String apikey, @Nullable InputStream content, + private String invoke(String httpMethod, String uri, String apiKey, @Nullable InputStream content, @Nullable String contentType) throws AmberElectricCommunicationException { logger.debug("Calling url: {}", uri); @Nullable String response; try { - response = HttpUtil.executeUrl(httpMethod, uri, getHttpHeaders(apikey), content, contentType, TIMEOUT_MS); + response = HttpUtil.executeUrl(httpMethod, uri, getHttpHeaders(apiKey), content, contentType, TIMEOUT_MS); } catch (IOException ex) { logger.debug("{}", ex.getLocalizedMessage(), ex); // Response will also be set to null if parsing in executeUrl fails so we use null here to make the diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties index 7378416625d4a..70f13da716e4d 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties @@ -37,3 +37,7 @@ channel-type.amberelectric.amber-electric-renewables.label = Current Renewables channel-type.amberelectric.amber-electric-renewables.description = Current level of renewables in the grid channel-type.amberelectric.amber-electric-spike.label = Energy Price Spike channel-type.amberelectric.amber-electric-spike.description = Report if the grid has a current price spike + +# thing status descriptions + +offline.conf-error.no-api-key = API key must be set diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 51d83992f790a..f3a73264f200d 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -4,24 +4,24 @@ 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"> - + Amber Electric - wholesale access to power prices - - - - - - - - - + + + + + + + + + - + API key from the Amber website @@ -29,7 +29,7 @@ NMI for your address (Optional) - + Specifies the refresh interval in seconds. 60 @@ -38,55 +38,55 @@ - - Number + + Number:EnergyPrice Current price to import power from the grid - + - - Number + + Number:EnergyPrice Current price to import power for Controlled Load - + - - Number + + Number:EnergyPrice Current price to export power to the grid - + - + String Current price status of grid import - + - + String Current price status of Controlled Load - + - + String Current price status of Feed-In - + - + String NEM time of last pricing update - - Number + + Number:Dimensionless Current level of renewables in the grid - + Switch Report if the grid has a current price spike From b7e83807b27ad6697a50a6b101b705a938be6665 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Fri, 7 Jun 2024 15:57:06 +0930 Subject: [PATCH 13/30] Remove poll delay Signed-off-by: Paul Smedley --- .../binding/amberelectric/internal/AmberElectricHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 61da6c0b317eb..adaf7f039f790 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -89,8 +89,8 @@ public void dispose() { private void schedulePoll() { ScheduledFuture pollFuture = this.pollFuture; - logger.debug("Scheduling poll for 1 second out, then every {} s", refreshInterval); - this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 1, refreshInterval, TimeUnit.SECONDS); + logger.debug("Scheduling poll every {} s", refreshInterval); + this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 0, refreshInterval, TimeUnit.SECONDS); } private void poll() { From 3b3795904d5910910a7232a633df76c47f5a32e6 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 07:37:27 +0930 Subject: [PATCH 14/30] Update bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml Co-authored-by: Jacob Laursen Signed-off-by: Paul Smedley --- .../src/main/resources/OH-INF/thing/thing-types.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index f3a73264f200d..88d513fb93ecb 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -42,6 +42,7 @@ Number:EnergyPrice Current price to import power from the grid + Price From 3c9da93aaeebebd606fb79b97d61028cc4f4715e Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 07:37:53 +0930 Subject: [PATCH 15/30] Update bundles/org.openhab.binding.amberelectric/README.md Co-authored-by: Jacob Laursen Signed-off-by: Paul Smedley --- bundles/org.openhab.binding.amberelectric/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 8b946725f2e14..f14b8d99f666c 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -4,7 +4,7 @@ A binding that supports the Australian energy retailer Amber's API (https://www. ## Supported Things -- `amber-electric` Amber Electric API +- `service` Amber Electric API ## Discovery From df9072964d43ac185e3f093c964891e6cdcd9997 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 07:38:03 +0930 Subject: [PATCH 16/30] Update bundles/org.openhab.binding.amberelectric/README.md Co-authored-by: Jacob Laursen Signed-off-by: Paul Smedley --- bundles/org.openhab.binding.amberelectric/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index f14b8d99f666c..7e2794d4e79e7 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -37,7 +37,7 @@ As a minimum, the IP address is needed: ### `amberelectric.things`: ```java -amberelectric:amberelectric:AmberElectric [ apiKey="psk_xxxxxxxxxxxxxxxxxxxx" ] +amberelectric:service:AmberElectric [ apiKey="psk_xxxxxxxxxxxxxxxxxxxx" ] ``` ### `amberelectric.items`: From 557a5ffa5dce53d016047271f267ac5559abdc9a Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 07:39:44 +0930 Subject: [PATCH 17/30] Update bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java Co-authored-by: Jacob Laursen Signed-off-by: Paul Smedley --- .../binding/amberelectric/internal/AmberElectricWebTargets.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index 7d9f96d4802b5..687edbc471166 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -33,7 +33,7 @@ @NonNullByDefault public class AmberElectricWebTargets { private static final int TIMEOUT_MS = 30000; - String baseUri = "https://api.amber.com.au/v1/"; + private static final String BASE_URI = "https://api.amber.com.au/v1/"; private final Logger logger = LoggerFactory.getLogger(AmberElectricWebTargets.class); public AmberElectricWebTargets() { From 6232ee2b7b8358665395b85881e7af80bf474362 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 07:42:27 +0930 Subject: [PATCH 18/30] Further improvements Signed-off-by: Paul Smedley --- .../amberelectric/internal/AmberElectricWebTargets.java | 4 ++-- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index 687edbc471166..2dfe351a766fd 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -40,13 +40,13 @@ public AmberElectricWebTargets() { } public Sites getSites(String apiKey, String nmi) throws AmberElectricCommunicationException { - String getSitesUri = baseUri + "sites"; + String getSitesUri = BASE_URI + "sites"; String response = invoke("GET", getSitesUri, apiKey); return Sites.parse(response, nmi); } public CurrentPrices getCurrentPrices(String siteid, String apiKey) throws AmberElectricCommunicationException { - String getCurrentPricesUri = baseUri + "sites/" + siteid + "/prices/current"; + String getCurrentPricesUri = BASE_URI + "sites/" + siteid + "/prices/current"; String response = invoke("GET", getCurrentPricesUri, apiKey); return CurrentPrices.parse(response); } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 88d513fb93ecb..c5df75489baaf 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -82,7 +82,7 @@ - Number:Dimensionless + Number:Dimensionless Current level of renewables in the grid From c1e63456271eba6cf9c415bc5f8b5beea51dfbf1 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 08:37:19 +0930 Subject: [PATCH 19/30] Improve thing definitions Signed-off-by: Paul Smedley --- .../resources/OH-INF/thing/thing-types.xml | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index c5df75489baaf..a1b4e77dd1708 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -45,36 +45,12 @@ Price - - Number:EnergyPrice - - Current price to import power for Controlled Load - - - - Number:EnergyPrice - - Current price to export power to the grid - - String Current price status of grid import - - String - - Current price status of Controlled Load - - - - String - - Current price status of Feed-In - - String @@ -94,4 +70,21 @@ + + + Current price to import power for Controlled Load + + + + Current price to export power to the grid + + + + Current price status of Controlled Load + + + + Current price status of Feed-In + + From 8b48144fb9ae7da6ae52cd6fff5e3e5952d690b0 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 08:45:48 +0930 Subject: [PATCH 20/30] Cleanups Signed-off-by: Paul Smedley --- .../src/main/resources/OH-INF/thing/thing-types.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index a1b4e77dd1708..7190ea17f66cf 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -82,9 +82,9 @@ Current price status of Controlled Load - - - Current price status of Feed-In - + + + Current price status of Feed-In + From 482e8328c0ac06b9bc3c3284991cf62fc8a0198e Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 08:53:30 +0930 Subject: [PATCH 21/30] Cleanups Signed-off-by: Paul Smedley --- .../amberelectric/internal/AmberElectricHandler.java | 1 - .../src/main/resources/OH-INF/thing/thing-types.xml | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index adaf7f039f790..dc992a0f476b4 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -88,7 +88,6 @@ public void dispose() { } private void schedulePoll() { - ScheduledFuture pollFuture = this.pollFuture; logger.debug("Scheduling poll every {} s", refreshInterval); this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 0, refreshInterval, TimeUnit.SECONDS); } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 7190ea17f66cf..577da6db4a4d2 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -81,10 +81,10 @@ Current price status of Controlled Load - - - - Current price status of Feed-In - + + + + Current price status of Feed-In + From fe30cbeace8d928622ee63e4dc12d8f4b7a23ce0 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 8 Jun 2024 14:37:16 +0930 Subject: [PATCH 22/30] Latest fixes Signed-off-by: Paul Smedley --- .../internal/AmberElectricHandler.java | 13 +++--- .../OH-INF/i18n/amberelectric.properties | 44 ++++++++----------- .../resources/OH-INF/thing/thing-types.xml | 40 +++++++---------- 3 files changed, 43 insertions(+), 54 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index dc992a0f476b4..e06b2b32499f1 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -13,6 +13,7 @@ package org.openhab.binding.amberelectric.internal; import java.io.IOException; +import java.util.Currency; import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -25,7 +26,6 @@ import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; -import org.openhab.core.library.unit.CurrencyUnits; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -124,15 +124,18 @@ private void pollStatus() throws IOException { } CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apiKey); + Currency currency = Currency.getInstance("AUD"); + String currencyCode = currency.getCurrencyCode(); + updateStatus(ThingStatus.ONLINE); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, - new QuantityType<>(currentPrices.elecPerKwh / 100, CurrencyUnits.BASE_ENERGY_PRICE)); + new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + currencyCode + "/kWh")); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, - new QuantityType<>(currentPrices.clPerKwh / 100, CurrencyUnits.BASE_ENERGY_PRICE)); + new QuantityType<>(currentPrices.clPerKwh / 100 + " " + currencyCode + "/kWh")); + updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, + new QuantityType<>(currentPrices.feedInPerKwh / 100 + " " + currencyCode + "/kWh")); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, new StringType(currentPrices.clStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, - new QuantityType<>(currentPrices.feedInPerKwh / 100, CurrencyUnits.BASE_ENERGY_PRICE)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, new StringType(currentPrices.elecStatus)); updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties index 70f13da716e4d..acc0c5bfed8a3 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties @@ -5,38 +5,30 @@ addon.amberelectric.description = This is the binding for Amber Electric. # thing types -thing-type.amberelectric.amber-electric.label = Amber Electric -thing-type.amberelectric.amber-electric.description = Amber Electric - wholesale access to power prices +thing-type.amberelectric.service.label = Amber Electric +thing-type.amberelectric.service.description = Amber Electric - wholesale access to power prices # thing types config -thing-type.config.amberelectric.amber-electric.apikey.label = API Key -thing-type.config.amberelectric.amber-electric.apikey.description = API key from the Amber website -thing-type.config.amberelectric.amber-electric.nmi.label = NMI -thing-type.config.amberelectric.amber-electric.nmi.description = NMI for your address (Optional) -thing-type.config.amberelectric.amber-electric.refresh.label = Refresh Interval -thing-type.config.amberelectric.amber-electric.refresh.description = Specifies the refresh interval in seconds. +thing-type.config.amberelectric.service.apiKey.label = API Key +thing-type.config.amberelectric.service.apiKey.description = API key from the Amber website +thing-type.config.amberelectric.service.nmi.label = NMI +thing-type.config.amberelectric.service.nmi.description = NMI for your address (Optional) +thing-type.config.amberelectric.service.refresh.label = Refresh Interval +thing-type.config.amberelectric.service.refresh.description = Specifies the refresh interval in seconds. # channel types -channel-type.amberelectric.amber-electric-clprice.label = Current Controlled Load Price -channel-type.amberelectric.amber-electric-clprice.description = Current price to import power for Controlled Load -channel-type.amberelectric.amber-electric-clstatus.label = Current Controlled Load Status -channel-type.amberelectric.amber-electric-clstatus.description = Current price status of Controlled Load -channel-type.amberelectric.amber-electric-elecprice.label = Current Electricity Price -channel-type.amberelectric.amber-electric-elecprice.description = Current price to import power from the grid -channel-type.amberelectric.amber-electric-elecstatus.label = Current Electricity Status -channel-type.amberelectric.amber-electric-elecstatus.description = Current price status of grid import -channel-type.amberelectric.amber-electric-feedinprice.label = Current Feed-In Price -channel-type.amberelectric.amber-electric-feedinprice.description = Current price to export power to the grid -channel-type.amberelectric.amber-electric-feedinstatus.label = Current Feed-In Status -channel-type.amberelectric.amber-electric-feedinstatus.description = Current price status of Feed-In -channel-type.amberelectric.amber-electric-nemtime.label = NEM Time -channel-type.amberelectric.amber-electric-nemtime.description = NEM time of last pricing update -channel-type.amberelectric.amber-electric-renewables.label = Current Renewables -channel-type.amberelectric.amber-electric-renewables.description = Current level of renewables in the grid -channel-type.amberelectric.amber-electric-spike.label = Energy Price Spike -channel-type.amberelectric.amber-electric-spike.description = Report if the grid has a current price spike +channel-type.amberelectric.electricity-price.label = Current Electricity Price +channel-type.amberelectric.electricity-price.description = Current price to import power from the grid +channel-type.amberelectric.electricity-status.label = Current Electricity Status +channel-type.amberelectric.electricity-status.description = Current price status of grid import +channel-type.amberelectric.nem-time.label = NEM Time +channel-type.amberelectric.nem-time.description = NEM time of last pricing update +channel-type.amberelectric.renewables.label = Current Renewables +channel-type.amberelectric.renewables.description = Current level of renewables in the grid +channel-type.amberelectric.spike.label = Energy Price Spike +channel-type.amberelectric.spike.description = Report if the grid has a current price spike # thing status descriptions diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 577da6db4a4d2..32b2de1521cf5 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -10,11 +10,23 @@ + + + Current price to import power for Controlled Load + + + + Current price to export power to the grid + - - - - + + + Current price status of Controlled Load + + + + Current price status of Feed-In + @@ -31,7 +43,7 @@ - Specifies the refresh interval in seconds. + Specifies the refresh interval in seconds 60 @@ -69,22 +81,4 @@ Report if the grid has a current price spike - - - - Current price to import power for Controlled Load - - - - Current price to export power to the grid - - - - Current price status of Controlled Load - - - - Current price status of Feed-In - - From 18c277a917fb8c46e0d0806d6db91eae68fdb49d Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sun, 9 Jun 2024 06:55:17 +0930 Subject: [PATCH 23/30] Update bundles/org.openhab.binding.amberelectric/README.md Co-authored-by: Jacob Laursen Signed-off-by: Paul Smedley --- bundles/org.openhab.binding.amberelectric/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 7e2794d4e79e7..7338ae7b9584f 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -43,9 +43,9 @@ amberelectric:service:AmberElectric [ apiKey="psk_xxxxxxxxxxxxxxxxxxxx" ] ### `amberelectric.items`: ```java -Number AmberElectric_ElectricityPrice { channel="amberelectric:service:AmberElectric:electricity-price" } -Number AmberElectric_ControlledLoadPrice { channel="amberelectric:service:AmberElectric:controlled-load-price" } -Number AmberElectric_FeedInPrice { channel="amberelectric:service:AmberElectric:feed-in-price" } +Number:EnergyPrice AmberElectric_ElectricityPrice { channel="amberelectric:service:AmberElectric:electricity-price" } +Number:EnergyPrice AmberElectric_ControlledLoadPrice { channel="amberelectric:service:AmberElectric:controlled-load-price" } +Number:EnergyPrice AmberElectric_FeedInPrice { channel="amberelectric:service:AmberElectric:feed-in-price" } String AmberElectric_ElectricityStatus { channel="amberelectric:service:AmberElectric:electricity-status" } String AmberElectric_ControlledLoadStatus { channel="amberelectric:service:AmberElectric:controlled-load-status" } String AmberElectric_FeedInStatus { channel="amberelectric:service:AmberElectric:feed-in-status" } From 5fb7a1f153b67d5a1edbb41ae7893e5c42de1193 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sun, 9 Jun 2024 07:21:50 +0930 Subject: [PATCH 24/30] Final? Updates Signed-off-by: Paul Smedley --- .../README.md | 4 +- .../AmberElectricBindingConstants.java | 18 ++++---- .../internal/AmberElectricHandler.java | 41 +++++++++---------- .../internal/AmberElectricWebTargets.java | 2 + .../internal/api/CurrentPrices.java | 5 --- .../amberelectric/internal/api/Sites.java | 5 --- .../OH-INF/i18n/amberelectric.properties | 10 ++++- .../resources/OH-INF/thing/thing-types.xml | 2 +- 8 files changed, 42 insertions(+), 45 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 7338ae7b9584f..2b53eb22d0a59 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -49,7 +49,7 @@ Number:EnergyPrice AmberElectric_FeedInPrice { channel="amberelectric:service:Am String AmberElectric_ElectricityStatus { channel="amberelectric:service:AmberElectric:electricity-status" } String AmberElectric_ControlledLoadStatus { channel="amberelectric:service:AmberElectric:controlled-load-status" } String AmberElectric_FeedInStatus { channel="amberelectric:service:AmberElectric:feed-in-status" } -String AmberElectric_nem-time { channel="amberelectric:service:AmberElectric:nem-time" } +String AmberElectric_nemtime { channel="amberelectric:service:AmberElectric:nem-time" } Number AmberElectric_Renewables { channel="amberelectric:service:AmberElectric:renewables" } Switch AmberElectric_Spike { channel="amberelectric:service:AmberElectric:spike" } ``` @@ -63,7 +63,7 @@ Text item=AmberElectric_FeedInPrice label="Feed-In Price" Text item=AmberElectric_ElectricityStatus label="Electricity Price Status" Text item=AmberElectric_ControlledLoadStatus label="Controlled Load Price Status" Text item=AmberElectric_FeedInStatus label="Feed-In Price Status" -Text item=AmberElectric_nem-time label="Current time of NEM pricing" +Text item=AmberElectric_nemtime label="Current time of NEM pricing" Text item=AmberElectric_Renewables label="Renewables Level" Switch item=AmberElectric_Spike label="Spike Status" ``` diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java index 8aafdbca67f4d..004bdc7c567f7 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricBindingConstants.java @@ -32,15 +32,15 @@ public class AmberElectricBindingConstants { public static final ThingTypeUID AMBERELECTRIC_THING = new ThingTypeUID(BINDING_ID, "service"); // List of all Channel ids - public static final String CHANNEL_AMBERELECTRIC_ELECPRICE = "electricity-price"; - public static final String CHANNEL_AMBERELECTRIC_CLPRICE = "controlled-load-price"; - public static final String CHANNEL_AMBERELECTRIC_FEEDINPRICE = "feed-in-price"; - public static final String CHANNEL_AMBERELECTRIC_ELECSTATUS = "electricity-status"; - public static final String CHANNEL_AMBERELECTRIC_CLSTATUS = "controlled-load-status"; - public static final String CHANNEL_AMBERELECTRIC_FEEDINSTATUS = "feed-in-status"; - public static final String CHANNEL_AMBERELECTRIC_NEMTIME = "nem-time"; - public static final String CHANNEL_AMBERELECTRIC_RENEWABLES = "renewables"; - public static final String CHANNEL_AMBERELECTRIC_SPIKE = "spike"; + public static final String CHANNEL_ELECTRICITY_PRICE = "electricity-price"; + public static final String CHANNEL_CONTROLLED_LOAD_PRICE = "controlled-load-price"; + public static final String CHANNEL_FEED_IN_PRICE = "feed-in-price"; + public static final String CHANNEL_ELECTRICITY_STATUS = "electricity-status"; + public static final String CHANNEL_CONTROLLED_LOAD_STATUS = "controlled-load-status"; + public static final String CHANNEL_FEED_IN_STATUS = "feed-in-status"; + public static final String CHANNEL_NEM_TIME = "nem-time"; + public static final String CHANNEL_RENEWABLES = "renewables"; + public static final String CHANNEL_SPIKE = "spike"; public static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(AMBERELECTRIC_THING); } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index e06b2b32499f1..1d5522399619f 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -13,7 +13,6 @@ package org.openhab.binding.amberelectric.internal; import java.io.IOException; -import java.util.Currency; import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -70,15 +69,16 @@ public void initialize() { if (config.apiKey.isBlank()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error.no-api-key"); - } else { - webTargets = new AmberElectricWebTargets(); - updateStatus(ThingStatus.UNKNOWN); - refreshInterval = config.refresh; - nmi = config.nmi; - apiKey = config.apiKey; - - schedulePoll(); + return; } + + webTargets = new AmberElectricWebTargets(); + updateStatus(ThingStatus.UNKNOWN); + refreshInterval = config.refresh; + nmi = config.nmi; + apiKey = config.apiKey; + + schedulePoll(); } @Override @@ -124,27 +124,24 @@ private void pollStatus() throws IOException { } CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apiKey); - Currency currency = Currency.getInstance("AUD"); - String currencyCode = currency.getCurrencyCode(); + String currencyCode = "AUD"; updateStatus(ThingStatus.ONLINE); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECPRICE, + updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + currencyCode + "/kWh")); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLPRICE, + updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_PRICE, new QuantityType<>(currentPrices.clPerKwh / 100 + " " + currencyCode + "/kWh")); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINPRICE, + updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_PRICE, new QuantityType<>(currentPrices.feedInPerKwh / 100 + " " + currencyCode + "/kWh")); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_CLSTATUS, + updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_STATUS, new StringType(currentPrices.clStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_ELECSTATUS, + updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_STATUS, new StringType(currentPrices.elecStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_FEEDINSTATUS, + updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_STATUS, new StringType(currentPrices.feedInStatus)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_NEMTIME, - new StringType(currentPrices.nemTime)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_RENEWABLES, - new DecimalType(currentPrices.renewables)); - updateState(AmberElectricBindingConstants.CHANNEL_AMBERELECTRIC_SPIKE, + updateState(AmberElectricBindingConstants.CHANNEL_NEM_TIME, new StringType(currentPrices.nemTime)); + updateState(AmberElectricBindingConstants.CHANNEL_RENEWABLES, new DecimalType(currentPrices.renewables)); + updateState(AmberElectricBindingConstants.CHANNEL_SPIKE, OnOffType.from(!"none".equals(currentPrices.spikeStatus))); } catch (AmberElectricCommunicationException e) { logger.debug("Unexpected error connecting to Amber Electric API", e); diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java index 2dfe351a766fd..d51d2e6145edc 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricWebTargets.java @@ -42,12 +42,14 @@ public AmberElectricWebTargets() { public Sites getSites(String apiKey, String nmi) throws AmberElectricCommunicationException { String getSitesUri = BASE_URI + "sites"; String response = invoke("GET", getSitesUri, apiKey); + logger.trace("Received response: \"{}\"", response); return Sites.parse(response, nmi); } public CurrentPrices getCurrentPrices(String siteid, String apiKey) throws AmberElectricCommunicationException { String getCurrentPricesUri = BASE_URI + "sites/" + siteid + "/prices/current"; String response = invoke("GET", getCurrentPricesUri, apiKey); + logger.trace("Received response: \"{}\"", response); return CurrentPrices.parse(response); } diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java index e427dc949f9f1..894bb4bc1c919 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/CurrentPrices.java @@ -13,8 +13,6 @@ package org.openhab.binding.amberelectric.internal.api; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -28,8 +26,6 @@ */ @NonNullByDefault public class CurrentPrices { - private static Logger LOGGER = LoggerFactory.getLogger(CurrentPrices.class); - public double elecPerKwh; public double clPerKwh; public double feedInPerKwh; @@ -44,7 +40,6 @@ private CurrentPrices() { } public static CurrentPrices parse(String response) { - LOGGER.debug("Parsing string: \"{}\"", response); /* parse json string */ JsonArray jsonArray = JsonParser.parseString(response).getAsJsonArray(); JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java index 7779b0d58f707..d387178b7c986 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/api/Sites.java @@ -13,8 +13,6 @@ package org.openhab.binding.amberelectric.internal.api; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -28,8 +26,6 @@ */ @NonNullByDefault public class Sites { - private static Logger LOGGER = LoggerFactory.getLogger(Sites.class); - public String siteid = ""; public String nmi = ""; @@ -37,7 +33,6 @@ private Sites() { } public static Sites parse(String response, String nem) { - LOGGER.debug("Parsing string: \"{}\"", response); /* parse json string */ JsonArray jsonArray = JsonParser.parseString(response).getAsJsonArray(); Sites sites = new Sites(); diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties index acc0c5bfed8a3..fc39b8515fb49 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/i18n/amberelectric.properties @@ -7,6 +7,14 @@ addon.amberelectric.description = This is the binding for Amber Electric. thing-type.amberelectric.service.label = Amber Electric thing-type.amberelectric.service.description = Amber Electric - wholesale access to power prices +thing-type.amberelectric.service.channel.controlled-load-price.label = Current Controlled Load Price +thing-type.amberelectric.service.channel.controlled-load-price.description = Current price to import power for Controlled Load +thing-type.amberelectric.service.channel.controlled-load-status.label = Current Controlled Load Status +thing-type.amberelectric.service.channel.controlled-load-status.description = Current price status of Controlled Load +thing-type.amberelectric.service.channel.feed-in-price.label = Current Feed-In Price +thing-type.amberelectric.service.channel.feed-in-price.description = Current price to export power to the grid +thing-type.amberelectric.service.channel.feed-in-status.label = Current Feed-In Status +thing-type.amberelectric.service.channel.feed-in-status.description = Current price status of Feed-In # thing types config @@ -15,7 +23,7 @@ thing-type.config.amberelectric.service.apiKey.description = API key from the Am thing-type.config.amberelectric.service.nmi.label = NMI thing-type.config.amberelectric.service.nmi.description = NMI for your address (Optional) thing-type.config.amberelectric.service.refresh.label = Refresh Interval -thing-type.config.amberelectric.service.refresh.description = Specifies the refresh interval in seconds. +thing-type.config.amberelectric.service.refresh.description = Specifies the refresh interval in seconds # channel types diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 32b2de1521cf5..60418dc6fd448 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -55,7 +55,7 @@ Current price to import power from the grid Price - + String From 404f663e405fec8c3d202d8d0e071a1db583a76c Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Mon, 10 Jun 2024 08:06:41 +0930 Subject: [PATCH 25/30] Update NMI config with the detected one if it's left empty Signed-off-by: Paul Smedley --- .../binding/amberelectric/internal/AmberElectricHandler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 1d5522399619f..448efd44f09f6 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.amberelectric.internal.api.CurrentPrices; import org.openhab.binding.amberelectric.internal.api.Sites; +import org.openhab.core.config.core.Configuration; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.QuantityType; @@ -120,6 +121,9 @@ private void pollStatus() throws IOException { Sites sites = webTargets.getSites(apiKey, nmi); // add error handling siteID = sites.siteid; + Configuration configuration = editConfiguration(); + configuration.put("nmi", sites.nmi); + updateConfiguration(configuration); logger.debug("Detected amber siteid is {}, for nmi {}", sites.siteid, sites.nmi); } From f6ca4d90795e35f6d75d4e3dbf51348e48aaeeef Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Tue, 11 Jun 2024 06:55:19 +0930 Subject: [PATCH 26/30] Tidy up the setting of electricity price Signed-off-by: Paul Smedley --- .../amberelectric/internal/AmberElectricHandler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 448efd44f09f6..1eb01a08b5532 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -128,15 +128,15 @@ private void pollStatus() throws IOException { } CurrentPrices currentPrices = webTargets.getCurrentPrices(siteID, apiKey); - String currencyCode = "AUD"; + final String electricityUnit = " AUD/kWh"; updateStatus(ThingStatus.ONLINE); updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, - new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + currencyCode + "/kWh")); + new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + electricityUnit)); updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_PRICE, - new QuantityType<>(currentPrices.clPerKwh / 100 + " " + currencyCode + "/kWh")); + new QuantityType<>(currentPrices.clPerKwh / 100 + " " + electricityUnit)); updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_PRICE, - new QuantityType<>(currentPrices.feedInPerKwh / 100 + " " + currencyCode + "/kWh")); + new QuantityType<>(currentPrices.feedInPerKwh / 100 + " " + electricityUnit)); updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_STATUS, new StringType(currentPrices.clStatus)); updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_STATUS, From f499c5f6a007640195ebddae9b6e852da9fdbf1b Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Thu, 13 Jun 2024 06:31:37 +0930 Subject: [PATCH 27/30] Fallback to DecimalType if AUD is unknown Signed-off-by: Paul Smedley --- .../internal/AmberElectricHandler.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 1eb01a08b5532..9a7b00cbabdb2 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -17,6 +17,8 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import javax.measure.Unit; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.amberelectric.internal.api.CurrentPrices; @@ -26,6 +28,7 @@ import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.CurrencyUnits; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -131,12 +134,23 @@ private void pollStatus() throws IOException { final String electricityUnit = " AUD/kWh"; updateStatus(ThingStatus.ONLINE); - updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, - new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + electricityUnit)); - updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_PRICE, - new QuantityType<>(currentPrices.clPerKwh / 100 + " " + electricityUnit)); - updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_PRICE, - new QuantityType<>(currentPrices.feedInPerKwh / 100 + " " + electricityUnit)); + Unit unit = CurrencyUnits.getInstance().getUnit("AUD"); + if (unit == null) { + logger.trace("Currency AUD is unknown, falling back to DecimalType"); + updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, + new DecimalType(currentPrices.elecPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_PRICE, + new DecimalType(currentPrices.clPerKwh)); + updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_PRICE, + new DecimalType(currentPrices.feedInPerKwh)); + } else { + updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, + new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + electricityUnit)); + updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_PRICE, + new QuantityType<>(currentPrices.clPerKwh / 100 + " " + electricityUnit)); + updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_PRICE, + new QuantityType<>(currentPrices.feedInPerKwh / 100 + " " + electricityUnit)); + } updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_STATUS, new StringType(currentPrices.clStatus)); updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_STATUS, From 01541fba6aaeaed7c1887e9790cc70f159762b37 Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 15 Jun 2024 06:44:16 +0930 Subject: [PATCH 28/30] Fixes Signed-off-by: Paul Smedley --- bundles/org.openhab.binding.amberelectric/README.md | 4 ++-- .../amberelectric/internal/AmberElectricHandler.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bundles/org.openhab.binding.amberelectric/README.md b/bundles/org.openhab.binding.amberelectric/README.md index 2b53eb22d0a59..f856eddbd425c 100644 --- a/bundles/org.openhab.binding.amberelectric/README.md +++ b/bundles/org.openhab.binding.amberelectric/README.md @@ -1,6 +1,6 @@ # Amber Electric Binding -A binding that supports the Australian energy retailer Amber's API (https://www.amber.com.au/) and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. +A binding that supports the Australian energy retailer Amber's API () and provides data on the current pricing for buying and selling power, as well as the current level of renewables in the NEM. ## Supported Things @@ -14,7 +14,7 @@ The binding does not support auto discovery. As a minimum, the IP address is needed: -- `apiKey` - The API key from the 'Developer' section of https://apps.amber.com.au +- `apiKey` - The API key from the 'Developer' section of - 'nmi' optional - the NMI for your property. Required if you have multiple properties with Amber - 'refresh' the refresh rate for querying the API. diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 9a7b00cbabdb2..35e88749f1bdf 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -138,11 +138,11 @@ private void pollStatus() throws IOException { if (unit == null) { logger.trace("Currency AUD is unknown, falling back to DecimalType"); updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, - new DecimalType(currentPrices.elecPerKwh)); + new DecimalType(currentPrices.elecPerKwh / 100)); updateState(AmberElectricBindingConstants.CHANNEL_CONTROLLED_LOAD_PRICE, - new DecimalType(currentPrices.clPerKwh)); + new DecimalType(currentPrices.clPerKwh / 100)); updateState(AmberElectricBindingConstants.CHANNEL_FEED_IN_PRICE, - new DecimalType(currentPrices.feedInPerKwh)); + new DecimalType(currentPrices.feedInPerKwh / 100)); } else { updateState(AmberElectricBindingConstants.CHANNEL_ELECTRICITY_PRICE, new QuantityType<>(currentPrices.elecPerKwh / 100 + " " + electricityUnit)); From 80d5e15f5ea6b27e2290fe704ba8c6830d85068b Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 15 Jun 2024 06:45:58 +0930 Subject: [PATCH 29/30] Fixes Signed-off-by: Paul Smedley --- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml index 60418dc6fd448..af7dea0c79e52 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amberelectric/src/main/resources/OH-INF/thing/thing-types.xml @@ -73,7 +73,7 @@ Number:Dimensionless Current level of renewables in the grid - + Switch From 075a8eedc1b8af44b1cb0dbefdfe5c144af8b67c Mon Sep 17 00:00:00 2001 From: Paul Smedley Date: Sat, 15 Jun 2024 09:40:34 +0930 Subject: [PATCH 30/30] (Hopefully) final updates before merge Signed-off-by: Paul Smedley --- CODEOWNERS | 1 + .../binding/amberelectric/internal/AmberElectricHandler.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index fbe2c959274ae..34fcdaefaba44 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -22,6 +22,7 @@ /bundles/org.openhab.binding.allplay/ @dominicdesu /bundles/org.openhab.binding.amazondashbutton/ @openhab/add-ons-maintainers /bundles/org.openhab.binding.amazonechocontrol/ @mgeramb +/bundles/org.openhab.binding.amberelectric/ @psmedley /bundles/org.openhab.binding.ambientweather/ @mhilbush /bundles/org.openhab.binding.amplipi/ @kaikreuzer /bundles/org.openhab.binding.androiddebugbridge/ @GiviMAD diff --git a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java index 35e88749f1bdf..aa91c4bab7575 100644 --- a/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java +++ b/bundles/org.openhab.binding.amberelectric/src/main/java/org/openhab/binding/amberelectric/internal/AmberElectricHandler.java @@ -118,7 +118,6 @@ private void stopPoll() { } private void pollStatus() throws IOException { - try { if (siteID.isEmpty()) { Sites sites = webTargets.getSites(apiKey, nmi);