Bringing electricity information from eloverblik.dk and energidataservice.dk into Openhab

@laursen : it’s Radius - GLN is 5790000705689

It should have changed at 17:00 - this is the currently valid record:

		{
			"ChargeOwner": "Radius Elnet A/S",
			"GLN_Number": "5790000705689",
			"ChargeType": "D03",
			"ChargeTypeCode": "DT_C_01",
			"Note": "Nettarif C time",
			"Description": "Nettarif C time",
			"ValidFrom": "2023-01-01T00:00:00",
			"ValidTo": "2023-02-01T00:00:00",
			"VATClass": "D02",
			"Price1": 0.1701,
			"Price2": 0.1701,
			"Price3": 0.1701,
			"Price4": 0.1701,
			"Price5": 0.1701,
			"Price6": 0.1701,
			"Price7": 0.5103,
			"Price8": 0.5103,
			"Price9": 0.5103,
			"Price10": 0.5103,
			"Price11": 0.5103,
			"Price12": 0.5103,
			"Price13": 0.5103,
			"Price14": 0.5103,
			"Price15": 0.5103,
			"Price16": 0.5103,
			"Price17": 0.5103,
			"Price18": 1.5308,
			"Price19": 1.5308,
			"Price20": 1.5308,
			"Price21": 1.5308,
			"Price22": 0.5103,
			"Price23": 0.5103,
			"Price24": 0.5103,
			"TransparentInvoicing": 0,
			"TaxIndicator": 0,
			"ResolutionDuration": "PT1H"
		}

Since it worked yesterday for the same record, did you change anything since yesterday? Do you use persistence with strategy forecast? In order to investigate further, I would need you to enable trace logging, and report back with some logs if you see this again.

Erhm, sorry, looked at the wrong record. This is the one:

		{
			"ChargeOwner": "Radius Elnet A/S",
			"GLN_Number": "5790000705689",
			"ChargeType": "D03",
			"ChargeTypeCode": "DT_C_01",
			"Note": "Nettarif C time",
			"Description": "Nettarif C time",
			"ValidFrom": "2023-10-01T00:00:00",
			"ValidTo": "2024-04-01T00:00:00",
			"VATClass": "D02",
			"Price1": 0.1215,
			"Price2": 0.1215,
			"Price3": 0.1215,
			"Price4": 0.1215,
			"Price5": 0.1215,
			"Price6": 0.1215,
			"Price7": 0.3645,
			"Price8": 0.3645,
			"Price9": 0.3645,
			"Price10": 0.3645,
			"Price11": 0.3645,
			"Price12": 0.3645,
			"Price13": 0.3645,
			"Price14": 0.3645,
			"Price15": 0.3645,
			"Price16": 0.3645,
			"Price17": 0.3645,
			"Price18": 1.0934,
			"Price19": 1.0934,
			"Price20": 1.0934,
			"Price21": 1.0934,
			"Price22": 0.3645,
			"Price23": 0.3645,
			"Price24": 0.3645,
			"TransparentInvoicing": 0,
			"TaxIndicator": 0,
			"ResolutionDuration": "PT1H"
		},

Now the numbers also match the ones you posted (just in this case excluding VAT). But it still should change at 17:00.

Ok, that looks strange. From the events.log I can see yesterday it was updated at 17:00 but today it was updated at 18:00:

