FHEM Tutorial-Reihe - Part 42: Regenradar integrieren
Einer meiner meist genutzen Smartphone-Apps ist Regenradar. Dort sieht man nicht nur ob es gerade regnet, sondern kann auch abschätzen wann es aufhört oder zu regnen beginnt. Gerade wenn ich eine längere Runde mit dem Hund plane, hat mich das schon oft vor dem Regen bewahrt.
Was wird benötigt?
- Eine FHEM-Installation
Video
Befehle
Angefangen habe ich mit dem einfachsten Fall: Einem Bild über einen weblink. Da es sich um ein animiertes gif handelt, muss man hier nichts weiter tun.
define OUT_RegenRadar weblink image http://images2.wetterdienst.de/maps/radar/Radarfilm_West.gif
Doch das war mir nicht schön genug. Ich wollte mehr! Also habe ich mich hingesetzt, und eine eigene Funktion geschrieben, welche die URL von WetterOnline zusammenbaut. Hier haben wir verschiedene Platzhalter, welche durch Jahr, Monat, Tag, Stunde und Minute ersetzt werden müssen. Die Schwierigkeit hierbei war, dass man natürlich nur 5-Minuten-Abstände realisieren darf. Ein bild zu 12:34 oder 15:18 existiert also nicht.
define OUT_RegenRadarNRW weblink htmlCode {regenRadarHtml()}
sub regenRadarHtml() {
my $now = DateTime->now();
return sprintf(
'<img src="https://www.wetteronline.de/?pid=p_radar_map&ireq=true&src=wmapsextract/vermarktung/global2maps/%d/%02d/%02d/NRW/grey_flat/%d%02d%02d%02d%02d_NRW.png"; />',
$now->year(),
$now->month(),
$now->day(),
$now->year(),
$now->month(),
$now->day(),
$now->hour(),
floor($now->minute() / 5) * 5
);
}
Dann wurde der Code immer weiter ausgebaut (wie im Video zu sehen). Dabei habe ich festgestellt, dass für die Zukunft (also die eigentliche Prognose) andere URLs zu den Bildern genutzt werden müssen. Weiterhin kann man nun noch einen diff als Parameter übergeben. Das sieht in meinem Fall so aus, dass man hier z.B. -10 schreiben kann (Regenradar von vor 10 Minuten), 0 für jetzt gerade übergeben kann oder auch positive Werte für eine Prognose holen kann.
sub regenRadarHtml($) {
my ($diff) = @_;
my $now = DateTime->now()->add(minutes => (floor($diff / 5) * 5));
my $minute = (floor($now->minute() / 5) * 5);
if ($diff <= 0) {
return sprintf(
'<img src="https://www.wetteronline.de/?pid=p_radar_map&ireq=true&src=wmapsextract/vermarktung/global2maps/%d/%02d/%02d/NRW/grey_flat/%d%02d%02d%02d%02d_NRW.png"; />',
$now->year(),
$now->month(),
$now->day(),
$now->year(),
$now->month(),
$now->day(),
$now->hour(),
$minute
);
} else {
return sprintf(
'<img src="https://www.wetteronline.de/?pid=p_radar_map&ireq=true&src=wmapsextract/vermarktung/prog2maps/short_range/%d/%02d/%02d/NRW/grey_flat/%d%02d%02d%02d%02d_NRW.png"; />',
$now->year(),
$now->month(),
$now->day(),
$now->year(),
$now->month(),
$now->day(),
$now->hour(),
$minute
);
}
}
Aber da ich eine Animation wollte (wie in den Apps), habe ich noch ein wenig ergänzt. Jetzt werden mehrere Bilder nacheinander geladen und in einen Container gepackt. Den Rest erledigt dann JavaScript (bisher noch etwas unsauber gelöst). Dazu werden dann alle Bilder versteckt, mit Nummern versehen und nacheinander mit einem Interval von einer Sekunde dargestellt. Ziemlich einfach, aber auch längst nicht perfekt.
Wie gesagt habe ich schon überlegt, ob es nicht Sinn macht daraus eine FHEM-Extension zu machen. Dann könnte man einfach die Region übergeben und der Rest läuft dann vollautomatisch ab. Noch cooler wäre es natürlich, wenn man die Bilder analysieren könnte um zu ermitteln ob es bald anfängt zu regnen. Und vor allem wann. Finde ich sehr spannend. Schreibt doch einfach mal was ihr davon haltet.
sub regenRadarHtml($) {
my ($diff) = @_;
my $now = DateTime->now()->add(minutes => (floor($diff / 5) * 5));
my $minute = (floor($now->minute() / 5) * 5);
if ($diff <= 0) {
return sprintf(
'<img class="image-slide" src="https://www.wetteronline.de/?pid=p_radar_map&ireq=true&src=wmapsextract/vermarktung/global2maps/%d/%02d/%02d/NRW/grey_flat/%d%02d%02d%02d%02d_NRW.png"; />',
$now->year(),
$now->month(),
$now->day(),
$now->year(),
$now->month(),
$now->day(),
$now->hour(),
$minute
);
} else {
return sprintf(
'<img class="image-slide" src="https://www.wetteronline.de/?pid=p_radar_map&ireq=true&src=wmapsextract/vermarktung/prog2maps/short_range/%d/%02d/%02d/NRW/grey_flat/%d%02d%02d%02d%02d_NRW.png"; />',
$now->year(),
$now->month(),
$now->day(),
$now->year(),
$now->month(),
$now->day(),
$now->hour(),
$minute
);
}
}
sub regenRadarMultipleHtml($$) {
my ($diff, $count) = @_;
my $ident = 'slider-' . int(rand(100));
my $ret = '';
for (my $i = 0; $i <= $count * 5; $i += 5) {
$ret .= regenRadarHtml($diff + $i);
}
return '
<script type="text/javascript">
jQuery(document).ready(function ($) {
// Image Slider
$("#' . $ident . ' .image-slide").each(function(index) {
$(this).attr("data-index", index);
if (index > 0) {
$(this).hide();
} else {
$(this).addClass("current");
}
});
setInterval(
function() {
var nextSlideId = parseInt($("#' . $ident . ' .image-slide.current").attr("data-index")) + 1;
var nextSlide = $("#' . $ident . ' .image-slide[data-index=" + nextSlideId + "]");
if (nextSlide.length == 0) {
nextSlide = $("#' . $ident . ' .image-slide[data-index=0]");
}
$("#' . $ident . ' .image-slide").each(function(index) {
$(this).removeClass("current");
$(this).hide();
});
nextSlide.show();
nextSlide.addClass("current");
},
1000
);
});
</script>
<div class="image-slides" id="' . $ident . '">' . $ret . '</div>';
}
Zusätzlich kann man auch noch ein Modul der Unwetterzentrale nutzen. Hier bekommt man aber nur Infos, ob gerade schlimmere Dinge bevorstehen. Also Regen gehört nicht dazu soweit ich weiß (nur Starkregen - Unwetter eben). Dies habe ich aus dem Video wieder rausgeschnitten, weil es nicht sonderlich spektakulär ist.
define OUT_Unwetterzentrale UWZ DE 33102 300
define OUT_UnwetterzentraleDetailiert weblink htmlCode {UWZAsHtml("OUT_Unwetterzentrale")}
define OUT_UnwetterzentraleKarteLand weblink htmlCode {UWZAsHtmlKarteLand("OUT_Unwetterzentrale", "nordrhein-westfalen")}
define OUT_UnwetterzentraleKarteMovie weblink htmlCode {UWZAsHtmlMovie("OUT_Unwetterzentrale", "niederschlag-wolken-de")}