From e9a149cb1598c6546a10ca4c378871659376b7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20K=C3=BCper?= Date: Mon, 15 Jan 2024 18:46:50 +0100 Subject: [PATCH] [tibber] Add time series support for Tibber prices (#16275) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sönke Küper Signed-off-by: Ciprian Pascu --- bundles/org.openhab.binding.tibber/README.md | 73 ++++++++++--------- .../internal/handler/TibberHandler.java | 32 +++++++- 2 files changed, 70 insertions(+), 35 deletions(-) diff --git a/bundles/org.openhab.binding.tibber/README.md b/bundles/org.openhab.binding.tibber/README.md index 18384df71c1..44fba1ed783 100644 --- a/bundles/org.openhab.binding.tibber/README.md +++ b/bundles/org.openhab.binding.tibber/README.md @@ -19,43 +19,47 @@ The channels (i.e. measurements) associated with the Binding: Tibber Default: -| Channel ID | Description | Read-only | -|--------------------|---------------------------------------------------------|-----------| -| Current Total | Current Total Price (energy + tax) | True | -| Starts At | Current Price Timestamp | True | -| Current Level | Current Price Level | True | -| Daily Cost | Daily Cost (last/previous day) | True | -| Daily Consumption | Daily Consumption (last/previous day) | True | -| Daily From | Timestamp (daily from) | True | -| Daily To | Timestamp (daily to) | True | -| Hourly Cost | Hourly Cost (last/previous hour) | True | -| Hourly Consumption | Hourly Consumption (last/previous hour) | True | -| Hourly From | Timestamp (hourly from) | True | -| Hourly To | Timestamp (hourly to) | True | -| Tomorrow prices | JSON array of tomorrow's prices. See below for example. | True | -| Today prices | JSON array of today's prices. See below for example. | True | +| Channel ID | Description | Read-only | Forecast | +|----------------------|---------------------------------------------------------|-----------|----------| +| current_total | Current Total Price (energy + tax) | True | yes | +| current_startsAt | Current Price Timestamp | True | no | +| current_level | Current Price Level | True | no | +| daily_cost | Daily Cost (last/previous day) | True | no | +| daily_consumption | Daily Consumption (last/previous day) | True | no | +| daily_from | Timestamp (daily from) | True | no | +| daily_to | Timestamp (daily to) | True | no | +| hourly_cost | Hourly Cost (last/previous hour) | True | no | +| hourly_consumption | Hourly Consumption (last/previous hour) | True | no | +| hourly_from | Timestamp (hourly from) | True | no | +| hourly_to | Timestamp (hourly to) | True | no | +| tomorrow_prices | JSON array of tomorrow's prices. See below for example. | True | no | +| today_prices | JSON array of today's prices. See below for example. | True | no | Tibber Pulse (optional): -| Channel ID | Description | Read-only | -|-------------------------|------------------------------------------|-----------| -| Timestamp | Timestamp for live measurements | True | -| Power | Live Power Consumption | True | -| Last Meter Consumption | Last Recorded Meter Consumption | True | -| Accumulated Consumption | Accumulated Consumption since Midnight | True | -| Accumulated Cost | Accumulated Cost since Midnight | True | -| Accumulated Reward | Accumulated Reward since Midnight | True | -| Currency | Currency of Cost | True | -| Min Power | Min Power Consumption since Midnight | True | -| Average Power | Average Power Consumption since Midnight | True | -| Max Power | Max Power Consumption since Midnight | True | -| Voltage 1-3 | Voltage per Phase | True | -| Current 1-3 | Current per Phase | True | -| Power Production | Live Power Production | True | -| Accumulated Production | Accumulated Production since Midnight | True | -| Last Meter Production | Last Recorded Meter Production | True | -| Min Power Production | Min Power Production since Midnight | True | -| Max Power Production | Max Power Production since Midnight | True | +| Channel ID | Description | Read-only | +|-----------------------------|------------------------------------------|-----------| +| live_timestamp | Timestamp for live measurements | True | +| live_power | Live Power Consumption | True | +| live_lastMeterConsumption | Last Recorded Meter Consumption | True | +| live_accumulatedConsumption | Accumulated Consumption since Midnight | True | +| live_accumulatedCost | Accumulated Cost since Midnight | True | +| live_accumulatedReward | Accumulated Reward since Midnight | True | +| live_currency | Currency of Cost | True | +| live_minPower | Min Power Consumption since Midnight | True | +| live_averagePower | Average Power Consumption since Midnight | True | +| live_maxPower | Max Power Consumption since Midnight | True | +| live_voltage1 | Voltage Phase 1 | True | +| live_voltage2 | Voltage Phase 2 | True | +| live_voltage3 | Voltage Phase 3 | True | +| live_current1 | Current Phase 1 | True | +| live_current2 | Current Phase 2 | True | +| live_current3 | Current Phase 3 | True | +| live_powerProduction | Live Power Production | True | +| live_accumulatedProduction | Accumulated Production since Midnight | True | +| live_lastMeterProduction | Last Recorded Meter Production | True | +| live_minPowerproduction | Min Power Production since Midnight | True | +| live_maxPowerproduction | Max Power Production since Midnight | True | ## Binding Configuration @@ -102,6 +106,7 @@ Tibber API will be auto discovered if provided input is correct. ## Tomorrow and Today Prices +The today and tomorrow prices are served as forecast on the `current_total` channel and as JSON data on the channels `today_prices` and `tomorrow_prices`. Example of tomorrow and today prices data structure - an array of tuples: ```json diff --git a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java index a93a5494a4e..d9217886628 100644 --- a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java +++ b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java @@ -19,6 +19,9 @@ import java.io.InputStream; import java.math.BigDecimal; import java.net.URI; import java.net.URISyntaxException; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; import java.util.Properties; import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; @@ -52,6 +55,7 @@ import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.openhab.core.types.TimeSeries; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -203,7 +207,10 @@ public class TibberHandler extends BaseThingHandler { .getAsJsonObject("home").getAsJsonObject("currentSubscription").getAsJsonObject("priceInfo") .getAsJsonArray("today"); updateState(TODAY_PRICES, new StringType(today.toString())); - } catch (JsonSyntaxException e) { + + TimeSeries timeSeries = buildTimeSeries(today, tomorrow); + sendTimeSeries(CURRENT_TOTAL, timeSeries); + } catch (JsonSyntaxException | DateTimeParseException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error communicating with Tibber API: " + e.getMessage()); } @@ -267,6 +274,29 @@ public class TibberHandler extends BaseThingHandler { } } + /** + * Builds the {@link TimeSeries} that represents the future tibber prices. + * + * @param today The prices for today + * @param tomorrow The prices for tomorrow. + * @return The {@link TimeSeries} with future values. + */ + private TimeSeries buildTimeSeries(JsonArray today, JsonArray tomorrow) { + final TimeSeries timeSeries = new TimeSeries(TimeSeries.Policy.REPLACE); + mapTimeSeriesEntries(today, timeSeries); + mapTimeSeriesEntries(tomorrow, timeSeries); + return timeSeries; + } + + private void mapTimeSeriesEntries(JsonArray prices, TimeSeries timeSeries) { + for (JsonElement entry : prices) { + JsonObject entryObject = entry.getAsJsonObject(); + final Instant startsAt = ZonedDateTime.parse(entryObject.get("startsAt").getAsString()).toInstant(); + final DecimalType value = new DecimalType(entryObject.get("total").getAsString()); + timeSeries.add(startsAt, value); + } + } + public void startRefresh(int refresh) { if (pollingJob == null) { pollingJob = scheduler.scheduleWithFixedDelay(() -> {