kotope / ha_nordpool_cheapest_hours

Home Assistant package to calculate cheapest hours using Nordpool integration
70 stars 9 forks source link

Cheapest hours in the past #17

Open happosade opened 6 days ago

happosade commented 6 days ago

I seem to get the cheapest hours put on the wrong day (1.1.1970). It also seems like our math between the me and the automation varies a bit. I don't know if it just default time in UTC (TZ: Europe/Helsinki) and it's completely confused, or what might be the case.

Expected behavior: Calendar event added for tomorrow (2024-11-09) between time 01:00 - 04:00 (localtime) Result: Calendar event created for 1970-01-01 from 02:00 - 05:00

Additional information:

Output of this step of the trace is:

Executed: November 8, 2024 at 17:28:25
Result:

params:
  domain: calendar
  service: create_event
  service_data:
    start_date_time: '1970-01-01T02:00:00+02:00'
    end_date_time: '1970-01-01T05:00:00+02:00'
    summary: Cheapest hours energy
    entity_id:
      - calendar.electricity
  target:
    entity_id:
      - calendar.electricity
running_script: false

The script as a whole is from repo:

# Package to create and handle cheapest hours from nord pool integration!
# This is the SINGLE entry version.
# For more details check out the blog post at https://www.creatingsmarthome.com/?p=1620

