Home Assistant – Anzeige der niederösterreichischen Flüsse

Nachdem ich die österreichischen Badeplätze (siehe Post) im Dashboard integriert hatte, wollte ich auch die aktuellen Daten der Flüsse in der näheren Umgebung sehen. Nachdem ich im Mostviertel aufgewachsen bin und nun in Wien lebe sind für mich vor allem die Flüsse Ybbs und Donau von Interesse.

Auf der Suche nach den entsprechenden Daten bin ich auf den “Hydrologischen Überblick” vom Land Niederösterreich gestoßen (https://www.noe.gv.at/wasserstand/#/de/Messstellen), wo man sehr aktuelle Daten zu Wasserstand, Temperatur, Durchfluss und Prognose der niederösterreichischen Flüße erhält.

Nach etwas Stöbern habe ich die JSON-Schnittstelle https://www.noel.gv.at/wasserstand/kidata/maplist/MapList.json gefunden, wo alle entsprechenden Daten publiziert werden. Diese Schnittstelle werden wir nun in Home Assistant einrichten um die Daten für die Flüsse Ybbs und Donau zu abonnieren und in weiterer folge im Dashboard zu visualiseren.

Visualisierung der Daten von Ybbs und Donau im Dashboard

Einrichtung der RESTful API

Editiere die Home Assistant Datei configuration.yaml und füge folgende Zeilen hinzu:

rest:
 - resource: https://www.noel.gv.at/wasserstand/kidata/maplist/MapList.json
    scan_interval: 7200
    sensor:
      - name: ybbs_greimpersdorf_temp
        device_class: temperature
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207688') | selectattr('Parameter', 'eq', 'Wassertemperatur') | map(attribute='Value') | first | float }}" 
        unit_of_measurement: "°C"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207688' && @.Parameter == 'Wassertemperatur')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: ybbs_greimpersdorf_wasserstand
        device_class: distance
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207688') | selectattr('Parameter', 'eq', 'Wasserstand') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "cm"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207688' && @.Parameter == 'Wasserstand')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: ybbs_greimpersdorf_wasserstand_prognose
        device_class: distance
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207688') | selectattr('Parameter', 'eq', 'WasserstandPrognose') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "cm"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207688' && @.Parameter == 'WasserstandPrognose')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: ybbs_greimpersdorf_durchfluss
        device_class: volume_flow_rate
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207688') | selectattr('Parameter', 'eq', 'Durchfluss') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "m³/s"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207688' && @.Parameter == 'Durchfluss')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: ybbs_greimpersdorf_durchfluss_prognose
        device_class: volume_flow_rate
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207688') | selectattr('Parameter', 'eq', 'DurchflussPrognose') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "m³/s"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207688' && @.Parameter == 'DurchflussPrognose')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: donau_baerndorf_temp
        device_class: temperature
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207365') | selectattr('Parameter', 'eq', 'Wassertemperatur') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "°C"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207365' && @.Parameter == 'Wassertemperatur')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: donau_baerndorf_wasserstand
        device_class: distance
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207365') | selectattr('Parameter', 'eq', 'Wasserstand') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "cm"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207365' && @.Parameter == 'Wasserstand')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: donau_korneuburg_durchfluss
        device_class: volume_flow_rate
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207241') | selectattr('Parameter', 'eq', 'Durchfluss') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "m³/s"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207241' && @.Parameter == 'Durchfluss')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: donau_korneuburg_durchfluss_prognose
        device_class: volume_flow_rate
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207241') | selectattr('Parameter', 'eq', 'DurchflussPrognose') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "m³/s"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207241' && @.Parameter == 'DurchflussPrognose')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: donau_korneuburg_wasserstand
        device_class: distance
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207241') | selectattr('Parameter', 'eq', 'Wasserstand') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "cm"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207241' && @.Parameter == 'Wasserstand')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter
      - name: donau_korneuburg_wasserstand_prognose
        device_class: distance
        value_template: "{{ value_json | selectattr('Stationnumber', 'eq', '207241') | selectattr('Parameter', 'eq', 'WasserstandPrognose') | map(attribute='Value') | first | float }}"
        unit_of_measurement: "cm"
        force_update: True
        json_attributes_path: "$[?(@.Stationnumber == '207241' && @.Parameter == 'WasserstandPrognose')]"
        json_attributes:
          - Stationname
          - Rivername
          - Parameter

