From ca2eacc15886d13601b2b08a42c57b97a554a356 Mon Sep 17 00:00:00 2001 From: betateilchen Date: Fri, 3 Oct 2025 16:05:29 +0000 Subject: [PATCH] 77_UWZ.pm: interims version without smartmatach/given/when git-svn-id: https://svn.fhem.de/fhem/trunk@30346 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/betateilchen/77_UWZ.pm | 3398 +++++++++++++++++++++++++++ 1 file changed, 3398 insertions(+) create mode 100644 fhem/contrib/betateilchen/77_UWZ.pm diff --git a/fhem/contrib/betateilchen/77_UWZ.pm b/fhem/contrib/betateilchen/77_UWZ.pm new file mode 100644 index 000000000..ca65ceb6b --- /dev/null +++ b/fhem/contrib/betateilchen/77_UWZ.pm @@ -0,0 +1,3398 @@ +#################################################################################################### +# +# 77_UWZ.pm +# +# (c) 2015-2016 Tobias D. Oestreicher +# (c) 2017-2021 Marko Oldenburg +# +# Special thanks goes to comitters: +# - Marko Oldenburg (fhemdevelopment at cooltux dot net) +# - Hanjo (Forum) patch for sort by creation +# - cb1 patch Replace Iconv with native perl encode() +# - KölnSolar (Markus) new write UWZAsHtml with smaler Code +# +# Storm warnings from unwetterzentrale.de +# inspired by 59_PROPLANTA.pm +# +# Copyright notice +# +# This script is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU General Public License can be found at +# http://www.gnu.org/copyleft/gpl.html. +# A copy is found in the text file GPL.txt and important notices to the license +# from the author is found in LICENSE.txt distributed with these scripts. +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# This copyright notice MUST APPEAR in all copies of the script! +# +# +# +# $Id: 77_UWZ.pm 25306 2021-12-06 05:27:48Z CoolTux $ +# +#################################################################################################### +# also a thanks goes to hexenmeister +############################################## + +package FHEM::UWZ; + +use strict; +use feature qw/say switch/; +use warnings; +use POSIX; +use GPUtils qw(GP_Import GP_Export); +use FHEM::Meta; +use Encode qw(encode_utf8); + +# use Data::Dumper; # Debug only + +no + if $] >= 5.017011, + warnings => 'experimental::lexical_subs'; + +my $missingModul; +eval 'use LWP::UserAgent;1' or $missingModul .= 'LWP::UserAgent '; +eval 'use LWP::Simple;1' or $missingModul .= 'LWP::Simple '; +eval 'use HTTP::Request;1' or $missingModul .= 'HTTP::Request '; +eval 'use HTML::Parser;1' or $missingModul .= 'HTML::Parser '; +eval 'use Encode::Guess;1' or $missingModul .= 'Encode::Guess '; + +require 'Blocking.pm'; +require 'HttpUtils.pm'; + +use vars qw($readingFnAttributes); +use vars qw(%defs); + +# try to use JSON::MaybeXS wrapper +# for chance of better performance + open code +eval { + require JSON::MaybeXS; + import JSON::MaybeXS qw( decode_json encode_json ); + 1; +}; + +if ($@) { + $@ = undef; + + # try to use JSON wrapper + # for chance of better performance + eval { + + # JSON preference order + local $ENV{PERL_JSON_BACKEND} = + 'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP' + unless ( defined( $ENV{PERL_JSON_BACKEND} ) ); + + require JSON; + import JSON qw( decode_json encode_json ); + 1; + }; + + if ($@) { + $@ = undef; + + # In rare cases, Cpanel::JSON::XS may + # be installed but JSON|JSON::MaybeXS not ... + eval { + require Cpanel::JSON::XS; + import Cpanel::JSON::XS qw(decode_json encode_json); + 1; + }; + + if ($@) { + $@ = undef; + + # In rare cases, JSON::XS may + # be installed but JSON not ... + eval { + require JSON::XS; + import JSON::XS qw(decode_json encode_json); + 1; + }; + + if ($@) { + $@ = undef; + + # Fallback to built-in JSON which SHOULD + # be available since 5.014 ... + eval { + require JSON::PP; + import JSON::PP qw(decode_json encode_json); + 1; + }; + + if ($@) { + $@ = undef; + + # Fallback to JSON::backportPP in really rare cases + require JSON::backportPP; + import JSON::backportPP qw(decode_json encode_json); + 1; + } + } + } + } +} + +## Import der FHEM Funktionen +#-- Run before package compilation +BEGIN { + + # Import from main context + GP_Import( + qw( + readingsSingleUpdate + readingsBulkUpdate + readingsBeginUpdate + readingsEndUpdate + defs + modules + Log3 + CommandAttr + CommandDeleteReading + readingFnAttributes + AttrVal + ReadingsVal + IsDisabled + gettimeofday + InternalTimer + RemoveInternalTimer + BlockingCall + BlockingKill + init_done + FW_httpheader + HttpUtils_BlockingGet + deviceEvents + contains_string) + ); +} + +#-- Export to main context with different name +GP_Export( + qw( + Initialize + Start + Run + Aborted + Done + ) +); + +my @DEweekdays = + qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag); +my @DEmonths = ( + 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', + 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' +); +my @NLweekdays = qw(zondag maandag dinsdag woensdag donderdag vrijdag zaterdag); +my @NLmonths = ( + 'januari', 'februari', 'maart', 'april', 'mei', 'juni', + 'juli', 'augustus', 'september', 'oktober', 'november', 'december' +); +my @FRweekdays = qw(dimanche lundi mardi mercredi jeudi vendredi samedi); +my @FRmonths = ( + 'janvier', 'février', 'mars', 'avril', 'mai', 'juin', + 'juillet', 'août', 'september', 'octobre', 'novembre', 'decembre' +); +my @ENweekdays = qw(sunday monday thuesday wednesday thursday friday saturday); +my @ENmonths = ( + 'January', 'February', 'March', 'April', 'Mäy', 'June', + 'July', 'August', 'September', 'October', 'November', 'December' +); + +# my $countrycode = 'DE'; +# my $plz = '77777'; +# my $uwz_alert_url = 'https://feed.alertspro.meteogroup.com/AlertsPro/AlertsProPollService.php?method=getWarning&language=de&areaID=UWZ' . $countrycode . $plz; + +######################################## +sub Log { + my $hash = shift; + my $loglevel = shift; + my $text = shift; + + my $MODUL = 'UWZ'; + my $xline = ( caller(0) )[2]; + + my $xsubroutine = ( caller(1) )[3]; + my $sub = ( split( ':', $xsubroutine ) )[2]; + $sub =~ s/UWZ_//; + + my $instName = ( ref($hash) eq 'HASH' ) ? $hash->{NAME} : $hash; + Log3 $instName, $loglevel, "$MODUL $instName: $sub.$xline " . $text; + + return; +} + +######################################## +sub Map2Movie { + my $smap = shift; + + my $uwz_movie_url = "https://www.meteocentrale.ch/uploads/media/"; + my $lmap; + + $smap = lc($smap); + + ## Euro + $lmap->{'niederschlag-wolken'} = + $uwz_movie_url . 'UWZ_EUROPE_COMPLETE_niwofi.mp4'; + $lmap->{'stroemung'} = $uwz_movie_url . 'UWZ_EUROPE_COMPLETE_stfi.mp4'; + $lmap->{'temperatur'} = $uwz_movie_url . 'UWZ_EUROPE_COMPLETE_theta_E.mp4'; + + ## DE + $lmap->{'niederschlag-wolken-de'} = + $uwz_movie_url . 'UWZ_EUROPE_GERMANY_COMPLETE_niwofi.mp4'; + $lmap->{'stroemung-de'} = + $uwz_movie_url . 'UWZ_EUROPE_GERMANY_COMPLETE_stfi.mp4'; + + ## CH + $lmap->{'niederschlag-wolken-ch'} = + $uwz_movie_url . 'UWZ_EUROPE_SWITZERLAND_COMPLETE_niwofi.mp4'; + $lmap->{'stroemung-ch'} = + $uwz_movie_url . 'UWZ_EUROPE_SWITZERLAND_COMPLETE_stfi.mp4'; + + ## AT + $lmap->{'niederschlag-wolken-at'} = + $uwz_movie_url . 'UWZ_EUROPE_AUSTRIA_COMPLETE_niwofi.mp4'; + $lmap->{'stroemung-at'} = + $uwz_movie_url . 'UWZ_EUROPE_AUSTRIA_COMPLETE_stfi.mp4'; + + ## NL + $lmap->{'neerslag-wolken-nl'} = + $uwz_movie_url . 'UWZ_EUROPE_BENELUX_COMPLETE_niwofi.mp4'; + $lmap->{'stroming-nl'} = + $uwz_movie_url . 'UWZ_EUROPE_BENELUX_COMPLETE_stfi.mp4'; + + ## FR + $lmap->{'nuages-precipitations-fr'} = + $uwz_movie_url . 'UWZ_EUROPE_FRANCE_COMPLETE_niwofi.mp4'; + $lmap->{'courants-fr'} = + $uwz_movie_url . 'UWZ_EUROPE_FRANCE_COMPLETE_stfi.mp4'; + + ## UK + $lmap->{'clouds-precipitation-uk'} = + $uwz_movie_url . 'UWZ_EUROPE_GREATBRITAIN_COMPLETE_niwofi.mp4'; + $lmap->{'currents-uk'} = + $uwz_movie_url . 'UWZ_EUROPE_GREATBRITAIN_COMPLETE_stfi.mp4'; + + ## IT + $lmap->{'niederschlag-wolken-it'} = + $uwz_movie_url . 'UWZ_EUROPE_ITALY_COMPLETE_niwofi.mp4'; + $lmap->{'stroemung-it'} = + $uwz_movie_url . 'UWZ_EUROPE_ITALY_COMPLETE_stfi.mp4'; + + return $lmap->{$smap}; +} + +######################################## +sub Map2Image { + my $smap = shift; + + my $uwz_de_url = 'https://www.unwetterzentrale.de/images/map/'; + my $uwz_at_url = 'https://unwetter.wetteralarm.at/images/map/'; + my $uwz_ch_url = 'https://alarm.meteocentrale.ch/images/map/'; + my $uwz_en_url = 'https://warnings.severe-weather-centre.co.uk/images/map/'; + my $uwz_li_url = 'https://alarm.meteocentrale.li/images/map/'; + my $uwz_be_url = 'https://alarm.meteo-info.be/images/map/'; + my $uwz_dk_url = 'https://alarm.vejrcentral.dk/images/map/'; + my $uwz_fi_url = 'https://vaaratasot.saa-varoitukset.fi/images/map/'; + my $uwz_fr_url = 'https://alerte.vigilance-meteo.fr/images/map/'; + my $uwz_lu_url = 'https://alarm.meteozentral.lu/images/map/'; + my $uwz_nl_url = 'https://alarm.noodweercentrale.nl/images/map/'; + my $uwz_no_url = 'https://advarsler.vaer-sentral.no/images/map/'; + my $uwz_pt_url = 'https://avisos.centrometeo.pt/images/map/'; + my $uwz_se_url = 'https://varningar.vader-alarm.se/images/map/'; + my $uwz_es_url = 'https://avisos.alertas-tiempo.es/images/map/'; + my $uwz_it_url = 'https://allarmi.meteo-allerta.it/images/map/'; + + my $lmap; + + $smap = lc($smap); + + ## Euro + $lmap->{'europa'} = $uwz_de_url . 'europe_index.png'; + + ## DE + $lmap->{'deutschland'} = $uwz_de_url . 'deutschland_index.png'; + $lmap->{'deutschland-small'} = $uwz_de_url . 'deutschland_preview.png'; + $lmap->{'niedersachsen'} = $uwz_de_url . 'niedersachsen_index.png'; + $lmap->{'bremen'} = $uwz_de_url . 'niedersachsen_index.png'; + $lmap->{'bayern'} = $uwz_de_url . 'bayern_index.png'; + $lmap->{'schleswig-holstein'} = $uwz_de_url . 'schleswig_index.png'; + $lmap->{'hamburg'} = $uwz_de_url . 'schleswig_index.png'; + $lmap->{'mecklenburg-vorpommern'} = $uwz_de_url . 'meckpom_index.png'; + $lmap->{'sachsen'} = $uwz_de_url . 'sachsen_index.png'; + $lmap->{'sachsen-anhalt'} = $uwz_de_url . 'sachsenanhalt_index.png'; + $lmap->{'nordrhein-westfalen'} = $uwz_de_url . 'nrw_index.png'; + $lmap->{'thueringen'} = $uwz_de_url . 'thueringen_index.png'; + $lmap->{'rheinland-pfalz'} = $uwz_de_url . 'rlp_index.png'; + $lmap->{'saarland'} = $uwz_de_url . 'rlp_index.png'; + $lmap->{'baden-wuerttemberg'} = $uwz_de_url . 'badenwuerttemberg_index.png'; + $lmap->{'hessen'} = $uwz_de_url . 'hessen_index.png'; + $lmap->{'brandenburg'} = $uwz_de_url . 'brandenburg_index.png'; + $lmap->{'berlin'} = $uwz_de_url . 'brandenburg_index.png'; + + ## AT + $lmap->{'oesterreich'} = $uwz_at_url . 'oesterreich_index.png'; + $lmap->{'burgenland'} = $uwz_at_url . 'burgenland_index.png'; + $lmap->{'kaernten'} = $uwz_at_url . 'kaernten_index.png'; + $lmap->{'niederoesterreich'} = $uwz_at_url . 'niederoesterreich_index.png'; + $lmap->{'oberoesterreich'} = $uwz_at_url . 'oberoesterreich_index.png'; + $lmap->{'salzburg'} = $uwz_at_url . 'salzburg_index.png'; + $lmap->{'steiermark'} = $uwz_at_url . 'steiermark_index.png'; + $lmap->{'tirol'} = $uwz_at_url . 'tirol_index.png'; + $lmap->{'vorarlberg'} = $uwz_at_url . 'vorarlberg_index.png'; + $lmap->{'wien'} = $uwz_at_url . 'wien_index.png'; + + ## CH + $lmap->{'schweiz'} = $uwz_ch_url . 'schweiz_index.png'; + $lmap->{'aargau'} = $uwz_ch_url . 'aargau_index.png'; + $lmap->{'appenzell_ausserrhoden'} = + $uwz_ch_url . 'appenzell_ausserrhoden_index.png'; + $lmap->{'appenzell_innerrhoden'} = + $uwz_ch_url . 'appenzell_innerrhoden_index.png'; + $lmap->{'basel_landschaft'} = $uwz_ch_url . 'basel_landschaft_index.png'; + $lmap->{'basel_stadt'} = $uwz_ch_url . 'basel_stadt_index.png'; + $lmap->{'bern'} = $uwz_ch_url . 'bern_index.png'; + $lmap->{'fribourg'} = $uwz_ch_url . 'fribourg_index.png'; + $lmap->{'geneve'} = $uwz_ch_url . 'geneve_index.png'; + $lmap->{'glarus'} = $uwz_ch_url . 'glarus_index.png'; + $lmap->{'graubuenden'} = $uwz_ch_url . 'graubuenden_index.png'; + $lmap->{'jura'} = $uwz_ch_url . 'jura_index.png'; + $lmap->{'luzern'} = $uwz_ch_url . 'luzern_index.png'; + $lmap->{'neuchatel'} = $uwz_ch_url . 'neuchatel_index.png'; + $lmap->{'nidwalden'} = $uwz_ch_url . 'nidwalden_index.png'; + $lmap->{'obwalden'} = $uwz_ch_url . 'obwalden_index.png'; + $lmap->{'schaffhausen'} = $uwz_ch_url . 'schaffhausen_index.png'; + $lmap->{'schwyz'} = $uwz_ch_url . 'schwyz_index.png'; + $lmap->{'solothurn'} = $uwz_ch_url . 'solothurn_index.png'; + $lmap->{'stgallen'} = $uwz_ch_url . 'stgallen_index.png'; + $lmap->{'ticino'} = $uwz_ch_url . 'ticino_index.png'; + $lmap->{'thurgau'} = $uwz_ch_url . 'thurgau_index.png'; + $lmap->{'uri'} = $uwz_ch_url . 'uri_index.png'; + $lmap->{'waadt'} = $uwz_ch_url . 'waadt_index.png'; + $lmap->{'wallis'} = $uwz_ch_url . 'wallis_index.png'; + $lmap->{'zug'} = $uwz_ch_url . 'zug_index.png'; + $lmap->{'zuerich'} = $uwz_ch_url . 'zuerich_index.png'; + + ## LI + $lmap->{'liechtenstein'} = $uwz_li_url . 'liechtenstein_index.png'; + + ## UK + $lmap->{'unitedkingdom'} = $uwz_en_url . 'unitedkingdom_index.png'; + $lmap->{'eastofengland'} = $uwz_en_url . 'eastofengland_index.png'; + $lmap->{'eastmidlands'} = $uwz_en_url . 'eastmidlands-index.png'; + $lmap->{'london'} = $uwz_en_url . 'london-index.png'; + $lmap->{'northeastengland'} = $uwz_en_url . 'northeastengland-index.png'; + $lmap->{'northernireland'} = $uwz_en_url . 'northernireland-index.png'; + $lmap->{'northwestengland'} = $uwz_en_url . 'northwestengland-index.png'; + $lmap->{'scotland'} = $uwz_en_url . 'scotland-index.png'; + $lmap->{'southeastengland'} = $uwz_en_url . 'southeastengland-index.png'; + $lmap->{'southwestengland'} = $uwz_en_url . 'southwestengland-index.png'; + $lmap->{'wales'} = $uwz_en_url . 'wales-index.png'; + $lmap->{'westmidlands'} = $uwz_en_url . 'westmidlands-index.png'; + $lmap->{'yorkshireandthehumber'} = + $uwz_en_url . 'yorkshireandthehumber-index.png'; + + ## BE + $lmap->{'belgique'} = $uwz_be_url . 'belgique_index.png'; + + ## DK + $lmap->{'denmark'} = $uwz_dk_url . 'denmark_index.png'; + + ## FI + $lmap->{'finnland'} = $uwz_fi_url . 'finnland_index.png'; + + ## FR + $lmap->{'france'} = $uwz_fr_url . 'france_index.png'; + $lmap->{'alsace'} = $uwz_fr_url . 'alsace_index.png'; + $lmap->{'aquitaine'} = $uwz_fr_url . 'aquitaine_index.png'; + $lmap->{'basse-normandie'} = $uwz_fr_url . 'basse-normandie_index.png'; + $lmap->{'bretagne'} = $uwz_fr_url . 'bretagne_index.png'; + $lmap->{'champagne-ardenne'} = $uwz_fr_url . 'champagne-ardenne_index.png'; + $lmap->{'franche-comte'} = $uwz_fr_url . 'franche-comte_index.png'; + $lmap->{'haute-normandie'} = $uwz_fr_url . 'haute-normandie_index.png'; + $lmap->{'ile-de-france'} = $uwz_fr_url . 'ile-de-france_index.png'; + $lmap->{'languedoc-roussillon'} = + $uwz_fr_url . 'languedoc-roussillon_index.png'; + $lmap->{'limousin'} = $uwz_fr_url . 'limousin_index.png'; + $lmap->{'lorraine'} = $uwz_fr_url . 'lorraine_index.png'; + $lmap->{'bourgogne'} = $uwz_fr_url . 'bourgogne_index.png'; + $lmap->{'centre'} = $uwz_fr_url . 'centre_index.png'; + $lmap->{'midi-pyrenees'} = $uwz_fr_url . 'midi-pyrenees_index.png'; + $lmap->{'nord-pas-de-calais'} = + $uwz_fr_url . 'nord-pas-de-calais_index.png'; + $lmap->{'pays-de-la-loire'} = $uwz_fr_url . 'pays-de-la-loire_index.png'; + $lmap->{'picardie'} = $uwz_fr_url . 'picardie_index.png'; + $lmap->{'poitou-charentes'} = $uwz_fr_url . 'poitou-charentes_index.png'; + $lmap->{'provence-alpes-cote-dazur'} = + $uwz_fr_url . 'provence-alpes-cote-dazur_index.png'; + $lmap->{'rhone-alpes'} = $uwz_fr_url . 'rhone-alpes_index.png'; + + ## LU + $lmap->{'letzebuerg'} = $uwz_lu_url . 'letzebuerg_index.png'; + + ## NL + $lmap->{'nederland'} = $uwz_nl_url . 'nederland_index.png'; + $lmap->{'drenthe'} = $uwz_nl_url . 'drenthe_index.png'; + $lmap->{'flevoland'} = $uwz_nl_url . 'flevoland_index.png'; + $lmap->{'friesland'} = $uwz_nl_url . 'friesland_index.png'; + $lmap->{'gelderland'} = $uwz_nl_url . 'gelderland_index.png'; + $lmap->{'groningen'} = $uwz_nl_url . 'groningen_index.png'; + $lmap->{'limburg'} = $uwz_nl_url . 'limburg_index.png'; + $lmap->{'noordbrabant'} = $uwz_nl_url . 'noordbrabant_index.png'; + $lmap->{'noordholland'} = $uwz_nl_url . 'noordholland_index.png'; + $lmap->{'overijssel'} = $uwz_nl_url . 'overijssel_index.png'; + $lmap->{'utrecht'} = $uwz_nl_url . 'utrecht_index.png'; + $lmap->{'zeeland'} = $uwz_nl_url . 'zeeland_index.png'; + $lmap->{'zuidholland'} = $uwz_nl_url . 'zuidholland_index.png'; + + ## NO + $lmap->{'norwegen'} = $uwz_no_url . 'norwegen_index.png'; + + ## PT + $lmap->{'portugal'} = $uwz_pt_url . 'portugal_index.png'; + + ## SE + $lmap->{'sverige'} = $uwz_se_url . 'sverige_index.png'; + + ## ES + $lmap->{'espana'} = $uwz_es_url . 'espana_index.png'; + + ## IT + $lmap->{'italia'} = $uwz_it_url . 'italia_index.png'; + $lmap->{'valledaosta'} = $uwz_it_url . 'valledaosta_index.png'; + $lmap->{'piemonte'} = $uwz_it_url . 'piemonte_index.png'; + $lmap->{'lombardia'} = $uwz_it_url . 'lombardia_index.png'; + $lmap->{'trentinoaltoadige'} = $uwz_it_url . 'trentinoaltoadige_index.png'; + $lmap->{'friuliveneziagiulia'} = + $uwz_it_url . 'friuliveneziagiulia_index.png'; + $lmap->{'veneto'} = $uwz_it_url . 'veneto_index.png'; + $lmap->{'liguria'} = $uwz_it_url . 'liguria_index.png'; + $lmap->{'emiliaromagna'} = $uwz_it_url . 'emiliaromagna_index.png'; + $lmap->{'toscana'} = $uwz_it_url . 'toscana_index.png'; + $lmap->{'marche'} = $uwz_it_url . 'marche_index.png'; + $lmap->{'umbria'} = $uwz_it_url . 'umbria_index.png'; + $lmap->{'lazio'} = $uwz_it_url . 'lazio_index.png'; + $lmap->{'molise'} = $uwz_it_url . 'molise_index.png'; + $lmap->{'abruzzo'} = $uwz_it_url . 'abruzzo_index.png'; + $lmap->{'campania'} = $uwz_it_url . 'campania_index.png'; + $lmap->{'puglia'} = $uwz_it_url . 'puglia_index.png'; + $lmap->{'basilicata'} = $uwz_it_url . 'basilicata_index.png'; + $lmap->{'calabria'} = $uwz_it_url . 'calabria_index.png'; + $lmap->{'sicilia'} = $uwz_it_url . 'sicilia_index.png'; + $lmap->{'sardegna'} = $uwz_it_url . 'sardegna_index.png'; + + ## Isobaren + $lmap->{'isobaren1'} = + 'https://www.unwetterzentrale.de/images/icons/UWZ_ISO_00.jpg'; + $lmap->{'isobaren2'} = + 'https://www.wetteralarm.at/uploads/pics/UWZ_EURO_ISO_GER_00.jpg'; + $lmap->{'isobaren3'} = +'https://www.severe-weather-centre.co.uk/uploads/pics/UWZ_EURO_ISO_ENG_00.jpg'; + + return $lmap->{$smap}; +} + +################################### +sub Initialize { + my $hash = shift; + + $hash->{DefFn} = \&Define; + $hash->{UndefFn} = \&Undef; + $hash->{SetFn} = \&Set; + $hash->{NotifyFn} = \&Notify; + $hash->{GetFn} = \&Get; + $hash->{AttrFn} = \&Attr; + $hash->{AttrList} = + 'download:0,1 ' + . 'savepath ' . 'maps ' + . 'humanreadable:0,1 ' + . 'htmlattr ' + . 'htmltitle ' + . 'htmltitleclass ' + . 'htmlsequence:ascending,descending ' . 'lang ' + . 'sort_readings_by:severity,start,creation ' + . 'localiconbase ' + . 'intervalAtWarnLevel ' + . 'disable:1 ' + . 'disabledForIntervals ' + . $readingFnAttributes; + $hash->{parseParams} = 1; + + return FHEM::Meta::InitMod( __FILE__, $hash ); +} + +################################### +sub Define { + my $hash = shift // return; + my $aArg = shift // return; + + return $@ unless ( FHEM::Meta::SetInternals($hash) ); + use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); + + return "Error: Perl moduls " . $missingModul . "are missing on this system" + if ($missingModul); + + return + "Wrong syntax: use define UWZ " + if ( scalar( @{$aArg} ) != 5 + && lc $aArg->[2] ne 'search' ); + + my $name = $hash->{NAME}; + my $lang = ''; + $hash->{VERSION} = version->parse($VERSION)->normal; + $hash->{NOTIFYDEV} = 'global,' . $name; + + if ( ( lc $aArg->[2] ) ne 'search' ) { + readingsSingleUpdate( $hash, 'state', 'Initializing', 1 ); + $hash->{CountryCode} = $aArg->[2]; + $hash->{PLZ} = $aArg->[3]; + + ## URL by CountryCode + + my $URL_language = 'en'; + if (contains_string($hash->{CountryCode},('DE', 'AT', 'CH'))) { + $URL_language = 'de'; + } + if ( $hash->{CountryCode} eq 'NL' ) { + $URL_language = 'nl'; + } + if ( $hash->{CountryCode} eq 'FR' ) { + $URL_language = 'fr'; + } + + $hash->{URL} = +'https://feed.alertspro.meteogroup.com/AlertsPro/AlertsProPollService.php?method=getWarning&language=' + . $URL_language + . '&areaID=UWZ' + . $aArg->[2] + . $aArg->[3]; + + $hash->{fhem}{LOCAL} = 0; + $hash->{INTERVAL} = $aArg->[4]; + $hash->{INTERVALWARN} = 0; + } + else { + readingsSingleUpdate( $hash, 'state', 'Search-Mode', 1 ); + $hash->{CountryCode} = uc $aArg->[2]; + } + + return; +} + +##################################### +sub Undef { + my $hash = shift; + my $arg = shift; + + RemoveInternalTimer($hash); + BlockingKill( $hash->{helper}{RUNNING_PID} ) + if ( defined( $hash->{helper}{RUNNING_PID} ) ); + + return; +} + +sub Attr { + my ( $cmd, $name, $attrName, $attrVal ) = @_; + my $hash = $defs{$name}; + + if ( $attrName eq "disabledForIntervals" ) { + if ( $cmd eq "set" ) { + return +"check disabledForIntervals Syntax HH:MM-HH:MM or 'HH:MM-HH:MM HH:MM-HH:MM ...'" + unless ( $attrVal =~ /^((\d{2}:\d{2})-(\d{2}:\d{2})\s?)+$/ ); + Log3( $name, 3, "UWZ ($name) - disabledForIntervals" ); + } + + elsif ( $cmd eq "del" ) { + Log3( $name, 3, "UWZ ($name) - enabled" ); + readingsSingleUpdate( $hash, "state", "active", 1 ); + } + } + + return; +} + +##################################### +sub Set { + my $hash = shift // return; + my $aArg = shift // return; + + my $name = shift @$aArg // return; + my $cmd = shift @$aArg // return qq{"set $name" needs at least one argument}; + + my $usage = "Unknown argument $cmd, choose one of update:noArg " + if ( ( lc $hash->{CountryCode} ) ne 'search' ); + + return $usage if ( scalar( @{$aArg} ) != 0 ); + + if ($cmd eq 'update') { + Log $hash, 4, 'set command: ' . $cmd; + $hash->{fhem}{LOCAL} = 1; + Start($hash); + $hash->{fhem}{LOCAL} = 0; + } else { # including $cmd eq '?' + return $usage; + } + + return; +} + +sub Notify { + my $hash = shift; + my $dev = shift; + + my $name = $hash->{NAME}; + + my $devname = $dev->{NAME}; + my $devtype = $dev->{TYPE}; + my $events = deviceEvents( $dev, 1 ); + return if ( !$events ); + + Start($hash) + if ( + ( + ( + ( + grep /^DEFINED.$name$/, + @{$events} + or grep /^DELETEATTR.$name.disable$/, + @{$events} + or grep /^ATTR.$name.disable.0$/, + @{$events} + ) + && $devname eq 'global' + && $init_done + ) + || ( + ( + grep /^INITIALIZED$/, + @{$events} + or grep /^REREADCFG$/, + @{$events} + or grep /^MODIFIED.$name$/, + @{$events} + ) + && $devname eq 'global' + ) + ) + && ReadingsVal( $name, 'state', 'Search-Mode' ) ne 'Search-Mode' + ); + + return; +} + +sub Get { + my $hash = shift // return; + my $aArg = shift // return; + + my $name = shift @$aArg // return; + my $cmd = shift @$aArg // return qq{"get $name" needs at least one argument}; + + if (contains_string($hash->{CountryCode},('DE', 'AT', 'CH'))) { + my $usage = +"Unknown argument $cmd, choose one of Sturm:noArg Schneefall:noArg Regen:noArg Extremfrost:noArg Waldbrand:noArg Gewitter:noArg Glaette:noArg Hitze:noArg Glatteisregen:noArg Bodenfrost:noArg Hagel:noArg "; + + return $usage if ( scalar( @{$aArg} ) != 0 ); + + return + $cmd =~ m{\ASturm}xms ? GetCurrent( $hash, 2 ) + : $cmd =~ m{\ASchneefall}xms ? GetCurrent( $hash, 3 ) + : $cmd =~ m{\ARegen}xms ? GetCurrent( $hash, 4 ) + : $cmd =~ m{\AExtremfrost}xms ? GetCurrent( $hash, 5 ) + : $cmd =~ m{\AWaldbrand}xms ? GetCurrent( $hash, 6 ) + : $cmd =~ m{\AGewitter}xms ? GetCurrent( $hash, 7 ) + : $cmd =~ m{\AGlaette}xms ? GetCurrent( $hash, 8 ) + : $cmd =~ m{\AHitze}xms ? GetCurrent( $hash, 9 ) + : $cmd =~ m{\AGlatteisregen}xms ? GetCurrent( $hash, 10 ) + : $cmd =~ m{\ABodenfrost}xms ? GetCurrent( $hash, 11 ) + : $cmd =~ m{\AHagel}xms ? GetCurrentHail($hash) + : $usage; + } + + elsif ( $hash->{CountryCode} eq 'NL' ) { + my $usage = +"Unknown argument $cmd, choose one of storm:noArg sneeuw:noArg regen:noArg strenge-vorst:noArg bosbrand:noArg onweer:noArg gladheid:noArg hitte:noArg ijzel:noArg grondvorst:noArg hagel:noArg "; + + return $usage if ( scalar( @{$aArg} ) != 0 ); + + return + $cmd =~ m{\Astorm}xms ? GetCurrent( $hash, 2 ) + : $cmd =~ m{\Asneeuw}xms ? GetCurrent( $hash, 3 ) + : $cmd =~ m{\Aregen}xms ? GetCurrent( $hash, 4 ) + : $cmd =~ m{\Astrenge-vorst}xms ? GetCurrent( $hash, 5 ) + : $cmd =~ m{\Abosbrand}xms ? GetCurrent( $hash, 6 ) + : $cmd =~ m{\Aonweer}xms ? GetCurrent( $hash, 7 ) + : $cmd =~ m{\Agladheid}xms ? GetCurrent( $hash, 8 ) + : $cmd =~ m{\Ahitte}xms ? GetCurrent( $hash, 9 ) + : $cmd =~ m{\Aijzel}xms ? GetCurrent( $hash, 10 ) + : $cmd =~ m{\Agrondvorst}xms ? GetCurrent( $hash, 11 ) + : $cmd =~ m{\Ahagel}xms ? GetCurrentHail($hash) + : $usage; + } + + elsif ( $hash->{CountryCode} eq 'FR' ) { + my $usage = +"Unknown argument $cmd, choose one of tempete:noArg neige:noArg pluie:noArg strenge-vorst:noArg incendie-de-foret:noArg orage:noArg glissange:noArg canicule:noArg verglas:noArg grondvorst:noArg grele:noArg "; + + return $usage if ( scalar( @{$aArg} ) != 0 ); + + return + $cmd =~ m{\Atempete}xms ? GetCurrent( $hash, 2 ) + : $cmd =~ m{\Aneige}xms ? GetCurrent( $hash, 3 ) + : $cmd =~ m{\Apluie}xms ? GetCurrent( $hash, 4 ) + : $cmd =~ m{\Atempérature}xms ? GetCurrent( $hash, 5 ) + : $cmd =~ m{\Afeu-de-forêt}xms ? GetCurrent( $hash, 6 ) + : $cmd =~ m{\Aorage}xms ? GetCurrent( $hash, 7 ) + : $cmd =~ m{\Aoute-glissante}xms ? GetCurrent( $hash, 8 ) + : $cmd =~ m{\Achaleur}xms ? GetCurrent( $hash, 9 ) + : $cmd =~ m{\Apluie-de-verglas}xms ? GetCurrent( $hash, 10 ) + : $cmd =~ m{\Agelée}xms ? GetCurrent( $hash, 11 ) + : $cmd =~ m{\Agrêle}xms ? GetCurrentHail($hash) + : $usage; + } + + elsif ( ( lc $hash->{CountryCode} ) eq 'search' ) { + my $usage = "Unknown argument $cmd, choose one of SearchAreaID "; + + return $usage if ( scalar( @{$aArg} ) != 1 ); + + if ( $cmd =~ m{\ASearchAreaID}xms ) { UWZSearchLatLon( $name, $aArg->[0] ); } + elsif ( $cmd =~ m{\AAreaID}xms ) { + my @splitparam = split( /,/, $aArg->[0] ); + UWZSearchAreaID( $splitparam[0], $splitparam[1] ); + } + else { return $usage; } + + } + else { + my $usage = +"Unknown argument $cmd, choose one of storm:noArg snow:noArg rain:noArg extremfrost:noArg forest-fire:noArg thunderstorms:noArg glaze:noArg heat:noArg glazed-rain:noArg soil-frost:noArg hail:noArg "; + + return $usage if ( scalar( @{$aArg} ) != 0 ); + + return + $cmd =~ m{\Astorm}xms ? GetCurrent( $hash, 2 ) + : $cmd =~ m{\Asnow}xms ? GetCurrent( $hash, 3 ) + : $cmd =~ m{\Arain}xms ? GetCurrent( $hash, 4 ) + : $cmd =~ m{\Aextremfrost}xms ? GetCurrent( $hash, 5 ) + : $cmd =~ m{\Aforest-fire}xms ? GetCurrent( $hash, 6 ) + : $cmd =~ m{\Athunderstorms}xms ? GetCurrent( $hash, 7 ) + : $cmd =~ m{\Aglaze}xms ? GetCurrent( $hash, 8 ) + : $cmd =~ m{\Aheat}xms ? GetCurrent( $hash, 9 ) + : $cmd =~ m{\Aglazed-rain}xms ? GetCurrent( $hash, 10 ) + : $cmd =~ m{\Asoil-frost}xms ? GetCurrent( $hash, 11 ) + : $cmd =~ m{\Ahail}xms ? GetCurrentHail($hash) + : $usage; + } +} + +##################################### +sub GetCurrent { + my $hash = shift; + my $type = shift; + + my $name = $hash->{NAME}; + my $out; + my $curTimestamp = time(); + if ( ReadingsVal( $name, 'WarnCount', 0 ) eq 0 ) { + $out = 'inactive'; + } + else { + for ( my $i = 0 ; $i < ReadingsVal( $name, 'WarnCount', 0 ) ; $i++ ) { + if ( + ( + ReadingsVal( $name, 'Warn_' . $i . '_Start', '' ) + le $curTimestamp + ) + && ( ReadingsVal( $name, 'Warn_' . $i . '_End', '' ) + ge $curTimestamp ) + && ( ReadingsVal( $name, 'Warn_' . $i . '_Type', '' ) eq $type ) + ) + { + $out = 'active'; + last; + } + else { + $out = 'inactive'; + } + } + } + + return $out; +} + +##################################### +sub GetCurrentHail($) { + my $hash = shift; + + my $name = $hash->{NAME}; + my $out; + my $curTimestamp = time(); + + if ( ReadingsVal( $name, "WarnCount", 0 ) eq 0 ) { + $out = 'inactive'; + } + else { + for ( my $i = 0 ; $i < ReadingsVal( $name, 'WarnCount', 0 ) ; $i++ ) { + if ( + ( + ReadingsVal( $name, 'Warn_' . $i . '_Start', '' ) + le $curTimestamp + ) + && ( ReadingsVal( $name, 'Warn_' . $i . '_End', '' ) + ge $curTimestamp ) + && ( ReadingsVal( $name, 'Warn_' . $i . '_Hail', '' ) eq 1 ) + ) + { + $out = 'active'; + last; + } + else { + $out = 'inactive'; + } + } + } + + return $out; +} + +##################################### +sub JSONAcquire { + my $hash = shift; + my $URL = shift; + + my $name = $hash->{NAME}; + + return + if ( !defined( $hash->{NAME} ) ); + + Log $hash, 4, "Start capturing of $URL"; + + my $param = { + url => $URL, + timeout => 5, + hash => $hash, + method => 'GET', + header => '', + }; + + my ( $err, $data ) = HttpUtils_BlockingGet($param); + + if ( $err ne '' ) { + my $err_log = "Can't get $URL -- " . $err; + readingsSingleUpdate( $hash, 'lastConnection', $err, 1 ); + Log $hash, 1, 'Error: ' . $err_log; + return encode_utf8( '{"Error": "' . $err . '"}' ); + } + + Log $hash, 4, + length($data) . ' characters captured: ' . encode_utf8($data); + return encode_utf8($data); +} + +##################################### +sub Start { + my $hash = shift; + + my $name = $hash->{NAME}; + + return + if ( !defined( $hash->{NAME} ) ); + + if ( !$hash->{fhem}{LOCAL} && $hash->{INTERVAL} > 0 ) + { # set up timer if automatically call + RemoveInternalTimer($hash); + InternalTimer( gettimeofday() + $hash->{INTERVAL}, 'UWZ_Start', $hash ); + + return readingsSingleUpdate( $hash, 'state', 'disabled', 1 ) + if ( IsDisabled($name) ); + + readingsSingleUpdate( $hash, 'currentIntervalMode', 'normal', 0 ); + } + + ## URL by CountryCode + my $URL_language = 'en'; + if ( AttrVal( $hash->{NAME}, 'lang', undef ) ) { + $URL_language = AttrVal( $hash->{NAME}, 'lang', '' ); + } + else { + if (contains_string($hash->{CountryCode},('DE', 'AT', 'CH'))) { + $URL_language = 'de'; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $URL_language = 'nl'; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $URL_language = 'fr'; + } + } + + $hash->{URL} = +'https://feed.alertspro.meteogroup.com/AlertsPro/AlertsProPollService.php?method=getWarning&language=' + . $URL_language + . '&areaID=UWZ' + . $hash->{CountryCode} + . $hash->{PLZ}; + + if ( !defined( $hash->{URL} ) ) { + + Log $hash, 3, 'missing URL'; + return; + } + + $hash->{helper}{RUNNING_PID} = BlockingCall( + 'UWZ_Run', # callback worker task + $name, # name of the device + 'UWZ_Done', # callback result method + 120, # timeout seconds + 'UWZ_Aborted', # callback for abortion + $hash + ); # parameter for abortion + + return; +} + +##################################### +sub Aborted { + my $hash = shift; + + delete( $hash->{helper}{RUNNING_PID} ); + + return; +} + +##################################### +# asyncronous callback by blocking +sub Done { + my $string = shift; + + return + if ( !defined($string) ); + + # all term are separated by '|' , the first is the name of the instance + my ( $name, %values ) = split( '\\|', $string ); + my $hash = $defs{$name}; + return + if ( !defined( $hash->{NAME} ) ); + + # delete the marker for RUNNING_PID process + delete( $hash->{helper}{RUNNING_PID} ); + + # UnWetterdaten speichern + readingsBeginUpdate($hash); + + if ( defined $values{Error} ) { + readingsBulkUpdate( $hash, 'lastConnection', $values{Error} ); + readingsBulkUpdate( $hash, 'state', + 'error at last run, please check >>lastConnection<< reading' ); + } + else { + + while ( my ( $rName, $rValue ) = each(%values) ) { + readingsBulkUpdate( $hash, $rName, $rValue ); + Log $hash, 5, "reading:$rName value:$rValue"; + } + + if ( keys %values > 0 ) { + my $newState; + Log $hash, 4, "Delete old Readings"; + for my $Counter ( $values{WarnCount} .. 9 ) { + CommandDeleteReading( undef, + "$hash->{NAME} Warn_${Counter}_.*" ); + } + + if ( defined $values{WarnCount} ) { + + # Message by CountryCode + + $newState = 'Warnings: ' . $values{WarnCount}; + $newState = 'Warnungen: ' . $values{WarnCount} + if ( contains_string($hash->{CountryCode},('DE', 'AT', 'CH')) ); + $newState = 'Aantal waarschuwingen: ' . $values{WarnCount} + if ( $hash->{CountryCode} eq 'NL' ); + $newState = 'Avertissements: ' . $values{WarnCount} + if ( $hash->{CountryCode} eq 'FR' ); + + # end Message by CountryCode + } + else { + $newState = +'Error: Could not capture all data. Please check CountryCode and PLZ.'; + } + + readingsBulkUpdate( $hash, 'state', $newState ); + readingsBulkUpdate( $hash, 'lastConnection', + keys(%values) + . ' values captured in ' + . $values{durationFetchReadings} + . ' s' ); + Log $hash, 4, keys(%values) . ' values captured'; + + } + else { + + readingsBulkUpdate( $hash, 'lastConnection', 'no data found' ); + Log $hash, 1, 'No data found. Check city name or URL.'; + + } + } + + readingsEndUpdate( $hash, 1 ); + + if ( AttrVal( $name, 'intervalAtWarnLevel', '' ) ne '' + && ReadingsVal( $name, 'WarnUWZLevel', 0 ) > 1 ) + { + + IntervalAtWarnLevel($hash); + Log $hash, 5, 'run Sub IntervalAtWarnLevel'; + } + + return; +} + +##################################### +sub Run { + my $name = shift; + + my $ptext = $name; + my $UWZ_download; + my $UWZ_savepath; + my $UWZ_humanreadable; + + return + if ( !defined($name) ); + + my $hash = $defs{$name}; + return + if ( !defined( $hash->{NAME} ) ); + + my $readingStartTime = time(); + my $attrdownload = AttrVal( $name, 'download', '' ); + my $attrsavepath = AttrVal( $name, 'savepath', '' ); + my $maps2fetch = AttrVal( $name, 'maps', '' ); + + ## begin redundant Reading switch + my $attrhumanreadable = AttrVal( $name, 'humanreadable', '' ); + ## end redundant Reading switch + + # preset download + if ( $attrdownload eq '' ) { + + $UWZ_download = 0; + } + else { + + $UWZ_download = $attrdownload; + } + + # preset savepath + if ( $attrsavepath eq '' ) { + + $UWZ_savepath = '/tmp/'; + } + else { + + $UWZ_savepath = $attrsavepath; + } + + # preset humanreadable + if ( $attrhumanreadable eq '' ) { + + $UWZ_humanreadable = 0; + } + else { + + $UWZ_humanreadable = $attrhumanreadable; + } + + if ( $UWZ_download == 1 ) { + if ( !defined($maps2fetch) ) { $maps2fetch = 'deutschland'; } + Log $hash, 4, 'Maps2Fetch : ' . $maps2fetch; + my @maps = split( ' ', $maps2fetch ); + my $uwz_de_url = 'https://www.unwetterzentrale.de/images/map/'; + + foreach my $smap (@maps) { + Log $hash, 4, 'Download map : ' . $smap; + my $img = Map2Image($smap); + + if ( !defined($img) ) { + $img = $uwz_de_url . 'deutschland_index.png'; + } + my $code = getstore( $img, $UWZ_savepath . $smap . '.png' ); + + if ( $code == 200 ) { + Log $hash, 4, 'Successfully downloaded map ' . $smap; + + } + else { + + Log $hash, 3, 'Failed to download map (' . $img . ')'; + } + } + + } + + # acquire the json-response + my $response = JSONAcquire( $hash, $hash->{URL} ); + + Log $hash, 5, length($response) . ' characters captured'; + + my $uwz_warnings = JSON->new->ascii->decode($response); + + my $message; + my $uwz_warncount; + + if ( !exists $uwz_warnings->{Error} ) { + my $enc = guess_encoding($uwz_warnings); + + $uwz_warncount = scalar( @{ $uwz_warnings->{'results'} } ); + Log $hash, 4, 'There are ' . $uwz_warncount . ' warnings active'; + my $sortby = AttrVal( $name, 'sort_readings_by', '' ); + my @sorted; + + if ( $sortby eq 'creation' ) { + Log $hash, 4, 'Sorting by creation'; + @sorted = + sort { $b->{payload}{creation} <=> $a->{payload}{creation} } + @{ $uwz_warnings->{'results'} }; + + } + elsif ( $sortby ne 'severity' ) { + Log $hash, 4, 'Sorting by dtgStart'; + @sorted = sort { $a->{dtgStart} <=> $b->{dtgStart} } + @{ $uwz_warnings->{'results'} }; + + } + else { + Log $hash, 4, 'Sorting by severity'; + @sorted = sort { $a->{severity} <=> $b->{severity} } + @{ $uwz_warnings->{'results'} }; + } + + my $i = 0; + + my %typenames = ( + '1' => 'unknown', # <===== FIX HERE + '2' => 'sturm', + '3' => 'schnee', + '4' => 'regen', + '5' => 'temperatur', + '6' => 'waldbrand', + '7' => 'gewitter', + '8' => 'strassenglaette', + '9' => 'temperatur', # 9 = hitzewarnung + '10' => 'glatteisregen', + '11' => 'temperatur' + ); # 11 = bodenfrost + + my %typenames_de_str = ( + '1' => 'unknown', # <===== FIX HERE + '2' => 'Sturm', + '3' => 'Schnee', + '4' => 'Regen', + '5' => 'Temperatur', + '6' => 'Waldbrand', + '7' => 'Gewitter', + '8' => 'Strassenglaette', + '9' => 'Hitze', # 9 = hitzewarnung + '10' => 'Glatteisregen', + '11' => 'Bodenfrost' + ); # 11 = bodenfrost + + my %typenames_nl_str = ( + '1' => 'unknown', # <===== FIX HERE + '2' => 'storm', + '3' => 'sneeuw', + '4' => 'regen', + '5' => 'temperatuur', + '6' => 'bosbrand', + '7' => 'onweer', + '8' => 'gladde wegen', + '9' => 'hitte', # 9 = hitzewarnung + '10' => 'ijzel', + '11' => 'grondvorst' + ); # 11 = bodenfrost + + my %typenames_fr_str = ( + '1' => 'unknown', # <===== FIX HERE + '2' => 'tempete', + '3' => 'neige', + '4' => 'pluie', + '5' => 'températur', + '6' => 'feu de forêt', + '7' => 'orage', + '8' => 'route glissante', + '9' => 'chaleur', # 9 = hitzewarnung + '10' => 'pluie de verglas', + '11' => 'gelée' + ); # 11 = bodenfrost + + my %typenames_en_str = ( + '1' => 'unknown', # <===== FIX HERE + '2' => 'storm', + '3' => 'snow', + '4' => 'rain', + '5' => 'temperatur', + '6' => 'forest fire', + '7' => 'thunderstorms', + '8' => 'slippery road', + '9' => 'heat', # 9 = hitzewarnung + '10' => 'black ice rain', + '11' => 'soil frost' + ); # 11 = bodenfrost + + my %severitycolor = ( + '0' => 'green', + '1' => 'unknown', # <===== FIX HERE + '2' => 'unknown', # <===== FIX HERE + '3' => 'unknown', # <===== FIX HERE + '4' => 'orange', + '5' => 'unknown', # <===== FIX HERE + '6' => 'unknown', # <===== FIX HERE + '7' => 'orange', + '8' => 'gelb', + '9' => 'gelb', # <===== FIX HERE + '10' => 'orange', + '11' => 'rot', + '12' => 'violett' + ); + + my @uwzmaxlevel; + foreach my $single_warning (@sorted) { + + push @uwzmaxlevel, + GetUWZLevel( $hash, $single_warning->{'payload'}{'levelName'} ); + + Log $hash, 4, + 'Warn_' . $i . '_EventID: ' . $single_warning->{'payload'}{'id'}; + $message .= + 'Warn_' + . $i + . '_EventID|' + . $single_warning->{'payload'}{'id'} . '|'; + + my $chopcreation = + substr( $single_warning->{'payload'}{'creation'}, 0, 10 ); + $chopcreation = $chopcreation; + + Log $hash, 4, 'Warn_' . $i . '_Creation: ' . $chopcreation; + $message .= 'Warn_' . $i . '_Creation|' . $chopcreation . '|'; + + Log $hash, 4, 'Warn_' . $i . '_Type: ' . $single_warning->{'type'}; + $message .= + 'Warn_' . $i . '_Type|' . $single_warning->{'type'} . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_uwzLevel: ' + . GetUWZLevel( $hash, $single_warning->{'payload'}{'levelName'} ); + $message .= 'Warn_' + . $i + . '_uwzLevel|' + . GetUWZLevel( $hash, $single_warning->{'payload'}{'levelName'} ) + . '|'; + + Log $hash, 4, + 'Warn_' . $i . '_Severity: ' . $single_warning->{'severity'}; + $message .= + 'Warn_' . $i . '_Severity|' . $single_warning->{'severity'} . '|'; + + Log $hash, 4, + 'Warn_' . $i . '_Start: ' . $single_warning->{'dtgStart'}; + $message .= + 'Warn_' . $i . '_Start|' . $single_warning->{'dtgStart'} . '|'; + + Log $hash, 4, 'Warn_' . $i . '_End: ' . $single_warning->{'dtgEnd'}; + $message .= + 'Warn_' . $i . '_End|' . $single_warning->{'dtgEnd'} . '|'; + + ## Begin of redundant Reading + if ( $UWZ_humanreadable eq 1 ) { + Log $hash, 4, + 'Warn_' + . $i + . '_Start_Date: ' + . strftime( "%d.%m.%Y", + localtime( $single_warning->{'dtgStart'} ) ); + $message .= 'Warn_' + . $i + . '_Start_Date|' + . strftime( "%d.%m.%Y", + localtime( $single_warning->{'dtgStart'} ) ) + . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_Start_Time: ' + . strftime( "%H:%M", + localtime( $single_warning->{'dtgStart'} ) ); + $message .= 'Warn_' + . $i + . '_Start_Time|' + . strftime( "%H:%M", + localtime( $single_warning->{'dtgStart'} ) ) + . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_End_Date: ' + . strftime( "%d.%m.%Y", + localtime( $single_warning->{'dtgEnd'} ) ); + $message .= 'Warn_' + . $i + . '_End_Date|' + . strftime( "%d.%m.%Y", + localtime( $single_warning->{'dtgEnd'} ) ) + . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_End_Time: ' + . strftime( "%H:%M", + localtime( $single_warning->{'dtgEnd'} ) ); + $message .= 'Warn_' + . $i + . '_End_Time|' + . strftime( "%H:%M", + localtime( $single_warning->{'dtgEnd'} ) ) + . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_Creation_Date: ' + . strftime( "%d.%m.%Y", localtime($chopcreation) ); + $message .= 'Warn_' + . $i + . '_Creation_Date|' + . strftime( "%d.%m.%Y", localtime($chopcreation) ) . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_Creation_Time: ' + . strftime( "%H:%M", localtime($chopcreation) ); + $message .= 'Warn_' + . $i + . '_Creation_Time|' + . strftime( "%H:%M", localtime($chopcreation) ) . '|'; + + # Begin Language by AttrVal + if ( contains_string($hash->{CountryCode},('DE', 'AT', 'CH')) ) { + Log $hash, 4, + 'Warn_' + . $i + . '_Type_Str: ' + . $typenames_de_str{ $single_warning->{'type'} }; + $message .= 'Warn_' + . $i + . '_Type_Str|' + . $typenames_de_str{ $single_warning->{'type'} } . '|'; + my %uwzlevelname = ( + '0' => 'Stufe Grün (keine Warnung)', + '1' => 'Stufe Dunkelgrün (Wetterhinweise)', + '2' => 'Stufe Gelb (Vorwarnung für Unwetterwarnung)', + '3' => 'Warnstufe Orange (Unwetterwarnung)', + '4' => 'Warnstufe Rot (Unwetterwarnung)', + '5' => 'Warnstufe Violett (Unwetterwarnung)' + ); + Log $hash, 4, + 'Warn_' + . $i + . '_uwzLevel_Str: ' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + }; + $message .= 'Warn_' + . $i + . '_uwzLevel_Str|' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + } + . '|'; + + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + Log $hash, 4, + 'Warn_' + . $i + . '_Type_Str: ' + . $typenames_nl_str{ $single_warning->{'type'} }; + $message .= 'Warn_' + . $i + . '_Type_Str|' + . $typenames_nl_str{ $single_warning->{'type'} } . '|'; + my %uwzlevelname = ( + '0' => 'niveau groen (geen waarschuwingen)', + '1' => 'niveau donkergroen (weermelding)', + '2' => 'niveau geel (voorwaarschuwing)', + '3' => +'waarschuwingsniveau oranje (waarschuwing voor matig noodweer)', + '4' => +'waarschuwingsniveau rood (waarschuwing voor zwaar noodweer)', + '5' => +'waarschuwingsniveau violet (waarschuwing voor zeer zwaar noodweer)' + ); + Log $hash, 4, + 'Warn_' + . $i + . '_uwzLevel_Str: ' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + }; + $message .= 'Warn_' + . $i + . '_uwzLevel_Str|' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + } + . '|'; + + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + Log $hash, 4, + 'Warn_' + . $i + . '_Type_Str: ' + . $typenames_nl_str{ $single_warning->{'type'} }; + $message .= 'Warn_' + . $i + . '_Type_Str|' + . $typenames_nl_str{ $single_warning->{'type'} } . '|'; + my %uwzlevelname = ( + '0' => 'niveau vert (aucune alerte)', + '1' => 'niveau vert foncé (indication météo)', + '2' => 'niveau jaune (pré-alerte)', + '3' => 'niveau d\' alerte orange (alerte météo)', + '4' => 'niveau d\' alerte rouge (alerte météo)', + '5' => 'niveau d\' alerte violet (alerte météo)' + ); + Log $hash, 4, + 'Warn_' + . $i + . '_uwzLevel_Str: ' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + }; + $message .= 'Warn_' + . $i + . '_uwzLevel_Str|' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + } + . '|'; + + } + else { + Log $hash, 4, + 'Warn_' + . $i + . '_Type_Str: ' + . $typenames_en_str{ $single_warning->{'type'} }; + $message .= 'Warn_' + . $i + . '_Type_Str|' + . $typenames_en_str{ $single_warning->{'type'} } . '|'; + my %uwzlevelname = ( + '0' => 'level green (no warnings)', + '1' => 'level dark green (weather notice)', + '2' => 'level yellow (severe weather watch)', + '3' => 'Alert level Orange', + '4' => 'Alert level Red', + '5' => 'Alert level Violet' + ); + Log $hash, 4, + 'Warn_' + . $i + . '_uwzLevel_Str: ' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + }; + $message .= 'Warn_' + . $i + . '_uwzLevel_Str|' + . $uwzlevelname{ + GetUWZLevel( $hash, + $single_warning->{'payload'}{'levelName'} ) + } + . '|'; + + } + + } + ## End of redundant Reading + + Log $hash, 4, + 'Warn_' + . $i + . '_levelName: ' + . $single_warning->{'payload'}{'levelName'}; + $message .= 'Warn_' + . $i + . '_levelName|' + . $single_warning->{'payload'}{'levelName'} . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_AltitudeMin: ' + . $enc->decode( $single_warning->{'payload'}{'altMin'} ); + + $message .= 'Warn_' + . $i + . '_AltitudeMin|' + . encode( 'UTF-8', + decode( 'iso-8859-1', $single_warning->{'payload'}{'altMin'} ) ) + . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_AltitudeMax: ' + . $enc->decode( $single_warning->{'payload'}{'altMax'} ); + + $message .= 'Warn_' + . $i + . '_AltitudeMax|' + . encode( 'UTF-8', + decode( 'iso-8859-1', $single_warning->{'payload'}{'altMax'} ) ) + . '|'; + + my $uclang = 'EN'; + if ( AttrVal( $name, 'lang', undef ) ) { + $uclang = uc AttrVal( $name, 'lang', '' ); + } + else { + # Begin Language by AttrVal + if ( contains_string($hash->{CountryCode},('DE','AT','CH')) ) { + $uclang = 'DE'; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $uclang = 'NL'; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $uclang = 'FR'; + } + else { + $uclang = 'EN'; + } + } + Log $hash, 4, + 'Warn_' + . $i + . '_LongText: ' + . $enc->decode( + $single_warning->{'payload'}{'translationsLongText'}{$uclang} ); + + $message .= 'Warn_' + . $i + . '_LongText|' + . encode( + 'UTF-8', + decode( + 'iso-8859-1', + $single_warning->{'payload'}{'translationsLongText'} + {$uclang} + ) + ) . '|'; + + Log $hash, 4, + 'Warn_' + . $i + . '_ShortText: ' + . $enc->decode( + $single_warning->{'payload'}{'translationsShortText'}{$uclang} + ); + + $message .= 'Warn_' + . $i + . '_ShortText|' + . encode( + 'UTF-8', + decode( + 'iso-8859-1', + $single_warning->{'payload'}{'translationsShortText'} + {$uclang} + ) + ) . '|'; + + ### + if ( AttrVal( $name, 'localiconbase', undef ) ) { + Log $hash, 4, + 'Warn_' + . $i + . '_IconURL: ' + . AttrVal( $name, 'localiconbase', undef ) + . $typenames{ $single_warning->{'type'} } . '-' + . $single_warning->{'severity'} . '.png'; + $message .= 'Warn_' + . $i + . '_IconURL|' + . AttrVal( $name, 'localiconbase', undef ) + . $typenames{ $single_warning->{'type'} } . '-' + . GetSeverityColor( + $hash, + GetUWZLevel( + $hash, $single_warning->{'payload'}{'levelName'} + ) + ) . '.png|'; + + } + else { + Log $hash, 4, + 'Warn_' + . $i + . '_IconURL: https://www.unwetterzentrale.de/images/icons/' + . $typenames{ $single_warning->{'type'} } . '-' + . $single_warning->{'severity'} . '.gif'; + $message .= 'Warn_' + . $i + . '_IconURL|https://www.unwetterzentrale.de/images/icons/' + . $typenames{ $single_warning->{'type'} } . '-' + . GetSeverityColor( + $hash, + GetUWZLevel( + $hash, $single_warning->{'payload'}{'levelName'} + ) + ) . '.gif|'; + } + ### + + ## Hagel start + my $hagelcount = 0; + + # Begin Language by AttrVal + + if ( contains_string($hash->{CountryCode},('DE', 'AT', 'CH')) ) { + + $hagelcount = my @hagelmatch = + $single_warning->{'payload'}{'translationsLongText'}{'DE'} =~ + /Hagel/g; + + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + + $hagelcount = my @hagelmatch = + $single_warning->{'payload'}{'translationsLongText'}{'NL'} =~ + /hagel/g; + + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + + $hagelcount = my @hagelmatch = + $single_warning->{'payload'}{'translationsLongText'}{'FR'} =~ + /grêle/g; + + } + else { + + $hagelcount = my @hagelmatch = + $single_warning->{'payload'}{'translationsLongText'}{'EN'} =~ + /Hail/g; + } + + # end language by AttrVal + if ( $hagelcount ne 0 ) { + + Log $hash, 4, 'Warn_' . $i . '_Hail: 1'; + $message .= 'Warn_' . $i . '_Hail|1|'; + + } + else { + + Log $hash, 4, 'Warn_' . $i . '_Hail: 0'; + $message .= 'Warn_' . $i . '_Hail|0|'; + } + ## Hagel end + + $i++; + } + + my $max = 0; + for (@uwzmaxlevel) { + $max = $_ if !$max || $_ > $max; + } + + $message .= 'WarnUWZLevel|'; + $message .= $max . '|'; + + Log $hash, 4, 'WarnUWZLevel_Color: ' . GetSeverityColor( $hash, $max ); + $message .= + 'WarnUWZLevel_Color|' . GetSeverityColor( $hash, $max ) . '|'; + + ## Begin of redundant Reading + if ( $UWZ_humanreadable eq 1 ) { + if ( contains_string($hash->{CountryCode},('DE', 'AT', 'CH')) ) { + my %uwzlevelname = ( + '0' => 'Stufe Grün (keine Warnung)', + '1' => 'Stufe Dunkelgrün (Wetterhinweise)', + '2' => 'Stufe Gelb (Vorwarnung für Unwetterwarnung)', + '3' => 'Warnstufe Orange (Unwetterwarnung)', + '4' => 'Warnstufe Rot (Unwetterwarnung)', + '5' => 'Warnstufe Violett (Unwetterwarnung)' + ); + Log $hash, 4, 'WarnUWZLevel_Str: ' . $uwzlevelname{$max}; + $message .= 'WarnUWZLevel_Str|' . $uwzlevelname{$max} . '|'; + + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + my %uwzlevelname = ( + '0' => 'niveau groen (geen waarschuwingen)', + '1' => 'niveau donkergroen (voorwaarschuwing)', + '2' => 'niveau geel (voorwaarschuwing)', + '3' => +'waarschuwingsniveau oranje (waarschuwing voor matig noodweer)', + '4' => +'waarschuwingsniveau rood (waarschuwing voor zwaar noodweer)', + '5' => +'waarschuwingsniveau violet (waarschuwing voor zeer zwaar noodweer)' + ); + Log $hash, 4, 'WarnUWZLevel_Str: ' . $uwzlevelname{$max}; + $message .= 'WarnUWZLevel_Str|' . $uwzlevelname{$max} . '|'; + + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + my %uwzlevelname = ( + '0' => 'niveau vert (aucune alerte)', + '1' => 'niveau vert foncé (indication météo)', + '2' => 'niveau jaune (pré-alerte)', + '3' => 'niveau d\' alerte orange (alerte météo)', + '4' => 'niveau d\' alerte rouge (alerte météo)', + '5' => 'niveau d\' alerte violet (alerte météo)' + ); + Log $hash, 4, 'WarnUWZLevel_Str: ' . $uwzlevelname{$max}; + $message .= 'WarnUWZLevel_Str|' . $uwzlevelname{$max} . '|'; + + } + else { + my %uwzlevelname = ( + '0' => 'level green (no warnings)', + '1' => 'level dark green (weather notice)', + '2' => 'level yellow (severe weather watch)', + '3' => 'Alert level Orange', + '4' => 'Alert level Red', + '5' => 'Alert level Violet' + ); + Log $hash, 4, 'WarnUWZLevel_Str: ' . $uwzlevelname{$max}; + $message .= 'WarnUWZLevel_Str|' . $uwzlevelname{$max} . '|'; + } + } + + $message .= 'durationFetchReadings|'; + $message .= sprintf "%.2f", time() - $readingStartTime; + + Log $hash, 3, 'Done fetching data'; + Log $hash, 4, + 'Will return : ' . "$name|$message|WarnCount|$uwz_warncount"; + } + else { + $message = 'Error|' . $uwz_warnings->{Error}; + $uwz_warncount = -1; + } + + return "$name|$message|WarnCount|$uwz_warncount"; +} + +##################################### +sub UWZAsHtml { + my $name = shift; + + my $ret = ''; + my $hash = $defs{$name}; + + my $htmlsequence = AttrVal( $name, 'htmlsequence', 'none' ); + my $htmltitle = AttrVal( $name, 'htmltitle', '' ); + my $htmltitleclass = AttrVal( $name, 'htmltitleclass', '' ); + + my $attr; + if ( AttrVal( $name, 'htmlattr', 'none' ) ne 'none' ) { + $attr = AttrVal( $name, 'htmlattr', '' ); + } + else { + $attr = 'width="100%"'; + } + + if ( ReadingsVal( $name, 'WarnCount', 0 ) != 0 ) { + + $ret .= ''; + $ret .= '
'; + $ret .= + ''; + + if ( $htmlsequence eq 'descending' ) { + for ( + my $i = ReadingsVal( $name, 'WarnCount', -1 ) - 1 ; + $i >= 0 ; + $i-- + ) + { + $ret .= UWZHtmlFrame( $hash, 'Warn_' . $i, $attr, 1 ); + + } + } + else { + for ( my $i = 0 ; $i < ReadingsVal( $name, 'WarnCount', 0 ) ; $i++ ) + { + + $ret .= UWZHtmlFrame( $hash, 'Warn_' . $i, $attr, 1 ); + } + } + + $ret .= '
' + . $htmltitle + . '
'; + $ret .= '
'; + + } + else { + + $ret .= ''; + $ret .= '
'; + $ret .= + ''; + $ret .= ''; + $ret .= '
' + . $htmltitle + . '
'; + + # language by AttrVal + if ( contains_string($hash->{CountryCode},('DE','AT','CH')) ) { + $ret .= 'Keine Warnungen'; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $ret .= 'Geen waarschuwingen'; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $ret .= 'Aucune alerte'; + } + else { + $ret .= 'No Warnings'; + } + + # end language by AttrVal + $ret .= '
'; + $ret .= '
'; + } + + return $ret; +} + +##################################### +sub UWZAsHtmlLite { + my $name = shift; + + my $ret = ''; + my $hash = $defs{$name}; + my $htmlsequence = AttrVal( $name, 'htmlsequence', 'none' ); + my $htmltitle = AttrVal( $name, 'htmltitle', '' ); + my $htmltitleclass = AttrVal( $name, 'htmltitleclass', '' ); + my $attr; + + if ( AttrVal( $name, 'htmlattr', 'none' ) ne 'none' ) { + $attr = AttrVal( $name, 'htmlattr', '' ); + } + else { + $attr = 'width="100%"'; + } + + if ( ReadingsVal( $name, 'WarnCount', '' ) != 0 ) { + + $ret .= ''; + $ret .= '
'; + $ret .= + ''; + + if ( $htmlsequence eq 'descending' ) { + for ( + my $i = ReadingsVal( $name, 'WarnCount', '' ) - 1 ; + $i >= 0 ; + $i-- + ) + { + $ret .= UWZHtmlFrame( $hash, 'Warn_' . $i, $attr, 0 ); + } + } + else { + for ( my $i = 0 ; + $i < ReadingsVal( $name, 'WarnCount', '' ) ; $i++ ) + { + $ret .= UWZHtmlFrame( $hash, 'Warn_' . $i, $attr, 0 ); + } + } + $ret .= '
' + . $htmltitle + . '
'; + $ret .= '
'; + + } + else { + + $ret .= ''; + $ret .= '
'; + $ret .= + ''; + $ret .= ''; + $ret .= '
' + . $htmltitle + . '
'; + + # language by AttrVal + if ( contains_string($hash->{CountryCode},('DE','AT','CH')) ) { + $ret .= 'Keine Warnungen'; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $ret .= 'Geen waarschuwingen'; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $ret .= 'Aucune alerte'; + } + else { + $ret .= 'No Warnings'; + } + + # end language by AttrVal + $ret .= '
'; + $ret .= '
'; + } + + return $ret; +} + +##################################### +sub UWZAsHtmlFP { + my $name = shift; + + my $tablewidth = ReadingsVal( $name, 'WarnCount', '' ) * 80; + my $htmlsequence = AttrVal( $name, 'htmlsequence', 'none' ); + my $htmltitle = AttrVal( $name, 'htmltitle', '' ); + my $htmltitleclass = AttrVal( $name, 'htmltitleclass', '' ); + my $ret = ''; + + $ret .= + ''; + $ret .= ''; + + if ( $htmlsequence eq 'descending' ) { + for ( + my $i = ReadingsVal( $name, 'WarnCount', '' ) - 1 ; + $i >= 0 ; + $i-- + ) + { + $ret .= + ''; + } + } + else { + for ( my $i = 0 ; $i < ReadingsVal( $name, 'WarnCount', '' ) ; $i++ ) { + $ret .= + ''; + } + } + $ret .= ''; + $ret .= '
' + . $htmltitle + . '
'; + + return $ret; +} + +##################################### +sub UWZAsHtmlMovie { + my $name = shift; + my $land = shift; + + my $url = Map2Movie($land); + my $hash = $defs{$name}; + + my $ret = ''; + $ret .= '
'; + + $ret .= ''; + $ret .= '
'; + + if ( defined($url) ) { + $ret .= ''; + + } + else { + # language by AttrVal + if ( contains_string($hash->{CountryCode} ,('DE','AT','CH')) ) { + $ret .= 'unbekannte Landbezeichnung'; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $ret .= 'Onbekende landcode'; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $ret .= 'code de pays inconnu'; + } + else { + $ret .= 'unknown movie setting'; + } + + # end language by AttrVal + } + + $ret .= '
'; + + return $ret; +} + +##################################### +sub UWZAsHtmlKarteLand { + my $name = shift; + my $land = shift; + + my $url = Map2Image($land); + my $hash = $defs{$name}; + + my $ret = ''; + $ret .= '
'; + + $ret .= ''; + $ret .= '
'; + + if ( defined($url) ) { + $ret .= ''; + + } + else { + # language by AttrVal + if ( contains_string($hash->{CountryCode},('DE','AT','CH')) ) { + $ret .= 'unbekannte Landbezeichnung'; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $ret .= 'onbekende landcode'; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $ret .= 'code de pays inconnu'; + } + else { + $ret .= 'unknown map setting'; + } + + # end language by AttrVal + } + + $ret .= '
'; + + return $ret; +} + +##################################### +sub UWZHtmlFrame { + my ( $hash, $readingStart, $attr, $parm ) = @_; + + my $ret = ''; + my $name = $hash->{NAME}; + $ret .= + ''; + $ret .= + '' + . ReadingsVal( $name, $readingStart . '_ShortText', '' ) + . '

