DWD OpenData

Aus FHEMWiki
Zur Navigation springen Zur Suche springen
Info blue.png
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 Beitrag).


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.

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:

DWDODmeteogram4d3h.png

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: DWDODweblink.png

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;
}