2024-01-14 13:00:05.499 [INFO ] [hab.event.ItemTimeSeriesUpdatedEvent] - Item 'TransmissionNetTariff' updated timeseries [Entry[timestamp=2024-01-13T12:00:00Z, state=0.09250000]]
2024-01-14 15:00:00.005 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.30093750 to 2.33048751875 through NetTariff
2024-01-14 17:00:00.167 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'NetTariff' changed from 0.45562500 to 1.36675000
2024-01-14 17:00:00.182 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.41941253625 to 3.33053753625 through NetTariff
2024-01-14 21:00:00.005 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'NetTariff' changed from 1.36675000 to 0.45562500
2024-01-14 23:00:00.007 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.26588752750 to 2.18665000875 through NetTariff
2024-01-15 00:00:00.004 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'NetTariff' changed from 0.45562500 to 0.15187500
2024-01-15 00:00:00.011 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.21237503000 to 1.90862503000 through NetTariff
2024-01-15 06:00:00.008 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'NetTariff' changed from 0.15187500 to 0.45562500
2024-01-15 06:00:00.018 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.00463752750 to 2.30838752750 through NetTariff
2024-01-15 09:00:00.006 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.4887625125 to 2.49798751875 through NetTariff
2024-01-15 13:00:12.577 [INFO ] [openhab.event.ItemTimeSeriesEvent   ] - Item 'NetTariff' shall process timeseries [Entry[timestamp=2024-01-14T12:00:00Z, state=0.45562500], Entry[timestamp=2024-01-14T16:00:00Z, state=1.36675000], Entry[timestamp=2024-01-14T20:00:00Z, state=0.45562500], Entry[timestamp=2024-01-14T23:00:00Z, state=0.15187500], Entry[timestamp=2024-01-15T05:00:00Z, state=0.45562500], Entry[timestamp=2024-01-15T16:00:00Z, state=1.36675000], Entry[timestamp=2024-01-15T20:00:00Z, state=0.45562500], Entry[timestamp=2024-01-15T23:00:00Z, state=0.15187500], Entry[timestamp=2024-01-16T05:00:00Z, state=0.45562500], Entry[timestamp=2024-01-16T16:00:00Z, state=1.36675000], Entry[timestamp=2024-01-16T20:00:00Z, state=0.45562500]]
2024-01-15 13:00:12.578 [INFO ] [openhab.event.ItemTimeSeriesEvent   ] - Item 'TransmissionNetTariff' shall process timeseries [Entry[timestamp=2024-01-14T12:00:00Z, state=0.09250000]]
2024-01-15 13:00:13.517 [INFO ] [hab.event.ItemTimeSeriesUpdatedEvent] - Item 'NetTariff' updated timeseries [Entry[timestamp=2024-01-14T12:00:00Z, state=0.45562500], Entry[timestamp=2024-01-14T16:00:00Z, state=1.36675000], Entry[timestamp=2024-01-14T20:00:00Z, state=0.45562500], Entry[timestamp=2024-01-14T23:00:00Z, state=0.15187500], Entry[timestamp=2024-01-15T05:00:00Z, state=0.45562500], Entry[timestamp=2024-01-15T16:00:00Z, state=1.36675000], Entry[timestamp=2024-01-15T20:00:00Z, state=0.45562500], Entry[timestamp=2024-01-15T23:00:00Z, state=0.15187500], Entry[timestamp=2024-01-16T05:00:00Z, state=0.45562500], Entry[timestamp=2024-01-16T16:00:00Z, state=1.36675000], Entry[timestamp=2024-01-16T20:00:00Z, state=0.45562500]]
2024-01-15 13:00:13.518 [INFO ] [hab.event.ItemTimeSeriesUpdatedEvent] - Item 'TransmissionNetTariff' updated timeseries [Entry[timestamp=2024-01-14T12:00:00Z, state=0.09250000]]
2024-01-15 14:00:00.007 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.32889999375 to 2.35081253000 through NetTariff
2024-01-15 18:00:00.010 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'TotalPrice' changed from 2.64043747000 to 3.55156247000 through NetTariff
2024-01-15 18:00:00.018 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'NetTariff' changed from 0.45562500 to 1.36675000

This is 17:00, so it was published correctly as time series.

Do you use persistence with strategy forecast? If you do, it should have been updated on the event bus automatically by core. If not, it should still have been updated by the hourly job. In any case, trace logs will be needed.

1 Like

@DanielMalmgren - I don’t want to change the topic in this thread:

But I’m wondering if you by any chance are in price area SE3 or SE4? It seems Energi Data Service provides spot prices for those areas, so in this case you might be able to use this binding. The configuration needed:

With Freecurrency installed as well:

With VAT if you’d like:

With persistence:

I just did a quick backport of Freecurrency to 4.1, but did not yet test it:
org.openhab.binding.freecurrency-4.1.3-SNAPSHOT.jar

Yep, I’m in SE3, so this is exactly what I need! Also I don’t really care about currency, what I need right now is just information about which hours are the cheapest :wink:

I tried though and can’t really get it to work. I now have a script with the following code:

val actions = getActions("energidataservice", "energidataservice:service:energidataservice")
var java.util.Map<String, Object> result = actions.calculateCheapestPeriod(now.toInstant(), now.plusHours(12).toInstant(), java.time.Duration.ofMinutes(90))

…which I think should give me a nice Map, but all I get is the following error:
Script execution of rule with UID ‘9b226fe25a’ failed: Instance is not an EnergiDataServiceActions class.

Any idea what could be wrong?

