Zum Inhalt springen
Alles Automatisch

Klima: Adaptive Beschattung (Hitze + Blendschutz)

Sonnenstand-basierte Beschattung für 5 Räume. Berechnet Azimut pro Raum, fährt Rolladen bei Hitze (>24C) oder Blendung (>10.000 Lux) runter. Pausiert bei laufender Aufnahme. Debug-Logging optional.

Entitäten:coversensorinput_boolean

Themen:KlimaJalousienSonnenstandAutomatisch

Aktualisiert: 30. April 2026

Was brauchst du dafür?

Integrationen
  • Jalousie/Rolladen-Integration
Geräte
  • Sensor
  • Jalousie/Rolladen
Helper
  • Input Boolean Helper

Was musst du anpassen?

PlatzhalterErsetze mit
DEIN_TEMPERATURSENSOR_WOHNZIMMERErsetze mit deiner Entity-ID
DEIN_TEMPERATURSENSOR_BUEROErsetze mit deiner Entity-ID
DEIN_TEMPERATURSENSOR_KINDERZIMMERErsetze mit deiner Entity-ID
DEIN_LUX_SENSOR_AUSSENErsetze mit deiner Entity-ID
DEIN_ROLLLADEN_WOHNZIMMER_RECHTSErsetze mit deiner Entity-ID
DEIN_ROLLLADEN_WOHNZIMMER_LINKSErsetze mit deiner Entity-ID
DEIN_ROLLLADEN_BUEROErsetze mit deiner Entity-ID
DEIN_DACHFENSTER_KINDERZIMMERErsetze mit deiner Entity-ID
DEIN_TEMPERATURSENSOR_SPIELZIMMERErsetze mit deiner Entity-ID
DEIN_DACHFENSTER_SPIELZIMMERErsetze mit deiner Entity-ID
DEIN_TEMPERATURSENSOR_KUECHEErsetze mit deiner Entity-ID
DEIN_ROLLLADEN_KUECHEErsetze mit deiner Entity-ID
Klima: Adaptive Beschattung (Hitze + Blendschutz)
# Entity-IDs sind anonymisiert. Ersetze sie durch deine eigenen.
# Beispiel: light.dein_wohnzimmer_licht -> light.wohnzimmer_deckenlampe
# Klima: Adaptive Beschattung (Hitze + Blendschutz)
# Vollautomatische Sonnenstand-basierte Beschattung fuer mehrere Raeume.
# Logik pro Raum:
#   1. Sonne nicht im Sichtfeld ODER bewoelkt -> 100% (offen)
#   2. Sonne im Sichtfeld + Temp ueber Komfort -> Hitzeschutz (20-30%)
#   3. Sonne im Sichtfeld + Temp ok + flacher Winkel (<25) -> Aggressiver Blendschutz (30-40%)
#   4. Sonne im Sichtfeld + Temp ok + hoher Winkel -> Moderater Blendschutz (50-60%)
#
# Klar = Wolkenbedeckung < 70% ODER Aussen-Lux > 8000.
# Pause: input_boolean.adaptive_rolladen_aktiv (off = pausiert).
# Aufnahme: input_boolean.aufnahme_aktiv (on = Buero-Cover fixiert).
# Auto pausiert bei Elevation < 15 Grad.

id: klima_adaptive_rolladen_hitze_blendschutz
alias: "Klima: Adaptive Beschattung (Hitze + Blendschutz)"
description: >-
  Vollautomatische Sonnenstand-basierte Beschattung fuer 5 Raeume:
  Wohnzimmer (Eckverglasung SO+S, bodentief),
  Buero (SSW/SW, bodentief, Bildschirm-Blendschutz, pausiert bei Aufnahme),
  Kinderzimmer Dachfenster (N/W),
  Spielzimmer Dachfenster (S/O),
  Kueche (S/O, normales Fenster).

  Logik pro Raum:
  1. Sonne nicht im Sichtfeld ODER bewoelkt -> 100% (offen)
  2. Sonne im Sichtfeld + Temp ueber Komfort -> Hitzeschutz (20-30%)
  3. Sonne im Sichtfeld + Temp ok + flacher Winkel (<25) -> Aggressiver Blendschutz (30%)
  4. Sonne im Sichtfeld + Temp ok + hoher Winkel -> Moderater Blendschutz (50%)

  Klar = Wolkenbedeckung < 70% ODER Aussen-Lux > 8000.
  Pause: input_boolean.adaptive_rolladen_aktiv (off = pausiert).
  Aufnahme: input_boolean.aufnahme_aktiv (on = Buero-Cover fixiert).
  Auto pausiert bei Elevation < 15 Grad.