template:
  -  sensor:
      # The actual cheapest hour sensor. If multiple entries are required, copy and set unique_id and configure attributes.
      - name: "Cheapest hours energy"
        unique_id: cheapest_hours_energy
        device_class: timestamp
        state: >
          {%- set sensor = (this.attributes.get('sensor', 'sensor.nordpool_kwh_fi_eur_3_10_01') | 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 + 1 -%}
            {%- 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 -%}
        attributes:
          # CHANGE-ME: Set your personal configurations in here
          number_of_sequential_hours: 3 # Amount of sequantial cheapest hours in search
          first_hour: 18 # 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: nordpool_kwh_fi_eur_3_10_0255 # Nord pool sensor id. Check it ouf from your integrations page!
          fail_safe_starting: '00:00' # If nordpool fetch fails, starting time to make the calendar entry

automation:
  # 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: ''
    trigger:
    - platform: calendar
      event: start
      entity_id: calendar.electricity
    - platform: calendar
      event: end
      entity_id: calendar.electricity
    condition:
    - condition: template
      value_template: >
        {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
        {{ (state_attr(sensorId, 'friendly_name') | string) == trigger.calendar_event.summary }}
    action:
    - if:
      - condition: template
        value_template: '{{ trigger.event == ''start'' }}'
      then:
      # 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
    mode: single

  # -- GLOBAL CONFIGURATIONS BELOW, NO NEED TO CHANGE UNLESS CREATING MULTIPLE SEQUENCES --
  # 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'
    trigger:
    - platform: time_pattern
      hours: /1
    condition:
    - condition: template
      # from which sensor we should try the tomorrow price validation
      value_template: >
        {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
        {{ state_attr((state_attr(sensorId, 'sensor') | string), 'tomorrow_valid') == true }}
    - condition: state
      entity_id: input_boolean.cheapest_hours_set
      state: 'off'
    action:
    - service: input_boolean.turn_on
      data: {}
      target:
        entity_id: input_boolean.cheapest_hours_set
    # Event creation
    - service: calendar.create_event
      data:
        start_date_time: >
          {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
          {{ as_timestamp(states(sensorId), 0) | timestamp_local }}
        end_date_time: >
          {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
          {{ (as_timestamp(states(sensorId), 0) + (3600 * state_attr(sensorId, 'number_of_sequential_hours') | float)) | timestamp_local }}
        summary: >
          {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
          {{ state_attr(sensorId, 'friendly_name') | string }}
      target:
        entity_id: calendar.electricity
    # If multiple cheapest hours sequences are required, copy 'calendar.create_event' block from aboce and change the 'sensorId' variabes values to match corresponding new cheapest hours templated sensor
    mode: single

  # Failsafe
  - id: 'cheapest_hours_failsafe'
    alias: 'Cheapest hours: Failsafe'
    description: 'Failsafe: Set cheapest hours from fail_safe value to amount of hours'
    trigger:
    - platform: time
      at: '23:15'
    condition:
    - condition: state
      entity_id: input_boolean.cheapest_hours_set
      state: 'off'
    action:
    - service: input_boolean.turn_on
      data: {}
      target:
        entity_id: input_boolean.cheapest_hours_set
    # Failsafe action
    - service: calendar.create_event
      data:
        start_date_time: >
          {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
          {{ as_timestamp(today_at(state_attr(sensorId, 'fail_safe_starting')) + timedelta( hours = 24 ), 0) | timestamp_local }}
        end_date_time: >
          {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
          {{ (as_timestamp(today_at(state_attr(sensorId, 'fail_safe_starting')) + timedelta( hours = 24 ), 0) + (3600 * state_attr(sensorId, 'number_of_sequential_hours') | float)) | timestamp_local }}
        summary: >
          {%- set sensorId = 'sensor.cheapest_hours_energy' -%}
          {{ state_attr(sensorId, 'friendly_name') | string }}
      target:
        entity_id: calendar.electricity
    # If multiple cheapest hours sequences are required, make a copy of 'calendar.create_event' block above and set the 'sensorId' values to match the new one
    mode: single

  # input_boolean reset
  - id: 'cheapest_hours_clear_set_flag'
    alias: 'Cheapest hours: Reset the set helper for the next day'
    description: 'Clears cheapes hours helper boolean when the day changes.'
    trigger:
    - platform: time
      at: '01:15:00'
    condition: []
    action:
    - service: input_boolean.turn_off
      data: {}
      target:
        entity_id: input_boolean.cheapest_hours_set
    mode: single

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

The nordpool sensor has currently this value:

state_class: total
average: 1.419875
off_peak_1: 1.35925
off_peak_2: 0.39575
peak: 1.8016666666666667
min: 0.314
max: 3.906
mean: 0.8025
unit: kWh
currency: EUR
country: Finland
region: FI
low_price: true
price_percent_to_average: 0.6486486486486487
today:
  - 2.787
  - 2.198
  - 0.803
  - 0.498
  - 0.489
  - 0.491
  - 0.63
  - 2.978
  - 3.769
  - 3.906
  - 3.677
  - 2.073
  - 2.008
  - 1.551
  - 0.802
  - 0.717
  - 0.861
  - 0.921
  - 0.596
  - 0.739
  - 0.483
  - 0.41
  - 0.376
  - 0.314
tomorrow:
  - 0.241
  - 0.004
  - 0
  - 0.001
  - 0.079
  - 0.19
  - 0.323
  - 0.526
  - 0.784
  - 1.163
  - 2.323
  - 4.526
  - 3.824
  - 5.045
  - 5.979
  - 6.767
  - 9.844
  - 11.496
  - 12.088
  - 12.102
  - 12.263
  - 11.57
  - 11.107
  - 10.04
tomorrow_valid: true
raw_today:
  - start: "2024-11-08T00:00:00+02:00"
    end: "2024-11-08T01:00:00+02:00"
    value: 2.787
  - start: "2024-11-08T01:00:00+02:00"
    end: "2024-11-08T02:00:00+02:00"
    value: 2.198
  - start: "2024-11-08T02:00:00+02:00"
    end: "2024-11-08T03:00:00+02:00"
    value: 0.803
  - start: "2024-11-08T03:00:00+02:00"
    end: "2024-11-08T04:00:00+02:00"
    value: 0.498
  - start: "2024-11-08T04:00:00+02:00"
    end: "2024-11-08T05:00:00+02:00"
    value: 0.489
  - start: "2024-11-08T05:00:00+02:00"
    end: "2024-11-08T06:00:00+02:00"
    value: 0.491
  - start: "2024-11-08T06:00:00+02:00"
    end: "2024-11-08T07:00:00+02:00"
    value: 0.63
  - start: "2024-11-08T07:00:00+02:00"
    end: "2024-11-08T08:00:00+02:00"
    value: 2.978
  - start: "2024-11-08T08:00:00+02:00"
    end: "2024-11-08T09:00:00+02:00"
    value: 3.769
  - start: "2024-11-08T09:00:00+02:00"
    end: "2024-11-08T10:00:00+02:00"
    value: 3.906
  - start: "2024-11-08T10:00:00+02:00"
    end: "2024-11-08T11:00:00+02:00"
    value: 3.677
  - start: "2024-11-08T11:00:00+02:00"
    end: "2024-11-08T12:00:00+02:00"
    value: 2.073
  - start: "2024-11-08T12:00:00+02:00"
    end: "2024-11-08T13:00:00+02:00"
    value: 2.008
  - start: "2024-11-08T13:00:00+02:00"
    end: "2024-11-08T14:00:00+02:00"
    value: 1.551
  - start: "2024-11-08T14:00:00+02:00"
    end: "2024-11-08T15:00:00+02:00"
    value: 0.802
  - start: "2024-11-08T15:00:00+02:00"
    end: "2024-11-08T16:00:00+02:00"
    value: 0.717
  - start: "2024-11-08T16:00:00+02:00"
    end: "2024-11-08T17:00:00+02:00"
    value: 0.861
  - start: "2024-11-08T17:00:00+02:00"
    end: "2024-11-08T18:00:00+02:00"
    value: 0.921
  - start: "2024-11-08T18:00:00+02:00"
    end: "2024-11-08T19:00:00+02:00"
    value: 0.596
  - start: "2024-11-08T19:00:00+02:00"
    end: "2024-11-08T20:00:00+02:00"
    value: 0.739
  - start: "2024-11-08T20:00:00+02:00"
    end: "2024-11-08T21:00:00+02:00"
    value: 0.483
  - start: "2024-11-08T21:00:00+02:00"
    end: "2024-11-08T22:00:00+02:00"
    value: 0.41
  - start: "2024-11-08T22:00:00+02:00"
    end: "2024-11-08T23:00:00+02:00"
    value: 0.376
  - start: "2024-11-08T23:00:00+02:00"
    end: "2024-11-09T00:00:00+02:00"
    value: 0.314
raw_tomorrow:
  - start: "2024-11-09T00:00:00+02:00"
    end: "2024-11-09T01:00:00+02:00"
    value: 0.241
  - start: "2024-11-09T01:00:00+02:00"
    end: "2024-11-09T02:00:00+02:00"
    value: 0.004
  - start: "2024-11-09T02:00:00+02:00"
    end: "2024-11-09T03:00:00+02:00"
    value: 0
  - start: "2024-11-09T03:00:00+02:00"
    end: "2024-11-09T04:00:00+02:00"
    value: 0.001
  - start: "2024-11-09T04:00:00+02:00"
    end: "2024-11-09T05:00:00+02:00"
    value: 0.079
  - start: "2024-11-09T05:00:00+02:00"
    end: "2024-11-09T06:00:00+02:00"
    value: 0.19
  - start: "2024-11-09T06:00:00+02:00"
    end: "2024-11-09T07:00:00+02:00"
    value: 0.323
  - start: "2024-11-09T07:00:00+02:00"
    end: "2024-11-09T08:00:00+02:00"
    value: 0.526
  - start: "2024-11-09T08:00:00+02:00"
    end: "2024-11-09T09:00:00+02:00"
    value: 0.784
  - start: "2024-11-09T09:00:00+02:00"
    end: "2024-11-09T10:00:00+02:00"
    value: 1.163
  - start: "2024-11-09T10:00:00+02:00"
    end: "2024-11-09T11:00:00+02:00"
    value: 2.323
  - start: "2024-11-09T11:00:00+02:00"
    end: "2024-11-09T12:00:00+02:00"
    value: 4.526
  - start: "2024-11-09T12:00:00+02:00"
    end: "2024-11-09T13:00:00+02:00"
    value: 3.824
  - start: "2024-11-09T13:00:00+02:00"
    end: "2024-11-09T14:00:00+02:00"
    value: 5.045
  - start: "2024-11-09T14:00:00+02:00"
    end: "2024-11-09T15:00:00+02:00"
    value: 5.979
  - start: "2024-11-09T15:00:00+02:00"
    end: "2024-11-09T16:00:00+02:00"
    value: 6.767
  - start: "2024-11-09T16:00:00+02:00"
    end: "2024-11-09T17:00:00+02:00"
    value: 9.844
  - start: "2024-11-09T17:00:00+02:00"
    end: "2024-11-09T18:00:00+02:00"
    value: 11.496
  - start: "2024-11-09T18:00:00+02:00"
    end: "2024-11-09T19:00:00+02:00"
    value: 12.088
  - start: "2024-11-09T19:00:00+02:00"
    end: "2024-11-09T20:00:00+02:00"
    value: 12.102
  - start: "2024-11-09T20:00:00+02:00"
    end: "2024-11-09T21:00:00+02:00"
    value: 12.263
  - start: "2024-11-09T21:00:00+02:00"
    end: "2024-11-09T22:00:00+02:00"
    value: 11.57
  - start: "2024-11-09T22:00:00+02:00"
    end: "2024-11-09T23:00:00+02:00"
    value: 11.107
  - start: "2024-11-09T23:00:00+02:00"
    end: "2024-11-10T00:00:00+02:00"
    value: 10.04
current_price: 0.921
additional_costs_current_hour: 0
price_in_cents: true
unit_of_measurement: c/kWh
device_class: monetary
icon: mdi:flash
friendly_name: nordpool_kwh_fi_eur_3_10_0255

Current version:

Home Assistant

Core 2024.10.4
Frontend 20241002.4

I think this broke few weeks ago and it has been just fallback that I've been given.

TTV 189 for reference. image

kotope commented 6 days ago

Sounds really odd issue here..

Anyhow, I've created a new (easier) approach for the cheapest hours so I don't really maintain this one that much anymore. You might want to check out the new integration at https://github.com/kotope/aio_energy_management