Hellis81
(Hellis81)
January 13, 2023, 8:33am
3
I think something like this:
{% set ns = namespace(sum = 0, count = 0) %}
{% for item in state_attr('sensor.sensor', 'forcast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% set ns.sum = ns.sum + item.price %}
{% set ns.count = ns.count + 1 %}
{% endif %}
{%- endfor %}
{{ ns.count }}
{{ ns.sum }}
{{ ns.sum/ns.count }}
1 Like
Tyfoon
(@Tyfoon)
January 13, 2023, 8:40am
4
Good point. Only notice now. Ill need to check that.
Tyfoon
(@Tyfoon)
January 13, 2023, 8:42am
5
Wow. Thanks! This works and is super useful for some other stuff I want to create.
Sorry for the noob question but how do I now get this into a template sensor? Never worked worked with a template like this using variables.
Hellis81
(Hellis81)
January 13, 2023, 8:44am
6
You can test if first in developer tools → template to make sure it works.
Tyfoon
(@Tyfoon)
January 13, 2023, 8:54am
8
Already tested when I sent the thank you. Works fine!
Now need to create a sensor out of it to build some automations. Hence my question
Tyfoon
(@Tyfoon)
January 13, 2023, 9:38am
9
@Troon thanks for the pointer. @Hellis81 thanks for the solution. For completeness the complete solution. Really happy with this!
- platform: template
sensors:
avg_energy_price:
friendly_name: Average current energy price
value_template: >
{% set ns = namespace(sum = 0, count = 0) %}
{% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% set ns.sum = ns.sum + item.price %}
{% set ns.count = ns.count + 1 %}
{% endif %}
{%- endfor %}
{{ (ns.sum/ns.count/100000) }}
Tyfoon
(@Tyfoon)
January 13, 2023, 9:44am
10
@Hellis81 Maybe pushing my luck here but any chance you could help me with another problem?
From the same attributes trying to get the #of hours until the cheapest rate in the future.
So for example assuming it would be 10:00 now and at 14:00 it would be the lowest rate of ANY of the forecasted rates (ignoring date/today as at 12:00 the forecast will be updated with another batch of data which includes data of the next day), the outcome would be 4 (=4 hours from 10:00)
Hellis81
(Hellis81)
January 13, 2023, 2:04pm
11
I didn’t expect it to work on the first try that is why I asked you to test it first
You would need to create two more name space variables
{% set ns = namespace(lowest = 9999999, time = "") %}
{% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% if item.price < ns.lowest %}
{% set ns.lowest = item.price %}
{% set ns.time = item.datetime.time() %}
{% endif %}
{% endif %}
{%- endfor %}
{{ ns.lowest ~ " at " ~ns.time }}
EDIT sorry the above needs to be adjusted to be placed in the attributes
Troon
(Troon)
January 13, 2023, 2:26pm
12
One-liner to just return the datetime
of the first occurrence of the lowest price:
{{ (state_attr('sensor.zonneplan_current_electricity_tariff','forcast')|selectattr('price','eq',state_attr('sensor.zonneplan_current_electricity_tariff','forcast')|map(attribute='price')|list|min)|first)['datetime'] }}
Expanded out for readability:
{% set fclist = state_attr('sensor.zonneplan_current_electricity_tariff','forcast') %}
{% set pmin = fclist|map(attribute='price')|list|min %}
{{ (fclist|selectattr('price','eq',pmin)|first)['datetime'] }}
Tyfoon
(@Tyfoon)
January 14, 2023, 2:58pm
13
Thanks again! And I somewhat understand what your are doing/your logic. With small modification it has an output however it also looks ‘backward’ eg this one produces an outcome in the past while the lowest price is actually ahead (at 6am the next day). This is probably because it only looks at today and not the day after ?
Works:
{% set ns = namespace(lowest = 9999999, time = "") %}
{% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% if item.price < ns.lowest %}
{% set ns.lowest = item.price %}
{% set ns.time = item.datetime %}
{% endif %}
{% endif %}
{%- endfor %}
{{ ns.lowest/100000 ~ " at " ~ns.time }}
Tyfoon
(@Tyfoon)
January 14, 2023, 2:59pm
14
Thanks @Troon this works.
Would it be super complicated to add logic to find the lowest 2 or 3 consecutive hours?
Hellis81
(Hellis81)
January 14, 2023, 3:25pm
15
So you mean for example at 12 the price is 10, and at 13 it’s 5, the sum is 15.
Now is this sum of two hours the lowest of all consecutive hours of the day.
Well it’s a completely different animal for sure.
My simple thought is if you want two hours then we would need two arrays.
One that holds for instance the sum of prices at 11 and 12 o’clock then 13 and 14, and one that holds 12 and 13 then 14 and 15.
This makes the two arrays offset of each other.
Now if we get the lowest price from each of these arrays and compare them then we should get the two lowest consecutive hours.
I’m currently making dinner so not available at the time, perhaps not for the weekend.
But I’ll think about if there is a simpler solution.
Regarding the previous task, I would go for the method Trion posted.
Troon
(Troon)
January 14, 2023, 3:34pm
16
Much more involved, yes. I used to do this with the Octopus Agile electricity tariff, with its half- hourly pricing. I used AppDaemon for this. See the discussion starting here:
I’ve put some code together that finds the cheapest “n” hour block and works out the price. It works with https://www.home-assistant.io/docs/ecosystem/appdaemon/
Once AppDaemon is installed, edit /config/appdaemon/apps.yaml - the module and class sections need to remain as below, but the title, and number of hours can be set as you like.
It is only coded to work with whole hours, not halves, i.e. not 2.5, but you can have as many different ones as you need. Also I haven’t considered daylight s…
As you read down, you’ll get to a Python script I wrote to do this, initially without using AppDaemon. Eventually, I moved it across to AD for various reasons — I had to install it for a different project anyway.
Tyfoon
(@Tyfoon)
January 14, 2023, 3:55pm
17
I’m already thankful for what you and @Troon did up till now and make sure you enjoy your diner!
To illustrate see below graph. In some cases you have tasks (eg running the washing machine) that take (for example) 2 hours. In that case you want to begin at a time you mimimize cost over those 2 hours and in those case starting at the lowest point is not always the best moment. The shorter the task, the less of problem it is but with very long tasks (eg charging your EV or heating your hottub) you want to be able to choose the right window with the right starting time.
p.s. below is using both your templates;
Hellis81
(Hellis81)
January 14, 2023, 5:39pm
18
If this day is common then it seems the three cheapest hours are consecutive from one hour before to one hour after the cheapest price.
Which seems to make sense in my opinion.
Tyfoon
(@Tyfoon)
January 16, 2023, 7:11am
19
@Troon Having some issues with this to my surprise as the data seemed correct the last 2 days…
See below graph; It things the lowest price is now while it clearly in the future. Do you understand what is going on?
\
This is the sensor:
- platform: template
sensors:
time_low_coming:
friendly_name: Time lowest price
unique_id: time_low_coming
device_class: timestamp
value_template: >
{% set fclist = state_attr('sensor.zonneplan_current_electricity_tariff','forcast') %}
{% set pmin = fclist|map(attribute='price')|list|min %}
{{ (fclist|selectattr('price','eq',pmin)|first)['datetime'] }}
This is the arttribute data
state_class: measurement
forcast:
- price: 1690007
electricity_price: 1690007
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T07:00:00.000000Z'
sustainability_score: 544
carbon_footprint_in_grams: 0
- price: 2007026
electricity_price: 2007026
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T08:00:00.000000Z'
sustainability_score: 558
carbon_footprint_in_grams: 0
- price: 2024693
electricity_price: 2024693
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T09:00:00.000000Z'
sustainability_score: 643
carbon_footprint_in_grams: 0
- price: 2460777
electricity_price: 2460777
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T10:00:00.000000Z'
sustainability_score: 708
carbon_footprint_in_grams: 0
- price: 2522487
electricity_price: 2522487
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T11:00:00.000000Z'
sustainability_score: 765
carbon_footprint_in_grams: 0
- price: 2341108
electricity_price: 2341108
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T12:00:00.000000Z'
sustainability_score: 805
carbon_footprint_in_grams: 0
- price: 2524302
electricity_price: 2524302
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T13:00:00.000000Z'
sustainability_score: 763
carbon_footprint_in_grams: 0
- price: 2595329
electricity_price: 2595329
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T14:00:00.000000Z'
sustainability_score: 663
carbon_footprint_in_grams: 0
- price: 2703987
electricity_price: 2703987
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T15:00:00.000000Z'
sustainability_score: 533
carbon_footprint_in_grams: 0
- price: 3244130
electricity_price: 3244130
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T16:00:00.000000Z'
sustainability_score: 453
carbon_footprint_in_grams: 0
- price: 3667147
electricity_price: 3667147
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T17:00:00.000000Z'
sustainability_score: 395
carbon_footprint_in_grams: 0
- price: 3946656
electricity_price: 3946656
tariff_group: high
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T18:00:00.000000Z'
sustainability_score: 361
carbon_footprint_in_grams: 0
- price: 3973277
electricity_price: 3973277
tariff_group: high
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T19:00:00.000000Z'
sustainability_score: 306
carbon_footprint_in_grams: 0
- price: 3591401
electricity_price: 3591401
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T20:00:00.000000Z'
sustainability_score: 253
carbon_footprint_in_grams: 0
- price: 3490487
electricity_price: 3490487
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T21:00:00.000000Z'
sustainability_score: 216
carbon_footprint_in_grams: 0
- price: 3163787
electricity_price: 3163787
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T22:00:00.000000Z'
sustainability_score: 227
carbon_footprint_in_grams: 0
- price: 2280608
electricity_price: 2280608
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-15T23:00:00.000000Z'
sustainability_score: 218
carbon_footprint_in_grams: 0
- price: 2280608
electricity_price: 2280608
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T00:00:00.000000Z'
sustainability_score: 204
carbon_footprint_in_grams: 0
- price: 2313399
electricity_price: 2313399
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T01:00:00.000000Z'
sustainability_score: 195
carbon_footprint_in_grams: 0
- price: 2233297
electricity_price: 2233297
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T02:00:00.000000Z'
sustainability_score: 188
carbon_footprint_in_grams: 0
- price: 2320417
electricity_price: 2320417
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T03:00:00.000000Z'
sustainability_score: 219
carbon_footprint_in_grams: 0
- price: 2607186
electricity_price: 2607186
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T04:00:00.000000Z'
sustainability_score: 200
carbon_footprint_in_grams: 0
- price: 3425510
electricity_price: 3425510
gas_price: 13988606
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T05:00:00.000000Z'
sustainability_score: 202
carbon_footprint_in_grams: 1312
- price: 3673318
electricity_price: 3673318
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T06:00:00.000000Z'
sustainability_score: 185
carbon_footprint_in_grams: 0
- price: 3804966
electricity_price: 3804966
tariff_group: high
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T07:00:00.000000Z'
sustainability_score: 185
carbon_footprint_in_grams: 0
- price: 3611487
electricity_price: 3611487
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T08:00:00.000000Z'
sustainability_score: 211
carbon_footprint_in_grams: 0
- price: 3975697
electricity_price: 3975697
tariff_group: high
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T09:00:00.000000Z'
sustainability_score: 289
carbon_footprint_in_grams: 0
- price: 3558247
electricity_price: 3558247
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T10:00:00.000000Z'
sustainability_score: 280
carbon_footprint_in_grams: 0
- price: 3352426
electricity_price: 3352426
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T11:00:00.000000Z'
sustainability_score: 284
carbon_footprint_in_grams: 0
- price: 3314673
electricity_price: 3314673
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T12:00:00.000000Z'
sustainability_score: 279
carbon_footprint_in_grams: 0
- price: 3322297
electricity_price: 3322297
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T13:00:00.000000Z'
sustainability_score: 269
carbon_footprint_in_grams: 0
- price: 3368277
electricity_price: 3368277
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T14:00:00.000000Z'
sustainability_score: 245
carbon_footprint_in_grams: 0
- price: 3387032
electricity_price: 3387032
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T15:00:00.000000Z'
sustainability_score: 184
carbon_footprint_in_grams: 0
- price: 3572646
electricity_price: 3572646
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T16:00:00.000000Z'
sustainability_score: 145
carbon_footprint_in_grams: 0
- price: 3656498
electricity_price: 3656498
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T17:00:00.000000Z'
sustainability_score: 148
carbon_footprint_in_grams: 0
- price: 3375537
electricity_price: 3375537
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T18:00:00.000000Z'
sustainability_score: 165
carbon_footprint_in_grams: 0
- price: 3319877
electricity_price: 3319877
tariff_group: normal
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T19:00:00.000000Z'
sustainability_score: 159
carbon_footprint_in_grams: 0
- price: 3151324
electricity_price: 3151324
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T20:00:00.000000Z'
sustainability_score: 242
carbon_footprint_in_grams: 0
- price: 3094938
electricity_price: 3094938
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T21:00:00.000000Z'
sustainability_score: 330
carbon_footprint_in_grams: 0
- price: 3006487
electricity_price: 3006487
tariff_group: low
solar_percentage: 0
solar_yield: 0
datetime: '2023-01-16T22:00:00.000000Z'
sustainability_score: 375
carbon_footprint_in_grams: 0
unit_of_measurement: €/kWh
icon: mdi:cash
friendly_name: Zonneplan current electricity tariff
Troon
(Troon)
January 16, 2023, 7:52am
20
Take a look at the times and prices in the data you posted. Which time period in your data has a lower price than the first price of 1690007?
Looks to me like the graph and the data don’t match.
Troon
(Troon)
January 16, 2023, 8:13am
21
Here’s how to do an hourly cheapest-rate finder:
{% set fclist = state_attr('sensor.zonneplan_current_electricity_tariff','forcast') %}
{% set plist = fclist|map(attribute='price')|list %}
{% set ns = namespace(fc2=[]) %}
{%- for fc in fclist[:-1] -%}
{%- set ns.fc2 = ns.fc2 + [{'datetime':fc['datetime'],'price':(plist[loop.index0] + plist[loop.index0+1])/2}] -%}
{%- endfor -%}
{% set pmin = ns.fc2|map(attribute='price')|list|min %}
{{ (ns.fc2|selectattr('price','eq',pmin)|first)['datetime'] }}
It reads through the forecast up to the penultimate item (that’s what fclist[:-1]
means) and builds a list of dictionaries with the datetime
copied from the original sensor, and the price
calculated as the mean of that slot and the next one.
We then do the same process of finding the minimum price in the new list and find the matching datetime
.
You can expand this to any size of time period — just add subsequent items and adjust the total divisor in the mean calculation, and adjust the end point of the list so that your “looking forward” doesn’t go past the end.
Tyfoon
(@Tyfoon)
January 16, 2023, 8:14am
22
I guess you are in a different timezone or looked at the wrong date (the price you mention is from 15/01)?
The ‘NOW’ in the screenshot was the 8-9am slot on the 16/01 (@ a price of 36.11) then at 22:00 (in attribute data and graph) the price is 30.06