# --- Trigger ---
triggers:
  - alias: "Alle 5 Min: Routinemaessige Neuberechnung"
    trigger: time_pattern
    minutes: "/5"

  - alias: "Wohnzimmer warm: sofort reagieren"
    trigger: numeric_state
    entity_id: sensor.DEIN_TEMPERATURSENSOR_WOHNZIMMER
    above: 23

  - alias: "Buero warm: sofort reagieren"
    trigger: numeric_state
    entity_id: sensor.DEIN_TEMPERATURSENSOR_BUERO
    above: 22

  - alias: "Kinderzimmer warm: Dachfenster reagieren"
    trigger: numeric_state
    entity_id: sensor.DEIN_TEMPERATURSENSOR_KINDERZIMMER
    above: 24

  - alias: "Sonne ueber Horizont: bei Sonnenaufgang aktivieren"
    trigger: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: 10

  - alias: "Wolken stark zunehmend (ueber 70%): Cover wieder oeffnen"
    trigger: numeric_state
    entity_id: weather.forecast_home
    attribute: cloud_coverage
    above: 70

  - alias: "Wolken stark abnehmend (unter 50%): Beschattung neu pruefen"
    trigger: numeric_state
    entity_id: weather.forecast_home
    attribute: cloud_coverage
    below: 50

# --- Bedingungen ---
conditions:
  - alias: "Override-Schalter pruefen"
    condition: state
    entity_id: input_boolean.adaptive_rolladen_aktiv
    state: "on"

  - alias: "Nur tagsueber: Sonne ueber 15 Grad"
    condition: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: 15