'; + $ret .= ReadingsVal( $name, $readingStart . '_LongText', '' ) . '

' + if ($parm); + + $ret .= UWZHtmlTimestamp( $hash, $readingStart . '_Start', $attr ); + $ret .= UWZHtmlTimestamp( $hash, $readingStart . '_End', $attr ); + $ret .= ''; + $ret .= ''; + + return $ret; +} + +##################################### +sub UWZHtmlTimestamp { + + my @DEText = qw(Anfang: Ende: Uhr); + my @NLText = qw(Begin: Einde: uur); + my @FRText = ( "Valide à partir du:", "Jusqu\'au:", "heure" ); + my @ENText = qw(Start: End: hour); + + my $hash = shift; + my $reading = shift; + my $attr = shift; + + my $ret; + my $StartEnd = ''; + my $name = $hash->{NAME}; + + if ( substr( $reading, 7, 1 ) eq 'S' ) { + $StartEnd = 0; + $ret .= ''; + } + else { $StartEnd = 1; } + + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = + localtime( ReadingsVal( $name, $reading, '' ) ); + + if ( length($hour) == 1 ) { $hour = "0$hour"; } + if ( length($min) == 1 ) { $min = "0$min"; } + + # language by AttrVal + if ( contains_string($hash->{CountryCode},('DE','AT','CH')) ) { + $ret .= + ""; + } + elsif ( $hash->{CountryCode} eq 'NL' ) { + $ret .= + ""; + } + elsif ( $hash->{CountryCode} eq 'FR' ) { + $ret .= + ""; + } + else { + $ret .= + ""; + } + + return $ret; +} + +##################################### +sub GetSeverityColor { + my $name = shift; + my $uwzlevel = shift; + my $alertcolor = ''; + + my %UWZSeverity = ( + '0' => 'gruen', + '1' => 'orange', + '2' => 'gelb', + '3' => 'orange', + '4' => 'rot', + '5' => 'violett' + ); + + return $UWZSeverity{$uwzlevel}; +} + +##################################### +sub GetUWZLevel { + my $name = shift; + my $warnname = shift; + + my @alert = split( /_/, $warnname ); + + if ( $alert[0] eq 'notice' ) { + return '1'; + } + elsif ( $alert[1] eq 'forewarn' ) { + return '2'; + } + else { + + my %UWZSeverity = ( + 'green' => '0', + 'yellow' => '2', + 'orange' => '3', + 'red' => '4', + 'violet' => '5' + ); + + return $UWZSeverity{ $alert[2] }; + } + + return; +} + +##################################### +sub IntervalAtWarnLevel { + my $hash = shift; + + my $name = $hash->{NAME}; + my $warnLevel = ReadingsVal( $name, 'WarnUWZLevel', 0 ); + my @valuestring = split( ',', AttrVal( $name, 'intervalAtWarnLevel', '' ) ); + my %warnLevelInterval; + + readingsSingleUpdate( $hash, 'currentIntervalMode', 'warn', 0 ); + + foreach (@valuestring) { + + my @values = split( '=', $_ ); + $warnLevelInterval{ $values[0] } = $values[1]; + } + + if ( defined( $warnLevelInterval{$warnLevel} ) + && $hash->{INTERVALWARN} != $warnLevelInterval{$warnLevel} ) + { + + $hash->{INTERVALWARN} = $warnLevelInterval{$warnLevel}; + + RemoveInternalTimer($hash); + InternalTimer( gettimeofday() + $hash->{INTERVALWARN}, + 'UWZ_Start', $hash ); + + Log $hash, 4, + "restart internal timer with interval $hash->{INTERVALWARN}"; + + } + else { + + RemoveInternalTimer($hash); + InternalTimer( gettimeofday() + $hash->{INTERVALWARN}, + "UWZ_Start", $hash ); + + Log $hash, 4, + "restart internal timer with interval $hash->{INTERVALWARN}"; + } + + return; +} + +##################################### +## +## UWZ Helper Functions +## +##################################### + +sub UWZSearchLatLon { + my $name = shift; + my $loc = shift; + + my $err_log = ''; + my $url = +'https://alertspro.geoservice.meteogroup.de/weatherpro/SearchFeed.php?search=' + . $loc; + my $agent = LWP::UserAgent->new( + env_proxy => 1, + keep_alive => 1, + protocols_allowed => ['http'], + timeout => 10 + ); + my $request = HTTP::Request->new( GET => $url ); + my $response = $agent->request($request); + $err_log = 'Can\'t get ' . $url . ' -- ' . $response->status_line + if ( !$response->is_success ); + + if ( $err_log ne '' ) { + print 'Error|Error ' . $response->status_line; + } + + use XML::Simple qw(:strict); + use Encode qw(decode encode); + + my $uwzxmlparser = XML::Simple->new(); + my $search = $uwzxmlparser->XMLin( + $response->content, + KeyAttr => { 'city' => 'id' }, + ForceArray => ['city'] + ); + + my $ret = '
$DEText[$StartEnd]" + . "$DEweekdays[$wday], $mday $DEmonths[$mon] " + . ( 1900 + $year ) + . " $hour:$min " + . "$DEText[2]$NLText[$StartEnd]" + . "$NLweekdays[$wday], $mday $NLmonths[$mon] " + . ( 1900 + $year ) + . " $hour:$min " + . "$NLText[2]$FRText[$StartEnd]" + . "$FRweekdays[$wday], $mday $FRmonths[$mon] " + . ( 1900 + $year ) + . " $hour:$min " + . "$FRText[2]$ENText[$StartEnd]" + . "$ENweekdays[$wday], $mday $ENmonths[$mon] " + . ( 1900 + $year ) + . " $hour:$min " + . "$ENText[2]
'; + $ret .= '
'; + + $ret .= ''; + + $ret .= ''; + $ret .= ''; + $ret .= ''; + $ret .= ''; + $ret .= ''; + $ret .= ''; + + foreach my $locres ( $search->{cities}->{city} ) { + my $linecount = 1; + while ( my ( $key, $value ) = each(%$locres) ) { + if ( $linecount % 2 == 0 ) { + $ret .= ''; + } + else { + $ret .= ''; + } + $ret .= ''; + $ret .= ''; + $ret .= ''; + $ret .= ''; + + my $aHref = + 'Get AreaID'; + + $ret .= ''; + $ret .= ''; + $linecount++; + } + } + + $ret .= '
citycountrylatitudelongitude
' . encode( 'utf-8', $value->{'name'} ) . '' . $value->{'country-name'} . '' . $value->{'latitude'} . '' . $value->{'longitude'} . '' . $aHref . '
'; + + return $ret; +} + +##################################### +sub UWZSearchAreaID { + my $lat = shift; + my $lon = shift; + + my $err_log = ''; + my $url = +'https://feed.alertspro.meteogroup.com/AlertsPro/AlertsProPollService.php?method=lookupCoord&lat=' + . $lat . '&lon=' + . $lon; + my $agent = LWP::UserAgent->new( + env_proxy => 1, + keep_alive => 1, + protocols_allowed => ['http'], + timeout => 10 + ); + my $request = HTTP::Request->new( GET => $url ); + my $response = $agent->request($request); + $err_log = "Can't get $url -- " . $response->status_line + if ( !$response->is_success ); + + if ( $err_log ne '' ) { + print "Error|Error " . $response->status_line; + } + use JSON; + my @perl_scalar = @{ JSON->new->utf8->decode( $response->content ) }; + + my $AreaType = $perl_scalar[0]->{'AREA_TYPE'}; + my $CC = substr $perl_scalar[0]->{'AREA_ID'}, 3, 2; + my $AreaID = substr $perl_scalar[0]->{'AREA_ID'}, 5, 5; + + if ( $AreaType eq 'UWZ' ) { + my $ret = +'Please use the following statement to define Unwetterzentrale for your location:

