Grünlandtemperatursumme (GTS) in Home Assistant: Vegetationsbeginn automatisch berechnen

Was ist die Grünlandtemperatursumme?

Die Grünlandtemperatursumme (GTS) ist ein agrarmeteorologischer Index, der in der Landwirtschaft seit Jahrzehnten verwendet wird, um den Beginn der Vegetationsperiode vorherzusagen. Entwickelt wurde das Verfahren, um einen zuverlässigen Anhaltspunkt zu geben, wann das Graswachstum einsetzt — und damit der richtige Zeitpunkt für die erste Düngung gekommen ist.

Das Prinzip

Ab dem 1. Januar werden die positiven Tagesmitteltemperaturen aufsummiert — allerdings nicht gleichmäßig:

MonatFaktorBegründung
Januar× 0,5Niedrige Sonneneinstrahlung, Boden meist gefroren
Februar× 0,75Übergangsmonat, Boden beginnt sich zu erwärmen
März – September× 1,0Volle Gewichtung

Negative Tagesmittel werden ignoriert — sie fließen als 0 in die Berechnung ein.

Sobald die Summe den Wert 200 °Cd (Gradtage) erreicht, gilt der nachhaltige Vegetationsbeginn als erreicht. In Deutschland ist das je nach Region und Witterung typischerweise zwischen Mitte Februar (mild, Rheingraben) und April (Mittelgebirgslagen).

Warum ist das relevant?

  • Düngeverordnung: Die erste Stickstoffdüngung auf Grünland darf erst nach Vegetationsbeginn erfolgen
  • Pflanzenschutz: Viele Schädlinge und Pilze werden mit Vegetationsbeginn aktiv
  • Gartenplanung: Auch für Hobbygärtner ein guter Indikator, wann es "losgeht"

Was wir bauen

Unser Home-Assistant-Setup besteht aus drei Komponenten:

  1. Helper — Speichern die Messwerte, Zähler und Ergebnisse
  2. Automation — Sammelt stündlich Temperaturen, berechnet Tageswerte und erstellt Prognosen
  3. Template-Sensor — Fasst alles in einem übersichtlichen Sensor mit Phasen-Anzeige zusammen

Am Ende erhältst du:

  • Einen GTS-Wert, der sich automatisch über das Jahr aufbaut
  • Eine Prognose basierend auf deiner Wetter-Integration, wann der Vegetationsbeginn erreicht wird
  • Benachrichtigungen, wenn es soweit ist
  • Einen Sensor mit Phasenangabe (Tiefwinter, Vorfrühling, Vegetationsbeginn, etc.)

Schritt 1: Helper anlegen

Wir benötigen insgesamt fünf input_number-Helper und einen input_boolean-Helper. Du kannst sie über Einstellungen → Geräte & Dienste → Helper → Helper erstellen anlegen, oder direkt in deiner configuration.yaml.

Variante A: Über die UI

Gehe zu Einstellungen → Geräte & Dienste → Helper und erstelle nacheinander:

1. GTS Gesamtwert

EigenschaftWert
NameGTS: Grünlandtemperatursumme
Entity-IDinput_number.gts
Minimum0
Maximum10000
Schrittweite0.01
Einheit°Cd
ModusBox
Iconmdi:sigma

2. Tagessumme Temperatur

EigenschaftWert
NameGTS: Tagessumme Temperatur
Entity-IDinput_number.gts_tagessumme_temp
Minimum-10000
Maximum10000
Schrittweite0.01
Einheit°C
ModusBox
Iconmdi:temperature-celsius

3. Anzahl Tagesmessungen

EigenschaftWert
NameGTS: Anzahl Tagesmessungen
Entity-IDinput_number.gts_tages_messungen
Minimum0
Maximum100
Schrittweite1
Einheit(leer)
ModusBox
Iconmdi:counter

4. GTS Prognosewert

EigenschaftWert
NameGTS: Prognosewert
Entity-IDinput_number.gts_prognose
Minimum0
Maximum10000
Schrittweite0.1
Einheit°Cd
ModusBox
Iconmdi:thermometer-alert

5. Tage bis Vegetationsbeginn

