Skip to content

Instantly share code, notes, and snippets.

@JohanAlvedal
Last active October 9, 2025 14:16
Show Gist options
  • Select an option

  • Save JohanAlvedal/66b21a648a1a4ca261f6f3476b3f82e3 to your computer and use it in GitHub Desktop.

Select an option

Save JohanAlvedal/66b21a648a1a4ca261f6f3476b3f82e3 to your computer and use it in GitHub Desktop.
This blueprints uses the nordpool integration and lets you choose howe many hours you will define as expesive, and make a sensor block temperature based on that information.
blueprint:
name: Block heat (15-min safe)
description: >
Blockerar värme (sätter virtuell temperatur) under de dyraste timmarna baserat
på Nordpool-priser. Under billiga perioder speglar den utetemperaturen med
ett valt uppdateringsintervall. Fungerar med 60- och 15-minuterspriser samt DST.
domain: automation
input:
grid_area:
name: Grid Area Sensor
description: Din Nordpool-prissensor
selector:
entity:
domain: [sensor]
integration: nordpool
multiple: false
expensive_hours:
name: Expensive Hours
description: Antal timmar att blockera (omvandlas till slots automatiskt)
default: 4
selector:
number:
min: 0.0
max: 24.0
mode: slider
step: 1.0 # sätt 0.25 om du vill ha kvartsteg
temperature_sensor:
name: Temperature Sensor
description: Din riktiga utetemperatursensor
selector:
entity:
domain: [sensor]
device_class: [temperature]
multiple: false
refresh_temperature_delay:
name: Cheap Hours - Refresh Controllable Temperature Delay Time
description: Hur ofta den kontrollerbara temperaturen ska spegla ute-tempen under billiga perioder.
default: 5
selector:
number:
min: 0.0
max: 10.0
step: 0.25
unit_of_measurement: Minutes
mode: slider
controll_sensor:
name: Controllable Sensor
description: Din kontrollerbara sensor (t.ex. MQTT number)
selector:
entity:
domain: [number]
integration: mqtt
multiple: false
virtual_temperature:
name: Virtual Block Temp
description: Virtuell temperatur under dyra perioder (för att blockera värmen)
default: 20
selector:
number:
min: 0.0
max: 30.0
mode: slider
step: 1.0
unit_of_measurement: "°C"
source_url: https://gist.github.com/JohanAlvedal/66b21a648a1a4ca261f6f3476b3f82e3
variables:
grid_area: !input grid_area
expensive_hours: !input expensive_hours
temperature_sensor: !input temperature_sensor
refresh_temperature_delay: !input refresh_temperature_delay
controll_sensor: !input controll_sensor
virtual_temperature: !input virtual_temperature
trigger:
- platform: state
entity_id: !input grid_area
- platform: homeassistant
event: start
- platform: time_pattern
seconds: 30
mode: restart
action:
- choose:
- conditions:
- condition: template
# DYRT nu? -> blockera (sätt virtuell temperatur)
value_template: >
{% set cur = states(grid_area) | float(default=none) %}
{% set raw = state_attr(grid_area, 'raw_today') or [] %}
{% if cur is none or raw | length == 0 %}
false
{% else %}
{% set prices = raw | map(attribute='value') | map('float') | list %}
{% set L = prices | length %}
{% set slots = (expensive_hours * L / 24) | int %}
{% set slots = 1 if slots < 1 else (L if slots > L else slots) %}
{% set threshold = (prices | sort)[L - slots] %}
{{ cur >= threshold }}
{% endif %}
sequence:
- service: number.set_value
target:
entity_id: !input controll_sensor
data:
value: !input virtual_temperature
- conditions:
- condition: template
# BILLIGT nu? -> spegla ute-temp, repetera tills det blir dyrt
value_template: >
{% set cur = states(grid_area) | float(default=none) %}
{% set raw = state_attr(grid_area, 'raw_today') or [] %}
{% if cur is none or raw | length == 0 %}
false
{% else %}
{% set prices = raw | map(attribute='value') | map('float') | list %}
{% set L = prices | length %}
{% set slots = (expensive_hours * L / 24) | int %}
{% set slots = 1 if slots < 1 else (L if slots > L else slots) %}
{% set threshold = (prices | sort)[L - slots] %}
{{ cur < threshold }}
{% endif %}
sequence:
- alias: Refresh controllable temperature during cheap period
repeat:
until: >
{% set cur = states(grid_area) | float(default=none) %}
{% set raw = state_attr(grid_area, 'raw_today') or [] %}
{% if cur is none or raw | length == 0 %}
true
{% else %}
{% set prices = raw | map(attribute='value') | map('float') | list %}
{% set L = prices | length %}
{% set slots = (expensive_hours * L / 24) | int %}
{% set slots = 1 if slots < 1 else (L if slots > L else slots) %}
{% set threshold = (prices | sort)[L - slots] %}
{{ cur >= threshold }}
{% endif %}
sequence:
- service: number.set_value
target:
entity_id: !input controll_sensor
data:
value: "{{ states(temperature_sensor) | float(0) }}"
- delay:
minutes: !input refresh_temperature_delay
default: []
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment