
Home Assistant: Advanced Nord Pool Cheapest Hours automation with local calendar support
In few weeks I finally have to move from constant electricity price to the spot price and I’m going to have to expand my automations a bit. In the most popular article how to use Nord Pool cheapest hours and automate devices I did the automation that will search for cheapest sequential hours. However, there are some flaws in that I wanted to finally handle myself and create even better automation!
One of the biggest issue (in my opinion) was the automation time of next day being set at 23:15. I want to be able to see the next days cheapest hours “immediately” when next day prices are published by the Nord Pool. So that really got me thinking, that I just don’t want to use one variable to store the time, but I could use a calendar to actually mark the sequential hours and run the automations by the calendar entries instead!
Second issue was only able to use one single day (the next day) prices and the automation was not able expand between two days (e.g. 22 – 08).
And one more thing (not a big problem for me), I think the configurations were a bit messy, so maybe its time to try to make this package a bit more configurable 🙂
If you wish to know more and see exact features that this package has to offer, continue reading next sections..

Features and what does this package has to REALLY offer
Here’s the list this automation package implements (feature list):
- Calculate wanted number of sequential cheapest hours for the next day immediately when available
- Support for two days (today + tomorrow)
- Required hour range needs to be easily configurable (e.g. during night, full day, etc.. just like in the previous version)
- Once prices are received from the Nord Pool, a calendar event is created for the cheapest hours
- Devices(s) will start when ‘cheapest hours’ -calendar event begins
- Device(s) will stop when ‘cheapest hours’ -calendar event is over
- If prices are not fetched by 23:15, create a static cheapest hours event from 00:00 to XX:XX depending on the selected number of sequential hours. This will provide us a failsafe that no critical devices are being left out of electricity (e.g. water boiler).
- Support to use multiple separate cheapest hours sequences for different devices (e.g. car charging, water boiler…)
That’s about it.. with those features in place, it should be rather simple and error proof to run devices during the hours of cheapest electricity prices.
Using the local calendar
Home Assistant release 2022.12 finally introduced a local calendar support that can be used exactly like these situations! No longer we need to rely on a cloud based calendar, no-one wants to run critical automations based on a cloud connection, right? And we don’t even need those pesky little time helpers to hold our information anymore.
Anyhow, there is still one missing features with the local calendar implementation that we need to handle or make a workaround:
- We can’t check if calendar event has already been created
This can luckily be worked around though with a small boolean helper utility to keep the information about calendar mark being created.
That’s the necessary background information now.. time to get hands dirty set the package + configurations!
Setting up the local calendar
So we need to create a calendar, great! In my package, the calendar is called ‘electricity‘ so I suggest to use the same or else you need to rename the calendar events in the package as well.
Creating the calendar can be done by going to Home Assistant Settings -> Devices & Services -> + Add Integration (bottom right corner) -> Search for ‘Local Calendar’ and click it.
Next enter name ‘electricity’ and press Submit, done! Now the calendar is in place and we are ready to move on to the actual automations!