# --- Aktionen ---
actions:
  # Globale Daten sammeln (Sonne, Wetter, Aussen-Lux)
  - alias: "Globale Daten sammeln (Sonne, Wetter, Aussen-Lux)"
    variables:
      sun_az: "{{ state_attr('sun.sun', 'azimuth') | float(0) }}"
      sun_el: "{{ state_attr('sun.sun', 'elevation') | float(0) }}"
      clouds: "{{ state_attr('weather.forecast_home', 'cloud_coverage') | float(50) }}"
      lux_outdoor: "{{ states('sensor.DEIN_LUX_SENSOR_AUSSEN') | float(0) }}"
      is_sunny: "{{ (state_attr('weather.forecast_home', 'cloud_coverage') | float(50)) < 70 or (states('sensor.DEIN_LUX_SENSOR_AUSSEN') | float(0)) > 8000 }}"

  # Wohnzimmer
  - alias: "Wohnzimmer: Werte berechnen"
    variables:
      wz_dist_raw: "{{ (sun_az - 157) | abs }}"
      wz_dist: "{{ wz_dist_raw if wz_dist_raw | float <= 180 else 360 - wz_dist_raw | float }}"
      wz_in_view: "{{ wz_dist | float < 60 and sun_el > 10 }}"
      wz_temp: "{{ states('sensor.DEIN_TEMPERATURSENSOR_WOHNZIMMER') | float(0) }}"
      wz_pos: >-
        {% if not wz_in_view or not is_sunny %}100{% elif wz_temp > 23 %}30{% else %}60{% endif %}

  - alias: "Wohnzimmer: Cover auf berechnete Position fahren"
    action: cover.set_cover_position
    target:
      entity_id:
        - cover.DEIN_ROLLLADEN_WOHNZIMMER_RECHTS
        - cover.DEIN_ROLLLADEN_WOHNZIMMER_LINKS
    data:
      position: "{{ wz_pos | int }}"

  # Buero
  - alias: "Buero: Werte berechnen (SSW/SW-Fenster, erweitertes Sichtfeld, Blendschutz fuer Monitore)"
    variables:
      bu_dist_raw: "{{ (sun_az - 215) | abs }}"
      bu_dist: "{{ bu_dist_raw if bu_dist_raw | float <= 180 else 360 - bu_dist_raw | float }}"
      bu_in_view: "{{ bu_dist | float < 65 and sun_el > 5 }}"
      bu_temp: "{{ states('sensor.DEIN_TEMPERATURSENSOR_BUERO') | float(0) }}"
      bu_pos: >-
        {% if not bu_in_view or not is_sunny %}100{% elif bu_temp > 22 %}30{% elif sun_el < 25 %}40{% else %}50{% endif %}

  - alias: "Buero: Cover fahren (nur wenn keine Aufnahme laeuft)"
    if:
      - condition: state
        entity_id: input_boolean.aufnahme_aktiv
        state: "off"
    then:
      - action: cover.set_cover_position
        target:
          entity_id:
            - cover.DEIN_ROLLLADEN_BUERO
        data:
          position: "{{ bu_pos | int }}"

  # Kinderzimmer (Dachfenster N/W)
  - alias: "Kinderzimmer (Dachfenster N/W): Werte berechnen"
    variables:
      kz_dist_raw: "{{ (sun_az - 315) | abs }}"
      kz_dist: "{{ kz_dist_raw if kz_dist_raw | float <= 180 else 360 - kz_dist_raw | float }}"
      kz_in_view: "{{ kz_dist | float < 45 and sun_el > 10 }}"
      kz_temp: "{{ states('sensor.DEIN_TEMPERATURSENSOR_KINDERZIMMER') | float(0) }}"
      kz_pos: >-
        {% if not kz_in_view or not is_sunny %}100{% elif kz_temp > 24 %}20{% else %}50{% endif %}

  - alias: "Kinderzimmer (Dachfenster N/W): Cover fahren"
    action: cover.set_cover_position
    target:
      entity_id:
        - cover.DEIN_DACHFENSTER_KINDERZIMMER
    data:
      position: "{{ kz_pos | int }}"

  # Spielzimmer (Dachfenster S/O)
  - alias: "Spielzimmer (Dachfenster S/O): Werte berechnen"
    variables:
      sp_dist_raw: "{{ (sun_az - 135) | abs }}"
      sp_dist: "{{ sp_dist_raw if sp_dist_raw | float <= 180 else 360 - sp_dist_raw | float }}"
      sp_in_view: "{{ sp_dist | float < 45 and sun_el > 10 }}"
      sp_temp: "{{ states('sensor.DEIN_TEMPERATURSENSOR_SPIELZIMMER') | float(0) }}"
      sp_pos: >-
        {% if not sp_in_view or not is_sunny %}100{% elif sp_temp > 23 %}25{% else %}50{% endif %}

  - alias: "Spielzimmer (Dachfenster S/O): Cover fahren"
    action: cover.set_cover_position
    target:
      entity_id:
        - cover.DEIN_DACHFENSTER_SPIELZIMMER
    data:
      position: "{{ sp_pos | int }}"

  # Kueche (S/O)
  - alias: "Kueche (S/O): Werte berechnen"
    variables:
      kc_dist_raw: "{{ (sun_az - 135) | abs }}"
      kc_dist: "{{ kc_dist_raw if kc_dist_raw | float <= 180 else 360 - kc_dist_raw | float }}"
      kc_in_view: "{{ kc_dist | float < 45 and sun_el > 10 }}"
      kc_temp: "{{ states('sensor.DEIN_TEMPERATURSENSOR_KUECHE') | float(0) }}"
      kc_pos: >-
        {% if not kc_in_view or not is_sunny %}100{% elif kc_temp > 23 %}30{% else %}60{% endif %}

  - alias: "Kueche (S/O): Cover fahren"
    action: cover.set_cover_position
    target:
      entity_id:
        - cover.DEIN_ROLLLADEN_KUECHE
    data:
      position: "{{ kc_pos | int }}"

  # Debug-Log
  - alias: "Debug-Log"
    action: logbook.log
    data:
      name: "Adaptive Beschattung"
      message: >-
        Az {{ sun_az | round(0) }} El {{ sun_el | round(0) }}, Wolken {{ clouds | round(0) }}%, klar={{ is_sunny }} > WZ {{ wz_pos }}% BU {{ bu_pos }}%(Aufn={{ is_state('input_boolean.aufnahme_aktiv', 'on') }}) KZ {{ kz_pos }}% SP {{ sp_pos }}% KC {{ kc_pos }}%

mode: single
max_exceeded: silent