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:

    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 🙂


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:

# 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
# 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:

  1. 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.
  2. Make a copy of the first automationcheapest_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.
  3. On the second automation ‘cheapest_hours_set_sequence‘, make again a new copycalendar.create_eventaction. On this new action, rename all the sensorIds from this action to the templated sensor (unique_id) you made previously.
  4. Last, but not least, make the failsafe work with the new automation. Make once again a copy of another ‘calendar.create_eventaction 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?

63 Replies to “Home Assistant: Advanced Nord Pool Cheapest Hours automation with local calendar support”

  1. Hello Toni,
    Smart work done!

    Can’t get it running though.

    YAML configuration invalid!
    extra keys not allowed @ data[‘cheapest_hours’]

    1. 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!

      1. Hi again!

        Checked it out straight away, my package installation guide missed one line (packages:)

        Should work now 🙂

  2. 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 🙂

  3. 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.

    1. Hi!

      It’s always good to hear that the stuff I do are useful. Thanks for the feedback! 🙂

  4. 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?

    1. Hi!

      Yes, its possible of course.

      Here’s an example how to do that (turn on only):

      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 🙂

      1. 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 ^^

        1. 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 🙂

  5. 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 .

    1. 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 🙂

  6. 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?

    1. 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 🙂

      1. 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 🙂

      2. 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

        1. 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 🙂

          1. HI.

            Thanks. Did not work. I have following code (nnly changed the “”, ie no name change for now,
            – sensor:
            # The actual cheapest hour sensor. If multiple entries are required, copy and set unique_id and configure attributes.
            – name: “Cheapest hours energy (full day)”
            unique_id: cheapest_hours_energy_full_day
            device_class: timestamp
            state: >
            {%- set sensor = (this.attributes.get(‘sensor’, ‘sensor.nordpool_kwh_oslo_nok_3_01_025’) | string) -%}
            {%- set numberOfSequentialHours = (this.attributes.get(‘number_of_sequential_hours’,1) | int) -%}
            {%- set lastHour = (this.attributes.get(‘last_hour’,23) | int) -%}
            {%- set firstHour = (this.attributes.get(‘first_hour’, 0) | int) -%}
            {%- set startingToday = (this.attributes.get(‘starting_today’, false) | bool) -%}
            {%- if state_attr(sensor, ‘tomorrow_valid’) == true -%}
            {%- set arr = state_attr(sensor, ‘today’) + state_attr(sensor, ‘tomorrow’) -%}
            {%- set ns = namespace(counter=0, list=[], cheapestHour=today_at(“00:00”), cheapestPrice=999.00) -%}
            {%- if startingToday == true -%}
            {%- set ns.starting = firstHour -%}
            {%- else -%}
            {%- set ns.starting = firstHour + 24 -%}
            {%- endif -%}
            {%- set ns.ending = lastHour + 24 -%}
            {%- for i in range(ns.starting + numberOfSequentialHours, ns.ending+1) -%}
            {%- set ns.counter = 0.0 -%}
            {%- for j in range(i-numberOfSequentialHours, i) -%}
            {%- set ns.counter = ns.counter + arr[j] -%}
            {%- endfor -%}
            {%- set ns.list = ns.list + [ns.counter] -%}
            {%- if ns.counter > ns.cheapestPrice -%}
            {%- set ns.cheapestPrice = ns.counter -%}
            {%- set ns.cheapestHour = today_at(“00:00”) + timedelta( hours = (i – numberOfSequentialHours)) -%}
            {%- endif -%}
            {%- endfor -%}
            {{ ns.cheapestHour }}
            {%- set ns.cheapestPrice = ns.cheapestPrice / numberOfSequentialHours -%}
            {%- endif -%}
            # CHANGE-ME: Set your personal configurations in here
            number_of_sequential_hours: 4 # Amount of sequantial cheapest hours in search
            first_hour: 23 # Search starting hour
            last_hour: 23 # Search ending hour
            starting_today: true # Is the first_hour today (true / false). If false, first_hour needs to be before last_hour.
            sensor: sensor.nordpool_kwh_oslo_nok_3_01_025 # Nord pool sensor id. Check it ouf from your integrations page!
            fail_safe_starting: ’01:00′ # If nordpool fetch fails, starting time to make the calendar entry


            CAn you see where the error is?

          2. Forgot to say, that the code made an event back in time. Made an event at 00:00 till 04:00 today, May 30., even the time now is 14:15

          3. Hi.
            As I wrote I did not make it work. But a smart colleague of mine, came up with one more needed change. Apart from what you mentioned. To make it work we also need to sett 0.00 and not 999 in:
            {%- set ns = namespace(counter=0, list=[], expensiveHour=today_at(“00:00”), expensivePrice=0.00) -%}

            Then it works perfect :-), Thanks to Thomas!

          4. Hi!

            Sorry I didn’t have time to test the change through and therefore my initial comments were rwong, but it’s great you got it working and thanks for sharing the info with others 🙂

          5. Hi Tony,

            This colleague of mine – when you get him going…

            Ref question of finding cheapest hours, not adjacent, as now. So now we are testing this code, that picks cheapest 4 each day:

            – platform: template
            value_template: >-
            {% set l=state_attr(‘sensor.nordpool_kwh_oslo_nok_3_10_025’, ‘raw_today’)|sort(attribute=’value’) %}
            {{ (now() >= l[0].start and now() = l[1].start and now() = l[2].start and now() = l[3].start and now() <= l[3].end) }}

            I let you know if it works OK

            /Erik – and thanks to Thomas

  7. 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


    1. 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

      1. found it, works now.
        removed minus – before service and did some changes for wrog indentation

  8. 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?

    1. 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).

      1. 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?

        1. 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: 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?

  9. 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 }}

    1. 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!

  10. 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

    1. 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!

  11. Hi,
    Amazing guys! I’ve managed to set it up but I wonder a couple of things.
    What is the point of the “Reset the set helper for the next day”. Should it be on or off? Do you need to interact with that, and if so why/when?

    Same question for the helper “Cheapest hours set for the next day”. Is this simply to show that the calendar was updated X time ago?

    And last one, is there a way to retrigger/update the calendar and I have change the config file? For example if I change the time in the config file, I might want to see the effect directly.
    Best Regards,

    1. Hi!

      The switch is automatically set on when the calendar event has been created for the next sequence.
      Currently Home Assistant can’t read entries from the calendar by id, so we have to make a workaround like that. So, you don’t need to interact with the switch manually.
      The switch will be reset every day a bit past 00:00.

      And for the next question, you can retrigger the calendar event creation by turning off the switch and running actions for the ‘Cheapest hours: Set next cheapest sequence’ through Home Assistant automations tab. However, just remember to delete the existing events from the calendar when you do this, otherwise there will be duplicates.
      ..and of course the automation will run only when the next day electric prices are available from the nordpool integration.

  12. Hi,

    I’m trying to get this working, but I’m getting this error:
    sensor.cheapest_hours_energy_boiler rendered invalid timestamp:

    Any ideas what might cause this?

    1. Hi!

      That’s a warning that is shown when tomorrow prices are not yet available.
      Try again later when next day electric prices are published by nordpool (about 15.00 CET).

      1. Thanks, it updated the prices and the error went away. Now I have another issue – I don’t have any calendar events, even the fallback ones. I double checked the calendar name and that I followed the guide step by step, but my electricity calendar is empty.

        1. Hi!

          Couple of things:
          – Check the case sensitivity, e.g. “Electricity” is not the same as “electricity”
          – Try to make a manual entry to the calendar, does it work?
          – Does the ‘next cheapest hours’ switch turn on during the evening or is it off always?

          This way you try to see in which part of the package the problem is.
          If the switch turns on, the problem is either within the calendar or calendar event creation automation.

          Also check the automation debug traces from all the automations to see if there are any issues visibile.

          1. Hi,

            I’ve narrowed it down to this error, the same as some other users previously had:’
            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

            Even though the default value seems to be there, it still gives this error.

  13. Hello,

    I got this working perfectly, however I got a question.
    Would it be possible to implement some sort of limit to the script, so that if for example the price of electricity is above a certain value (even tho it’s in the cheapest hour per day span) it will not trigger the actions? Like for some reason the price rushes above 0,6kWh (for example) and I want a limit on 0,5kWh so that it will not trigger as it’s higher than set value?

    1. Definitely possible, however there’s couple of points you might want to consider as well.
      Do you want to use average price of the sequence of starting price?
      Or would you just want to skip the single expensive hour if it’s in the middle of sequence?

      If ignoring the whole sequence, you could e.g. make a new condition in the ‘set next cheapest sequence’ that checks the price before making a calendar entry 🙂
      Skipping single values in between would be a more complicated since currently this does have support non-sequential cheapest hours.

  14. Hi Toni,

    I really like this and felt inspired to go ahead and make this a way to learn about Home Assistant and automation. I wrote up most of the automation logic in a custom Python script which simplifies the yaml and jinja templating, and also adds the capability to schedule multiple sequences of the same length:


    This lets you have the automations as pasted below. I hope you like my ideas! I’d like to keep working on it and add some more features.

    # Automation to trigger when calendar event hits the cheapest hour mark
    # start/stop automation
    – id: ‘cheapest_hours_calendar_entry’
    alias: ‘Cheapest hours: Calendar trigger’
    description: ”
    – platform: calendar
    event: start
    entity_id: calendar.electricity
    – platform: calendar
    event: end
    entity_id: calendar.electricity
    – condition: template
    value_template: >
    {%- set sensorId = ‘sensor.cheapest_hours_energy_water_boiler’ -%}
    {{ (state_attr(sensorId, ‘friendly_name’) | string) in trigger.calendar_event.summary }}
    – if:
    – condition: template
    value_template: ‘{{ trigger.event == ”start” }}’
    # CHANGE-ME: Actions to do when cheapest hours starts
    – service: light.turn_on
    entity_id: light.office_work
    # CHANGE-ME: Actions to do when cheapest hours ends
    – service: light.turn_off
    entity_id: light.office_work
    mode: single

    # Create calendar event
    – id: ‘cheapest_hours_set_sequence’
    alias: ‘Cheapest hours: Set next cheapest sequence’
    description: ‘Checks tomorrow energy prices every hour and create calendar entry when available AND events not yet created’
    – platform: time_pattern
    hours: /1
    # Event creation
    – service: python_script.cheapest_hours_energy
    number_of_sequential_hours: 2
    number_of_sequences: 2
    min_hours_between_sequences: 6
    cheapest_hours_set_bool: “input_boolean.cheapest_hours_set”
    fail_safe_hour: 23
    mode: single

    # input_boolean reset
    – id: ‘cheapest_hours_clear_set_flag’
    alias: ‘Cheapest hours: Reset the set helper for the next day’
    description: ‘Clears cheapest hours helper boolean when the day changes.’
    – platform: time
    at: ’01:15:00′
    condition: []
    – service: input_boolean.turn_off
    data: {}
    entity_id: input_boolean.cheapest_hours_set
    mode: single

    # We need a helper to know if the calendar mark(s) has already been set!
    name: Cheapest hours set for the next day
    icon: mdi:clock

    1. Excellent! Definitely will try your python script very soon 🙂
      Thanks for sharing!

      1. Updated the script (and messed around with github a bit to get it to work) So the updated URL is at: https://github.com/eibakke/hass_scripts

        The biggest update is that I support for putting the command to call when the calendar event starts and ends in the “cheapest_hours” service. This lets you reduce the number of triggers, and makes it easier to use setup automation for multiple devices. I haven’t actually tried multiple devices yet, and I suspect there is a bug where the cheapest_hours_set flag gets flipped when the script gets called for the first device. Haven’t fixed it yet because I haven’t decided what the best way to solve it is yet…

        As the README in the GitHub repo suggests I have some ideas for more automations that make use of the energy prices too, so I’ve got some fun work ahead of me 🙂

        1. Update again! (if you couldn’t tell I find this really fun to work on)

          I added the ability to schedule a certain number of hours, with a maximum amount of time off between on-time. You can read about it here: https://github.com/eibakke/hass_scripts#variable-length-sequences-max-hours-apart

          It’s still in progress, and I’m just starting to experiment with it, but I’m quite happy with it! In particular the configuration ends up looking really nice:

          # To add scheduling for other devices, simple add another call to the python_script.cheapest_non_sequential service.
          – service: python_script.cheapest_non_sequential
          max_hours_between_sequences: 12
          number_of_hours: 8
          service_to_call: switch
          start_method: turn_on
          end_method: turn_off
          automate_entity_id: switch.waterheater

          1. Nice work!
            How do make these scripts run in HA? 🙂
            Would be nice with some hints in your README file.

  15. Very informative guide. Will try to test it with water boiler.
    Maybe any updates coming soon?

    1. Hi!

      No updates in sight for now. Might add something like non-sequential hours in a month or two.

      1. Good to hear.
        Non sequential hours sounds fun for water heater or even smart robot vacuums to charge on cheapest hours.
        Hope you doing well, take care

  16. I would need a script which uses human input. When button is pressed in UI, the script would use the timestamp of the press and would calculate the cheapest hours during next xx hours after the press. Any idea how to modify the script?

    1. Interesting approach!

      You could set the timestamp to some other entity attributes and refer that start time + end time from cheapest hours template sensor when the button is pressed:

      {%- set lastHour = (this.attributes.get('last_hour',23) | int) -%}
      {%- set firstHour = (this.attributes.get('first_hour', 0) | int) -%}

      At least that’s where I’d start to looking at.. most probably needs some more changes as well, but start point could be there 🙂

  17. Hi Tony,

    Thanks for a good solutions.
    Since I’m new to this, I hope I can get some help with my problem.
    Using your solution, I want to charge and discharge my battery bank, but would need an extension.

    I do not want to sell from the batteries if the price difference between the lowest and highest price is less than SEK 1. (losses and wear on the batteries are too expensive).

    I do not want to charge the batteries if the lowest price is over 0.5 SEK and the price difference between the lowest and highest price is less than 1 SEK. (if the price is under SEK 0.5, then it is cheap enough to have the batteries charged as a backup)

    Is there anything you can help me with?

    1. Hi!

      I think this cheapest hours sequence is not the right choice for the automation you are requesting.
      However, I’m currently implementing another automation that makes calendar entries for non-sequential hours when the price is below a certain range. That one could then most probably be modified to suit your needs.

      So please come back in a week or so to see if it can be used for your needs 🙂

  18. Getting the same error now as some people earlier:

    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

    Any idea how to fix this?

  19. I used to have the “simple” version running and that seemed to work fine, I have been trying to integrate the new version that sounds great, but I am not succeeding… however I try the following message keeps popping up behind the following lines: “Incorrect type. Expected “string”.”

    number_of_sequential_hours: 2
    first_hour: 22
    last_hour: 08

    And I get “Incorrect type.” behind this line:

    starting_today: true

    I have tried a thousand different ways, but I never get it to work…

    Would be very grateful if you could help, I would like to charge a battery when energy is cheap.

    1. Hi!

      Could you send me your modified package to creatingsmarthome (at) gmail.com and I’ll check if I can spot anything wrong?

  20. Hi i’m getting error sensor.cheapest_hours_energy rendered invalid timestamp. Something in the recent update broke alot of things.

    1. That’s usually a (normal) warning when nord pool has not yet published prices for the next day. What time of they day did you get this error and were there prices available already?

      1. I got the error in the evening after installing this. Nordpool works fine and i can see tomorrows price just fine but Cheapest hours energy still says unknown and keeps giving me invalid timestamp error. I had the other automation previously and it worked fine for sometime but noticed recently its cheapest hour sensor had also broken and showed unknown.

Leave a Reply

Your email address will not be published. Required fields are marked *