Setting up the package
Prerequisites for this package to work is to have Nord Pool integration installed. You can look for integration installation guide from the original cheapest hours article or directly from Nord Pool integration GitHub page. Once that is done, continue reading..
Advanced cheapest hours package can be found from my Cheapest hours GitHub page, so download it and copy it on your Home Assistant ‘config‘ folder.
After copied, find the homeassistant: -block from your configurations.yaml file and add the package include on it. If you don’t have homeassistant: -block, just copy the whole block in any root level of configuration.yaml file:
homeassistant:
packages:
cheapest_hours: !include advanced_cheapest_hours.yaml
More details about Home Assistant packages can be found from here. Or if in doubt, leave a comment on the comment field and I’ll try to help you out 🙂
Configurations
This version of the cheapest hours package is quite much easier to configure than the previous one. So open up the file advanced_cheapest_hours.yaml for editing. All the required lines to be edited can be found with #CHANGE-ME tag!
Mandatory configuration
First there are five sensor attributes that needs to be changed:
attributes:
# CHANGE-ME: Set your personal configurations in here
# Amount of sequantial cheapest hours in search
number_of_sequential_hours: 3
# Search starting hour
first_hour: 22
# Search ending hour
last_hour: 08
# Is the first_hour today (true / false). If false, first_hour needs to be before last_hour.
starting_today: true
# Nord pool sensor id. Check it ouf from your integrations page!
sensor: sensor.nordpool_kwh_fi_eur_3_10_01
# If nordpool fetch fails, starting time to make the calendar entry
fail_safe_starting: '00:00'
The example configuration above will search for cheapest three sequential hours between today 22:00 and tomorrow 08:00. If failing to get the hours, it will mark the time from 00:00 to 03:00.
Next thing to do is to implement the automation actions. In the package, there’s two more #CHANGE-ME tags in the next section. Those are the actual automation actions that should be done during the cheapest hours.
# CHANGE-ME: Actions to do when cheapest hours starts
- service: light.turn_on
entity_id: light.office_work
else:
# CHANGE-ME: Actions to do when cheapest hours ends
- service: light.turn_off
entity_id: light.office_work
In above example, there are actions to turn on and off the light.office entity during the cheapest hours. Just change these to what every you want to do during the cheapest hours configure previosy!
With these changes made, the automation should be ready to go! Just reload yaml file using ‘developer tools -> restart‘ -functionality. If everything is working properly, a calendar event should be created to the local calendar called ‘electricity’ when the clock hits full hours AND tomorrow prices are available. Along with that, the configured actions should start running once the calendar event (cheapest hour) is hit.
Creating multiple sequences (optional)
If it’s not enough to have one cheapest hours sequence, with this package it’s also possible to make multiple sequence. For example: five hours sequence to run the water boiler between 22-06 and load the car between 00-23 for 8 hours every day. Let me explain how to achieve that:
- Copy the templated sensor “Cheapest hours energy” and rename its unique_id and name something more suitable. Remember to write this unique_id down somewhere. You are going to need it on the later steps.
- Make a copy of the first automation ‘cheapest_hours_calendar_entry‘ and rename it to something more suitable (also change the id). After copied, rename the sensorId of to the templated sensor unique_id you made previously. And of course change the actions to what every you like to do during the cheapest hours sequence.
- On the second automation ‘cheapest_hours_set_sequence‘, make again a new copy ‘calendar.create_event‘ action. On this new action, rename all the sensorIds from this action to the templated sensor (unique_id) you made previously.
- Last, but not least, make the failsafe work with the new automation. Make once again a copy of another ‘calendar.create_event‘ action of the third automation ‘cheapest_hours_failsafe‘ and rename the all sensorIds of this new action to the templated sensor unique_id you made previously.
That’s about it! Multiple entires should now be created once cheapest hours are received and automations should run when specific calendar mark occurs!
In my GitHub page, there’s also an example with two separate time schedules in the same package. You can look example directly from that one.
Bonus: Making the UI
To make the advanced cheapest hours visible through Home Assistant UI it’s a good idea to add a calendar card in a view.
First go to a dashboard and select a view you would like to add the card. Then press ‘Menu’ -> ‘Edit Dashboard’. In edit mode, press ‘+ add new card‘ and select ‘Calendar’.
Remove all the pre-selected calendars (if any) and select one entity ‘electricity’. I’d suggest to use ‘List (7 days)’ as a display mode and it will create you a calendar card as shown below.