Erläuterungen:

  • resource: Endpoint API; die URL zur oben angeführten JSON-Datei
  • scan_interval: Aktualisierungsintervall in Sekunden; 7200 bedeutet, dass die Werte alle 2 Stunden aktualisiert werden. Dies ist für meine Anforderung ausreichend.
    • Anmerkung: Es handelt sich hier um eine undokumentierte Schnitttstelle und ihre Verwendung ist eigentlich nur für Webseite (https://www.noe.gv.at/wasserstand/#/de/Messstellen) vorgesehen. Es ist daher dem Land NÖ vorbehalten, die Schnittstelle jederzeit zu ändern sodass wir keine Daten mehr erhalten können. Bitte strapaziere auch die API nicht zu oft, indem du sehr kurze Aktualisierungsintervalle wählst!
  • die grün markierten Felder können angepasst werden, sodass du Daten von anderen Gewässern abonnieren kannst. Wichtig ist dabei die Stationnumber entsprechend anzupassen. Die Stationnumber kannst du im JSON (https://www.noel.gv.at/wasserstand/kidata/maplist/MapList.json) heraussuchen.
  • die json_attributes extrahieren die folgenden Felder.
    • Stationname: Name der Mess-Station
    • Rivername: Name des Flusses
    • Parameter: Beschreibung, um welche Daten es sich gerade handelt (Temperatur, Durchfluss, WasserstandPrognose).

Nun Öffnen wir Home Assistant | Entwicklerwerkzeuge | Überprüfen und neu starten und klicken auf “Konfiguration prüfen”. Ist die Konfiguration valide klicken wir auf “Neu starten” um Home Assistant neu zu starten. Nach dem Neustart sollte für jedes name-Attribut in der Konfiguration ein Entity existieren (bspw. sensor.ybbs_greimpersdorf_temp) und den entsprechenden aktuellen Wert beinhalten. Als Attribute sind zusätzlich noch die Werte für Stationname, Rivername und Parameter vorhanden.

Visualisierung im Dashboard

Nun folgt das Visualiseren der zuvor abonnierten Daten im Dashboard.

Hinweis: Um die Werte darzustellen verwende ich template-entity-row aus HACS – siehe https://github.com/thomasloven/lovelace-template-entity-row

Visualisierung der Temperatur

Lege eine neue Karte im Dashboard an und wähle “Manuell”. Im Yaml Code Editor füge dann folgendes ein. Passe eventuell den Namen der Entity an.

type: entities
entities:
  - entity: sensor.ybbs_greimpersdorf_temp
    name: Temperatur | Greimpersdorf
    secondary_info: last-updated
footer:
  type: graph
  entity: sensor.ybbs_greimpersdorf_temp
  hours_to_show: 168

Nach dem Speichern siehst du den aktuellen Wert sowie den Graph über die letzte Woche (168 Stunden)

Visualisierung der Temperatur von der Ybbs

Visualisierung Wasserstand und Wasserstandsprognose

Lege eine neue Karte im Dashboard an und wähle “Manuell”. Im Yaml Code Editor füge dann folgendes ein – passe auch hier eventuelle die Namen der Entities an!

type: entities
entities:
  - type: custom:template-entity-row
    entity: sensor.ybbs_greimpersdorf_wasserstand
    name: Wasserstand | Greimpersdorf
    state: '{{states.sensor.ybbs_greimpersdorf_wasserstand.state_with_unit}}'
  - type: custom:template-entity-row
    entity: sensor.ybbs_greimpersdorf_wasserstand_prognose
    name: Prognose
    state: '{{states.sensor.ybbs_greimpersdorf_wasserstand_prognose.state_with_unit}}'
    color: >
      {% set now = states('sensor.ybbs_greimpersdorf_wasserstand') | float %} 
      {% set now_progn =
      states('sensor.ybbs_greimpersdorf_wasserstand_prognose') | float %} {% if
      now_progn > now %}
        #ff0e0e
      {% elif now_progn < now  %}
        #04a01a
      {% endif %}
    icon: >
      {% set now = states('sensor.ybbs_greimpersdorf_wasserstand') | float %} 
      {% set now_progn =
      states('sensor.ybbs_greimpersdorf_wasserstand_prognose') | float %}  {% if
      now_progn == now %}
        mdi:trending-neutral
      {% elif now_progn > now %}
        mdi:trending-up
      {% else %}
        mdi:trending-down
      {% endif %}
footer:
  type: graph
  entity: sensor.ybbs_greimpersdorf_wasserstand
  hours_to_show: 168

Nach dem Speichern siehst du den aktuellen Wasserstand sowie die aktuelle Prognose und einen Graph vom Wasserstand der letzten Woche (168h). Je nach Prognose wird das Icon angepasst.

Visualisierung des Wasserstands und seiner Prognose von der Ybbs

Visualisierung Durchfluss und Durchflussprognose

Lege eine neue Karte im Dashboard an und wähle “Manuell”. Im Yaml Code Editor füge dann folgendes ein – passe auch hier eventuell die Namen der Entities an!

type: entities
entities:
  - type: custom:template-entity-row
    entity: sensor.ybbs_greimpersdorf_durchfluss
    name: Durchfluss | Greimpersdorf
    icon: mdi:waves-arrow-right
    state: '{{states.sensor.ybbs_greimpersdorf_durchfluss.state_with_unit}}'
  - type: custom:template-entity-row
    entity: sensor.ybbs_greimpersdorf_durchfluss_prognose
    name: Prognose
    state: '{{states.sensor.ybbs_greimpersdorf_durchfluss_prognose.state_with_unit}}'
    color: >
      {% set now = states('sensor.ybbs_greimpersdorf_durchfluss') | float %}  {%
      set now_progn = states('sensor.ybbs_greimpersdorf_durchfluss_prognose') |
      float %} {% if now_progn > now %}
        #ff0e0e
      {% elif now_progn < now  %}
        #04a01a
      {% endif %}
    icon: >
      {% set now = states('sensor.ybbs_greimpersdorf_durchfluss') | float %}  {%
      set now_progn = states('sensor.ybbs_greimpersdorf_durchfluss_prognose') |
      float %}  {% if now_progn == now %}
        mdi:trending-neutral
      {% elif now_progn > now %}
        mdi:trending-up
      {% else %}
        mdi:trending-down
      {% endif %}
footer:
  type: graph
  entity: sensor.ybbs_greimpersdorf_durchfluss
  hours_to_show: 168

Nach dem Speichern siehst du den aktuellen Durchfluss sowie die aktuelle Prognose und einen Graph vom Durchfluss der letzten Woche (168h). Je nach Prognose wird das Icon angepasst.

Visualisierung des Durchflusses und seiner Prognose von der Ybbs

Home Assistant – Anzeige der österreichische Badegewässer und Badeplätze

Nachdem ich mich intensiv mit Homeassistant (HASS) beschäftigt habe, kam sehr bald der Wunsch auf, auch externe Datensätze im Dashboard visualisieren zu können. Der Sommer steht vor der Tür, und ich wollte die aktuellen Daten (Temperatur, Wasserqualität, Unterwasser-Sichtweite und Keimbelastung) der Badeplätze in der näheren Umgebung am Dashboard darstellen.

Die AGES macht in den Sommermonaten mindestens fünf Messungen an den verschiedenen Badeplätzen/Gewässern und publiziert diese auf ihrer Webseite https://www.ages.at/umwelt/wasser/badegewaesser-monitoring.

Weiters ist unter https://www.data.gv.at/katalog/dataset/badegewaesser der Link zur JSON-API aufgeführt um die Daten maschinenlesbar auszuwerten: http://www.ages.at/typo3temp/badegewaesser_db.json

Diese Schnittstelle verwenden wir nun im Home Assistant um bspw. die Messungen der Alten Donau beim Gänsehäufel zu abonnieren. Gehe dazu wie folgt vor:

Einrichtung der RESTful API

Editiere die Home Assistant Datei configuration.yaml und füge folgende Zeilen hinzu:


rest:
  - resource: https://www.ages.at/typo3temp/badegewaesser_db.json
    scan_interval: 21600
    sensor:
      - name: altedonau_gaensehauefl_temp
        device_class: temperature
        value_template: "{{ value_json['BUNDESLAENDER'] | selectattr('BUNDESLAND', 'eq', 'Wien') | map(attribute='BADEGEWAESSER') | first | selectattr('BADEGEWAESSERID', 'eq', 'AT1300002200010030') | map(attribute='MESSWERTE') | first | map(attribute='W') | first | float }}"
        unit_of_measurement: "°C"
        force_update: True
        json_attributes_path: "$.BUNDESLAENDER[?(@.BUNDESLAND== 'Wien')].BADEGEWAESSER[?(@.BADEGEWAESSERID=='AT1300002200010030')].MESSWERTE[0]"
        json_attributes:
          - D
          - S
          - A
          - E
          - E_C

Erläuterungen:

  • resource: Endpoint API; die URL zur oben angeführten JSON-Datei
  • scan_interval: Aktualisierungsintervall in Sekunden; 21600 bedeutet, dass die Werte alle 6 Stunden aktualisiert werden. Tipp: Die Daten ändern sich nur sehr selten – eine Aktualisierungshäufigkeit von 6 Stunden sollte ausreichend sein und sollte die gratis angebotene JSON-API nicht unnötig oft strapazieren.
  • die grün markierten Felder können für andere/weitere Badegewässer angepasst werden. Die entsprechenden Werte können Sie sich im JSON (https://www.ages.at/typo3temp/badegewaesser_db.json) heraussuchen.
  • die json_attributes extrahieren die folgenden Felder:
    • D: Datum der Messung
    • S: Sichtweite in Meter
    • A: Wasserqualität; 1=Ausgezeichnet, 4=Baden verboten
    • E: Anzahl Keime Intestinale Enterokokken
    • E_C: Anzahl Keime Escherichia coli
    • Hinweis: Laut https://www.ages.at/umwelt/wasser/badegewaesser-monitoring soll der Wert der Enterokokken sowie der Escherichia coli den Wert von 100 KBE/100 ml nicht überschreiten.

Nun Öffnen wir Home Assistant | Entwicklerwerkzeuge | Überprüfen und neu starten und klicken auf “Konfiguration prüfen”. Ist die Konfiguration valide klicken wir auf “Neu starten” um Home Assistant neu zu starten. Nach dem Neustart sollte die Entity sensor.altedonau_gaensehauefl_temp existieren und den Wert der Temperatur beinhalten. Als Attribute sind zusätzlich noch die Werte für D, S, A, E, E_C vorhanden.

Visualisierung im Dashboard

Nun folgt das Visualiseren der zuvor abonnierten Daten im Dashboard.
Hinweis: Um die Werte aus den Attributes darzustellen verwende ich template-entity-row aus HACS – siehe https://github.com/thomasloven/lovelace-template-entity-row

Lege dazu eine neue Karte im Dashboard an und wähle “Manuell”. Im Yaml Code Editor füge dann folgendes ein:

type: entities
entities:
  - type: custom:template-entity-row
    icon: mdi:percent
    entity: sensor.altedonau_gaensehauefl_temp
    name: Wasserqualität
    color: >
      {% set quality = state_attr('sensor.altedonau_gaensehauefl_temp', 'A') %}
      {% if quality == 1 %}
        #04a01a
      {% elif quality == 2 %}
        #ffb70e
      {% elif quality == 3 %} 
        #ff520e
      {% elif quality == 4 %}
        #ff0e0e
      {% endif %}
    state: >
      {% set quality = state_attr('sensor.altedonau_gaensehauefl_temp', 'A') %}
      {% if quality == 1 %}
        Ausgezeichnet
      {% elif quality == 2 %}
        Gut
      {% elif quality == 3 %}
        Mangelhaft
      {% elif quality == 4 %}
        Baden verboten
      {% else %}
        Not mapped: {{quality}}
      {% endif %}
  - type: custom:template-entity-row
    icon: mdi:thermometer-water
    entity: sensor.altedonau_gaensehauefl_temp
    name: Temperatur
    state: '{{states.sensor.altedonau_gaensehauefl_temp.state_with_unit}}'
    secondary: ''
  - type: custom:template-entity-row
    icon: mdi:eye
    entity: sensor.altedonau_gaensehauefl_temp
    name: Sichttiefe
    state: '{{state_attr(''sensor.altedonau_gaensehauefl_temp'', ''S'')}} m'
  - type: custom:template-entity-row
    icon: mdi:counter
    entity: sensor.altedonau_gaensehauefl_temp
    name: Anzahl Keime Enterokokken
    state: '{{state_attr(''sensor.altedonau_gaensehauefl_temp'', ''E'')}} KBE/100ml'
    secondary: < 100 OK
  - type: custom:template-entity-row
    icon: mdi:counter
    entity: sensor.altedonau_gaensehauefl_temp
    name: Anzahl Keime E-Coli
    state: '{{state_attr(''sensor.altedonau_gaensehauefl_temp'', ''E_C'')}} KBE/100ml'
    secondary: < 100 OK
  - type: custom:template-entity-row
    icon: mdi:calendar
    entity: sensor.altedonau_gaensehauefl_temp
    name: Stand
    state: '{{state_attr(''sensor.altedonau_gaensehauefl_temp'', ''D'')}}'
    secondary: >-
      Updated {{states.sensor.altedonau_gaensehauefl_temp.last_updated |
      as_datetime | relative_time}} ago
    color: >
      {% set daysSince = ((as_timestamp(now()) - as_timestamp(strptime(state_attr('sensor.altedonau_gaensehauefl_temp', 'D'), "%d.%m.%Y") | as_datetime)) / 86400) | int %}     
      {% if daysSince < 15 %}
        #04a01a
      {% else %}
        #ff0e0e
      {% endif %}

Nach erfolgtem Speichern siehst du nun eine Karte mit den visualisierten Daten:

Weiteres …

Du kannst natürlich mehrere Gewässer abonnieren und visualisieren. Füge dazu einfach zusätzliche “name: gewaessername_temp” – Blöcke zur configuration.yaml unterhalb von “sensor:” hinzu.

Bspw für den Donau-Altarm in Greifenstein:

      - name: donau_greifenstein_temp
        device_class: temperature
        value_template: "{{ value_json['BUNDESLAENDER'] | selectattr('BUNDESLAND', 'eq', 'Niederösterreich') | map(attribute='BADEGEWAESSER') | first | selectattr('BADEGEWAESSERID', 'eq', 'AT1260007800190020') | map(attribute='MESSWERTE') | first | map(attribute='W') | first | float }}"
        unit_of_measurement: "°C"
        force_update: True
        json_attributes_path: "$.BUNDESLAENDER[?(@.BUNDESLAND== 'Niederösterreich')].BADEGEWAESSER[?(@.BADEGEWAESSERID=='AT1260007800190020')].MESSWERTE[0]"
        json_attributes:
          - D
          - S
          - A
          - S
          - E
          - E_C

Für die Visualiserung musst du natürlich jeweils eine neue Karte anlegen und alle Referenzen zur Entity aktualisieren.

Persönliches Badegewässer Dashboard

Mein persönliches Badegewässer Dashboard beinhaltet die Messungen der folgenden für mich interessanten Badeplätze:

  • Neue Donau (Wasserskilift)
  • Alte Donau (Gänsehäufel Süd)
  • Greifenstein (Altarm)
  • Neusiedlersee (Podersdorf)
  • Lunzer See (Lunz)

Der Sommer kann kommen :-)

Persönliches Dashboard mit Daten von fünf Badeplätzen