DWD OpenData: Unterschied zwischen den Versionen
JensB (Diskussion | Beiträge) KKeine Bearbeitungszusammenfassung |
F Klee (Diskussion | Beiträge) K (→Readings) |
||
(14 dazwischenliegende Versionen von 6 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}} | {{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}} | ||
{{Infobox Modul | {{Infobox Modul | ||
|ModPurpose=Daten vom DWD OpenData Server abrufen | |ModPurpose=Daten vom DWD OpenData Server abrufen | ||
Zeile 9: | Zeile 8: | ||
|ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]]) | |ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]]) | ||
}} | }} | ||
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls] oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml. | |||
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls]. | |||
== Anwendung == | == Anwendung == | ||
Zeile 20: | Zeile 18: | ||
1. Für die Wettervorhersage und die Wetterwarnungen: | 1. Für die Wettervorhersage und die Wetterwarnungen: | ||
Installation des Perl-Moduls ''XML::LibXML'' über die System-Kommandozeile mit | Installation des Perl-Moduls ''XML::LibXML'' über die System-Kommandozeile mit | ||
< | <syntaxhighlight lang="bash"> | ||
sudo apt-get install libxml-libxml-perl | sudo apt-get install libxml-libxml-perl | ||
</ | </syntaxhighlight> | ||
oder mit CPAN. | oder mit CPAN. | ||
2. Weiterhin ist das Perl-Modul '' DateTime'' erforderlich. Dieses lässt sich mit < | 2. Weiterhin ist das Perl-Modul '' DateTime'' erforderlich. Dieses lässt sich mit <syntaxhighlight lang="bash">sudo apt-get install libdatetime-perl</syntaxhighlight> installieren. | ||
3. Falls man einen eigenen Internet-Proxy nutzt: | 3. Falls man einen eigenen Internet-Proxy nutzt: | ||
Zeile 77: | Zeile 75: | ||
=== Attributes === | === Attributes === | ||
Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}. | Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}. | ||
=== Readings === | |||
Die Prognosewerte sind wie folgt aufgebaut: | |||
fc<day>_[<sample>_]<property> | |||
Eine Beschreibung der über 70 verfügbaren Eigenschaften und ihrer Maßeinheiten finden Sie hier. Die Maßeinheiten für Temperaturen und Windgeschwindigkeiten werden jeweils in °C und km/h umgerechnet. In den folgenden Abschnitten sind nur einige ausgewählte Eigenschaften aufgeführt: | |||
* day – relativer Tag (0 .. 9) basierend auf dem Zeitzonenattribut, wobei 0 für heute steht | |||
* sample – relative Zeit (0 .. 3, 7 oder 23), die einem Vielfachen von 6, 3 oder 1 Stunde UTC entspricht, abhängig vom Attribut forecastResolution | |||
* day properties (normalerweise für 06:00 Uhr Stationszeit, siehe Rohdaten der Station für tatsächliche Zeitbeziehung) | |||
date – Datum basierend auf dem Zeitzonenattribut | |||
weekday – abgekürzter Wochentag basierend auf dem Zeitzonenattribut in der Sprache Ihres FHEM-Systems | |||
Tn [°C] – Mindesttemperatur der letzten 12 Stunden | |||
Tx [°C] – Höchsttemperatur der letzten 12 Stunden (normalerweise um 18:00 Stationszeit) | |||
Tm [°C] – Durchschnittstemperatur der letzten 24 Stunden | |||
Tg [°C] – Mindesttemperatur 5 cm über dem Boden der letzten 12 Stunden | |||
PEvap [kg/m2] – Evapotranspiration der letzten 24 Stunden | |||
SunD [s] - Gesamtsonnenscheindauer des vorherigen Tages | |||
* hour properties | |||
time - Zeit basierend auf dem Zeitzonenattribut | |||
TTT [°C] - Trockentemperatur in 2 Metern Höhe über dem Boden | |||
Td [°C] - Taupunkttemperatur in 2 Metern Höhe über dem Boden | |||
DD [°] - durchschnittliche Windrichtung in 10 m Höhe über dem Boden | |||
FF [km/h] - durchschnittliche Windgeschwindigkeit in 10 m Höhe über dem Boden | |||
FX1 [km/h] - maximale Windgeschwindigkeit in der letzten Stunde | |||
SunD1 [s] - Sonnenscheindauer in der letzten Stunde | |||
SunD3 [s] - Sonnenscheindauer in den letzten 3 Stunden | |||
RR1c [kg/m2] - Niederschlagsmenge in der letzten Stunde | |||
RR3c [kg/m2] - Niederschlagsmenge in den letzten 3 Stunden | |||
RR6c [kg/m2] - Niederschlagsmenge in den letzten 6 Stunden | |||
R600 [%] - Regenwahrscheinlichkeit in den letzten 6 Stunden | |||
RRhc [kg/m2] - Niederschlagsmenge in den letzten 12 Stunden | |||
Rh00 [%] - Regenwahrscheinlichkeit in den letzten 12 Stunden | |||
RRdc [kg/m2] - Niederschlagsmenge in den letzten 24 Stunden | |||
Rd00 [%] - Regenwahrscheinlichkeit in den letzten 24 Stunden | |||
ww - Wettercode (siehe WMO 4680/4677, SYNOP) | |||
wwd - deutsche Wettercodebeschreibung | |||
VV [m] - horizontale Sichtweite | |||
Neff [%] - effektive Wolkenbedeckung | |||
Nl [%] - untere Wolkenbedeckung unter 2000 m | |||
Nm [%] - mittlere Wolkenbedeckung unter 7000 m | |||
Nh [%] - hohe Wolkenbedeckung über 7000 m | |||
PPPP [hPa] - Druckäquivalent auf Meereshöhe | |||
* Zusätzliche Tageseigenschaften, nicht vom DWD bereitgestellt | |||
SunRise - Sonnenaufgangszeit basierend auf dem Zeitzonenattribut | |||
SunSet - Sonnenuntergangszeit basierend auf dem Zeitzonenattribut | |||
* Zusätzliche Stundeneigenschaften, nicht vom DWD bereitgestellt | |||
SunAz [°] - Sonnenazimut | |||
SunEl [°] - Sonnenhöhe | |||
SunUp - Sonnenaufgang (0: Nacht, 1: Tag) | |||
Zusätzlich gibt es globale Prognosewerte: | |||
* fc_state - Status der letzten Prognoseaktualisierung, mögliche Werte sind „updated“ und „error: ...“ | |||
* fc_station - Prognosestationscode (WMO oder DWD) | |||
* fc_description - Stationsbeschreibung | |||
* fc_coordinates - Weltkoordinate und Höhe der Station | |||
* fc_time - Zeitpunkt der Veröffentlichung der Prognose basierend auf dem Zeitzonenattribut | |||
* fc_copyright - rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen | |||
Die Alarmwerte sind nach Beginn sortiert und folgendermaßen aufgebaut: | |||
a_<index>_<property> | |||
* index - Alarmindex, beginnend mit 0, Gesamtanzahl a_count, sortiert nach Beginn | |||
* alert properties | |||
category - „Met“ oder „Health“ | |||
event - numerischer Ereigniscode, siehe DWD-Dokumentation für Details | |||
eventDesc - kurze Ereignisbeschreibung in ausgewählter Sprache | |||
eventGroup - Ereignisgruppe, siehe DWD-Dokumentation für Details | |||
responseType - „None“ = nein Anweisungen, „Vorbereiten“ = Anweisungen, „AllClear“ = Alarm gelöscht | |||
urgency – „Immediate“ = Warnung oder „Zukünftig“ = Information | |||
severity – „Minor, „Moderate“, „Severe“ or „Extreme“ | |||
areaColor – RGB-Farbe je nach Dringlichkeit und Schweregrad, durch Komma getrennte Dezimalzahlen | |||
onset – Startzeit des Alarms basierend auf dem Zeitzonenattribut | |||
expires – Endzeit des Alarms basierend auf dem Zeitzonenattribut | |||
headline – Überschrift in ausgewählter Sprache, normalerweise eine Kombination der Eigenschaften Dringlichkeit und Ereignis | |||
description – Beschreibung des Alarms in ausgewählter Sprache | |||
instruction – Sicherheitsanweisungen in ausgewählter Sprache | |||
area – numerische Warnzellen-ID | |||
areaDesc – Beschreibung des Bereichs, z. B. „Stadt Berlin“ | |||
altitude – min. Höhe [m] | |||
ceiling – max. Höhe [m] | |||
Zusätzlich gibt es einige globale Alarmwerte: | |||
* a_state – Status der letzten Alarmaktualisierung, mögliche Werte sind „aktualisiert“ und „Fehler: ...“ | |||
* a_time – Zeitpunkt des Downloads der letzten Alarmaktualisierung, basierend auf der Zeitzone attribut | |||
* a_count – Anzahl der für die ausgewählte Warnzellen-ID verfügbaren Alarme | |||
* a_copyright – rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen, nicht verfügbar, wenn count null ist | |||
Alarme sollten unabhängig von der Dringlichkeit für onset <= now < expires und responseType != „AllClear“ als aktiv betrachtet werden. Inaktive Alarme mit responseType = „AllClear“ können relevante Anweisungen enthalten. | |||
Beachten Sie, dass alle Alarmwerte bei jeder Aktualisierung vollständig ersetzt und neu indexiert werden! | |||
Weitere Informationen zu den Alarmeigenschaften finden Sie in der Dokumentation des CAP DWS-Profils. | |||
== Anwendungsbeispiele == | == Anwendungsbeispiele == | ||
Zeile 113: | Zeile 215: | ||
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]). | Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]). | ||
< | <syntaxhighlight lang="perl"> | ||
package main; | package main; | ||
Zeile 289: | Zeile 391: | ||
1; | 1; | ||
</ | </syntaxhighlight> | ||
2. LogProxy | 2. LogProxy | ||
Zeile 424: | Zeile 526: | ||
[[File:DWDODmeteogram4d3h.png|500px]] | [[File:DWDODmeteogram4d3h.png|500px]] | ||
=== Beispiel für die Einrichtung eines Weblinks === | === Beispiel für die Einrichtung eines Weblinks === | ||
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/ | Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/98_DWD_OpenData_Weblink.pm 98_DWD_OpenData_Weblink.pm] zur Verfügung. | ||
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis ''fhem/FHEM'' kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit ''wget'') oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie ''°C'' falsch angezeigt. | Zunächst die Moduldatei herunterladen und in das Modulverzeichnis ''fhem/FHEM'' kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit ''wget'') oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie ''°C'' falsch angezeigt. | ||
Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden: | Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden: | ||
<syntaxhighlight lang="text"> | |||
< | |||
define DWD_Weblink_Generator DWD_OpenData_Weblink | define DWD_Weblink_Generator DWD_OpenData_Weblink | ||
attr DWD_Weblink_Generator IODev DWD | attr DWD_Weblink_Generator IODev DWD | ||
Zeile 441: | Zeile 541: | ||
define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH("DWD_Weblink_Generator") } | define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH("DWD_Weblink_Generator") } | ||
</ | </syntaxhighlight> | ||
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut ''forecastProperties'' des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. | Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut ''forecastProperties'' des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. | ||
Zeile 447: | Zeile 547: | ||
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut ''refreshRate'' auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert. | Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut ''refreshRate'' auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert. | ||
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von '' | Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von ''98_DWD_OpenData_Weblink.pm'', die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann. | ||
Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]: | Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]: | ||
[[File:DWDODweblink.png|500px]] | |||
=== Beispiel für die Einbindung auf einer Webseite außerhalb von FHEM === | |||
Für manche Anwendungsfälle, etwa die Ansicht in FTUI, ist es erforderlich, das mit dem '''DWD_Weblink_Generator''' erzeugte Bild an anderer Stelle in eine Webseite einzubinden. Dazu kann man folgende Schritte verwenden. | |||
Zunächst wird ein statisches CSS-Stylesheet erzeugt, etwa in der Datei ''ftui_weather.css'' im Unterverzeichnis ''css''. Dorthin werden die ganzen CSS-Klassen geschrieben, die der Webbrowser benötigt, um aus den Daten des DWD_Weblink_Generator eine Tabelle zu machen (siehe den etwas länglichen Code am Ende dieses Abschnitts). | |||
Dann ist zunächst dafür zu sorgen, dass im Header der Webseite, die später die Wettervorhersage anzeigen soll, dieses Stylesheet eingebunden wird. Dazu muss in den Header die Zeile | |||
<syntaxhighlight lang="html"> | |||
<link rel="stylesheet" href="css/ftui_weather.css"/> | |||
</syntaxhighlight> | |||
eingetragen werden. | |||
Der zweite Schritt besteht darin, ebenfalls in den Header der betreffenden Webseite ein paar Zeilen JavaScript einzubinden, die dem Holen der Daten dienen: | |||
<syntaxhighlight lang="html"> | |||
<script> | |||
function getDWDOpenDataWeblink() { | |||
var fwcsrf = "<HIER DER csrf-Token DES ENTFERNTEN FHEM-SERVERS>"; | |||
$. get ("http://<HIER DIE ADRESSE DES ENTFERNTEN FHEM-SERVERS>:8083/fhem?cmd=get%20DWD_Weblink_Generator%20horizontalForecast&XHR=1&fwcsrf=" + fwcsrf, | |||
function (forecastElements) { | |||
$("#DWD_OpenData_Weblink").html(forecastElements); | |||
}); | |||
} | |||
function getdata() { | |||
getDWDOpenDataWeblink(); | |||
setInterval(getDWDOpenDataWeblink, 900000); | |||
$(window).on("focus", getDWDOpenDataWeblink); | |||
}; | |||
</script> | |||
</syntaxhighlight> | |||
Der dritte Schritt besteht darin, auf der betreffenden Webseite einen Ort zu definieren, an welchen das Wettervorhersagebild geschoben wird, z.B. | |||
<syntaxhighlight lang="html"> | |||
<div id="DWD_OpenData_Weblink" style="position:absolute; left:10px;top:500px; width:600px; height:200px; float:left; overflow-y:hidden;overflow-x:auto;"></div> | |||
</syntaxhighlight> | |||
Der letzte Schritt sorgt dafür, dass die oben definierte JavaScript-Funktion beim Laden der Webseite auch aufgerufen wird. Dazu muss ein entsprechendes Attribut im body-Tag der Seite eingebaut werden: | |||
<syntaxhighlight lang="html"> | |||
<body onload="getdata()"> | |||
</syntaxhighlight> | |||
Nachstehend nun der etwas längliche CSS-Code für das statische Stylesheet: | |||
<syntaxhighlight lang="css"> | |||
/* weather table with fixed column width */ | |||
.weatherForecast { | |||
display: table; | |||
table-layout: fixed; | |||
column-gap: 40px; | |||
} | |||
/* weather table header row */ | |||
.weatherHeaderRow { | |||
display: table-header-group; | |||
white-space: nowrap; | |||
} | |||
/* weather table data row */ | |||
.weatherDataRow { | |||
display: table-row-group; | |||
} | |||
/* weather table data cells */ | |||
#weatherFontBold { | |||
font-weight: bold; | |||
} | |||
.weatherWeekday { | |||
display: table-cell; | |||
min-width: 80px; | |||
text-align: center; | |||
vertical-align: middle; | |||
} | |||
.weatherCondition { | |||
display: table-cell; | |||
position: relative; | |||
top: -4px; | |||
text-align: center; | |||
vertical-align: middle; | |||
font-size: 80%; | |||
word-wrap: break-word; | |||
} | |||
.weatherTemperature { | |||
display: table-cell; | |||
text-align: center; | |||
vertical-align: middle; | |||
font-size: 100%; | |||
white-space: nowrap; | |||
} | |||
.weatherWind { | |||
display: table-cell; | |||
text-align: center; | |||
vertical-align: middle; | |||
font-size: 80%; | |||
padding-top: 3px; | |||
} | |||
/* weather table condition icon cell */ | |||
.weatherIcon { | |||
display: table-cell; | |||
position: relative; | |||
text-align: center; | |||
} | |||
/* weather icon */ | |||
.weatherIcon img { | |||
width: 100%; | |||
height: auto; | |||
position: relative; | |||
} | |||
/* embedded alert icon with pointer support */ | |||
.weatherAlertIcon { | |||
position: absolute; | |||
top: 5px; | |||
right: 5px; | |||
width: 25px; | |||
height: 22px; | |||
background-size: 25px 22px; | |||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAMAAADM4ogkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NjcyOSwgMjAxMi8wNS8wMy0xMzo0MDowMyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDEyLjAgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1RjU1NzJBRDMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1RjU1NzJBRTMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjVGNTU3MkFCMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjVGNTU3MkFDMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+oFydjAAAAwBQTFRF9fX267W51Csy9d7c1VBV9uPc/vz89+nl5YB/2Flk2mZp1Cgv0Csw5pWR7K2t1Soy1Cow7b6y0iUr+/r61jI54X+A+uvq21xV44qO/fj400tU1kxG3nNx2mJp34Bz/Pj2a2tr4Ht91S43fn5+1jA31S0y0iYu1TA1/ff3+/TxEhIS3W1u1jA010Q++efj1kVH1Tk+gYGB6qWh4oWEtra21TI48sjH1VVc1tbW1jY22ltd4YF/1kFHl5eX/vz7/Pz84nZt+evt9+Tm2mNu1Sw14YSD1Ss04YKC0isv4X5/0zc21CUu8cnL0jA20jAz22xy1jE422Zv1i800isw1Cgx11xjKysr1FFZ4X190iQsGRkZ0jY+1TE41Cww0y0y0ykt1i431i4z0y800ikvPz4/AAAA////DQwM1TI30yYs1TE31TA21TE21S401S801S810ycs//7+1TA3///+/v791TI2/v//0Sov0iYt0yYt6urqkZGR1TM40ycu1S414ODg4YB3+/Hw7bK0/vv78fHxh4eH+OPf0i8w1DI30icu1y843Zia/PX13Nvb6aWZ4YKE+fDv21RT00E83G5y3m9x7tDF3Gdu99fW1EJK1ktK3t7e5I+R4oeH3WNp3oCF+vH16ZOJ1Sw27cG31i018dDL4qOf3Wde7Kqe+O7m2ERH+e3o+u/t4YuY/Pb15IqG5p2R4np52TA82mhx2V1p3mpx5oWL66uiRkZG4YOR/v7+1ygz1TxC8dDV9dHS2VJL1CUw8by79+Hg7bq3vr6+9dnR1Tc49d/X11le77yv22hl2lVY+Ofo33540icspqan+/f49N/h5J6m2HB7zczN3nZ88c3FsrKz3HZ74ICC4YGA1oJy10JD+Onj8c3J1Dk71T494oaE4HpxNTU14XRz7Ozs7+/vcG9v+/bz/Pj1/fr3IiIi676/5IJx4Hpr6amn56On6aGd2mlu4X2A22Vm2WFk1jI33GNk+/Ds2VJU2FZW8/Pz78jD3V1v55iY3W1x////C1yJRAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAMKSURBVHjajNEFWBNxGAbwOXEoUzYnqCgGuPMUUFE8sRuwgDlUEJmK8z6/XWyEEjrswu7u7u7u7u4u7G7FWxoj/J6L9/7v77nnQpTpMM7XFkocV0UOK2VKbkt3/R+4KY0Zlnw8d7ikBeu9VroRcoXPg5F1Y5Mn5wYPaRnGqOxMfPbIGXZfFMxxJGtg0lxzhoWlKpYfSrCd9f4rc4JPKs1l9B1aeabGoLRQTnBxG8T2K2DwLV7FRVTOHi47yKKmxGyAagoGxb7x2cLSMuS0eZIAMopJUaWtkR3M1yUBpe8lkuoj4WYYm8Bf98gaxjdsSik7toKydPQ0OKEzUnGuWcOLWgZPXoCe3Wi6HlS+zVMG/35Zwfq7eqO+wxk4T9N0OYDXKQylnZ4VnKdxM5bfAtDTh6arAlT4IldxXYo6woyS3hwxpRHA12ia7gUA3yKUKL8f7wCPiClMOSsA0VPTMwIkeeoQm+39F1asZECZ02kBFGlH06eEM+Rt0RvFHyX/wNUy7JGex9Q3EGB1U4BCLVXK9D1/wxu1lJS8lMTc36Pp/eZQcaoM9Us9/oSJL8QUGbrDXMNmOvqBJe3TxqC22p/wgIbBlrMsLZSju1pT93dSZDsW/Q3rF/NG3r+xte4zqKY1QY0IBuVvwQ4LazFGUTzRVhexJziahkzyTht8PM6AwXUbWbutj3za2W+5IIxEovYAKxwlww+KV7buYTfzL7TODOGry/tb4KdaCSg/VsFWDfSx/ELLLK9CILl9hBnOEaOq4DN7BZe6lv36++plJ3ST/zDBfEOEN6udBNnNWDHFhTpnihIbNkXKUNfLyyuqeciVOwFvr7oHrApqHhTiPjog6EqdNVFVDIji/JmiiYQbopFM3R0XF6fT6VJ15jFFnUJhSqQRETV5RXfnGykhMea9B2M624ezBaOmuKiv1GDg9TxJ8sIxltB7E0QsT/BqpdrPT9g4P7VaTcZKL4vGDP/psq71BpdSLj9nTmod3mTC+HDfN+FN2jodjlwfGRnoFNg2cH2B7+ca/xJgAFL1l3PxpIx4AAAAAElFTkSuQmCC); | |||
} | |||
.weatherAlertIcon:hover { | |||
opacity: 0.7; | |||
} | |||
.weatherAlertIcon:focus { | |||
opacity: 1.0; | |||
} | |||
/* opaque white background for alerts dialog */ | |||
.weatherOverlay { | |||
display: none; | |||
position: fixed; | |||
z-index: 1; | |||
opacity: 0.2; | |||
top: 0; | |||
left: 0; | |||
width: 100%; | |||
height: 100%; | |||
background: white; | |||
} | |||
.weatherAlertIcon:focus .weatherOverlay { | |||
display: block; | |||
} | |||
/* alerts dialog box */ | |||
[class ^= weatherAlertBox] { | |||
display: none; | |||
position: absolute; | |||
z-index: 2; | |||
opacity: 1; | |||
top: 0; | |||
border: 3px solid white; | |||
border-radius: 3px; | |||
box-shadow: 0px 0px 6px 4px #666; | |||
background: #EEE; | |||
} | |||
.weatherAlertIcon:focus .weatherAlertBoxLeft { | |||
display: block; | |||
right: -268px; | |||
} | |||
.weatherAlertIcon:focus .weatherAlertBoxCenter { | |||
display: block; | |||
left: -178px; | |||
} | |||
.weatherAlertIcon:focus .weatherAlertBoxRight { | |||
display: block; | |||
left: -312px; | |||
} | |||
/* alerts dialog close button */ | |||
.weatherAlertsClose { | |||
position: absolute; | |||
top: -12px; | |||
right: -13px; | |||
border-radius: 12px; | |||
box-shadow: 1px 1px 3px #666; | |||
line-height: 21px; | |||
width: 21px; | |||
background: #606061; | |||
text-align: center; | |||
text-decoration: none; | |||
font-family: Sans-serif; | |||
font-weight: bold; | |||
color: white; | |||
} | |||
.weatherAlertsClose:hover { | |||
opacity: 0.8; | |||
} | |||
/* alerts dialog title */ | |||
.weaterAlertsTitle { | |||
font-weight: bold; | |||
color: black; | |||
} | |||
/* alert messages */ | |||
[class ^= weaterAlertMessage] { | |||
float: left; | |||
text-align: left; | |||
white-space: nowrap; | |||
} | |||
.weaterAlertMessage p { | |||
white-space: normal; | |||
} | |||
</syntaxhighlight> |
Aktuelle Version vom 28. Juni 2024, 19:45 Uhr
DWD_OpenData | |
---|---|
Zweck / Funktion | |
Daten vom DWD OpenData Server abrufen | |
Allgemein | |
Typ | Gerätemodul |
Details | |
Dokumentation | EN / DE |
Support (Forum) | Unterstützende Dienste/Wettermodule |
Modulname | 55_DWD_OpenData.pm |
Ersteller | JensB (Forum /Wiki) |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den Open Data Server zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle OpenData_weather_content.xls oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml.
Anwendung
Aufgrund der unterschiedlichen vom DWD bereitgestellten Datenformate benötigt das Modul zur Dekodierung je nach gewünschtem Funktionsumfang zusätzliche Perl-Module, die nicht standardmäßig vorinstalliert sind und je nach Systemkonfiguration nachinstalliert werden müssen. Außerdem unterstützt das Modul Zeitzonen, um z.B. die Wettervorhersage internationaler Stationen in Ortszeit darstellen zu können. Hierfür sind je nach Systemkonfiguration weitere Einstellungen erforderlich. Auch die Sprache der Wochentage für die Wettervorhersage ist frei wählbar. Je nach Systemkonfiguration ist aber die Standardsprache u.U. auf Englisch eingestellt, was weitere Anpassungen der Systemkonfiguration erforderlich macht.
Vorbereitung
Im folgenden wird z.T. von einem System mit Rasbian oder Debian mit System-V Startsystem ausgegangen. Auf anderen Betriebssystemen und auf Systemen mit System-D müssen die Installationsschritte ggf. angepasst werden.
1. Für die Wettervorhersage und die Wetterwarnungen: Installation des Perl-Moduls XML::LibXML über die System-Kommandozeile mit
sudo apt-get install libxml-libxml-perl
oder mit CPAN.
2. Weiterhin ist das Perl-Modul DateTime erforderlich. Dieses lässt sich mit
sudo apt-get install libdatetime-perl
installieren.
3. Falls man einen eigenen Internet-Proxy nutzt: Die Konfiguration des Proxies für FHEM erfolgt z.B. durch Eintrag von
attr global proxy <myProxyHost>:<myProxyPort>
in die Konfiguration, wobei myProxyHost durch den Namen oder die IP-Adresse des Proxy-Servers ersetzt werden muss und für myProxyPort der Port des Proxy-Servers eingetragen werden muss (oft 3128).
3. FHEM Uhrzeit und Zeitzone: Durch Eingabe von
{localtime()}
in die FHEM-Kommandozeile überprüfen, ob die FHEM-Uhrzeit plausibel ist. Ist dies nicht der Fall sollten die Uhrzeit auf Systemebene überprüft werden und ggf. die Systemeinstellungen angepasst werden. Ermitteln der Bezeichnung der eigenen Zeitzone über die System-Kommandozeile mit
tzselect
und diese Bezeichnung in die Datei /etc/timezone eintragen und
export TZ=`cat /etc/timezone`
der Datei /etc/profile hinzufügen und dann das System neu starten. Nun muss die Zeitanzeige in FHEM korrekt sein.
4. FHEM Sprache: Durch Eingabe von
{$ENV{LANG}}
in die FHEM-Kommandozeile überprüfen, in welcher Sprache der Wochentag angezeigt wird. Stimmt die Sprache nicht, dann auf der System-Kommandozeile
dpkg-reconfigure locales
eingeben und aus der Liste z.B. de_DE.UTF-8 zusätzlich auswählen. Dieser Befehl gilt für Debian-basierte Betriebssysteme - für andere Betriebssysteme ist eine analoge Funktion zu verwenden. Mit Eingabe von
locale -a
auf der System-Kommandozeile überprüfen, ob die ausgewählte Sprache nun zur Verfügung steht. Sollte FHEM nach einem Neustart noch immer nicht die gewünschte Sprache verwenden, kann man auf einem System V Linux durch Hinzufügen von z.B.
export LANG=de_DE.UTF-8
in die Datei /etc/init.d/fhem (irgendwo zwischen start und perl) und erneutem Neustart von FHEM die Sprache für FHEM erzwingen. Bei einem Systemd Linux kann man die Einstellungen mit systemctl edit --full fhem.service bearbeiten. Spätestes jetzt muss die Wochentagsanzeige in FHEM korrekt sein.
5. Nur für den Weblink erforderlich: Installation des Perl-Moduls DateTime über die System-Kommandozeile mit
sudo apt-get install libdatetime-perl
oder mit CPAN.
Define
Siehe Commandref.
Attributes
Siehe Commandref.
Readings
Die Prognosewerte sind wie folgt aufgebaut:
fc<day>_[<sample>_]<property>
Eine Beschreibung der über 70 verfügbaren Eigenschaften und ihrer Maßeinheiten finden Sie hier. Die Maßeinheiten für Temperaturen und Windgeschwindigkeiten werden jeweils in °C und km/h umgerechnet. In den folgenden Abschnitten sind nur einige ausgewählte Eigenschaften aufgeführt:
- day – relativer Tag (0 .. 9) basierend auf dem Zeitzonenattribut, wobei 0 für heute steht
- sample – relative Zeit (0 .. 3, 7 oder 23), die einem Vielfachen von 6, 3 oder 1 Stunde UTC entspricht, abhängig vom Attribut forecastResolution
- day properties (normalerweise für 06:00 Uhr Stationszeit, siehe Rohdaten der Station für tatsächliche Zeitbeziehung)
date – Datum basierend auf dem Zeitzonenattribut weekday – abgekürzter Wochentag basierend auf dem Zeitzonenattribut in der Sprache Ihres FHEM-Systems Tn [°C] – Mindesttemperatur der letzten 12 Stunden Tx [°C] – Höchsttemperatur der letzten 12 Stunden (normalerweise um 18:00 Stationszeit) Tm [°C] – Durchschnittstemperatur der letzten 24 Stunden Tg [°C] – Mindesttemperatur 5 cm über dem Boden der letzten 12 Stunden PEvap [kg/m2] – Evapotranspiration der letzten 24 Stunden SunD [s] - Gesamtsonnenscheindauer des vorherigen Tages
- hour properties
time - Zeit basierend auf dem Zeitzonenattribut TTT [°C] - Trockentemperatur in 2 Metern Höhe über dem Boden Td [°C] - Taupunkttemperatur in 2 Metern Höhe über dem Boden DD [°] - durchschnittliche Windrichtung in 10 m Höhe über dem Boden FF [km/h] - durchschnittliche Windgeschwindigkeit in 10 m Höhe über dem Boden FX1 [km/h] - maximale Windgeschwindigkeit in der letzten Stunde SunD1 [s] - Sonnenscheindauer in der letzten Stunde SunD3 [s] - Sonnenscheindauer in den letzten 3 Stunden RR1c [kg/m2] - Niederschlagsmenge in der letzten Stunde RR3c [kg/m2] - Niederschlagsmenge in den letzten 3 Stunden RR6c [kg/m2] - Niederschlagsmenge in den letzten 6 Stunden R600 [%] - Regenwahrscheinlichkeit in den letzten 6 Stunden RRhc [kg/m2] - Niederschlagsmenge in den letzten 12 Stunden Rh00 [%] - Regenwahrscheinlichkeit in den letzten 12 Stunden RRdc [kg/m2] - Niederschlagsmenge in den letzten 24 Stunden Rd00 [%] - Regenwahrscheinlichkeit in den letzten 24 Stunden ww - Wettercode (siehe WMO 4680/4677, SYNOP) wwd - deutsche Wettercodebeschreibung VV [m] - horizontale Sichtweite Neff [%] - effektive Wolkenbedeckung Nl [%] - untere Wolkenbedeckung unter 2000 m Nm [%] - mittlere Wolkenbedeckung unter 7000 m Nh [%] - hohe Wolkenbedeckung über 7000 m PPPP [hPa] - Druckäquivalent auf Meereshöhe
- Zusätzliche Tageseigenschaften, nicht vom DWD bereitgestellt
SunRise - Sonnenaufgangszeit basierend auf dem Zeitzonenattribut SunSet - Sonnenuntergangszeit basierend auf dem Zeitzonenattribut
- Zusätzliche Stundeneigenschaften, nicht vom DWD bereitgestellt
SunAz [°] - Sonnenazimut SunEl [°] - Sonnenhöhe SunUp - Sonnenaufgang (0: Nacht, 1: Tag)
Zusätzlich gibt es globale Prognosewerte:
- fc_state - Status der letzten Prognoseaktualisierung, mögliche Werte sind „updated“ und „error: ...“
- fc_station - Prognosestationscode (WMO oder DWD)
- fc_description - Stationsbeschreibung
- fc_coordinates - Weltkoordinate und Höhe der Station
- fc_time - Zeitpunkt der Veröffentlichung der Prognose basierend auf dem Zeitzonenattribut
- fc_copyright - rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen
Die Alarmwerte sind nach Beginn sortiert und folgendermaßen aufgebaut:
a_<index>_<property>
- index - Alarmindex, beginnend mit 0, Gesamtanzahl a_count, sortiert nach Beginn
- alert properties
category - „Met“ oder „Health“ event - numerischer Ereigniscode, siehe DWD-Dokumentation für Details eventDesc - kurze Ereignisbeschreibung in ausgewählter Sprache eventGroup - Ereignisgruppe, siehe DWD-Dokumentation für Details responseType - „None“ = nein Anweisungen, „Vorbereiten“ = Anweisungen, „AllClear“ = Alarm gelöscht urgency – „Immediate“ = Warnung oder „Zukünftig“ = Information severity – „Minor, „Moderate“, „Severe“ or „Extreme“ areaColor – RGB-Farbe je nach Dringlichkeit und Schweregrad, durch Komma getrennte Dezimalzahlen onset – Startzeit des Alarms basierend auf dem Zeitzonenattribut expires – Endzeit des Alarms basierend auf dem Zeitzonenattribut headline – Überschrift in ausgewählter Sprache, normalerweise eine Kombination der Eigenschaften Dringlichkeit und Ereignis description – Beschreibung des Alarms in ausgewählter Sprache instruction – Sicherheitsanweisungen in ausgewählter Sprache area – numerische Warnzellen-ID areaDesc – Beschreibung des Bereichs, z. B. „Stadt Berlin“ altitude – min. Höhe [m] ceiling – max. Höhe [m]
Zusätzlich gibt es einige globale Alarmwerte:
- a_state – Status der letzten Alarmaktualisierung, mögliche Werte sind „aktualisiert“ und „Fehler: ...“
- a_time – Zeitpunkt des Downloads der letzten Alarmaktualisierung, basierend auf der Zeitzone attribut
- a_count – Anzahl der für die ausgewählte Warnzellen-ID verfügbaren Alarme
- a_copyright – rechtliche Informationen, müssen mit Prognosedaten angezeigt werden, siehe DWD-Nutzungsbedingungen, nicht verfügbar, wenn count null ist
Alarme sollten unabhängig von der Dringlichkeit für onset <= now < expires und responseType != „AllClear“ als aktiv betrachtet werden. Inaktive Alarme mit responseType = „AllClear“ können relevante Anweisungen enthalten.
Beachten Sie, dass alle Alarmwerte bei jeder Aktualisierung vollständig ersetzt und neu indexiert werden!
Weitere Informationen zu den Alarmeigenschaften finden Sie in der Dokumentation des CAP DWS-Profils.
Anwendungsbeispiele
Beispiel zur Modul-Einrichtung
- Wettervorhersage
Für die Wettervorhersage muss der Stationscode ermittelt werden. Dazu den MOSMIX Stationskatalog herunterladen, öffnen und die gewünschte Station heraussuchen (Spalte id). Einen Teil der deutschen Stationen kann man auch der Bodenmessnetzkarte entnehmen. Den ermittelten Stationscode kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando get forecast verwenden oder für die automatische Aktualisierung als Attribut forecastStation hinterlegen. Insgesamt werden vom DWD mehr als 70 Merkmale zur Verfügung gestellt. Eine Auflistung findet sich im Dokument MetElementDefinition. Nur ein kleiner Teil der Merkmale wird in der Standardeinstellung des Moduls als Reading zur Verfügung gestellt. Wer andere Merkmale benötigt muss sie mit Komma getrennt dem Attribut forecastProperties zuweisen. Es empfiehlt sich zur Performance-Optimierung sowohl das Attribut forecastDays als auch das Attribut forecastProperties auf den tatsächlichen Bedarf einzustellen.
- Wetterwarnungen
Für die Wetterwarnungen muss die Warnzelle ermittelt werden. Dazu Warnzellen-ID Katalog herunterladen, öffnen und die gewünschte Warnzelle heraussuchen. Unterstützt werden Gemeinden (beginnen mit 8), Landkreise (beginnen mit 1 oder 9) oder Küste (beginnen mit 5). Die Warnzellen-ID kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando get alerts verwenden oder für die automatische Aktualisierung als Attribut alertArea hinterlegen. Die Warnzellen-ID ist ab der 2. Stelle identisch mit den ersten Ziffern des amtlichen Gemeindeschlüssels. Man kann z.B. den Namen von Gemeinde oder Landkreis bei den Statistischen Ämtern des Bundes und der Länder eingeben, den amtlichen Gemeindeschlüssel ermitteln und dann mit vorangestellter 1, 8 oder 9 im Warnzellen-ID Katalog des DWD nach einem Eintrag mit exakter oder weitgehender Übereinstimmung suchen. Wem das zu kompliziert vorkommt, der kann bei mehrdeutigen Gemeinde- bzw. Landkreisbezeichnungen auch versuchen auszuprobieren, welche die richtige Warnzellen-ID ist.
Um das Modul mit automatisch Aktualisierung von Vorhersage und Wetterwarnungen zu nutzen, kann z.B. folgendes in die Konfiguration eingetragen werden:
define DWD DWD_OpenData attr DWD alertArea 111000000 attr DWD forecastStation 99810 attr DWD forecastDays 3 attr DWD forecastWW2Text 1
- Performance
Das DWD_OpenData-Modul ist ein Datenmodul mit relativ vielen Readings. In der Standardkonfiguration wird, wie bei jedem anderen FHEM Modul, bei jeder Änderung jedes Readings ein FHEM internes Ereignis erzeugt, damit andere FHEM Devices auf diese Änderungen reagieren können. Diese Ereignisse sorgen auch dafür, dass man Änderungen in der Weboberfläche sofort angezeigt bekommt, ohne die Webseite neu aufzurufen. Interessiert sich aber kein FHEM Device für die Änderungsbenachrichtigung bestimmter Readings, entsteht unnötiger Verarbeitungs-Overhead, der je nach FHEM Konfiguration und verfügbarer CPU-Leistung auch mehrere Sekunden benötigen kann und in dieser Zeit andere Abläufe blockiert. Um die Performance zu optimieren, empfiehlt es sich, mit event-on-update-reading für eine angepasste und dadurch effizientere Verarbeitung zu sorgen, indem man nur für jene Readings Ereignisse zulässt, welche man für die Weiterverarbeitung braucht. Der DWD_OpenData_Weblink braucht z.B. gar keine Ereignisse, um zu funktionieren. Hier eine minimalistische Beispielkonfiguration:
attr DWD event-on-update-reading state,fc_state,a_state
Weitere Details zur Installation und Konfiguration des Moduls finden sich in der Commandref.
Beispiel für die Einrichtung eines Meteogramms
Um den vorhergesagten Wetterverlauf als Meteogramm in Kurvenform mit SVG darzustellen, kann man wie folgt vorgehen:
1. 99_myUtils.pm
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe 99_myUtils_anlegen).
package main;
use strict;
use warnings;
...
#
# (c) mumpitzstuff 19.12.2018
#
# see https://forum.fhem.de/index.php/topic,83097.msg874150.html#msg874150
#
sub logProxy_dwd2Plot($$$$;$$$)
{
my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;
my $regex;
my @rl;
return undef if(!$device);
if ($fcValue =~ s/_$//)
{
$regex = "^fc[\\d]+_[\\d]+_".$fcValue."\$";
}
else
{
$regex = "^fc[\\d]+_".$fcValue."\$";
}
$fcHour = 12 if(!defined($fcHour));
$expMode = "point" if(!defined($expMode));
#Log3 undef,2, "Regex: ".$regex;
# ermitteln aller relevanten Readings
if ( defined($defs{$device}) )
{
if ( $defs{$device}{TYPE} eq "DWD_OpenData" )
{
@rl = sort
{
my ($an) = ($a =~ m/fc(\d+)_.*/);
my ($bn) = ($b =~ m/fc(\d+)_.*/);
my ($ao) = ($a =~ m/fc\d+_(\d+).*/);
my ($bo) = ($b =~ m/fc\d+_(\d+).*/);
$an <=> $bn or $ao <=> $bo or $a cmp $b;
} ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );
return undef if ( !@rl );
}
else
{
Log3 undef, 2, "logProxy_dwd2Plot: $device is not a DWD_OpenData device";
return undef;
}
}
my $fromsec = SVG_time_to_sec($from);
my $tosec = SVG_time_to_sec($to);
my $sec = $fromsec;
my ($h, $hp, $fcDay, $mday, $mon, $year);
my $timestamp;
my $reading;
my $value;
my $prev_value;
my $min = 999999;
my $max = -999999;
my $ret = "";
# while not end of plot range reached
while (($sec < $tosec) && @rl)
{
#remember previous value for start of plot range
$prev_value = $value;
$reading = shift @rl;
($fcDay) = $reading =~ m/^fc(\d+).*/;
($hp) = $reading =~ m/^fc\d+_(\d+).*/;
#Log 1, "hp: ".$hp;
if ($hp)
{
$h = ReadingsVal($device, "fc".$fcDay."_".$hp."_time", $fcHour);
if ($h =~ m/^(\d+):\d+/)
{
$h = $1;
}
}
else
{
$h = $fcHour;
}
$value = ReadingsVal($device, $reading, undef);
# calculate minutes of sunshine per hour
if ($fcValue =~ /^SunD(\d+)/)
{
if (defined($1))
{
$value = $value / ($1 * 36);
}
else
{
$value = $value / (12 * 36);
}
}
# calculate amount of rain per hour
if ($fcValue =~ /^RR(\d+)c$/)
{
if (defined($1))
{
$value /= $1;
}
}
($year, $mon, $mday) = split('\-',ReadingsVal($device, "fc".$fcDay."_date",undef));
$timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, $h, 0, 0);
$sec = SVG_time_to_sec($timestamp);
if (defined($shiftTime))
{
$sec += $shiftTime;
$timestamp = logProxy_shiftTime($timestamp, $shiftTime);
}
# skip all values before start of plot range
next if ( $sec < $fromsec );
# add first value at start of plot range
if ( !$ret && $prev_value )
{
$min = $prev_value if ( $prev_value < $min );
$max = $prev_value if ( $prev_value > $max );
$ret .= "$from $prev_value\n";
}
# done if after end of plot range
last if ($sec > $tosec);
$min = $value if ( $value < $min );
$max = $value if ( $value > $max );
# add actual control point
$ret .= "$timestamp $value\n";
}
if (($sec < $tosec) && !@rl && ($expMode eq "day"))
{
$timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, 23, 59, 59);
$_ = SVG_time_to_sec($timestamp);
if (defined($shiftTime))
{
$_ += $shiftTime;
$timestamp = logProxy_shiftTime($timestamp, $shiftTime);
}
if ($_ < $tosec)
{
$ret .= "$timestamp $value\n";
}
else
{
$ret .= "$to $value\n";
}
}
elsif (($sec > $tosec) && ($expMode eq "day"))
{
$value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;
$ret .= "$to $value\n";
}
return ($ret, $min, $max, $prev_value);
}
1;
2. LogProxy
Wer bereits ein logProxy-Device hat, muss den Namen seines logProxy-Devices in die weiter unter aufgeführte GPlot-Konfiguration eintragen. Ansonsten wird es wie folgt neu erstellt:
define LogProxy logProxy
3. FileLog
Das Meteogramm kennt anders als andere FHEM-Plots keine Vergangenheit außer heute. Trotzdem wird aus formalen Gründen ein FileLog-Device benötigt. Dazu kann ein beliebiges vorhandenes FileLog-Device verwendet werden. Wer will, kann hierfür aber auch ein neues FileLog Device für das DWD_OpenData-Device anlegen (Achtung: wird schnell umfangreich):
define FileLog_DWD FileLog ./log/DWD-%Y-%m.log DWD
Im folgenden wird für das FileLog-Device der Platzhalter FileLog_Dummy verwendet, der mit dem Namen des gewählten FileLog-Devices zu ersetzen ist.
4. SVG Plot
Das eigentliche Meteogramm ist ein SVG-Device. Will man mehrere Tage darstellen bietet sich die folgende Definition an:
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT attr SVG_DWD fixedoffset 6 attr SVG_DWD fixedrange 7days attr SVG_DWD nrAxis 1,2
Dabei muss das SVG-Attribut fixedoffset entweder gleich oder kleiner als die Einstellung des DWD_OpenData-Attributs forecastDays (Standardwert: 6 Tage) gewählt werden und das SVG-Attribut fixedrange um eins größer als fixedoffset eingestellt werden.
Will man stattdessen nur die nächsten 24 Stunden anzeigen, nimmt man folgende Einstellungen:
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT attr SVG_DWD endPlotNow 1 attr SVG_DWD fixedoffset 1 attr SVG_FileLog_WETTER_DWD_3 label "Tmin: $data{max1} °C, Tmax: $data{min1} °C" attr SVG_DWD nrAxis 1,2
Um die DWD_OpenData-Readings mit dem Plot zu verknüpfen, muss man nun die GPlot-Konfigurationsdatei des SVG-Plots manuell bearbeiten. Dazu auf den Link klicken, der im SVG_DWD-Device am Internal GPLOTFILE steht. Die y-Wertebereiche für die Regenmenge und die Temperaturen sind im Beispiel auskommentiert (Autorange). Das kann man so lassen oder man stellt sie nach den eigenen Wetter-Gegebenheiten ein. Je nach Konfiguration des DWD_OpenData-Attributs forecastResolution sind aber noch einige weitere Einstellungen anzupassen. Das folgende Beispiel ist für die 3h-Auflösung:
set terminal png transparent size <SIZE> crop set output '<OUT>.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" set xlabel " " set title 'Wettervorhersage' set ytics set y2tics set grid ytics set ylabel "Regen [mm]" #set yrange [0:4] set y2label "Temperatur [°C]" #set y2range [-5:35] set y3label "Wolken/Regen/Sonne [%]" set y3range [0:100] #LogProxy Func:logProxy_dwd2Plot("DWD","TTT_",$from,$to,0,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","Tx",$from,$to,18,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","Tn",$from,$to,6,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","SunD3_",$from,$to,0,"day",(-3*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","RR3c_",$from,$to,0,"day",(-3*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","FX1_",$from,$to,0,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","R600_",$from,$to,0,"day",(-3*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","Neff_",$from,$to,0,"day") #LogProxy ConstX:TimeNow(),0,100 #LogProxy ConstY:0 plot "<IN>" using 1:2 axes x1y2 title 'T' ls l0 lw 2 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y2 title 'Tmax' ls l0dot lw 2 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y2 title 'Tmin' ls l0dot lw 2 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 title 'Sonne' ls l4fill lw 1 with lines,\ "<IN>" using 1:2 axes x1y1 title 'Regenmenge' ls l2fill lw 1 with steps,\ "<IN>" using 1:2 axes x1y3 title 'Wind' ls l1 lw 1 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 title 'Regen' ls l5fill lw 1 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 title 'Wolken' ls l6fill lw 1 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 notitle ls l5 lw 4 with lines,\ "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 1 with lines
Verwendet man dagegen eine Auflösung von 1 Stunde, sind folgende LogProxy-Einträge erforderlich:
#LogProxy Func:logProxy_dwd2Plot("DWD","TTT_",$from,$to,0,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","Tx",$from,$to,18,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","Tn",$from,$to,6,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","SunD1_",$from,$to,0,"day",(-1*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","RR1c_",$from,$to,0,"day",(-1*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","FX1_",$from,$to,0,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","R101_",$from,$to,0,"day",(-0.5*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","Neff_",$from,$to,0,"day") #LogProxy ConstX:TimeNow(),0,100 #LogProxy ConstY:0
Für die Darstellung der nächsten 24 Stunden mit einer Auflösung von 1 Stunde nimmt man folgende GPlot-Konfiguration:
set terminal png transparent size <SIZE> crop set output '<OUT>.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" set xlabel " " set title '<L1>' set ytics set y2tics set y3tics set grid xtics y2tics set ylabel "Regen [mm]" set y2label "Temperatur [°C]" set y3label "Wolken/Regen/Sonne [%]" set y3range [0:100] #LogProxy Func:logProxy_dwd2Plot("DWD","TTT_",$from,$to,0,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","SunD1_",$from,$to,0,"day",(-1*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","RR1c_",$from,$to,0,"day",(-1*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","FX1_",$from,$to,0,"day") #LogProxy Func:logProxy_dwd2Plot("DWD","R101_",$from,$to,0,"day",(-0.5*3600)) #LogProxy Func:logProxy_dwd2Plot("DWD","Neff_",$from,$to,0,"day") #LogProxy ConstY:0 plot "<IN>" using 1:2 axes x1y2 title 'T' ls l0 lw 2 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 title 'Sonne' ls l4fill lw 1 with lines,\ "<IN>" using 1:2 axes x1y1 title 'Regenmenge' ls l2fill lw 1 with steps,\ "<IN>" using 1:2 axes x1y3 title 'Wind' ls l1 lw 1 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 title 'Regen' ls l5fill lw 1 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y3 title 'Wolken' ls l6fill lw 1 with quadraticSmooth,\ "<IN>" using 1:2 axes x1y2 notitle ls l2 lw 2 with lines
Je nachdem, welche Auflösung man verwendet, werden unterschiedliche Readings des DWD_OpenData-Devices benötigt. Diese sind in den LogProxy-Zeilen in der GPlot-Konfigurationsdatei zu finden und müssen auf jeden Fall dem Attribut forecastProperties des DWD_OpenData-Device hinzugefügt werden.
Viele Detaileinstellungen des Meteogramms lassen sich individualisieren. Man kann z.B. mehr oder weniger Daten anzeigen und zumindest für heute auch aktuelle Messwerte hinzufügen.
Hier ein Beispiel für ein Meteogramm über 4 Tage mit 3 Stunden Auflösung:
Beispiel für die Einrichtung eines Weblinks
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit FHEMWEB steht das Modul 98_DWD_OpenData_Weblink.pm zur Verfügung.
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis fhem/FHEM kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit wget) oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie °C falsch angezeigt.
Anschließend kann in die Konfiguration z.B. folgendes eingetragen werden:
define DWD_Weblink_Generator DWD_OpenData_Weblink
attr DWD_Weblink_Generator IODev DWD
attr DWD_Weblink_Generator forecastDays 4
# refreshRate nur dann setzten, wenn der Browser Java-Script beherrscht:
attr DWD_Weblink_Generator refreshRate 900
define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH("DWD_Weblink_Generator") }
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der weblink selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut forecastProperties des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen.
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut refreshRate auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert.
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von 98_DWD_OpenData_Weblink.pm, die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann.
Hier ein Ausschnitt aus der Darstellung des Weblinks mit FHEMWEB:
Beispiel für die Einbindung auf einer Webseite außerhalb von FHEM
Für manche Anwendungsfälle, etwa die Ansicht in FTUI, ist es erforderlich, das mit dem DWD_Weblink_Generator erzeugte Bild an anderer Stelle in eine Webseite einzubinden. Dazu kann man folgende Schritte verwenden.
Zunächst wird ein statisches CSS-Stylesheet erzeugt, etwa in der Datei ftui_weather.css im Unterverzeichnis css. Dorthin werden die ganzen CSS-Klassen geschrieben, die der Webbrowser benötigt, um aus den Daten des DWD_Weblink_Generator eine Tabelle zu machen (siehe den etwas länglichen Code am Ende dieses Abschnitts).
Dann ist zunächst dafür zu sorgen, dass im Header der Webseite, die später die Wettervorhersage anzeigen soll, dieses Stylesheet eingebunden wird. Dazu muss in den Header die Zeile
<link rel="stylesheet" href="css/ftui_weather.css"/>
eingetragen werden.
Der zweite Schritt besteht darin, ebenfalls in den Header der betreffenden Webseite ein paar Zeilen JavaScript einzubinden, die dem Holen der Daten dienen:
<script>
function getDWDOpenDataWeblink() {
var fwcsrf = "<HIER DER csrf-Token DES ENTFERNTEN FHEM-SERVERS>";
$. get ("http://<HIER DIE ADRESSE DES ENTFERNTEN FHEM-SERVERS>:8083/fhem?cmd=get%20DWD_Weblink_Generator%20horizontalForecast&XHR=1&fwcsrf=" + fwcsrf,
function (forecastElements) {
$("#DWD_OpenData_Weblink").html(forecastElements);
});
}
function getdata() {
getDWDOpenDataWeblink();
setInterval(getDWDOpenDataWeblink, 900000);
$(window).on("focus", getDWDOpenDataWeblink);
};
</script>
Der dritte Schritt besteht darin, auf der betreffenden Webseite einen Ort zu definieren, an welchen das Wettervorhersagebild geschoben wird, z.B.
<div id="DWD_OpenData_Weblink" style="position:absolute; left:10px;top:500px; width:600px; height:200px; float:left; overflow-y:hidden;overflow-x:auto;"></div>
Der letzte Schritt sorgt dafür, dass die oben definierte JavaScript-Funktion beim Laden der Webseite auch aufgerufen wird. Dazu muss ein entsprechendes Attribut im body-Tag der Seite eingebaut werden:
<body onload="getdata()">
Nachstehend nun der etwas längliche CSS-Code für das statische Stylesheet:
/* weather table with fixed column width */
.weatherForecast {
display: table;
table-layout: fixed;
column-gap: 40px;
}
/* weather table header row */
.weatherHeaderRow {
display: table-header-group;
white-space: nowrap;
}
/* weather table data row */
.weatherDataRow {
display: table-row-group;
}
/* weather table data cells */
#weatherFontBold {
font-weight: bold;
}
.weatherWeekday {
display: table-cell;
min-width: 80px;
text-align: center;
vertical-align: middle;
}
.weatherCondition {
display: table-cell;
position: relative;
top: -4px;
text-align: center;
vertical-align: middle;
font-size: 80%;
word-wrap: break-word;
}
.weatherTemperature {
display: table-cell;
text-align: center;
vertical-align: middle;
font-size: 100%;
white-space: nowrap;
}
.weatherWind {
display: table-cell;
text-align: center;
vertical-align: middle;
font-size: 80%;
padding-top: 3px;
}
/* weather table condition icon cell */
.weatherIcon {
display: table-cell;
position: relative;
text-align: center;
}
/* weather icon */
.weatherIcon img {
width: 100%;
height: auto;
position: relative;
}
/* embedded alert icon with pointer support */
.weatherAlertIcon {
position: absolute;
top: 5px;
right: 5px;
width: 25px;
height: 22px;
background-size: 25px 22px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAMAAADM4ogkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NjcyOSwgMjAxMi8wNS8wMy0xMzo0MDowMyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDEyLjAgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1RjU1NzJBRDMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1RjU1NzJBRTMyRTcxMUU1QTk4MkI0RTkwODEwODQ1QSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjVGNTU3MkFCMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjVGNTU3MkFDMzJFNzExRTVBOTgyQjRFOTA4MTA4NDVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+oFydjAAAAwBQTFRF9fX267W51Csy9d7c1VBV9uPc/vz89+nl5YB/2Flk2mZp1Cgv0Csw5pWR7K2t1Soy1Cow7b6y0iUr+/r61jI54X+A+uvq21xV44qO/fj400tU1kxG3nNx2mJp34Bz/Pj2a2tr4Ht91S43fn5+1jA31S0y0iYu1TA1/ff3+/TxEhIS3W1u1jA010Q++efj1kVH1Tk+gYGB6qWh4oWEtra21TI48sjH1VVc1tbW1jY22ltd4YF/1kFHl5eX/vz7/Pz84nZt+evt9+Tm2mNu1Sw14YSD1Ss04YKC0isv4X5/0zc21CUu8cnL0jA20jAz22xy1jE422Zv1i800isw1Cgx11xjKysr1FFZ4X190iQsGRkZ0jY+1TE41Cww0y0y0ykt1i431i4z0y800ikvPz4/AAAA////DQwM1TI30yYs1TE31TA21TE21S401S801S810ycs//7+1TA3///+/v791TI2/v//0Sov0iYt0yYt6urqkZGR1TM40ycu1S414ODg4YB3+/Hw7bK0/vv78fHxh4eH+OPf0i8w1DI30icu1y843Zia/PX13Nvb6aWZ4YKE+fDv21RT00E83G5y3m9x7tDF3Gdu99fW1EJK1ktK3t7e5I+R4oeH3WNp3oCF+vH16ZOJ1Sw27cG31i018dDL4qOf3Wde7Kqe+O7m2ERH+e3o+u/t4YuY/Pb15IqG5p2R4np52TA82mhx2V1p3mpx5oWL66uiRkZG4YOR/v7+1ygz1TxC8dDV9dHS2VJL1CUw8by79+Hg7bq3vr6+9dnR1Tc49d/X11le77yv22hl2lVY+Ofo33540icspqan+/f49N/h5J6m2HB7zczN3nZ88c3FsrKz3HZ74ICC4YGA1oJy10JD+Onj8c3J1Dk71T494oaE4HpxNTU14XRz7Ozs7+/vcG9v+/bz/Pj1/fr3IiIi676/5IJx4Hpr6amn56On6aGd2mlu4X2A22Vm2WFk1jI33GNk+/Ds2VJU2FZW8/Pz78jD3V1v55iY3W1x////C1yJRAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAMKSURBVHjajNEFWBNxGAbwOXEoUzYnqCgGuPMUUFE8sRuwgDlUEJmK8z6/XWyEEjrswu7u7u7u7u4u7G7FWxoj/J6L9/7v77nnQpTpMM7XFkocV0UOK2VKbkt3/R+4KY0Zlnw8d7ikBeu9VroRcoXPg5F1Y5Mn5wYPaRnGqOxMfPbIGXZfFMxxJGtg0lxzhoWlKpYfSrCd9f4rc4JPKs1l9B1aeabGoLRQTnBxG8T2K2DwLV7FRVTOHi47yKKmxGyAagoGxb7x2cLSMuS0eZIAMopJUaWtkR3M1yUBpe8lkuoj4WYYm8Bf98gaxjdsSik7toKydPQ0OKEzUnGuWcOLWgZPXoCe3Wi6HlS+zVMG/35Zwfq7eqO+wxk4T9N0OYDXKQylnZ4VnKdxM5bfAtDTh6arAlT4IldxXYo6woyS3hwxpRHA12ia7gUA3yKUKL8f7wCPiClMOSsA0VPTMwIkeeoQm+39F1asZECZ02kBFGlH06eEM+Rt0RvFHyX/wNUy7JGex9Q3EGB1U4BCLVXK9D1/wxu1lJS8lMTc36Pp/eZQcaoM9Us9/oSJL8QUGbrDXMNmOvqBJe3TxqC22p/wgIbBlrMsLZSju1pT93dSZDsW/Q3rF/NG3r+xte4zqKY1QY0IBuVvwQ4LazFGUTzRVhexJziahkzyTht8PM6AwXUbWbutj3za2W+5IIxEovYAKxwlww+KV7buYTfzL7TODOGry/tb4KdaCSg/VsFWDfSx/ELLLK9CILl9hBnOEaOq4DN7BZe6lv36++plJ3ST/zDBfEOEN6udBNnNWDHFhTpnihIbNkXKUNfLyyuqeciVOwFvr7oHrApqHhTiPjog6EqdNVFVDIji/JmiiYQbopFM3R0XF6fT6VJ15jFFnUJhSqQRETV5RXfnGykhMea9B2M624ezBaOmuKiv1GDg9TxJ8sIxltB7E0QsT/BqpdrPT9g4P7VaTcZKL4vGDP/psq71BpdSLj9nTmod3mTC+HDfN+FN2jodjlwfGRnoFNg2cH2B7+ca/xJgAFL1l3PxpIx4AAAAAElFTkSuQmCC);
}
.weatherAlertIcon:hover {
opacity: 0.7;
}
.weatherAlertIcon:focus {
opacity: 1.0;
}
/* opaque white background for alerts dialog */
.weatherOverlay {
display: none;
position: fixed;
z-index: 1;
opacity: 0.2;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
}
.weatherAlertIcon:focus .weatherOverlay {
display: block;
}
/* alerts dialog box */
[class ^= weatherAlertBox] {
display: none;
position: absolute;
z-index: 2;
opacity: 1;
top: 0;
border: 3px solid white;
border-radius: 3px;
box-shadow: 0px 0px 6px 4px #666;
background: #EEE;
}
.weatherAlertIcon:focus .weatherAlertBoxLeft {
display: block;
right: -268px;
}
.weatherAlertIcon:focus .weatherAlertBoxCenter {
display: block;
left: -178px;
}
.weatherAlertIcon:focus .weatherAlertBoxRight {
display: block;
left: -312px;
}
/* alerts dialog close button */
.weatherAlertsClose {
position: absolute;
top: -12px;
right: -13px;
border-radius: 12px;
box-shadow: 1px 1px 3px #666;
line-height: 21px;
width: 21px;
background: #606061;
text-align: center;
text-decoration: none;
font-family: Sans-serif;
font-weight: bold;
color: white;
}
.weatherAlertsClose:hover {
opacity: 0.8;
}
/* alerts dialog title */
.weaterAlertsTitle {
font-weight: bold;
color: black;
}
/* alert messages */
[class ^= weaterAlertMessage] {
float: left;
text-align: left;
white-space: nowrap;
}
.weaterAlertMessage p {
white-space: normal;
}