Conclusion and what’s next
I’ve been running this automation for a week now and so far it has worked great!
The configuration is now much easier, but I’m not still very happy when configuring for multiple sequences. For this, I’m planning to implement a configuration utility to web that will construct the package dynamically based on given information. That way user just has to enter all the info he/she want’s and the package will be automatically generated and can be downloaded without touching the contents of the file itself at all!
However, based on the time I’ve got in my hands, it might take ‘some time’. So keep checking the blog frequently to get the utility immediately when available 🙂
Another thing what do next is to handle non-sequential hours. Some device doesn’t need the hours to be sequential and could be activated when ever the electricity is cheap. E.g. water boiler could run over night for five hours, but those hours don’t need to be sequential.
Anyhow, drop a comment below and say what do you think about this package? Is this better or worse than the previous version? And what would you improve or do you have any feature requests?
Hello Toni,
Smart work done!
Can’t get it running though.
YAML configuration invalid!
extra keys not allowed @ data[‘cheapest_hours’]
Got same feedback from another person too yesterday. I will look into this today in a clean Home Assistant environment, most probably just some minor issue somewhere in the guide/code.
Thanks for your patience!
Hi again!
Checked it out straight away, my package installation guide missed one line (packages:)
Should work now 🙂
Another issue was found with using a comment block while updating next cheapest hours. So if you’ve downloaded the package before 14/04/2022 18:00 (EEST), please get the package again 🙂
Hi Toni, awesome automations! Thanks for sharing and educating us!
I also got this automation to work and love it that it works over the span of two days and the calendar overview for multiple devices.
The non-consecutive hours would also be a great extension.
Hi!
It’s always good to hear that the stuff I do are useful. Thanks for the feedback! 🙂
Thanks, Works great. I have a question tho. Im a beginner in home assistant. Is it Possible to add like at price under xx.xx always on and over xx.xx always off?
Hi!
Yes, its possible of course.
Here’s an example how to do that (turn on only):
https://pastebin.com/G26Y0X3D
However, if you are using my cheapest hours package, you need to take care of situation that the devices are not being turned off while working on cheapest hours sequence.
If you need a more advanced setup, please comment and I’ll help you more 🙂
thanx Toni. im thinking more and gonna try to explain what im trying to do ^^
When checking for the X(2 for me now) cheapes hours to add to the calendar im thinking Dont add those hours if the price is above xx.xx$, and add all hours below xx.xx$ always(not just those 2h but all the day if under that price).
im using it for my wallbox and dont need to charge every day so im trying to max it out so cheap i can ^^
Hi and thanks for clarification, now I see what you are trying to achieve 🙂
The idea is of course doable, but needs to be thought a bit more, since managing a calendar with multiple time slots might get confusing at the end.
Maybe a more simple approach of just enabling/disabling the charging when price goes below X would be a better choice.
Anyhow, I can’t give you a direct example for now, but once I implement ‘non-sequential hours’ support to the current package, it could get you a bit closer to this 🙂
Hi Toni,
I’m new to home assistant, and love what you’ve done here!
I’ve got a question:
Would it be possible to e.g. have an if statement in the sensor (or somewhere else)? Wat I’m trying to do is to find the cheapest price from Nord pool between 18-09 on Monday, Tuesday and Thursday( and add calendar entries), the rest of the week I want to add calendar entries for the cheapest price between 00-23.
I’ve tried to make some changes in your example, but I fail miserably, since I’m new to home assistant (and programming). Any tips/help would be greatly appreciated .
Interesting idea and definately doable!
I need to play around a bit to see what would be the best way to go, but I will absolutely get back to you on this 🙂
Hi. I got some help to add this program on to my HA. Works very well – thank you! But why only pick the adjacent cheapest hours? Eg a water heater, electric car etc, can run well without adjacent heating/charging hours. Hence, will it be possible to modify your excellent program to pick the cheapest X hours the next day? And even more, when Nordpool update prices at 14:00, if next day is more expensive than some of the remaining hours of today – make an option to pick some of them, instead of picking all from next day. What do you think?
For car charging (at least on winter times), I think it’s better to keep the hours sequential to avoid unecessary battery heating.
However, for water boiler this could work in some cases.. unless all the cheapest hours are in the beginning of the day and next day in the end of the day.. that would make almost 48h without heating and at least in our household it would be too long period.
Anyhow, non-sequential hours is something I’m planning to do as soon as I can 🙂
Thanks!
I agree that if heating comes too far apart, it might get too cold water. But I have made an “emergency hot water heat” automation, that triggers if water temp gets too low. No mater what the price is, but only raising temp to 40C . Not very often it has triggered in our house 🙂
Hi. And one more. Is it much change in the code for the program to identfy eg. the 5 most expensive hours, instead of cheapest? Will use it to tell when the battery pack should deliver energy to the house. /Erik
Hi!
In theory, changing templated sensors comparison to “bigger than” should do the trick: {%- if ns.counter > ns.cheapestPrice -%}
And then making the automations work as opposite.. of course I’d recommend to change the names “cheapestPrice” to “expensivePrice” etc.
And note that I’ve not tested this, but in theory should work that easy 🙂
Nice work
Tried this and charged my battery at cheapest hours.
But when trying the multiple code and two devices only one automation shows??
Any idea
Niklas
Hi!
There should be total of five automations in the list for “Cheapest Hours” if using two devices (set sequence, reset helper, failsafe and one for each actual automation).
Ensure all the variables and entities are correct and also check if there are any information coming in home-assistant.log
found it, works now.
removed minus – before service and did some changes for wrog indentation
Excellent, great to hear you got it working 🙂
Hi Toni, thanks for this, it is really useful.
I have been experimenting with the advanced package,
I had some trouble getting the “set next cheapest sequence” automations to run.
It turned out that the run condition is a tomorrow_valid attribute being set on the cheapest_hours_energy, but that attribute does not exist on that sensor definition.
There is one on the Nordpool sensor, so i changed the sensor name to get it working, but I am not sure whether that was the intention or whether you would have preferred another attribute being set inside cheapest_hours_energy?
Yes, tomorrow_valid should be received directly from the nordpool sensor (and also in my example it’s referring to the nordpool one in the cheapest_hours_energy templated sensor).
Hei, thanks, not sure i understand though: the advanced_cheapest_hour automation cheapest_hours_set_sequence has a condition that points to the sensor.cheapest_hours_energy on line 94.
if the tomorrow_valid is an attribute of the nordpool sensor does this line need to be changed to point to the nordpool sensor instead?
I had a different issue at the same place of the code as well. Apparently home assistant had an issue finding the sensor value when being time triggered, it ran fine when triggered manually for some reason. I resolved this by replacing the condition state_attr((state_attr(sensorId, ‘sensor’) | string), ‘tomorrow_valid’) == true with the following state_attr(sensorId, ‘tomorrow_valid’) == true
so the condition for the set_sequence automation working for me, now looks like this:
condition:
– condition: template
# from which sensor we should try the tomorrow price validation
value_template: >
{%- set sensorId = ‘sensor.nordpool_kwh_bergen_eur_3_10_025’ -%}
{{ state_attr((state_attr(sensorId, ‘sensor’) | string), ‘tomorrow_valid’) == true }}
– condition: state
entity_id: input_boolean.cheapest_hours_set
state: ‘off’
does this look meaningful?
I got errors about as_timestamp() command has unknown value. I think latest versions of HA need extra default value described there. I got it working with these modifications:
{{ as_timestamp(states(sensorId), 0) | timestamp_local }}
Well spotted, even though I haven’t noticed anything after latest upgrade. Will investigate that a bit as well, but thanks for reporting and providing a fix!
After updating HA to latest, this stopped working.
Cheapest hours: Set next cheapest sequence – automation gives this
Executed: 27. toukokuuta 2023 klo 00.11.51
Error: Error rendering data template: ValueError: Template error: float got invalid input ‘None’ when rendering template ‘{%- set sensorId = ‘sensor.cheapest_hours_energy’ -%} {{ (as_timestamp(states(sensorId), 0) + (3600 * state_attr(sensorId, ‘number_of_sequential_hours’) | float)) | timestamp_local }}’ but no default was specified
Hi!
In previous comments another person has also reported this issue.
My Home Assistant instance was actually not updated properly (which I didn’t notice), but after succesfully updating I get the same error.
As in previous comment stated, changing the as_timestamp function to contain default value will fix the issue:
{{ as_timestamp(states(sensorId)) | timestamp_local }}
->
{{ as_timestamp(states(sensorId), 0) | timestamp_local }}
I will need to wait until next day nordpool prices are available to be able to fully test this and will commit the change to the GitHub after that.
Thanks for reporting!