EigenschaftWert
NameGTS: Tage bis Vegetationsbeginn
Entity-IDinput_number.gts_tage_bis_vegetation
Minimum-1
Maximum365
Schrittweite1
EinheitTage
ModusSlider
Iconmdi:calendar-arrow-right

6. Vegetationsbeginn erreicht (Boolean)

EigenschaftWert
NameGTS: Vegetationsbeginn erreicht
Entity-IDinput_boolean.vegetationsbeginn_erreicht
Iconmdi:sprout

Variante B: Über configuration.yaml

Falls du es lieber in YAML definierst:

input_number:
  gts:
    name: "GTS: Grünlandtemperatursumme"
    min: 0
    max: 10000
    step: 0.01
    unit_of_measurement: "°Cd"
    icon: mdi:sigma
    mode: box

  gts_tagessumme_temp:
    name: "GTS: Tagessumme Temperatur"
    min: -10000
    max: 10000
    step: 0.01
    unit_of_measurement: "°C"
    icon: mdi:temperature-celsius
    mode: box

  gts_tages_messungen:
    name: "GTS: Anzahl Tagesmessungen"
    min: 0
    max: 100
    step: 1
    icon: mdi:counter
    mode: box

  gts_prognose:
    name: "GTS: Prognosewert"
    min: 0
    max: 10000
    step: 0.1
    unit_of_measurement: "°Cd"
    icon: mdi:thermometer-alert
    mode: box

  gts_tage_bis_vegetation:
    name: "GTS: Tage bis Vegetationsbeginn"
    min: -1
    max: 365
    step: 1
    unit_of_measurement: "Tage"
    icon: mdi:calendar-arrow-right
    mode: slider

input_boolean:
  vegetationsbeginn_erreicht:
    name: "GTS: Vegetationsbeginn erreicht"
    icon: mdi:sprout

Hinweis: Der Wert -1 bei "Tage bis Vegetationsbeginn" dient als Indikator, dass entweder der Vegetationsbeginn bereits erreicht wurde oder keine Prognose möglich ist.


Schritt 2: Die Automation

Die Automation ist das Herzstück des Systems. Sie erledigt vier Aufgaben:

  1. Stündlich Temperatur messen und aufsummieren
  2. Um 23:59 den Tageswert berechnen und zur GTS addieren
  3. Mehrmals täglich eine Prognose basierend auf Wetterdaten erstellen
  4. Am 30. September alles für das neue Jahr zurücksetzen

Voraussetzung

Du benötigst:

  • Einen Außentemperatur-Sensor (z.B. sensor.aussentemperatur)
  • Eine Wetter-Integration mit Vorhersagedaten (z.B. weather.zuhause — die Standard-Met.no-Integration funktioniert hier gut)

Automation anlegen

Gehe zu Einstellungen → Automatisierungen → Neue Automatisierung erstellen → In YAML bearbeiten und füge folgenden Code ein.

Wichtig: Passe die Entity-IDs sensor.aussentemperatur und weather.zuhause an deine eigenen Entitäten an!

alias: "GTS: Grünlandtemperatursumme"
description: >-
  Sammelt stündlich Temperaturen, berechnet Tageswert um 23:59,
  erstellt Prognosen und setzt am 30. September zurück.
triggers:
  # Stündliche Messung
  - hours: /1
    id: stundlicher_sammler
    trigger: time_pattern

  # Tagesabschluss um 23:59
  - at: "23:59:00"
    id: tagesabschluss
    trigger: time

  # Prognose-Updates
  - at: "08:00:00"
    id: prognose
    trigger: time
  - at: "12:00:00"
    id: prognose
    trigger: time
  - at: "16:00:00"
    id: prognose
    trigger: time
  - event: start
    id: prognose
    trigger: homeassistant

conditions:
  - condition: template
    value_template: "{{ now().month < 10 }}"
    alias: Nur von Januar bis September ausführen