Can you show your Thing definition? If created from the UI, perhaps the thingUID is not energidataservice:service:energidataservice?

I assume you also have this in the beginning of your DSL rule:

import java.time.Duration
import java.util.Map

Ah, you’re right! The UID of my thing actually is “energidataservice:service:635c20512c”. I guess that’s auto generated in some way when creating the Thing through GUI. Works better now!

However, I’m stuck again at the next step, trying to get the actual time. I’m doing this:
logInfo(“Cheapest start”, (result.get(“CheapestStart”) as Instant).toString)

and I get the following in my log:

12:36:21.316 [WARN ] [ernal.action.EnergiDataServiceActions] - Cannot calculate sum when spot price currency is EUR
12:36:21.320 [WARN ] [ernal.action.EnergiDataServiceActions] - Price missing at 2024-03-25T11:00:00Z
12:36:21.323 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘9b226fe25a’ failed: cannot invoke method public java.lang.String java.time.Instant.toString() on null

Changing from EUR to DKK in the Thing configuration makes the first disappear, I guess it’s some conversion error?

Tried with debug logging on for the binding:

12:47:01.591 [DEBUG] [rnal.handler.EnergiDataServiceHandler] - Cached spot prices still valid, skipping download.
12:47:01.592 [DEBUG] [rnal.handler.EnergiDataServiceHandler] - Cached tariffs of type SYSTEM_TARIFF still valid, skipping download.
12:47:01.596 [DEBUG] [rnal.handler.EnergiDataServiceHandler] - Cached tariffs of type TRANSMISSION_GRID_TARIFF still valid, skipping download.
12:47:01.598 [DEBUG] [rnal.handler.EnergiDataServiceHandler] - Cached tariffs of type ELECTRICITY_TAX still valid, skipping download.
12:47:01.603 [WARN ] [ernal.action.EnergiDataServiceActions] - Price missing at 2024-03-25T23:00:00Z
12:47:01.605 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘9b226fe25a’ failed: cannot invoke method public java.lang.String java.time.Instant.toString() on null

edit: After some more digging (with my limited knowledge of Java) I’ve come to the conclusion that calculateCheapestPeriod returns an empty map for me. Don’t really know where to go from that knowledge…

I need to look into this one. I think I’m missing an overload of the method taking price components into consideration. Since tariffs will always be in DKK, it’s not possible to create a sum of EUR and DKK. The problem is that the method will take tariffs into consideration as well, but there are actually no tariffs to be considered in your case. I will check later. For now you can use DKK, and if you prefer EUR or SEK, you can use Freecurrency.

This is actually correct since your rule calculates 12 hours into the future, but there are still no prices available after midnight. Please try again in three minutes, or adjust your rule. :slight_smile:

1 Like

Ah, that makes sense. Now I get a correct time out of it! Just need to get the logic together and I’ll get my house battery charging when it’s at the cheapest :smiling_face_with_three_hearts:

1 Like

Hi @laursen :

I noticed some weird issue with the data and maybe you can give me some hints where to look. I have defined NetTariff below:

Number              NetTariff                     "Current El Net Tariff [%.2f kr/kWh]"             <price>    (TotalPrice)                    {channel="energidataservice:service:energidataservice:electricity#grid-tariff" [profile="transform:VAT"]}

It used to work fine but don’t know since when it returns UNDEF value, and make the current EL price wrong. It also look strange to me that hourly price looks like the following:

{"hourStart":"2024-04-27T14:00:00Z","spotPrice":0.156080002,"spotPriceCurrency":"DKK","systemTariff":0.051000,"transmissionGridTariff":0.761000,"electricityTax":0.008000,"reducedElectricityTax":0.074000}

I’m no expert in taxation, but doesn’t looks right to me that reducedElectricityTax is higher than electricityTax. transmissionGridTariff also seem to be the same value for all hours. Could there be some API change recently?
Many thanks in advance!

This depends on your Thing and channel configuration, i.e. which grid company you are using and if you have custom filters for the grid tariff channel. I can see from previous messages that your grid company is Radius, and they recently made some changes. The built-in filter has been adjusted accordingly:

To fix it in the version of openHAB you are using, you can configure the channel like this:

It seems the prices were mixed up by mistake. The last three are:

  • transmissionGridTariff
  • electricityTax,
  • reducedElectricityTax

But they were provided in this order:

  • electricityTax
  • reducedElectricityTax
  • transmissionGridTariff

