Mein Ziel war es, Wetterwarnungen für eine bestimmte Region auf einer Webseite (www.merkenonline.de Info-Plattform für den Ort Düren-Merken) darzustellen. Glücklicherweise bietet der Deutsche Wetterdienst Unwetterwarnung in verschiedenen Varianten kostenlos an. Mein erster Ansatz war das Parsen der Unwetterdaten im Json-Format:
http://www.dwd.de/DWD/warnungen/warnapp/json/warnings.json
Daten-Beispiel:
{ "time":1484853036000, "warnings":{ "105512000":[{ //Warncell-ID des Landkreises "start":1484841600000, "end":1484910000000, "regionName":"Stadt Bottrop", "level":2, "type":5, "altitudeStart":null, "event":"FROST", "headline":"Amtliche WARNUNG vor FROST", "description":"Es tritt mäßiger Frost zwischen -4 °C und -9 °C auf.", "altitudeEnd":null, "stateShort":“NRW“, "instruction":"", "state":"Nordrhein-Westfalen" }] }, "vorabInformation":{ ## gleiches Format ## } }
Tabelle mit Warncell-IDs für die Landkreise:
http://www.dwd.de/DE/leistungen/gds/help/warnungen/cap_warncellids_csv.csv?__blob=publicationFile&v=4
Der DWD liefert genauer gesagt im JSONP-Format und nicht im reinen JSON-Format. Der einzige Unterschied liegt jedoch darin, dass das reine JSON in „warnWetter.loadWarnings(‚“ und „);“ eingeschlossen ist.
Mit folgendem Script werden die Daten gelesen und entsprechend formatiert ausgegeben.
JSONP-Daten einlesen, JSON extrahieren und in Array speichern:
$jsonp = file_get_contents("http://www.wettergefahren.de/DWD/warnungen/warnapp/warnings.json"); $json = extract_unit($jsonp, 'warnWetter.loadWarnings(', ');'); $alert_list = json_decode($json, true); $relevant_alerts = $alert_list["warnings"]["105358000"]; $relevant_prealerts = $alert_list["vorabInformation"]["105358000"]; if($relevant_alerts == null) $relevant_alerts = array(); if($relevant_prealerts == null) $relevant_prealerts = array(); $relevant_alerts = array_merge($relevant_prealerts, $relevant_alerts);
Array nach Warnstufe sortieren:
$sortArray = array(); foreach($relevant_alerts as $key => $array) { $sortArray[$key] = $array['level']; } array_multisort($sortArray, SORT_ASC, SORT_NUMERIC, $relevant_alerts);
Titelzeile ausgeben wenn Warnungen vorliegen:
$numberOfAlerts = count($relevant_alerts); if($numberOfAlerts == 1) { echo "<center><h3>Es liegt 1 Warnmeldung vor!</h3></center>"; } elseif($numberOfAlerts > 0) { echo "<center><h3>Es liegen ".count($relevant_alerts)." Warnmeldungen vor!</h3></center>"; } else { exit(); }
Warnungen ausgeben (Warnungstext mit Gültigkeit im Tooltip):
echo "<ul>"; $cnt = 0; foreach($relevant_alerts as $alert) { $event = $alert['event']; $headline = $alert['headline']; $description = $alert['description']; $regionName = $alert['regionName']; $level = $alert['level']; $start = utf8_decode(date('d.m.Y H:i', substr($alert['start'], 0, 10))); $end = utf8_decode(date('d.m.Y H:i', substr($alert['end'], 0, 10))); echo "<li style='padding-left: 5px;background: transparent'><span class='tooltip'><img src='$level.png' width='18' height='18' /> $event<br /> <span class='tooltiptext'>$headline für die $regionName<br />Gültig von $start bis $end<br />$description</span></span> </li>"; $cnt += 1; } echo "</ul>";
extract_unit Funktion um reines JSON zu extrahieren:
function extract_unit($string, $start, $end) { $pos = stripos($string, $start); $str = substr($string, $pos); $str_two = substr($str, strlen($start)); $second_pos = stripos($str_two, $end); $str_three = substr($str_two, 0, $second_pos); $unit = trim($str_three); // remove whitespaces return $unit; } ?>
CSS-Style:
.tooltip .tooltiptext { visibility: hidden; width: 600px; background-color: black; color: #fff; text-align: left; border-radius: 6px; padding: 5px; /* Position the tooltip */ position: absolute; z-index: 1; } .tooltip:hover .tooltiptext { visibility: visible; } .tooltip { vertical-align: top; }
Fazit:
Das ganze funktioniert zwar wie gewünscht, nur leider musste ich feststellen, dass der DWD in dieser Variante nur Warnungen auf Landkreisebene zur Verfügung stellt. Das heißt, wenn in einer Gemeinde im Kreis eine Warnung besteht, wird diese für den kompletten Landkreis angezeigt. Seit Mitte letzten Jahres bietet der DWD deswegen auch Unwetterwarnungen auf Gemeindeebene an, jedoch nicht im JSON-Format, sondern per CAP-Dateien auf einem FTP-Server. Ich habe somit ein neues Ziel gefunden. Mehr dazu im nächsten Beitrag.
Hier geht es zum nächsten Beitrag: Wetterwarnungen vom DWD – Alternative: GDS (FTP)
Klasse Anleitung! Danke für die Arbeit!
das ganze in html
https://dj0001.github.io/DWD/
Mittlerweile wird das json File auch auf Gemeindeebene angeboten (https://www.dwd.de/DE/wetter/warnungen_aktuell/objekt_einbindung/objekteinbindung_node.html#doc582840bodyText9)
Das müsste meiner Meinung nach einfacher sein als das Basteln mit den ZIP-Dateien.
Hallo Alex,
danke für deine Rückmeldung.
Soweit ich das gesehen habe, ist die JSONP-Datei auf Gemeindeebene jedoch nur über den WebFeatureService (WFS) zu bekommen. Ich habe keine Infos gefunden, wie man diesen abfragt.
Ein Vorteil von CAP-Dateien ist die fortlaufende Versionierung von Warnmeldungen. So kann man in Zukunft vielleicht noch eine WarnId mitliefern um das aktualisieren oder Aufheben von Warnungen darzustellen. So wie die Weiterentwicklung vom CAP-standard aussieht, scheint das auch die Zukunft beim DWD zu sein. Durch den OpenData-Server ist es im Vergleich zur FTP-variante ja schon deutlich einfacher geworden. Vor Kurzem wurde vom DWD für Januar ein Update der CAP-Struktur angekündigt. Ich bin gespannt, was dann kommt.
Viele Grüße
eMpTy
Hallo,
ich weiß zwar nicht ob das Interesse noch besteht aber hier ein Beispiel wie man Daten über den WFS (WebFeatureService) abfrägt:
https://maps.dwd.de/geoserver/dwd/wfs?SERVICE=WFS&REQUEST=GetCapabilities
-> gibt Auskunst über die möglichkeiten des Services
https://maps.dwd.de/geoserver/dwd/wfs?service=WFS&request=DescribeFeatureType&version=2.0.0&typeName=dwd:Warnungen_Gemeinden&namespace=xmlns(dwd=http://www.dwd.de)
-> beschreibt die Attributfelder für eine Gemeinde
https://maps.dwd.de/geoserver/dwd/wfs?service=WFS&request=GetFeature&typeName=dwd:Warnungen_Gemeinden&srsName=EPSG:4326&count=3
-> so bekommt man maximal 3 Gemeinden
https://maps.dwd.de/geoserver/dwd/wfs?service=WFS&request=GetFeature&typeName=dwd:Warnungen_Gemeinden&srsName=EPSG:4326&count=3&outputFormat=application/json
-> so bekommt man die Daten als JSON
https://maps.dwd.de/geoserver/dwd/wfs?service=WFS&request=GetFeature&typeName=dwd:Warnungen_Gemeinden&srsName=EPSG:4326&&outputFormat=application/json&cql_filter=AREADESC='Karlsfeld‚
-> so frägt man Informationen zur Gemeinde ‚Karlsfeld‘ ab
Mehr Informationen zum WFS gibt es hier:
– http://docs.geoserver.org/latest/en/user/services/wfs/reference.html
– http://www.opengeospatial.org/standards/wfs
Grüße
Mathias
Hallo Matthias,
vielen Dank für die Zusammenstellung der Links!
Ich habe mir das Thema mal etwas genauer angeschaut und festgestellt, dass das Holen der Warnung per JSON darüber sehr praktisch sein kann, aber da der GeoServer so ein festgesetzter Standard ist und nahezu für alles eingesetzt werden kann, finde ich, dass man da sehr schwer durchblickt, was alles geht und was nicht (ohne sich die komplette Anleitung durchzulesen).
Vielleicht wird das in Zukunft noch interessant, da es zur Zeit noch entscheidende Nachteile gibt (Auszug der Dienstbeschreibung des DWD):
– Es besteht derzeit kein Anspruch auf Verfügbarkeit dieser Dienste.
– Auch im Hochlastfall oder bei Wartungsarbeiten können die Server ohne Vorankündigung für eine gewisse Zeit nicht zur Verfügung stehen.
– Bitte setzen Sie die Abrufintervalle nicht unter 5 Minuten, damit der Webservice nicht durch zu hohe Abrufraten unnötig belastet wird.
– Produkte, Produktnamen oder Pfade können jederzeit vom Deutschen Wetterdienst angepasst werden.
Gruß
eMpTy
Hallo Mathias,
vielen Dank für die Links. Der JSON-Abruf für eine Gemeinde ist sehr interessant. Weißt du evtl., ob es auch eine Liste der verfügbaren Gemeinden gibt? Der Abruf mit Gemeindename liefert ja ein leeres Array und man weiß in dem Fall nicht, ob keine Warnungen vorhanden sind oder ob man einen Tippfehler im Gemeindename hat (oder der DWD die Gemeinde anders schreibt). Vielen Dank.
Ronny
Hat sich erledigt. Bei der Abfrage kann in der URL auch die WARNCELLID verwendet werden (statt AREADESC).
Dazu kann man die Warncell-Liste des DWD als Basis verwenden:
https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.html
Hier ein ganz simples PHP-Beispiel, wie man Wetterwarnungen auf Gemeindebene mittels der WARNCELLID über den DWD Geoserver mit JSON abrufen und darstellen kann:
features as $warning)
{
echo $warning->properties->HEADLINE .“;
echo ‚Gueltig von ‚.date(‚d.m.Y H:i‘, strtotime(substr($warning->properties->ONSET,0,20))).‘ Uhr bis ‚.date(‚d.m.Y H:i‘, strtotime(substr($warning->properties->EXPIRES,0,20))).‘ Uhr‘;
echo $warning->properties->DESCRIPTION .“;
}
?>
Da wurde scheinbar die Hälfte des Scripts beim abschicken verschluckt:
features as $warning)
{
echo $warning->properties->HEADLINE .“;
echo ‚Gueltig von ‚.date(‚d.m.Y H:i‘, strtotime(substr($warning->properties->ONSET,0,20))).‘ Uhr bis ‚.date(‚d.m.Y H:i‘, strtotime(substr($warning->properties->EXPIRES,0,20))).‘ Uhr‘;
echo $warning->properties->DESCRIPTION .“;
}
?>
Hi zusammen, ist schon eine Weile her aber kann mir jemand helfen bei dem Code? Ich bekomme es nicht hin das ich was angezeigt bekomme. Funktioniert der Code den noch? Eventuell kann mir jemand die Datei als fertige zip zur Verfügung stellen. Ich hoffe auf Hilfe.
Hallo Dennis,
grundsätzlich wüsste ich nicht, warum der Code nicht mehr funktionieren sollte. Das Format, was von der JSONP-Datei kommt, ist noch immer identisch. Vielleicht gibt es zur Zeit keine Meldungen oder die Warncell-ID, die du angegeben hast, stimmt nicht.
Gruß
eMpTy
Hallo,
vielen Dank! Eine Frage, wie kann man noch nach der Höhe filtern?
Also z. B. nur Warnungen unter 500 Metern anzeigen?
Grüße
Max
Hallo Max,
die Werte altitudeStart und altitudeEnd geben (wenn vorhanden) an, auf welche Höhenlagen sich die Meldung bezieht.
Viele Grüße
eMpTy
Hallo, das ist ja cool!
Aber kann ich das auch irgendwie in dem Script nutzen? So dass mir z. B. nur Warnungen <1000 Metern angezeigt werden? Kann ich da noch irgnedwo ein if <1000 einfügen?
Grüße
Max