actions:
  - choose:
      # =============================================
      # STÜNDLICHE TEMPERATURMESSUNG
      # =============================================
      - conditions:
          - condition: trigger
            id: stundlicher_sammler
        sequence:
          - target:
              entity_id: input_number.gts_tagessumme_temp
            data:
              value: >
                {{ states('input_number.gts_tagessumme_temp') | float(0)
                   + states('sensor.aussentemperatur') | float(0) }}
            action: input_number.set_value
            alias: Temperatur zur Tagessumme addieren
          - target:
              entity_id: input_number.gts_tages_messungen
            data:
              value: >
                {{ states('input_number.gts_tages_messungen') | float(0) + 1 }}
            action: input_number.set_value
            alias: Messungszähler erhöhen
        alias: Regelmäßige Temperaturmessungen aufsummieren

      # =============================================
      # TAGESABSCHLUSS UM 23:59
      # =============================================
      - conditions:
          - condition: trigger
            id: tagesabschluss
        sequence:
          - variables:
              messungen: >
                {{ states('input_number.gts_tages_messungen') | float(0) }}
          - if:
              - condition: template
                value_template: "{{ messungen > 0 }}"
                alias: Nur wenn Messungen registriert wurden
            then:
              - variables:
                  tagesmittel: >
                    {% set m = states('input_number.gts_tages_messungen') | float(0) %}
                    {% if m > 0 %}
                      {{ (states('input_number.gts_tagessumme_temp') | float(0) / m) | round(2) }}
                    {% else %}
                      0
                    {% endif %}
                  monat: "{{ now().month }}"
                  faktor: >
                    {% set monat = now().month %}
                    {% if monat == 1 %}0.5
                    {% elif monat == 2 %}0.75
                    {% else %}1.0
                    {% endif %}
                  beitrag: >
                    {% set m = states('input_number.gts_tages_messungen') | float(0) %}
                    {% if m > 0 %}
                      {% set mittel = (states('input_number.gts_tagessumme_temp') | float(0) / m) %}
                      {% set faktor = 0.5 if now().month == 1 else (0.75 if now().month == 2 else 1.0) %}
                      {% if mittel > 0 %}
                        {{ (mittel * faktor) | round(2) }}
                      {% else %}
                        0
                      {% endif %}
                    {% else %}
                      0
                    {% endif %}
                  new_gts: >
                    {{ (states('input_number.gts') | float(0) + beitrag | float) | round(2) }}

              # GTS-Gesamtwert aktualisieren
              - target:
                  entity_id: input_number.gts
                data:
                  value: "{{ new_gts }}"
                action: input_number.set_value

              # Tagesbericht als Benachrichtigung
              - data:
                  title: "🌱 GTS Tagesbericht {{ now().strftime('%d.%m.%Y') }}"
                  message: >
                    Messungen heute: {{ messungen | int }}
                    Tagesmittel: {{ tagesmittel }}°C
                    Faktor (Monat {{ monat }}): {{ faktor }}
                    Beitrag heute: {{ beitrag }}°C
                    GTS gesamt: {{ new_gts }}°C
                action: notify.persistent_notification
            else:
              - data:
                  title: "⚠️ GTS Fehler {{ now().strftime('%d.%m.%Y') }}"
                  message: >-
                    Heute wurden keine Temperaturmessungen registriert.
                    Der GTS-Tageswert konnte nicht berechnet werden.
                action: notify.persistent_notification

          # Tageszähler zurücksetzen
          - target:
              entity_id: input_number.gts_tagessumme_temp
            data:
              value: 0
            action: input_number.set_value
            alias: Tagessumme zurücksetzen

          - target:
              entity_id: input_number.gts_tages_messungen
            data:
              value: 0
            action: input_number.set_value
            alias: Messungszähler zurücksetzen

          # Vegetationsbeginn-Flag prüfen
          - if:
              - condition: template
                value_template: >
                  {{ states('input_number.gts') | float(0) >= 200 }}
            then:
              - action: input_boolean.turn_on
                target:
                  entity_id: input_boolean.vegetationsbeginn_erreicht

          # Jahresreset am 30. September
          - if:
              - condition: template
                value_template: "{{ now().month == 9 and now().day == 30 }}"
            then:
              - target:
                  entity_id: input_number.gts
                data:
                  value: 0
                action: input_number.set_value
              - target:
                  entity_id: input_number.gts_prognose
                data:
                  value: 0
                action: input_number.set_value
              - target:
                  entity_id: input_number.gts_tage_bis_vegetation
                data:
                  value: -1
                action: input_number.set_value
              - action: input_boolean.turn_off
                target:
                  entity_id: input_boolean.vegetationsbeginn_erreicht
              - data:
                  title: "🔄 GTS Jahresreset"
                  message: >-
                    Die Grünlandtemperatursumme wurde für das neue
                    Berechnungsjahr zurückgesetzt.
                action: notify.persistent_notification
        alias: Tagesabschluss und Reset

      # =============================================
      # PROGNOSE BERECHNEN
      # =============================================
      - conditions:
          - condition: trigger
            id: prognose
        sequence:
          # Wettervorhersage abrufen
          - target:
              entity_id: weather.zuhause
            data:
              type: daily
            response_variable: forecast_data
            action: weather.get_forecasts

          # Prognose berechnen
          - target:
              entity_id: input_number.gts_prognose
            data:
              value: >
                {% set gts_aktuell = states('input_number.gts') | float(0) %}
                {% set forecast = forecast_data['weather.zuhause']['forecast'] %}
                {% set prognose = namespace(summe=gts_aktuell) %}
                {% for tag in forecast %}
                  {% set datum = tag.datetime | as_datetime | as_local %}
                  {% set monat = datum.month %}
                  {% set faktor = 0.5 if monat == 1 else (0.75 if monat == 2 else 1.0) %}
                  {% set tmax = tag.temperature | float(0) %}
                  {% set tmin = tag.templow | float(0) %}
                  {% set tmittel = ((tmax + tmin) / 2) | round(2) %}
                  {% if tmittel > 0 %}
                    {% set prognose.summe = prognose.summe + (tmittel * faktor) %}
                  {% endif %}
                {% endfor %}
                {{ prognose.summe | round(1) }}
            action: input_number.set_value

          # Tage bis Vegetationsbeginn berechnen
          - target:
              entity_id: input_number.gts_tage_bis_vegetation
            data:
              value: >
                {% if states('input_number.gts') | float(0) >= 200 %}
                  0
                {% else %}
                  {% set gts_aktuell = states('input_number.gts') | float(0) %}
                  {% set forecast = forecast_data['weather.zuhause']['forecast'] %}
                  {% set ns = namespace(summe=gts_aktuell, tage=-1, gefunden=false) %}
                  {% for tag in forecast %}
                    {% if not ns.gefunden %}
                      {% set datum = tag.datetime | as_datetime | as_local %}
                      {% set monat = datum.month %}
                      {% set faktor = 0.5 if monat == 1 else (0.75 if monat == 2 else 1.0) %}
                      {% set tmax = tag.temperature | float(0) %}
                      {% set tmin = tag.templow | float(0) %}
                      {% set tmittel = ((tmax + tmin) / 2) | round(2) %}
                      {% if tmittel > 0 %}
                        {% set ns.summe = ns.summe + (tmittel * faktor) %}
                      {% endif %}
                      {% if ns.summe >= 200 and not ns.gefunden %}
                        {% set ns.tage = loop.index %}
                        {% set ns.gefunden = true %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                  {{ ns.tage }}
                {% endif %}
            action: input_number.set_value

          # Benachrichtigungen je nach Prognose-Stand
          - choose:
              - conditions:
                  - condition: numeric_state
                    entity_id: input_number.gts_prognose
                    above: 199.99
                sequence:
                  - data:
                      title: "🟢 Vegetationsbeginn erreicht!"
                      message: >
                        GTS gemessen: {{ states('input_number.gts') | float(0) | round(1) }}°Cd

                        GTS Prognose: {{ states('input_number.gts_prognose') | float(0) | round(1) }}°Cd

                        🌱 Vegetationsbeginn ist erreicht oder in Kürze zu erwarten!
                    action: notify.persistent_notification
              - conditions:
                  - condition: numeric_state
                    entity_id: input_number.gts_prognose
                    above: 169.99
                sequence:
                  - data:
                      title: >-
                        🟠 Vegetationsbeginn in ~{{
                        states('input_number.gts_tage_bis_vegetation') | int }} Tagen
                      message: >
                        GTS gemessen: {{ states('input_number.gts') | float(0) | round(1) }}°Cd

                        GTS Prognose: {{ states('input_number.gts_prognose') | float(0) | round(1) }}°Cd

                        Düngemaßnahmen vorbereiten!
                    action: notify.persistent_notification
              - conditions:
                  - condition: numeric_state
                    entity_id: input_number.gts_prognose
                    above: 149.99
                sequence:
                  - data:
                      title: >-
                        🟡 GTS nähert sich 200 — noch {{
                        states('input_number.gts_tage_bis_vegetation') | int }} Tage
                      message: >
                        GTS gemessen: {{ states('input_number.gts') | float(0) | round(1) }}°Cd

                        GTS Prognose: {{ states('input_number.gts_prognose') | float(0) | round(1) }}°Cd

                        Tägliche Beobachtung empfohlen!
                    action: notify.persistent_notification
        alias: Prognose berechnen

mode: single

Was passiert wann?

Tabelle kopieren
TriggerZeitpunktAktion
stundlicher_sammlerJede volle StundeAußentemperatur ablesen und aufsummieren
tagesabschluss23:59 UhrTagesmittel berechnen, Faktor anwenden, GTS aktualisieren
prognose08:00, 12:00, 16:00 + HA-StartWettervorhersage abrufen, GTS hochrechnen

Die Monatsfaktoren im Detail

Die unterschiedliche Gewichtung nach Monat bildet ab, dass warme Januartage noch kaum Vegetationswirkung haben — der Boden ist gefroren, die Tage zu kurz. Erst ab März zählt jeder Gradtag voll:

 
Januar:    Tagesmittel × 0,50
Februar:   Tagesmittel × 0,75
März–Sep:  Tagesmittel × 1,00

Prognose-Logik

Die Prognose nutzt die weather.get_forecasts-Action deiner Wetter-Integration. Sie iteriert über die kommenden Tage, berechnet für jeden Tag das Mittel aus Hoch- und Tieftemperatur und summiert es mit den jeweiligen Monatsfaktoren auf die aktuelle GTS auf. So erhältst du eine Schätzung, wann der Wert 200 erreicht wird.


Schritt 3: Template-Sensor

Der Template-Sensor gibt dir einen übersichtlichen Gesamtstatus mit mehreren Attributen: aktuelle Phase, Jahreszeit, Fortschritt in Prozent und ob der Vegetationsbeginn bereits erreicht wurde.

Füge folgenden Code in deine configuration.yaml ein (oder in eine separate Datei, falls du Template-Sensoren ausgelagert hast):

template:
  - sensor:
      - name: "GTS: Status"
        unique_id: gts_status_001
        unit_of_measurement: "°Cd"
        icon: mdi:grass
        state: >
          {{ states('input_number.gts') | float(0) | round(1) }}
        attributes:
          phase: >
            {% set gts = states('input_number.gts') | float(0) %}
            {% set monat = now().month %}

            {# ========== WINTER (Dez - Feb) ========== #}
            {% if monat == 12 or (monat in [1, 2] and gts < 50) %}
              Tiefwinter ❄️
            {% elif monat in [1, 2] and gts < 100 %}
              Spätwinter 🌨️

            {# ========== VORFRÜHLING / FRÜHLING ========== #}
            {% elif gts < 50 %}
              Winterruhe ❄️
            {% elif gts < 100 %}
              Frühes Vorfrühjahr 🌨️
            {% elif gts < 150 %}
              Vorfrühjahr 🌤️
            {% elif gts < 200 %}
              Kurz vor Vegetationsbeginn 🌱
            {% elif gts < 300 %}
              Vegetationsbeginn ✅

            {# ========== SOMMER ========== #}
            {% elif monat in [6, 7, 8] and gts >= 300 %}
              Frühsommer 🌞
            {% elif monat == 6 and gts >= 400 %}
              Hochsommer ☀️
            {% elif monat in [7, 8] and gts >= 500 %}
              Hochsommer ☀️
            {% elif monat == 8 and gts >= 700 %}
              Spätsommer 🌤️

            {# ========== HERBST ========== #}
            {% elif monat == 9 %}
              Frühherbst 🍂
            {% elif monat == 10 %}
              Herbst 🍁
            {% elif monat == 11 and gts > 50 %}
              Spätherbst 🌫️
            {% elif monat == 11 %}
              Vorwinter 🌧️

            {# ========== FALLBACK ========== #}
            {% else %}
              Übergangszeit 🌈
            {% endif %}

          jahreszeit: >
            {% set monat = now().month %}
            {% if monat in [12, 1, 2] %}
              Winter ❄️
            {% elif monat in [3, 4, 5] %}
              Frühling 🌸
            {% elif monat in [6, 7, 8] %}
              Sommer ☀️
            {% else %}
              Herbst 🍂
            {% endif %}

          vegetationsbeginn_erreicht: >
            {{ states('input_number.gts') | float(0) >= 200 }}

          fortschritt_prozent: >
            {% set gts = states('input_number.gts') | float(0) %}
            {{ [((gts / 200) * 100) | round(0) | int, 100] | min }}

          prognose: >
            {{ states('input_number.gts_prognose') | float(0) | round(1) }}

          tage_bis_vegetation: >
            {{ states('input_number.gts_tage_bis_vegetation') | int(-1) }}

Attribute im Überblick

Tabelle kopieren
AttributBeschreibungBeispielwert
phaseAktuelle phänologische PhaseVorfrühjahr 🌤️
jahreszeitKalendarische JahreszeitFrühling 🌸
vegetationsbeginn_erreichtWurde GTS ≥ 200 erreicht?true / false
fortschritt_prozentFortschritt Richtung 200°Cd73
prognosePrognostizierter GTS-Endwert187.4
tage_bis_vegetationGeschätzte Tage bis Vegetationsbeginn12

Anpassungen

Anderen Temperatursensor verwenden

Ersetze in der Automation sensor.aussentemperatur durch deine eigene Entity-ID. Jeder Sensor mit Temperaturwerten in °C funktioniert.

Andere Wetter-Integration

Ersetze weather.zuhause an beiden Stellen in der Prognose-Sektion (im target und im Template bei forecast_data['weather.zuhause']).

Benachrichtigungen anpassen

Die Automation nutzt notify.persistent_notification, was Home-Assistant-interne Benachrichtigungen erzeugt. Du kannst das durch jeden anderen Notify-Dienst ersetzen, z.B.:

  • notify.mobile_app_dein_handy — Push-Nachricht
  • notify.telegram — Telegram-Bot
  • notify.email — E-Mail

Dashboard-Karte

Ein einfaches Beispiel für eine Dashboard-Karte:

type: entities
title: 🌱 Grünlandtemperatursumme
entities:
  - entity: sensor.gts_status
    name: GTS Wert
  - type: attribute
    entity: sensor.gts_status
    attribute: phase
    name: Phase
  - type: attribute
    entity: sensor.gts_status
    attribute: fortschritt_prozent
    name: Fortschritt
    suffix: "%"
  - type: attribute
    entity: sensor.gts_status
    attribute: prognose
    name: Prognose
    suffix: "°Cd"
  - type: attribute
    entity: sensor.gts_status
    attribute: tage_bis_vegetation
    name: Tage bis Vegetation
  - entity: input_boolean.vegetationsbeginn_erreicht
    name: Vegetationsbeginn erreicht

Fazit

Mit diesen drei Komponenten hast du ein vollständiges agrarmeteorologisches Messsystem in Home Assistant. Die stündliche Messung sorgt für ein verlässliches Tagesmittel, die Monatsfaktoren bilden die reale Vegetationswirkung ab, und die Prognose-Funktion gibt dir rechtzeitig Bescheid, wann es Zeit wird, den Dünger rauszuholen.

Die GTS ist natürlich nur ein Modell — regionale Besonderheiten, Bodenart und Exposition spielen ebenfalls eine Rolle. Aber als datengestützter Richtwert direkt aus deinem Smart Home ist sie ein starkes Werkzeug für jeden, der Grünland bewirtschaftet oder einfach wissen will, wann der Frühling wirklich beginnt. 🌱

Kommentare

PostadresseE-MailadresseFestnetzMobiltelefonSMS/SignalThreemaTwitter DirektnachrichtFAXWeb Page