So 0.761000 is the electricity tax, 0.008000 is the reduced electricity tax and 0.074000 is the transmission grid tariff. None of them changes by the hour. Sorry for the inconvenience.

Please note that the hourly-prices channel is obsoleted and will be removed in 4.2:

Blockquote
To fix it in the version of openHAB you are using, you can configure the channel like this:

Strange I cannot seem to save the configuration for the channel, maybe a bug in OpenHAB? Or could it be because I configured the item in items file? Is there a way to configure the channel by text file?

Blockquote
Please note that the hourly-prices channel is obsoleted and will be removed in 4.2:

Thanks, that’s good to know! I currently only use hourly-prices as a trigger to know anything changes. I guess I can default to a hourly cron schedule instead after it’s removed.

Yes, it’s not a bug, you cannot edit unmanaged configuration in the UI. See channel configuration parameters here: Energi Data Service - Bindings | openHAB - and an example here: Energi Data Service - Bindings | openHAB

Yes, that should give almost the same result, since the JSON for that channel changes every hour when older prices slides out of scope. The only exception is that when receiving new spot prices slightly after 13:00, the hourly-prices channel would also update. I don’t know if that makes a difference to you, it depends what the purpose of “knowing anything changed” is.

Thank you, it works now :slight_smile:

Blockquote
I don’t know if that makes a difference to you, it depends what the purpose of “knowing anything changed” is.

I listen to the changes for the following reason:

  1. It tells me when the prices for tomorrow has arrived, and I can send notification when I know the cheap/expensive period tomorrow
  2. I use the stock persistency service which doesn’t support query, hence I don’t have time series. Instead I have items for each hour and I manually update each hour’s price.

(channel hourly-prices)

So you trigger when the item is updated and then parse the JSON looking for tomorrow’s prices to distinguish between the hourly update and the ~13:00 update when new prices are available?

You have two options for refactoring this:

Both are available in 4.1. I don’t currently have good idea for replacing the trigger. There are properties lastCall and nextCall, but I don’t think they can be accessed from rules. Maybe this is something to look into, because it would be neat also being able to detect firmware upgrades etc., and firmware version is often updated as a property.

If you don’t need the notification to be exactly when new prices are available, you could still trigger every hour, and have an additional trigger 13:01:00. It won’t be immediate though, and also it won’t support scenarios where prices are not available as expected, resulting in retries with exponential backoff strategy.

You can use InMemory persistence for this purpose.

Perhaps a trigger channel could be a solution, i.e. triggered when new spot prices have been fetched.

Hi, thank you for your reply! I actually use the hourly prices channel only for the trigger of rules, inside the rule I fetch hourly prices by action getPrices, and it worked quite well. So essentially I need a trigger that tells me:

  1. Tomorrow’s prices have arrived (usually at 13:00)
  2. Date roll - copy tomorrow’s prices to today’s and reset to UNDEF
    It is based on the assumption that once prices are available it’s not updated during the day.

Blockquote
You can use InMemory persistence for this purpose.

I need to look into how to use it - but for me storing hourly prices in items gives one benefit (which I’m not sure InMemory persistence will give) that I can compare to history. For example what I do now to compare avg price during 17-21 (the expensive period) to avg prices in the past 7 days, and if the difference is more than 1 std deviation I notify myself that tomorrow evening price is higher than usual. Similarly I can compare midnight prices and decide if it’s good for charging or I should wait till tomorrow (usually lower 21-24 price means lower 0-6 prices).

Would this work for you?

It would trigger only when starting the binding and around 13:00 after receiving spot prices for the next day.

Triggered as cron expression at midnight, right?

I think you can do all of this using Persistence Extensions. For example, you could use <item>.averageBetween(ZonedDateTime, ZonedDateTime) - example:

var tomorrowPeakStart = time.toZDT().plusDays(1).withHour(17).withMinute(0).withSecond(0).withNano(0);
var tomorrowPeakEnd = tomorrowPeakStart.plusHours(4);
var averageSpotPrice = items.Energi_Data_Service_Spot_Price.history.averageBetween(tomorrowPeakStart, tomorrowPeakEnd);
console.log(`Average spot price between ${tomorrowPeakStart} and ${tomorrowPeakEnd}: ${averageSpotPrice}`);

There are a few limitations though, for example Group SUM doesn’t support time series:

But in 4.2 it should be possible to work around this limitation by creating a rule to persist future total price:

This PR introduces persist(Item item, ZonedDateTime timestamp, State state, String serviceId) allowing rules to persist future states.

1 Like