'; + $ret .= '
'; + $ret .= ''; + $ret .= ''; + $ret .= +""; + $ret .= ''; + $ret .= '
define Unwetterzentrale UWZ $CC $AreaID 3600
'; + $ret .= '
'; + + $ret .= '
'; + $ret .= +'You can also use weblinks to add weathermaps. For a list of possible Weblinks see Commandref. For example to add the Europe Map use:
'; + + $ret .= '
'; + $ret .= ''; + $ret .= ''; + $ret .= +""; + $ret .= ''; + $ret .= '
define UWZ_Map_Europe weblink htmlCode { UWZAsHtmlKarteLand('Unwetterzentrale','europa') }
'; + $ret .= '
'; + + $ret .= ''; + + return $ret; + } + else { + return 'Sorry, nothing found or not implemented'; + } + + return; +} + +##################################### +1; + +=pod + +=item device +=item summary extracts thunderstorm warnings from unwetterzentrale.de +=item summary_DE extrahiert Unwetterwarnungen von unwetterzentrale.de + +=begin html + + +

UWZ

+
    + + This modul extracts thunderstorm warnings from www.unwetterzentrale.de. +
    + Therefore the same interface is used as the Android App Alerts Pro does. + A maximum of 10 thunderstorm warnings will be served. + Additional the module provides a few functions to create HTML-Templates which can be used with weblink. +
    + The following Perl-Modules are used within this module: HTTP::Request, LWP::UserAgent, JSON, Encode::Guess und HTML::Parse. +

    + Define +
      +
      + define <Name> UWZ [CountryCode] [AreaID] [INTERVAL] +


      + Example: +
      + + define Unwetterzentrale UWZ UK 08357 1800
      + attr Unwetterzentrale download 1
      + attr Unwetterzentrale humanreadable 1
      + attr Unwetterzentrale maps eastofengland unitedkingdom

      + define UnwetterDetails weblink htmlCode {FHEM::UWZ::UWZAsHtml("Unwetterzentrale")}
      + define UnwetterMapE_UK weblink htmlCode {FHEM::UWZ::UWZAsHtmlKarteLand("Unwetterzentrale","eastofengland")}
      + define UnwetterLite weblink htmlCode {FHEM::UWZ::UWZAsHtmlLite("Unwetterzentrale")} + define UnwetterMovie weblink htmlCode {FHEM::UWZ::UWZAsHtmlMovie("Unwetterzentrale","clouds-precipitation-uk")} +
      +
        + +
    • [CountryCode] +
      + Possible values: DE, AT, CH, UK, ...
      + (for other countries than germany use SEARCH for CountryCode to start device in search mode) +

    • +
    • [AreaID] +
      + For Germany you can use the postalcode, other countries use SEARCH for CountryCode to start device in search mode. +
      +

    • +
    • [INTERVAL] +
      + Defines the refresh interval. The interval is defined in seconds, so an interval of 3600 means that every hour a refresh will be triggered onetimes. +
      +

    • + +


      + Example Search-Mode: +
      + + define Unwetterzentrale UWZ SEARCH
      +
      +
      + now get the AreaID for your location (example shows london): +
      + + get Unwetterzentrale SearchAreaID London
      +
      +
      + now redefine your device with the outputted CountryCode and AreaID. +
      + +
        + + +
    +
    + + + Get +
      +
      +
    • get <name> soil-frost +
      + give info about current soil frost (active|inactive). +

    • +
    • get <name> extremfrost +
      + give info about current frost (active|inactive). +

    • +
    • get <name> thunderstorm +
      + give info about current thunderstorm (active|inactive). +

    • +
    • get <name> glaze +
      + give info about current glaze (active|inactive). +

    • +
    • get <name> glazed-rain +
      + give info about current freezing rain (active|inactive). +

    • +
    • get <name> hail +
      + give info about current hail (active|inactive). +

    • +
    • get <name> heat +
      + give info about current heat (active|inactive). +

    • +
    • get <name> rain +
      + give info about current rain (active|inactive). +

    • +
    • get <name> snow +
      + give info about current snow (active|inactive). +

    • +
    • get <name> storm +
      + give info about current storm (active|inactive). +

    • +
    • get <name> forest-fire +
      + give info about current forest fire (active|inactive). +

    • + +
    + +
    + + Get (Search-Mode) +
      +
      +
    • get <name> SearchAreaID <city> +
      + Get AreaID coresponnding to entered location. +

    • + +
    + +
    + + + + + Set +
      +
      +
    • set <name> update +
      + Executes an imediate update of thunderstorm warnings. +

    • +
    + +
    + + Attributes +
      +
      +
    • download +
      + Download maps during update (0|1). +
      +
    • +
    • savepath +
      + Define where to store the map png files (default: /tmp/). +
      +
    • +
    • maps +
      + Define the maps to download space seperated. For possible values see UWZAsHtmlKarteLand. +
      +
    • +
    • humanreadable +
      + Add additional Readings Warn_?_Start_Date, Warn_?_Start_Time, Warn_?_End_Date and Warn_?_End_Time containing the coresponding timetamp in a human readable manner. Additionally Warn_?_uwzLevel_Str and Warn_?_Type_Str will be added to device readings (0|1). +
      +
    • +
    • lang +
      + Overwrite requested language for short and long warn text. (de|en|it|fr|es|..). +
      +
    • +
    • sort_readings_by +
      + define how readings will be sortet (start|severity|creation). +
      +
    • +
    • htmlsequence +
      + define warn order of html output (ascending|descending). +
      +
    • +
    • htmltitle +
      + title / header for the html ouput +
      +
    • +
    • htmltitleclass +
      + css-Class of title / header for the html ouput +
      +
    • +
    • localiconbase +
      + define baseurl to host your own thunderstorm warn pics (filetype is png). +
      +
    • +
    • intervalAtWarnLevel +
      + define the interval per warnLevel. Example: 2=1800,3=900,4=300 +
      +
    • + + + +
      +
    + +
    + + + Readings +
      +
      +
    • Warn_0|1|2|3...|9_... - active warnings
    • +
    • WarnCount - warnings count
    • +
    • WarnUWZLevel - total warn level
    • +
    • WarnUWZLevel_Color - total warn level color
    • +
    • WarnUWZLevel_Str - total warn level string
    • +
    • Warn_0_AltitudeMin - minimum altitude for warning
    • +
    • Warn_0_AltitudeMax - maximum altitude for warning
    • +
    • Warn_0_EventID - warning EventID
    • +
    • Warn_0_Creation - warning creation
    • +
    • Warn_0_Creation_Date - warning creation datum
    • +
    • Warn_0_Creation_Time - warning creation time
    • +
    • currentIntervalMode - default/warn, Interval is read from INTERVAL or INTERVALWARN Internal
    • +
    • Warn_0_Start - begin of warnperiod
    • +
    • Warn_0_Start_Date - start date of warnperiod
    • +
    • Warn_0_Start_Time - start time of warnperiod
    • +
    • Warn_0_End - end of warnperiod
    • +
    • Warn_0_End_Date - end date of warnperiod
    • +
    • Warn_0_End_Time - end time of warnperiod
    • +
    • Warn_0_Severity - Severity of thunderstorm (0 no thunderstorm, 4, 7, 11, .. heavy thunderstorm)
    • +
    • Warn_0_Hail - warning contains hail
    • +
    • Warn_0_Type - kind of thunderstorm
    • +
    • Warn_0_Type_Str - kind of thunderstorm (text)
    • +
        +
      • 1 - unknown
      • +
      • 2 - storm
      • +
      • 3 - snow
      • +
      • 4 - rain
      • +
      • 5 - frost
      • +
      • 6 - forest fire
      • +
      • 7 - thunderstorm
      • +
      • 8 - glaze
      • +
      • 9 - heat
      • +
      • 10 - freezing rain
      • +
      • 11 - soil frost
      • +
      +
    • Warn_0_uwzLevel - Severity of thunderstorm (0-5)
    • +
    • Warn_0_uwzLevel_Str - Severity of thunderstorm (text)
    • +
    • Warn_0_levelName - Level Warn Name
    • +
    • Warn_0_ShortText - short warn text
    • +
    • Warn_0_LongText - detailed warn text
    • +
    • Warn_0_IconURL - cumulated URL to display warn-icons from www.unwetterzentrale.de
    • +
    +
    + + + Weblinks +
      +
      + + With the additional implemented functions UWZAsHtml, UWZAsHtmlLite, UWZAsHtmlFP, UWZAsHtmlKarteLand and UWZAsHtmlMovie HTML-Code will be created to display warnings and weathermovies, using weblinks. +


      + Example: +
      +
    • define UnwetterDetailiert weblink htmlCode {FHEM::UWZ::UWZAsHtml("Unwetterzentrale")}
    • +
      +
    • define UnwetterLite weblink htmlCode {FHEM::UWZ::UWZAsHtmlLite("Unwetterzentrale")}
    • +
      +
    • define UnwetterFloorplan weblink htmlCode {FHEM::UWZ::UWZAsHtmlFP("Unwetterzentrale")}
    • +
      +
    • define UnwetterKarteLand weblink htmlCode {FHEM::UWZ::UWZAsHtmlKarteLand("Unwetterzentrale","Bayern")}
    • +
        +
      • The second parameter should be one of: +
          +
        • europa
        • +
          +
        • deutschland
        • +
        • deutschland-small
        • +
        • niedersachsen
        • +
        • bremen
        • +
        • bayern
        • +
        • schleswig-holstein
        • +
        • hamburg
        • +
        • mecklenburg-vorpommern
        • +
        • sachsen
        • +
        • sachsen-anhalt
        • +
        • nordrhein-westfalen
        • +
        • thueringen
        • +
        • rheinland-pfalz
        • +
        • saarland
        • +
        • baden-wuerttemberg
        • +
        • hessen
        • +
        • brandenburg
        • +
        • berlin
        • +
          +
        • oesterreich
        • +
        • burgenland
        • +
        • kaernten
        • +
        • niederoesterreich
        • +
        • oberoesterreich
        • +
        • salzburg
        • +
        • steiermark
        • +
        • tirol
        • +
        • vorarlberg
        • +
        • wien
        • +
          +
        • schweiz
        • +
        • aargau
        • +
        • appenzell_ausserrhoden
        • +
        • appenzell_innerrhoden
        • +
        • basel_landschaft
        • +
        • basel_stadt
        • +
        • bern
        • +
        • fribourg
        • +
        • geneve
        • +
        • glarus
        • +
        • graubuenden
        • +
        • jura
        • +
        • luzern
        • +
        • neuchatel
        • +
        • nidwalden
        • +
        • obwalden
        • +
        • schaffhausen
        • +
        • schwyz
        • +
        • solothurn
        • +
        • stgallen
        • +
        • ticino
        • +
        • thurgau
        • +
        • uri
        • +
        • waadt
        • +
        • wallis
        • +
        • zug
        • +
        • zuerich
        • +
          +
        • liechtenstein
        • +
          +
        • belgique
        • +
          +
        • denmark
        • +
          +
        • finnland
        • +
          +
        • france
        • +
        • alsace
        • +
        • aquitaine
        • +
        • basse-normandie
        • +
        • bretagne
        • +
        • champagne-ardenne
        • +
        • franche-comte
        • +
        • haute-normandie
        • +
        • ile-de-france
        • +
        • languedoc-roussillon
        • +
        • limousin
        • +
        • lorraine
        • +
        • bourgogne
        • +
        • centre
        • +
        • midi-pyrenees
        • +
        • nord-pas-de-calais
        • +
        • pays-de-la-loire
        • +
        • picardie
        • +
        • poitou-charentes
        • +
        • provence-alpes-cote-dazur
        • +
        • rhone-alpes
        • +
          +
        • letzebuerg
        • +
          +
        • nederland
        • +
        • drenthe
        • +
        • flevoland
        • +
        • friesland
        • +
        • gelderland
        • +
        • groningen
        • +
        • limburg
        • +
        • noordbrabant
        • +
        • noordholland
        • +
        • overijssel
        • +
        • utrecht
        • +
        • zeeland
        • +
        • zuidholland
        • +
          +
        • norwegen
        • +
          +
        • portugal
        • +
          +
        • sverige
        • +
          +
        • espana
        • +
          +
        • unitedkingdom
        • +
        • eastofengland
        • +
        • eastmidlands
        • +
        • london
        • +
        • northeastengland
        • +
        • northernireland
        • +
        • northwestengland
        • +
        • scotland
        • +
        • southeastengland
        • +
        • southwestengland
        • +
        • wales
        • +
        • westmidlands
        • +
        • yorkshireandthehumber
        • +
          +
        • isobaren1
        • +
        • isobaren2
        • +
        • isobaren3
        • +
        +
      • +
      +
    • define UnwetterKarteMovie weblink htmlCode {FHEM::UWZ::UWZAsHtmlMovie("Unwetterzentrale","currents")}
    • +
        +
      • The second parameter should be one of: +
          +
        • niederschlag-wolken
        • +
        • stroemung
        • +
        • temperatur
        • +
          +
        • niederschlag-wolken-de
        • +
        • stroemung-de
        • +
          +
        • niederschlag-wolken-ch
        • +
        • stroemung-ch
        • +
          +
        • niederschlag-wolken-at
        • +
        • stroemung-at
        • +
          +
        • neerslag-wolken-nl
        • +
        • stroming-nl
        • +
          +
        • nuages-precipitations-fr
        • +
        • courants-fr
        • +
          +
        • clouds-precipitation-uk
        • +
        • currents-uk
        • +
          +
        +
      • +
      + +

      +
    +
    + + +
+ + + +=end html + +=begin html_DE + + +

UWZ

+
    + + Das Modul extrahiert Unwetterwarnungen von www.unwetterzentrale.de. +
    + Hierfür wird die selbe Schnittstelle verwendet die auch die Android App Alerts Pro nutzt. + Es werden maximal 10 Standortbezogene Unwetterwarnungen zur Verfügung gestellt. + Weiterhin verfügt das Modul über HTML-Templates welche als weblink verwendet werden können. +
    + Es nutzt die Perl-Module HTTP::Request, LWP::UserAgent, JSON, Encode::Guess und HTML::Parse. +

    + Define +
      +
      + define <Name> UWZ [Ländercode] [Postleitzahl] [INTERVAL] +


      + Beispiel: +
      + define Unwetterzentrale UWZ DE 86405 3600 +
        + +
    • [Ländercode] +
      + Mögliche Werte: DE, AT, CH, SEARCH, ...
      + (für ander Länder als Deutschland bitte den SEARCH Parameter nutzen um die AreaID zu ermitteln.) +

    • +
    • [Postleitzahl/AreaID] +
      + Die Postleitzahl/AreaID des Ortes für den Unwetterinformationen abgefragt werden sollen. +
      +

    • +
    • [INTERVAL] +
      + Definiert das Interval zur aktualisierung der Unwetterwarnungen. Das Interval wird in Sekunden angegeben, somit aktualisiert das Modul bei einem Interval von 3600 jede Stunde 1 mal. +
      +

    • +
    +
    + + + Get +
      +
      +
    • get <name> Bodenfrost +
      + Gibt aus ob aktuell eine Bodenfrostwarnung besteht (active|inactive). +

    • +
    • get <name> Extremfrost +
      + Gibt aus ob aktuell eine Extremfrostwarnung besteht (active|inactive). +

    • +
    • get <name> Gewitter +
      + Gibt aus ob aktuell eine Gewitter Warnung besteht (active|inactive). +

    • +
    • get <name> Glaette +
      + Gibt aus ob aktuell eine Glaettewarnung besteht (active|inactive). +

    • +
    • get <name> Glatteisregen +
      + Gibt aus ob aktuell eine Glatteisregen Warnung besteht (active|inactive). +

    • +
    • get <name> Hagel +
      + Gibt aus ob aktuell eine Hagel Warnung besteht (active|inactive). +

    • +
    • get <name> Hitze +
      + Gibt aus ob aktuell eine Hitze Warnung besteht (active|inactive). +

    • +
    • get <name> Regen +
      + Gibt aus ob aktuell eine Regen Warnung besteht (active|inactive). +

    • +
    • get <name> Schneefall +
      + Gibt aus ob aktuell eine Schneefall Warnung besteht (active|inactive). +

    • +
    • get <name> Sturm +
      + Gibt aus ob aktuell eine Sturm Warnung besteht (active|inactive). +

    • +
    • get <name> Waldbrand +
      + Gibt aus ob aktuell eine Waldbrand Warnung besteht (active|inactive). +

    • + + +
    + +
    + + Get (Search-Mode) +
      +
      +
    • get <name> SearchAreaID <gesuchte_stadt> +
      + Gibt die AreaID zum eingegebenen Ort aus. +

    • + +
    + +
    + + + + + Set +
      +
      +
    • set <name> update +
      + Startet sofort ein neues Auslesen der Unwetterinformationen. +

    • +
    + +
    + + + Attribute +
      +
      +
    • download +
      + Download Unwetterkarten während des updates (0|1). +
      +
    • +
    • savepath +
      + Pfad zum speichern der Karten (default: /tmp/). +
      +
    • +
    • maps +
      + Leerzeichen separierte Liste der zu speichernden Karten. Für mögliche Karten siehe UWZAsHtmlKarteLand. +
      +
    • +
    • humanreadable +
      + Anzeige weiterer Readings Warn_?_Start_Date, Warn_?_Start_Time, Warn_?_End_Date, Warn_?_End_Time. Diese Readings enthalten aus dem Timestamp kalkulierte Datums/Zeit Angaben. Weiterhin werden folgende Readings aktivier: Warn_?_Type_Str und Warn_?_uwzLevel_Str welche den Unwettertyp als auch das Unwetter-Warn-Level als Text ausgeben. (0|1) +
      +
    • +
    • lang +
      + Umschalten der angeforderten Sprache für kurz und lange warn text. (de|en|it|fr|es|..). +
      +
    • +
    • sort_readings_by +
      + Sortierreihenfolge der Warnmeldungen. (start|severity|creation). +
      +
    • +
    • htmlsequence +
      + Anzeigereihenfolge der html warnungen. (ascending|descending). +
      +
    • +
    • htmltitle +
      + Titel / Ueberschrift der HTML Ausgabe +
      +
    • +
    • htmltitleclass +
      + css-Class des Titels der HTML Ausgabe +
      +
    • +
    • localiconbase +
      + BaseURL angeben um Warn Icons lokal zu hosten. (Dateityp ist png). +
      +
    • +
    • intervalAtWarnLevel +
      + konfiguriert den Interval je nach WarnLevel. Beispiel: 2=1800,3=900,4=300 +
      +
    • + +
      +
    + +
    + + + Readings +
      +
      +
    • Warn_0|1|2|3...|9_... - aktive Warnmeldungen
    • +
    • WarnCount - Anzahl der aktiven Warnmeldungen
    • +
    • WarnUWZLevel - Gesamt Warn Level
    • +
    • WarnUWZLevel_Color - Gesamt Warn Level Farbe
    • +
    • WarnUWZLevel_Str - Gesamt Warn Level Text
    • +
    • Warn_0_AltitudeMin - minimum Höhe für Warnung
    • +
    • Warn_0_AltitudeMax - maximum Höhe für Warnung
    • +
    • Warn_0_EventID - EventID der Warnung
    • +
    • Warn_0_Creation - Warnungs Erzeugung
    • +
    • Warn_0_Creation_Date - Warnungs Erzeugungs Datum
    • +
    • Warn_0_Creation_Time - Warnungs Erzeugungs Zeit
    • +
    • currentIntervalMode - default/warn, aktuell Verwendeter Interval. Internal INTERVAL oder INTERVALWARN
    • +
    • Warn_0_Start - Begin der Warnung
    • +
    • Warn_0_Start_Date - Startdatum der Warnung
    • +
    • Warn_0_Start_Time - Startzeit der Warnung
    • +
    • Warn_0_End - Warn Ende
    • +
    • Warn_0_End_Date - Enddatum der Warnung
    • +
    • Warn_0_End_Time - Endzeit der Warnung
    • +
    • Warn_0_Severity - Schwere des Unwetters (0 kein Unwetter, 12 massives Unwetter)
    • +
    • Warn_0_Hail - Hagelwarnung (1|0)
    • +
    • Warn_0_Type - Art des Unwetters
    • +
    • Warn_0_Type_Str - Art des Unwetters (text)
    • +
        +
      • 1 - unbekannt
      • +
      • 2 - Sturm/Orkan
      • +
      • 3 - Schneefall
      • +
      • 4 - Regen
      • +
      • 5 - Extremfrost
      • +
      • 6 - Waldbrandgefahr
      • +
      • 7 - Gewitter
      • +
      • 8 - Glätte
      • +
      • 9 - Hitze
      • +
      • 10 - Glatteisregen
      • +
      • 11 - Bodenfrost
      • +
      +
    • Warn_0_uwzLevel - Unwetterwarnstufe (0-5)
    • +
    • Warn_0_uwzLevel_Str - Unwetterwarnstufe (text)
    • +
    • Warn_0_levelName - Level Warn Name
    • +
    • Warn_0_ShortText - Kurzbeschreibung der Warnung
    • +
    • Warn_0_LongText - Ausführliche Unwetterbeschreibung
    • +
    • Warn_0_IconURL - Kumulierte URL um Warnungs-Icon von www.unwetterzentrale.de anzuzeigen
    • +
    +
    + + + Weblinks +
      +
      + + Über die Funktionen UWZAsHtml, UWZAsHtmlLite, UWZAsHtmlFP, UWZAsHtmlKarteLand, UWZAsHtmlMovie wird HTML-Code zur Warnanzeige und Wetterfilme über weblinks erzeugt. +


      + Beispiele: +
      +
    • define UnwetterDetailiert weblink htmlCode {FHEM::UWZ::UWZAsHtml("Unwetterzentrale")}
    • +
      +
    • define UnwetterLite weblink htmlCode {FHEM::UWZ::UWZAsHtmlLite("Unwetterzentrale")}
    • +
      +
    • define UnwetterFloorplan weblink htmlCode {FHEM::UWZ::UWZAsHtmlFP("Unwetterzentrale")}
    • +
      +
    • define UnwetterKarteLand weblink htmlCode {FHEM::UWZ::UWZAsHtmlKarteLand("Unwetterzentrale","Bayern")}
    • +
        +
      • Der zweite Parameter kann einer der folgenden sein: +
          +
        • europa
        • +
          +
        • deutschland
        • +
        • deutschland-small
        • +
        • niedersachsen
        • +
        • bremen
        • +
        • bayern
        • +
        • schleswig-holstein
        • +
        • hamburg
        • +
        • mecklenburg-vorpommern
        • +
        • sachsen
        • +
        • sachsen-anhalt
        • +
        • nordrhein-westfalen
        • +
        • thueringen
        • +
        • rheinland-pfalz
        • +
        • saarland
        • +
        • baden-wuerttemberg
        • +
        • hessen
        • +
        • brandenburg
        • +
        • berlin
        • +
          +
        • oesterreich
        • +
        • burgenland
        • +
        • kaernten
        • +
        • niederoesterreich
        • +
        • oberoesterreich
        • +
        • salzburg
        • +
        • steiermark
        • +
        • tirol
        • +
        • vorarlberg
        • +
        • wien
        • +
          +
        • schweiz
        • +
        • aargau
        • +
        • appenzell_ausserrhoden
        • +
        • appenzell_innerrhoden
        • +
        • basel_landschaft
        • +
        • basel_stadt
        • +
        • bern
        • +
        • fribourg
        • +
        • geneve
        • +
        • glarus
        • +
        • graubuenden
        • +
        • jura
        • +
        • luzern
        • +
        • neuchatel
        • +
        • nidwalden
        • +
        • obwalden
        • +
        • schaffhausen
        • +
        • schwyz
        • +
        • solothurn
        • +
        • stgallen
        • +
        • ticino
        • +
        • thurgau
        • +
        • uri
        • +
        • waadt
        • +
        • wallis
        • +
        • zug
        • +
        • zuerich
        • +
          +
        • liechtenstein
        • +
          +
        • belgique
        • +
          +
        • denmark
        • +
          +
        • finnland
        • +
          +
        • france
        • +
        • alsace
        • +
        • aquitaine
        • +
        • basse-normandie
        • +
        • bretagne
        • +
        • champagne-ardenne
        • +
        • franche-comte
        • +
        • haute-normandie
        • +
        • ile-de-france
        • +
        • languedoc-roussillon
        • +
        • limousin
        • +
        • lorraine
        • +
        • bourgogne
        • +
        • centre
        • +
        • midi-pyrenees
        • +
        • nord-pas-de-calais
        • +
        • pays-de-la-loire
        • +
        • picardie
        • +
        • poitou-charentes
        • +
        • provence-alpes-cote-dazur
        • +
        • rhone-alpes
        • +
          +
        • letzebuerg
        • +
          +
        • nederland
        • +
        • drenthe
        • +
        • flevoland
        • +
        • friesland
        • +
        • gelderland
        • +
        • groningen
        • +
        • limburg
        • +
        • noordbrabant
        • +
        • noordholland
        • +
        • overijssel
        • +
        • utrecht
        • +
        • zeeland
        • +
        • zuidholland
        • +
          +
        • norwegen
        • +
          +
        • portugal
        • +
          +
        • sverige
        • +
          +
        • espana
        • +
          +
        • unitedkingdom
        • +
        • eastofengland
        • +
        • eastmidlands
        • +
        • london
        • +
        • northeastengland
        • +
        • northernireland
        • +
        • northwestengland
        • +
        • scotland
        • +
        • southeastengland
        • +
        • southwestengland
        • +
        • wales
        • +
        • westmidlands
        • +
        • yorkshireandthehumber
        • +
          +
        • isobaren1
        • +
        • isobaren2
        • +
        • isobaren3
        • +
        +
      • +
      +
    • define UnwetterKarteMovie weblink htmlCode {FHEM::UWZ::UWZAsHtmlMovie("Unwetterzentrale","niederschlag-wolken-de")}
    • +
        +
      • Der zweite Parameter kann einer der folgenden sein: +
          +
        • niederschlag-wolken
        • +
        • stroemung
        • +
        • temperatur
        • +
          +
        • niederschlag-wolken-de
        • +
        • stroemung-de
        • +
          +
        • niederschlag-wolken-ch
        • +
        • stroemung-ch
        • +
          +
        • niederschlag-wolken-at
        • +
        • stroemung-at
        • +
          +
        • neerslag-wolken-nl
        • +
        • stroming-nl
        • +
          +
        • nuages-precipitations-fr
        • +
        • courants-fr
        • +
          +
        • clouds-precipitation-uk
        • +
        • currents-uk
        • +
          +
        +
      • +
      + + +

      +
    +
    + + +
+ +=end html_DE + +=for :application/json;q=META.json 77_UWZ.pm +{ + "abstract": "Module to extracts thunderstorm warnings from unwetterzentrale.de", + "x_lang": { + "de": { + "abstract": "Modul zum anzeigen von Unwetterwarnungen von unwetterzentrale.de" + } + }, + "keywords": [ + "fhem-mod-device", + "fhem-core", + "Unwetter", + "Wetter", + "Warnungen" + ], + "release_status": "stable", + "license": "GPL_2", + "version": "v3.1.0", + "author": [ + "Marko Oldenburg " + ], + "x_fhem_maintainer": [ + "CoolTux" + ], + "x_fhem_maintainer_github": [ + "LeonGaultier" + ], + "prereqs": { + "runtime": { + "requires": { + "FHEM": 5.00918799, + "perl": 5.016, + "Meta": 0, + "JSON": 0, + "Date::Parse": 0 + }, + "recommends": { + }, + "suggests": { + } + } + } +} +=end :application/json;q=META.json + +=cut